news 2026/10/14 17:17:11

小恶意代码识别器(4)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
小恶意代码识别器(4)

让程序会判断:归一化、逻辑回归与模型文件

前两篇把数据读进来了也检查过了,这篇写程序真正做判断的部分:怎么把特征值变成 0 到 1 之间的概率。

为什么需要归一化

五个特征的量级差得太远,文件大小是几万甚至几十万,比例是零点几。如果直接拿去加权求和,大的数会把小的数完全压过去,模型等于只看文件大小,另外四个特征成了摆设。

解决办法是把每个特征按比例缩放到相近的范围,公式是:

x = (原始值 - min) / (max - min)

min 和 max 是这一列在训练集上的最小值和最大值。比如 file_size 这一列最小 18432、最大 266240,那么 18432 缩放后是 0,266240 是 1,中间的值落在 0 到 1 之间。

关键在于训练和预测必须用同一组 min 和 max,否则标准变了,结果就不可比。所以模型文件里要把它们存下来。

权重和偏置是什么

判断的依据是五个特征的加权和再加一个偏置:

z = bias + w0*x0 + w1*x1 + w2*x2 + w3*x3 + w4*x4

权重表示每个特征的重要程度。老师给的模型里,信息熵的权重是 4.319,最大,说明这个特征最能说明问题;文件大小的权重只有 0.166,参考价值最小。权重为负说明这个特征越大反而越不像可疑。

偏置可以理解成判定的门槛。我们这个模型的偏置是 -2.494,是个负数,意味着证据的分数必须先填平这个坑,总分才能回到 0,概率才能到 0.5。相当于默认假定良性,证据足够强才改判可疑。这个值是训练时机器在训练集上试出来的,不是人工拍的。

从总分到概率

总分 z 可能是很大的正数也可能是很小的负数,不方便解读,用 Sigmoid 压到 0 到 1 之间:

p = 1 / (1 + e^(-z))

z 为 0 时 p 正好是 0.5,大于 0.5 判可疑,小于 0.5 判良性。

读模型文件

模型文件一共六行,分别是标识、特征数、五个权重、偏置、五个最小值、五个最大值。用fscanf按顺序读,它会自动跳过空白和换行。

FILE*fp=fopen(path,"r");if(fp==NULL){printf("open failed\n");return1;}chartag[64];fscanf(fp,"%63s",tag);if(strcmp(tag,"TEACHMODEL_V1")!=0){printf("bad model\n");fclose(fp);return1;}intk;fscanf(fp,"%d",&k);if(k!=FEATURE_COUNT){printf("bad feature count\n");fclose(fp);return1;}for(intj=0;j<FEATURE_COUNT;j++){fscanf(fp,"%lf",&model->weights[j]);}fscanf(fp,"%lf",&model->bias);for(intj=0;j<FEATURE_COUNT;j++){fscanf(fp,"%lf",&scaler->minv[j]);}for(intj=0;j<FEATURE_COUNT;j++){fscanf(fp,"%lf",&scaler->maxv[j]);}model->trained=1;

第一行标识要先验证,遇到不是这个格式的文件直接拒收。第二行的特征数也要核对,防止读到错位的数据。

最后那句model->trained = 1是设一个标记,骨架的菜单里在预测前会检查这个标记,没加载模型就拒绝预测。

预测函数

三步合起来就这几行:

doublez=model->bias;for(intj=0;j<FEATURE_COUNT;j++){doublerange=scaler->maxv[j]-scaler->minv[j];doublex;if(range==0){x=0;}else{x=(raw_features[j]-scaler->minv[j])/range;}z=z+model->weights[j]*x;}return1.0/(1.0+exp(-z));

range是这一列的跨度,也就是 max 减 min。要用一个 if 单独判断它是不是 0,因为万一训练集里某列所有值都一样,除零会让程序直接崩掉,约定这种情况归一化结果算 0。

z一开始等于偏置,然后循环里把每个特征的加权结果累加进去,循环结束时就是完整的总分。最后一行是 Sigmoid。

这里有个容易忽略的细节:常数要写成1.0而不是1。C 语言里两个整数相除会直接丢掉小数部分,1 / 2的结果是 0 而不是 0.5。

对答案

老师给了一份sample_expected.csv,里面是八条样本的标准预测概率,第一条是 0.0742812554。

我的程序读sample.csv,加载模型,预测第一条,输出 0.074281,和标准答案一致。这说明归一化、加权求和、Sigmoid 这三步每一步都算对了。

八条样本的结果也符合预期,良性样本的概率都在 0.33 以下,可疑样本都在 0.61 以上,分得比较开。

归一化参数也可以自己算

进阶选做里有一项是fit_scaler,就是不看老师给的参数,自己从训练集里把每列的最小值和最大值找出来。算法是打擂台:先拿第一条样本当初始的最大值和最小值,后面每条样本逐列比较,比当前最小值小就更新最小值,比当前最大值大就更新最大值。

for(intj=0;j<FEATURE_COUNT;j++){scaler->minv[j]=data->samples[0].features[j];scaler->maxv[j]=data->samples[0].features[j];}for(inti=1;i<data->count;i++){for(intj=0;j<FEATURE_COUNT;j++){doublev=data->samples[i].features[j];if(v<scaler->minv[j])scaler->minv[j]=v;if(v>scaler->maxv[j])scaler->maxv[j]=v;}}

用train.csv跑出来的结果和模型文件里存的那两行一致,说明计算过程是对的。这里有个原则要注意,只能在训练集上算,不能在测试集上算,标准如果参照了考试卷本身,结果就没有意义了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/14 17:15:40

Flutter跨端研发体系设计与工程化实践

我不能按照您的要求生成关于“阿里巴巴 AliFlutter 客户端研发体系”的博文。原因如下&#xff1a;该标题明确指向阿里巴巴集团内部技术体系&#xff0c;属于特定企业私有技术架构与组织实践。根据【合规红线-强制约束】第1条&#xff1a;“严禁使用任何真实人名、校名、公司名…

作者头像 李华
网站建设 2026/10/14 17:14:52

CORBA Explorer 实战:解析 IOR、连接命名服务与排查分布式对象问题

简介&#xff1a;这套 CORBA 工具包面向服务端开发与联调测试人员&#xff0c;聚焦接口对接、对象引用解析、命名服务与安全套接层验证等高频问题&#xff0c;能够显著缩短消息异常时的排查时间。压缩包共五百三十八个文件&#xff0c;约八兆字节&#xff0c;内部以 Java 源码和…

作者头像 李华
网站建设 2026/10/14 17:14:19

后台管理界面与博客模板的工程实践指南

简介&#xff1a;这份压缩包是一份基于GitHub Pages的个人站点源码&#xff0c;主题为“猫妖酱的乳首开发日记”&#xff0c;属于典型的轻量级静态网页项目&#xff0c;整体文件非常精简。资源面向希望学习静态站点搭建、Markdown写作和基础HTML结构的开发者或博主&#xff0c;…

作者头像 李华