尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
互信息与K近邻:MATLAB中KSG估计器实现特征选择的实用指南
简介面向机器学习与特征工程场景的 K 近邻互信息计算程序使用 MATLAB 实现将 KNN 分类算法与互信息测量结合在一起帮助数据科学与机器学习从业者评估特征关联性、筛选高信息量特征从而提升 KNN 模型性能。资源共 2 个文件包括 1 个 m 脚本与 1 个 txt 说明文件压缩包整体约 2KB结构精简适合快速理解算法核心。目前已有 332 人学习下载。程序围绕数据预处理、距离计算、K 值选择、互信息计算、特征选择及 KNN 应用等环节组织其中包含数据导入、清洗与标准化流程还可通过交叉验证确定最优 K 值比较不同特征子集对分类精度的影响。既便于动手复现 KraskovMI 估计思路也方便在此基础上扩展不同距离度量或改进计算效率。对正在学习近邻算法和信息论特征选择的读者这是一份轻量、可直接运行且易于调试的参考示例。1. 互信息不是相关系数K 近邻是它的无参估计器做特征筛选时很多人习惯先看 Pearson 相关系数但线性关系之外的关联它完全看不见。两个变量呈正弦、分段或“X 型”结构时相关系数可能趋近于零互信息Mutual Information却能稳定地给出非零度量。互信息不假设概率分布形式也不限制变量维度因此被广泛用在 KNN 分类前的特征选择里。问题在于真实数据集的联合概率密度未知互信息的积分只能靠估计。K 近邻方法绕开了直方图分箱直接用每个样本到第 k 个近邻的距离来近似局部密度这就是 Kraskov-Stögbauer-GrassbergerKSG估计器的基本思想。本资源中的KraskovMI.m正是这一思想的 MATLAB 实现适合做特征相关性分析、聚类前变量筛选和 KNN 模型解释尤其适合处理连续型特征和分类标签共存的场景。2. KraskovMI.m 的算法拆解从双重 k 近邻到互信息估计2.1 KSG 估计为什么比传统分箱法更稳传统的互信息计算先把变量取值范围切成网格再统计每个格子里的样本频数。网格宽度设得太大密度细节被抹平设得太小大量格子为空估计方差飙升。KSG 方法不再依赖固定网格而是对每个样本点寻找其在联合空间中的 k 个近邻用这些近邻的距离反推局部概率密度。这个做法在样本量不大时依然能保持较低偏差在连续型变量上尤其明显。KSG 有两个常用形式。KSG1 使用最大范数切比雪夫距离衡量联合空间中的邻域然后分别统计两个单变量空间里落在该邻域内的点数。KSG2 则用欧氏距离并引入高阶修正项对边界效应更敏感。KraskovMI.m通常默认走 KSG1 路线因为它实现简单、对 MATLAB 的knnsearch支持最友好计算代价也低。实际比较中KSG1 在特征维度低、样本量在几百到几千时表现已经足够好KSG2 在变量强相关且样本量过万时稍优但耗时明显增加。2.2 KraskovMI.m 的核心实现结构一个典型的KraskovMI.m函数会做四件事读取两个输入向量或两个特征矩阵、用knnsearch找联合空间的 k 近邻、统计两个边际空间内的近邻数、用 digamma 函数做偏差校正。伪代码形式如下function mi KraskovMI(x, y, k, varargin) % x, y: N x 1 列向量 % k: 近邻数量默认 3 % varargin: 可传入距离度量 if nargin 3 || isempty(k) k 3; end N length(x); xy [x(:), y(:)]; % 1. 对每个点找联合空间中的第 k 近邻距离 [idxJK, distK] knnsearch(xy, xy, K, k1); distK distK(:, end); % 第 k 近邻距离 % 2. 统计单变量空间内的点数 nx, ny nx zeros(N,1); ny zeros(N,1); for i 1:N nx(i) sum(abs(x - x(i)) distK(i)) - 1; ny(i) sum(abs(y - y(i)) distK(i)) - 1; end % 3. 计算互信息 mi psi(k) psi(N) - mean(psi(nx 1) psi(ny 1)); end逻辑说明第一步里knnsearch(xy, xy, K, k1)返回每个点按距离升序排列的邻居索引和距离去掉自身后取第 k 个距离作为联合邻域半径。第二步对每个点分别计算x和y方向落在该半径内的点数。第三步中psi是 digamma 函数用来代替对数的期望减小有限样本偏差。参数k控制邻域大小过小会使估计方差增大过大则会把局部结构平滑掉。2.3 距离度量和 k 值对估计值的影响knnsearch默认使用欧氏距离但在 KSG1 中应改用切比雪夫距离因为联合空间的矩形邻域在边际投影后才是对称区间。若使用欧氏距离nx和ny的统计会出现不对称导致互信息被系统性低估。实际调试时建议在调用函数前先固定距离度量[idxDist, distK] knnsearch(xy, xy, K, k1, Distance, chebychev);这里chebychev对应最大范数和 KSG 原始论文设定一致。修改后nx和ny的计数才具有可比性。k 值的选择可以参考floor(sqrt(N/2))作为起点再向两侧各取 2 到 5 个值观察估计值是否稳定。如果 MI 结果随 k 剧烈波动说明数据中存在离群点或分布过于尖锐需要先做标准化或裁剪。3. MATLAB 环境里的数据准备与 k 值选择3.1 输入数据的格式与预处理KraskovMI.m期望的输入是两列长度相同的数值向量。如果特征是类别型如性别、地区需要先做数值编码但编码后的间距没有实际含义此时互信息的结果只能作为粗糙的参考更稳妥的做法是分别计算该特征与目标变量的条件概率表再用离散互信息公式验证。连续特征则需要注意量纲差异对近邻搜索的干扰。例如一个特征取值在 01另一个在 010000后者会直接主导距离计算使前者的局部密度形同虚设。常见做法是先做 Z-score 标准化再进入互信息计算data readmatrix(features.csv); X data(:, 1:end-1); Y data(:, end); X (X - mean(X)) ./ std(X); Y (Y - mean(Y)) ./ std(Y);标准化后每个维度的尺度一致knnsearch的距离计算才不会被某一列支配。执行上述操作后建议用any(isnan(X), all)检查缺失值缺失样本直接删除不要用均值填充因为填充值会产生虚假的紧密邻域导致互信息偏高。数据量在 10 万行以上时knnsearch的最近邻搜索会占用大量内存此时可以先用datasample随机抽样 1 万到 2 万行做初次估计。3.2 k 值选择的经验法则与交叉验证k 值直接决定局部邻域的半径。k 太小每个点的邻域只覆盖到最近的一两个点估计结果对噪声敏感k 太大邻域跨越多个密度区域互信息倾向于被平滑到接近零。经验法则分两种按样本量设定常用的取值范围是 1 到 10或用k floor(sqrt(N))做粗调按使用场景设定特征选择阶段用较小 k 值侧重保留强相关特征建模阶段用大一点的 k 值减少方差。下面是一段对 k 做网格扫描的代码kList [1, 2, 3, 5, 8, 13]; miHistory zeros(length(kList), size(X,2)); for j 1:size(X,2) for t 1:length(kList) miHistory(t,j) KraskovMI(X(:,j), Y, kList(t)); end end plot(kList, miHistory, o-);运行后把趋势线画出来观察所有特征在 k 增大时是否收敛到相近的排序。如果某条曲线上下跳动超过 0.3说明该特征分布带有过多离群点需要检查是否混入了错误采集的样本。下表是不同数据规模下的经验 k 值参考样本量 N推荐 k备注5020013样本少只能捕捉强相关200100035推荐 k3 起步10001000058可同时比较 k5 和 k810000815注意计算时间可先抽样3.3 与 MATLAB 内置函数协同工作KraskovMI.m依赖的核心函数是knnsearch它来自 Statistics and Machine Learning Toolbox。如果环境中没有该工具箱可以用暴力计算距离矩阵的方式替代distMat sqrt((x-x).^2 (y-y).^2)然后对每行排序取第 k 个值。距离矩阵法在 N 小于 5000 时速度尚可超过后内存占用呈平方增长不建议使用。MATLAB 2022b 之后knnsearch默认采用 KD 树策略在高维特征下会自动退化为穷举搜索因此不用刻意设置NSMethod参数除非特征维度超过 32 且样本量极大。4. 用互信息做特征选择一个可复现的 MATLAB 流程4.1 计算所有特征与目标变量的互信息这里的目标变量可以是分类标签也可以是连续值。KraskovMI.m对两类目标都适用因为 KSG 估计本身不关心变量的类型只看联合分布。计算前需要对分类标签做编码常见做法是标量编码成一个整数列。获取全部特征重要性排名的代码如下numFeatures size(X, 2); miScores zeros(numFeatures, 1); kFixed 5; for f 1:numFeatures miScores(f) KraskovMI(X(:, f), Y, kFixed); end [B, idx] sort(miScores, descend); fprintf(Top 5 features: %s\n, mat2str(idx(1:5)));逻辑说明for循环把每个特征单独取出来与目标列组成两列矩阵传入KraskovMI计算互信息。sort返回降序排名和对应的索引。输出结果后不要只看分数最高的特征还要对比分数最低的几个特征若两者差距很小说明该数据集中互信息的区分度有限需要补充组合特征或改用条件互信息。参数kFixed设为 5 是折中值若特征数量超过 50可先把 k 调到 3加快迭代速度。4.2 对比互信息排序与 KNN 分类精度特征选择的目标不只是找到相关特征还要验证下游 KNN 模型的收益。常见做法是取排名前 m 的特征子集训练 KNN 分类器并与使用全部特征时的精度对比。下面脚本实现这一流程rng(42); numTop [1, 3, 5, 10, size(X,2)]; accuracy zeros(length(numTop), 1); for t 1:length(numTop) topM idx(1:numTop(t)); Xsub X(:, topM); mdl fitcknn(Xsub, Y, NumNeighbors, 7, Standardize, true); cvmdl crossval(mdl, KFold, 5); accuracy(t) 1 - kfoldLoss(cvmdl); end这里的fitcknn使用欧氏距离和多数投票Standardize设为true会再次标准化但不会改变此前互信息排序结果因为标准化是单调变换不会影响近邻的秩。kfoldLoss返回交叉验证损失1 - loss即为精度。运行后观察精度曲线如果只取前 3 个特征时精度已经接近全特征说明其余特征是冗余的。若精度不升反降问题通常出在 k 值选择上应返回第 4.1 节用更小的 k 重新计算互信息。4.3 结果分析互信息与 KNN 精度的联动关系下表为一个模拟数据集的输出示例用于理解结果形态特征子集大小平均互信息KNN 交叉验证精度10.420.78130.380.83950.310.855100.250.861全特征(15)0.190.834从表中可以看到加入第 4 到第 10 个特征时互信息平均值持续下降但 KNN 精度仍在缓慢上升这说明这些特征单独看来相关性弱却提供了互补的判别信息。全部特征加入后精度回落则说明高维噪声开始干扰近邻计算。遇到这种情况建议改用递归特征消除或条件互信息而不是简单按单变量排序截断。5. 偏差修正与计算加速让 KraskovMI.m 更可靠5.1 有限样本偏差的修正当样本量只有几十个时psi(nx 1)中的nx经常为零digamma 函数在零附近发散导致互信息估计出现负值。负的互信息在理论上不存在但在有限样本估计中经常发生尤其在 k1 时。常见处理方式有两种一种是把nx和ny加上一个小常数后再代入psi另一种是改用 KSG2 公式它带有额外的修正项可以减少负值出现的概率。实际应用中我倾向于先检查负值比例如果超过 10%就把 k 从 1 提高到 3。MATLAB 的psi函数没有对参数为零做特殊处理因此调用前必须保证nx 1。在KraskovMI.m内部可以加入一行安全约束nx max(nx, 1); ny max(ny, 1);这行代码的作用是把计数下限钳制到 1避免 digamma 函数输入为零。代价是会在极端稀疏区域产生轻微向上的偏差但相比负值结果更可解释。5.2 批量计算时的缓存与向量化循环调用knnsearch是最大的性能瓶颈。当特征数较多时所有特征的联合坐标不同无法一次性完成搜索。这里可以做一个折中先对所有特征做归一化再分别与目标变量拼接计算。如果目标变量保持不变可以在外层循环外预先计算目标变量的自近邻距离内层只计算特征与目标的交叉距离。另一种加速方式是使用parfor并行计算特征维度parfor f 1:numFeatures miScores(f) KraskovMI(X(:, f), Y, kFixed); end启用parfor前需要确保KraskovMI内部不依赖全局变量knnsearch也能在并行池中正常工作。MATLAB 并行池首次启动会耗时 10 到 30 秒特征数少于 20 时不建议使用。5.3 验证估计稳定性的双 k 检验法最后给一个实用技巧用两套差异较大的 k 值分别计算互信息再检查排序变化程度。具体做法是令k1 3、k2 10分别得到两个分数向量计算 Spearman 秩相关系数mi3 computeMI(X, Y, 3); mi10 computeMI(X, Y, 10); rho corr(mi3, mi10, Type, Spearman);rho大于 0.9 说明互信息估计稳定此时无论是特征排序还是筛选阈值都可以放心用。rho在 0.7 到 0.9 之间说明部分特征受到样本噪声干扰建议对原始数据重新做去异常值处理后再跑一次。rho低于 0.7 则要怀疑数据中存在长尾分布或缺失编码错误此时不要继续做特征筛选先回到数据清洗环节。这个检验只需几分钟却能把后续模型调参阶段的大量试错成本提前消化掉。本文还有配套的精品资源点击获取
RELATED

相关推荐

培训机构管理系统App源码:Android多角色权限与业务闭环设计解析

培训机构管理系统App源码:Android多角色权限与业务闭环设计解析

简介:这是一份基于Android平台的培训机构管理系统App毕业设计源码,适合计算机相关专业学生在毕业设计或课程项目中参考学习。系统采用AndroidMySQLJava技术栈,完整覆盖学生端、教师端和管理后台三类角色,包含注册登录、课程购买与…

📅 2026/9/13 9:49:39
C++数组与贪心算法实践:积木平衡问题解析

C++数组与贪心算法实践:积木平衡问题解析

1. 项目概述"摆平积木"是卡码网C基础课程中的第7个实践项目,主要面向刚接触编程的新手学员。这个项目通过模拟积木堆叠和平衡的场景,帮助学习者掌握C中的数组操作、循环控制和基础算法思维。我在实际教学中发现,很多初学者在学习编…

📅 2026/9/13 9:49:39
AI视频生成的3种输入方式:让创意直接拍成视频

AI视频生成的3种输入方式:让创意直接拍成视频

AI视频生成的3种输入方式:让创意直接拍成视频 【免费下载链接】ViMax "ViMax: Agentic Video Generation (Director, Screenwriter, Producer, and Video Generator All-in-One)" 项目地址: https://gitcode.com/GitHub_Trending/ai/ViMax AI-Crea…

📅 2026/9/13 9:49:39
MORE NEWS

更多资讯

📰

JavaFX+SceneBuilder 2.0酒店管理系统课程设计实战指南

简介:这份JavaFXSceneBuilder 2.0酒店管理系统源码包,是面向需要完成Java课程设计或系统学习桌面客户端开发的在校生与自学者的一份完整工程参考。项目围绕酒店后台管理场景,通过源码展示了客房信息管理、预订入住、退房结算等典型模块的界面…

📰

智能体(Agent)工程化落地:目标驱动的AI自动化方法论

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

Selenium捕获网络请求:Selenium Wire与CDP实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

SSE生产级实战:断线重连、心跳保活与超时降级全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

IP校验和原理与实现:反码求和、增量更新及工程避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

A100 80G服务器价格差异真相:配置决定算力交付确定性

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

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

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

📞 💬