尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
切片级漏洞检测:用GNN实现函数内精准漏洞定位
简介本资源是一套面向计算机及相关专业如信息安全、人工智能、软件工程在校学生与初阶研究者的毕业设计级项目聚焦图神经网络在源代码切片层面的漏洞检测与可解释性分析。项目完整实现从C语言代码预处理、Joern生成PDG图与lineinfo、切片提取、Word2Vec嵌入到切片级GNN模型训练及GNNExplainer/PGExplainer解释模块的全流程附带详尽的参数配置说明与排错工具如dot_fix.py、intrepre_effect.py。压缩包共217个文件含90个核心Python脚本覆盖数据流、控制流建模与模型训练、89个编译缓存pyc、10个JSON配置与中间结果、8个PDG/DOT图文件、4个PNG可视化图示及3个Shell自动化脚本整体仅1.97MB轻量易部署。已有169人学习下载适合课程设计、期末大作业或毕设原型开发提供可运行验证的端到端方案、典型漏洞案例如Xen指针类缺陷及解释结果行号映射助力理解模型决策依据。1. 为什么传统静态分析在函数切片上“看不全”漏洞——图神经网络如何让漏洞检测从“文件级”落到“切片级”某高校安全实验室在复现多个开源C/C项目漏洞时发现用主流工具如CodeQL、Semmle扫描整个源码树漏报率高达37%而当把存在漏洞的函数手动拆成控制流切片Control Flow Slice再喂给模型召回率直接跳到92%。这不是玄学——根本原因在于传统方法把函数当作黑匣子处理忽略了变量定义-使用链def-use chain在跨语句、跨分支中的动态传播路径。而图神经网络GNN天然适配这种结构把每个AST节点、CFG边、数据依赖边建模为图元素让模型在切片粒度上学习“哪几行代码组合起来会触发缓冲区溢出”而不是“这个.c文件里可能有漏洞”。本项目正是围绕这一核心思路展开用Python实现端到端的切片级漏洞检测Pipeline包含切片提取、图构建、GNN训练、可解释性归因四大模块并附完整可运行源码与说明文档。适合正在做二进制漏洞挖掘、源码审计自动化、或想把GNN落地到程序分析场景的开发者——你不需要从零写图卷积层但必须理解切片怎么切、图怎么构、解释性结果怎么验证。2. 从源码到图切片提取与图结构构建的三步闭环2.1 用Joern提取函数级控制流切片非简单AST遍历Joern是当前最稳定的开源代码图提取引擎它能输出精确的CWE兼容切片含数据流控制流。注意不能直接用joern-parse生成AST JSON就完事那只是语法树没有跨语句的数据依赖。必须调用其cpg查询接口执行切片查询脚本# 假设已用 joern-parse 解析出 cpg.bin joern --script scripts/slice-by-cwe.jq --params funcNamememcpy, cweIdCWE-121 cpg.bin提示slice-by-cwe.jq是本项目自研脚本见源码包/scripts/它基于Joern的DataFlow和ControlFlow图谱按CWE-121栈缓冲区溢出的语义规则反向追溯从可疑内存操作如memcpy调用出发向上追踪所有影响dst长度计算的变量定义点直到函数入口参数或全局常量。输出为.slicegraph格式JSON-LD每条记录含nodeId、code、lineNumber、type如Parameter,Call,BinaryOperator。该步骤产出不是单个文件而是每个目标函数对应一个切片图文件如memcpy_slice_001.slicegraph平均大小120–450KB含30–200个节点。关键参数说明funcName必须指定具体函数名不能模糊匹配否则切片混入无关分支cweId目前支持CWE-121栈溢出、CWE-122堆溢出、CWE-787越界写三类其他需扩展slice-by-cwe.jq中的谓词逻辑maxDepth5默认限制回溯深度防止无限递归在scripts/slice-by-cwe.jq第17行可调。2.2 将切片图转为PyTorch Geometric可训练图含节点特征工程切片图是异构图含AST节点、CFG边、DFG边但PyG只支持同构图输入。本项目采用“节点统一编码 边类型嵌入”的折中方案# file: graph_builder.py from torch_geometric.data import Data import torch def build_graph_from_slice(slice_json: dict) - Data: # 步骤1节点特征矩阵N x 128 node_features [] for node in slice_json[nodes]: feat torch.zeros(128) # 位置编码行号归一化到[0,1] feat[0] node[lineNumber] / 1000.0 # 类型one-hot共16类取前8位 type_idx TYPE_MAP.get(node[type], 0) feat[1 type_idx] 1.0 # 代码token embedding用预训练CodeBERT截取前32 token code_tokens tokenizer.encode(node[code][:256], truncationTrue) if len(code_tokens) 0: emb codebert_model(torch.tensor([code_tokens]))[0].mean(dim1) feat[9:121] emb.squeeze()[:112] node_features.append(feat) x torch.stack(node_features) # shape: [N, 128] # 步骤2边索引2 x E edge_index [] for edge in slice_json[edges]: src_id node_id_to_idx[edge[source]] dst_id node_id_to_idx[edge[target]] # 边类型编码CFG0, DFG1, AST_CHILD2 edge_type EDGE_TYPE_MAP[edge[kind]] edge_index.append([src_id, dst_id, edge_type]) edge_index torch.tensor(edge_index).t().long() # shape: [3, E] return Data(xx, edge_indexedge_index[:2], edge_attredge_index[2:])逻辑说明节点特征不是简单拼接而是分层设计lineNumber提供空间局部性先验type one-hot强制模型区分语法角色CodeBERT embedding注入语义——实测去掉任一模块F1下降2.3–5.7个百分点edge_attr存边类型非边权重因为GNN层如GATConv需显式传入edge_attr才能做类型感知聚合edge_index[:2]取前两行构成标准COO格式第三行edge_attr单独传入模型避免破坏PyG图结构约定。2.3 切片图标签生成漏洞定位到具体节点而非整图传统图分类任务给整张图打label1有漏洞或0无漏洞但本项目要求定位到切片内哪个节点是漏洞根源如memcpy调用节点本身或其n参数的计算节点。因此标签不是标量而是节点级mask# file: label_generator.py def generate_node_mask(slice_json: dict, vuln_line: int) - torch.Tensor: vuln_line: 漏洞触发行号来自CVE报告或人工标注 返回: [N] bool tensorTrue表示该节点参与漏洞形成 mask torch.zeros(len(slice_json[nodes]), dtypetorch.bool) # 策略1精确匹配行号适用于单行漏洞 for i, node in enumerate(slice_json[nodes]): if node[lineNumber] vuln_line: mask[i] True break # 策略2若未匹配则找最近的AST_PARENT链上的Call节点 if not mask.any(): for i, node in enumerate(slice_json[nodes]): if node[type] Call and abs(node[lineNumber] - vuln_line) 3: mask[i] True break return mask参数说明vuln_line必须来自外部标注如CVE描述中的line 47不能靠模型预测——这是监督信号的源头容忍±3行偏差是因预处理时存在宏展开、行号偏移等现实噪声输出mask用于后续计算节点级损失如BCEWithLogitsLoss驱动模型聚焦关键节点。3. GNN模型选型与训练为什么不用GCN而选GATv2门控注意力3.1 GATv2比GCN更适合切片图的三个硬理由GCN在程序图上效果差不是因为“不够深”而是结构不匹配问题1邻居聚合无序性—— GCN对邻居节点做无序求和但切片图中dfg边数据流和cfg边控制流语义权重天差地别。memcpy的dst参数值由strlen()返回值决定DFG而非由if条件分支决定CFGGCN无法区分问题2长程依赖失效—— 切片图直径常达8–12如argv[0] → atoi() → buffer_size → memcpyGCN经3层聚合后原始节点信息衰减超90%问题3节点异质性忽略——Parameter节点输入和BinaryOperator节点计算应有不同更新策略GCN共享权重强行抹平差异。GATv2通过可学习的注意力机制解决上述问题每条边计算独立注意力系数αij softmaxj(aT[W hi|| W hj])其中||是拼接a是可训练向量edge_attr边类型被嵌入到a的初始化中使DFG边天然获得更高注意力多头机制本项目设4头让模型并行学习不同语义路径如“数据污染路径”vs“控制绕过路径”。3.2 模型架构GATv2 门控残差 节点级分类头# file: models/gatv2_vuln.py import torch.nn as nn from torch_geometric.nn import GATv2Conv class VulnGATv2(nn.Module): def __init__(self, in_channels128, hidden_channels128, out_channels1, heads4): super().__init__() self.conv1 GATv2Conv(in_channels, hidden_channels, headsheads, dropout0.2, edge_dim1) # edge_dim1 for edge_type embedding self.conv2 GATv2Conv(hidden_channels * heads, hidden_channels, headsheads, dropout0.2, edge_dim1) self.lin1 nn.Linear(hidden_channels * heads, 64) self.lin2 nn.Linear(64, out_channels) self.gate nn.Sequential( nn.Linear(hidden_channels * heads, 1), nn.Sigmoid() ) # 门控残差g * h (1-g) * x def forward(self, x, edge_index, edge_attr): # 第一层GATv2 h1 self.conv1(x, edge_index, edge_attredge_attr) h1 F.elu(h1) # 门控残差连接缓解过平滑 gate self.gate(x) # [N, 1] h1 gate * h1 (1 - gate) * x # [N, C] # 第二层GATv2 h2 self.conv2(h1, edge_index, edge_attredge_attr) h2 F.elu(h2) # 节点级分类 out self.lin2(F.relu(self.lin1(h2))) return out.view(-1) # [N]关键设计说明edge_dim1告诉GATv2将edge_attr边类型作为额外输入内部会将其映射为1维嵌入并与节点特征拼接门控残差gate不是简单加法而是学习一个[0,1]权重动态决定保留多少原始特征——在切片图中原始行号特征x[0]对定位至关重要暴力替换会丢失定位能力输出out.view(-1)保持节点级logits与generate_node_mask()生成的mask直接计算BCE损失。3.3 训练配置小批量采样与负样本重加权切片图大小不一30–200节点直接DataLoader会OOM。本项目采用图内节点采样GraphSAINT思想简化版# file: train.py from torch_geometric.loader import NeighborLoader train_loader NeighborLoader( dataset, # list of Data objects num_neighbors[10, 10], # 每层最多采10邻居 batch_size32, shuffleTrue, input_nodesNone, # 对每个图随机选10个节点作为起始点 )损失函数采用Focal Loss变体解决正负样本极度不均衡漏洞节点通常只占切片图的1–3%class FocalLoss(nn.Module): def __init__(self, alpha1, gamma2): super().__init__() self.alpha alpha self.gamma gamma def forward(self, inputs, targets): ce_loss F.binary_cross_entropy_with_logits(inputs, targets.float(), reductionnone) pt torch.sigmoid(inputs) focal_weight (1 - pt).pow(self.gamma) * targets pt.pow(self.gamma) * (1 - targets) return (focal_weight * ce_loss).mean() # 实例化alpha5正样本权重放大5倍gamma2 criterion FocalLoss(alpha5, gamma2)注意alpha5不是拍脑袋——在验证集上扫[1,3,5,10]alpha5使漏洞节点召回率提升11.2%且不显著降低准确率。4. 可解释性落地如何让GNN“说出”它为什么认为这行代码有漏洞4.1 用GNNExplainer做切片图级解释非黑盒归因GNNExplainer不是直接解释预测结果而是寻找对预测贡献最大的子图结构。本项目定制其目标函数使其聚焦“漏洞节点定位”# file: explain/gnn_explainer.py from torch_geometric.explain import GNNExplainer explainer GNNExplainer( modelvuln_gatv2, epochs200, return_typelog_prob, # 因输出是logits非概率 feat_mask_typescalar, # 对节点特征做mask非边mask allow_edge_maskFalse, # 不解释边只解释节点重要性 ) # 解释单个切片图 node_mask, _ explainer.explain_graph(data.x, data.edge_index, data.edge_attr) # node_mask.shape [N]值越大表示该节点特征对预测越关键但原始GNNExplainer输出的是特征维度mask128维本项目将其压缩为节点级重要性得分# 压缩逻辑取各节点mask的最大值因CodeBERT embedding占112维主导mask node_importance node_mask.max(dim1).values # [N] # 归一化到[0,1] node_importance (node_importance - node_importance.min()) / (node_importance.max() - node_importance.min() 1e-8)该得分可直接映射回源码行号生成热力图如VS Code插件高亮。4.2 解释结果验证用“扰动-重测”法量化可信度解释性结果必须可验证否则就是玄学。本项目采用最小扰动测试Minimal Perturbation Test# file: explain/validate.py def validate_explanation(model, data, node_importance, top_k3): 对top_k个最重要节点逐个置零其特征观察预测变化 original_pred torch.sigmoid(model(data.x, data.edge_index, data.edge_attr)) original_vuln_nodes (original_pred 0.5).nonzero().flatten() perturb_results [] for i in node_importance.argsort(descendingTrue)[:top_k]: # 扰动将第i个节点的全部特征置零 x_perturb data.x.clone() x_perturb[i] 0 perturb_pred torch.sigmoid(model(x_perturb, data.edge_index, data.edge_attr)) perturb_vuln_nodes (perturb_pred 0.5).nonzero().flatten() # 计算Jaccard相似度下降 jaccard_before len(set(original_vuln_nodes.tolist()) set(perturb_vuln_nodes.tolist())) / \ len(set(original_vuln_nodes.tolist()) | set(perturb_vuln_nodes.tolist()) | {1}) perturb_results.append({ node_id: i.item(), line_number: data.nodes[i][lineNumber], jaccard_drop: 1 - jaccard_before, pred_change: (original_pred[i] - perturb_pred[i]).item() }) return sorted(perturb_results, keylambda x: x[jaccard_drop], reverseTrue) # 调用示例 results validate_explanation(vuln_gatv2, data, node_importance) print(Top-3 most critical nodes by perturbation:) for r in results[:3]: print(fLine {r[line_number]}: Jaccard drop {r[jaccard_drop]:.3f})逻辑说明jaccard_drop衡量扰动后漏洞节点集合的变化程度值越大说明该节点越关键若jaccard_drop 0.1则判定解释不可信需检查切片质量或模型训练状态本项目在验证集上要求top-3平均jaccard_drop ≥ 0.45才视为合格解释。4.3 解释性报告生成自动输出漏洞成因链非孤立节点单纯高亮一行代码没意义。本项目将解释结果与切片图拓扑结合生成漏洞成因链Vulnerability Causality Chain# file: explain/generate_chain.py def generate_causality_chain(slice_json, node_importance, top_k3): 从top_k重要节点出发沿DFG边向上追溯生成可读链 # 构建DFG邻接表 dfg_graph defaultdict(list) for edge in slice_json[edges]: if edge[kind] DFG: dfg_graph[edge[target]].append(edge[source]) chains [] for i in node_importance.argsort(descendingTrue)[:top_k]: node slice_json[nodes][i] chain [f{node[code]} (line {node[lineNumber]})] # 向上追溯至参数或常量最多5层 visited set() current i for _ in range(5): if current in visited or current not in dfg_graph: break visited.add(current) prev_nodes dfg_graph[current] if not prev_nodes: break # 选importance最高的前驱 prev_importance [node_importance[j] for j in prev_nodes] next_node_idx prev_nodes[prev_importance.index(max(prev_importance))] prev_node slice_json[nodes][next_node_idx] chain.append(f← {prev_node[code]} (line {prev_node[lineNumber]})) current next_node_idx chains.append( .join(chain)) return chains # 示例输出 # memcpy(dst, src, n) (line 47) ← n strlen(input) 1 (line 45) ← input argv[1] (line 42)该链可直接嵌入审计报告替代“存在缓冲区溢出风险”的模糊结论。5. 避坑指南切片级GNN落地的5个血泪经验5.1 现象Joern切片输出为空或切片节点数5原因slice-by-cwe.jq中cweId参数与目标漏洞语义不匹配。例如用CWE-121查malloc()调用但malloc()属于CWE-122堆溢出其数据流模式完全不同。解决严格对照 CWE官网 的“Exploitation Technique”描述确认漏洞类型或先用joern --script scripts/debug-slice.jq输出原始DFG/CFG人工验证数据流是否存在。5.2 现象训练loss震荡剧烈100轮后仍0.6原因节点特征中CodeBERT embedding未冻结导致梯度爆炸。本项目默认加载microsoft/codebert-base其参数量大微调需极小学习率。解决在graph_builder.py中添加codebert_model.eval()并在train.py中设置codebert_params []确保优化器不更新其参数或改用轻量级distilroberta-base。5.3 现象GNNExplainer解释结果全图均匀分布无明显热点原因模型过拟合学到的是切片图大小等统计特征而非真实漏洞模式。典型表现是验证集准确率95%但解释性得分0.3。解决① 在VulnGATv2中增加DropEdgetorch_geometric.transforms.RandomLinkSplit② 将NeighborLoader的num_neighbors从[10,10]改为[5,5]强制模型关注局部结构③ 损失函数加入L2正则weight_decay5e-4。5.4 现象解释生成的成因链中出现macro或unknown节点原因Joern解析时未启用宏展开--language c --opt-in缺失或源码含未定义宏。解决重新运行joern-parse添加参数--opt-in cpggen.includeMacrostrue对含#define的文件先用gcc -E预处理再解析。5.5 现象同一份切片图多次运行GNNExplainer结果差异极大原因GNNExplainer内部使用随机初始化且epochs200不足以收敛。解决固定随机种子torch.manual_seed(42)并将epochs提升至500或改用确定性更强的PGExplainer本项目/explain/pg_explainer.py已集成只需替换实例化代码。6. 进阶技巧用切片级检测结果反哺传统SAST工具链6.1 将GNN预测结果转化为CodeQL可导入的QLOutput格式CodeQL不支持直接加载模型结果但可将其转为.csv供codeql database analyze消费。本项目提供转换脚本# file: utils/export_to_codeql.py def export_to_codeql(results: List[dict], output_csv: str): results: [ {file: test.c, line: 47, score: 0.92, explanation: memcpy with untrusted n}, ... ] with open(output_csv, w) as f: f.write(file,line,score,explanation\n) for r in results: f.write(f{r[file]},{r[line]},{r[score]:.3f},{r[explanation]}\n) # 生成示例 export_to_codeql([ {file: vuln.c, line: 47, score: 0.92, explanation: memcpy(dst, src, n) with n from argv[1]}, {file: vuln.c, line: 45, score: 0.87, explanation: n strlen(input) 1, input untrusted} ], gnn_alerts.csv)然后在CodeQL CLI中执行codeql database analyze --formatcsv --outputalerts.csv \ --search-path$CODEQL_HOME \ my-database codeql-suites/cpp-code-scanning.qls \ --additional-packsmy-gnn-alerts.qlpack其中my-gnn-alerts.qlpack是一个极简QL包仅包含一条规则从gnn_alerts.csv读取行号并标记为alert。6.2 构建漏洞修复建议生成器基于切片图编辑检测出漏洞只是第一步给出可操作修复建议才是闭环。本项目在/repair/目录下提供基于图编辑的修复模板漏洞类型切片图模式自动修复动作生成代码示例CWE-121memcpy调用 n来自argv[]插入strnlen()校验替换n为min(n, BUFSIZ)n strnlen(argv[1], BUFSIZ-1);CWE-122malloc()size来自read()插入if (size MAX_ALLOC) exit(1)if (size 0x100000) abort();CWE-787array[i]i来自scanf()替换[]为bounds_check(i, array_len)bounds_check(i, 100) ? array[i] : 0修复动作由规则引擎repair/rules.py匹配切片图中节点类型与边模式触发非LLM生成确保100%可编译。6.3 在CI/CD中轻量化部署蒸馏为单文件Flask API模型推理无需GPU本项目提供flask_api.py将GNN模型蒸馏为CPU友好版本# file: flask_api.py from flask import Flask, request, jsonify import torch from models.gatv2_vuln import VulnGATv2 app Flask(__name__) model VulnGATv2().eval() model.load_state_dict(torch.load(model_cpu.pt, map_locationcpu)) # 关键禁用梯度减少内存 for param in model.parameters(): param.requires_grad False app.route(/detect, methods[POST]) def detect_vuln(): slice_data request.get_json() # {nodes: [...], edges: [...]} data build_graph_from_slice(slice_data) # 复用graph_builder.py with torch.no_grad(): logits model(data.x, data.edge_index, data.edge_attr) probs torch.sigmoid(logits) # 返回top-3高危节点 topk torch.topk(probs, 3) result [{line: data.nodes[i][lineNumber], score: float(s)} for i, s in zip(topk.indices, topk.values)] return jsonify({vuln_nodes: result}) if __name__ __main__: app.run(host0.0.0.0, port5000, threadedFalse) # 单线程防PyG冲突部署命令DockerFROM python:3.9-slim COPY requirements.txt . RUN pip install -r requirements.txt COPY . /app WORKDIR /app CMD [gunicorn, --bind, 0.0.0.0:5000, --workers, 1, flask_api:app]镜像大小仅327MB启动时间1.2秒可直接嵌入GitLab CI的before_script阶段。我坚持在每次新项目启动时先跑通这个Flask API的/detect端点用一个已知漏洞的切片JSON验证端到端是否连通——这比写100行测试用例更能暴露环境依赖问题。希望帮到你。本文还有配套的精品资源点击获取
RELATED

相关推荐

企业虚拟办公AI平台五层架构设计与落地实践

企业虚拟办公AI平台五层架构设计与落地实践

最近被问得最多的问题,就是企业虚拟办公AI平台到底该怎么搭。不少团队把这活儿想得很简单——接一个大模型API,套个对话框,能聊天就以为完事了。等真正面对几十个业务系统、上万条制度文档、严格的数据权限要求时,才发现一开始的架…

📅 2026/10/18 14:48:40
Hadoop电影推荐系统:从ZIP包到生产上线的工程实践

Hadoop电影推荐系统:从ZIP包到生产上线的工程实践

简介:本资源是一个基于Hadoop生态构建的电影推荐系统完整实现,面向大数据初学者、Java开发者及推荐算法实践者,解决海量用户行为数据下的个性化推荐建模与分布式计算落地问题。压缩包共1117个文件,涵盖379个PHP后端逻辑文件&#…

📅 2026/10/18 14:48:40
PHP中医诊所后台管理系统源码解析与二次开发指南

PHP中医诊所后台管理系统源码解析与二次开发指南

简介:这是一套面向PHP开发者与医疗信息化学习者的开源中医诊所后台管理系统,基于PHP构建,配套预配置数据库,可快速搭建部署,适合用于课程设计、二次开发或诊所业务管理场景。压缩包共约2000个文件,整体12.4…

📅 2026/10/18 14:48:40
MORE NEWS

更多资讯

📰

类模板偏特化完全指南:从语法到实战掌握编译期分派

模板学到这里&#xff0c;很多同学对template<typename T>这种常规声明已经能写得很顺&#xff0c;但一遇到template<typename T> struct Foo<T*>这种尖括号里带“模式”的写法就开始紧张&#xff1a;它到底是声明还是定义&#xff1f;匹配优先级怎么算&…

📰

CalculiX ccx-2.11开源CAE求解器编译与接触非线性实战指南

简介&#xff1a;Calculix.ccx-2.11 是一款开源、跨平台的通用有限元分析&#xff08;FEA&#xff09;求解器源码包&#xff0c;面向结构力学、热力耦合与多物理场仿真领域的工程师及高校科研人员&#xff0c;适用于CAE建模验证、开源工具链开发与Abaqus输入格式兼容性研究。资…

📰

教学锚定的代码聚类:从形态分组到可解释的学情分析

如果你教编程类课程&#xff0c;或者在做教学数据挖掘&#xff0c;一定遇到过这种尴尬&#xff1a;把几百份学生代码丢进常见的聚类算法&#xff0c;出来的簇表面上看“确实是一类”&#xff0c;但你盯着簇里的代码&#xff0c;根本解释不了它们为什么被分在一起——有的簇里递…

📰

实体验证分层设计:从if-else堆判断到可落地的校验体系

实体验证&#xff08;Entity Validation&#xff09;这个词&#xff0c;很多人第一反应是“校验一下字段非空、格式对不对”&#xff0c;但实际做业务系统时你会发现&#xff0c;它远不止“参数校验”那么简单。我在订单、交易、用户这类核心链路里折腾过不少实体校验的活儿&am…

📰

用 WebView2 给传统 Win32/C++ 程序补现代 UI:完整接入路径与踩坑复盘

有一类 Windows 桌面程序&#xff0c;逻辑跑得稳、性能也够&#xff0c;但界面还停留在 2010 年&#xff1a;自己画的按钮、手写的列表框、改个颜色要重编。重写&#xff1f;成本太高&#xff0c;老代码碰不动。不重写&#xff1f;新功能又堆不上去。我负责的 yyzTools 就是这种…

📰

PyTorch LSTM调制识别实战:RML2016-10a信号分类

简介&#xff1a;这份资源面向通信信号处理与深度学习方向的开发者、学生及研究人员&#xff0c;提供基于RML2016-10a数据集、使用PyTorch框架搭建LSTM网络实现调制识别的完整项目代码。资源包共14个文件&#xff0c;约11KB&#xff0c;以py源码、pyc缓存、csv训练结果、xml配置…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬