ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

机器学习学习笔记(四):KNN——距离、特征预处理与交叉验证

机器学习学习笔记(四):KNN——距离、特征预处理与交叉验证 系列第四篇。KNN 是思想最简单的算法“看邻居投票”但它带出了两个重量级话题特征预处理把概述篇欠的归一化/标准化公式账还上和分类评估体系混淆矩阵、精确率、召回率、F1后面所有分类问题都离不开这套东西。本篇看完要回答的四个面试题K 值过大或过小会怎样归一化和标准化的公式与适用场景精确率和召回率的区别什么场景优先保召回率F1-score 为什么用调和平均而不是算术平均一、KNN看邻居投票K-近邻算法K Nearest Neighbor的核心思想一句话一个样本在特征空间中 k 个最相似的样本大多数属于某个类别那它就属于这个类别。相似用什么衡量当然是距离。同一任务数据集中距离越近的样本越相似。距离用欧氏距离d(x,y)∑i1n(xi−yi)2d(x, y) \sqrt{\sum_{i1}^{n}(x_i - y_i)^2}d(x,y)i1∑n​(xi​−yi​)2​课件的例子很直观用搞笑镜头数、拥抱镜头数、打斗镜头数三个特征给电影分类。《唐人街探案》和《伦敦陷落》的距离d(2−3)2(3−3)2(55−17)242.42d \sqrt{(2-3)^2 (3-3)^2 (55-17)^2} 42.42d(2−3)2(3−3)2(55−17)2​42.42分别算出它和 9 部已知类型电影的距离取最近的 K5 部里面动作片占多数就判它是动作片。分类和回归的流程只有最后一步不同计算未知样本到每一个训练样本的距离按距离升序排列取出最近的 K 个样本分类问题做多数表决票数最多的类别胜出回归问题取K 个样本目标值的均值API 对应两个分类用KNeighborsClassifier回归用KNeighborsRegressor。二、K 值选择过犹不及K 是 KNN 唯一的核心超参数选择逻辑就是对欠拟合/过拟合的直接应用K 值模型风险K 太小模型变复杂决策只看极小邻域容易受异常点影响过拟合K 合适模型复杂度适配——K 太大模型变简单邻域大到远亲也来投票容易欠拟合K N全部样本无论输入什么永远预测训练集中样本最多的类别完全失效且受样本均衡影响KN 的极端情况最好记全体邻居投票永远赢的是多数类模型的判断力彻底归零。实际怎么选 K交给交叉验证 网格搜索本文第六节实战。三、特征预处理归一化与标准化公式还账概述篇给过结论优先标准化这篇把公式和实测补全。为什么需要预处理特征的单位或数值范围相差悬殊时身高 1.75 米、体重 70 千克、视力 0.2~2.0数值大的特征会支配距离计算。KNN 尤其敏感因为它的每一步都建立在距离上。3.1 归一化MinMaxScaler把数据压缩到固定区间[mi,mx][mi, mx][mi,mx]默认[0,1][0, 1][0,1]x′x−xminxmax−xminx \frac{x - x_{min}}{x_{max} - x_{min}}x′xmax​−xmin​x−xmin​​最大值最小值非常容易受异常点影响鲁棒性差只适合传统精确小数据场景。3.2 标准化StandardScaler把数据转成均值 0、标准差 1 的分布x′x−μσx \frac{x - \mu}{\sigma}x′σx−μ​其中μ\muμ是特征均值σ\sigmaσ是标准差方差开根号方差衡量数据的离散程度。异常点通过影响均值和标准差间接影响结果但当样本数量较大时单点对均值和标准差的影响可以忽略所以标准化鲁棒得多。3.3 异常值实验一 Compare 见高下拿身高/体重/视力数据做实验先看正常情况下的转换结果再混入一个体重 300kg 的异常样本对比两个缩放器的表现。import numpy as np from sklearn.preprocessing import MinMaxScaler, StandardScaler data np.array([ [1.70, 67, 1.5], [1.71, 80, 0.8], [1.75, 70, 1.5], [1.76, 68, 1.2], ]) print(np.round(MinMaxScaler().fit_transform(data), 4)) print(np.round(StandardScaler().fit_transform(data), 4))正常运行结果归一化后: [[0. 0. 1. ] [0.1667 1. 0. ] [0.8333 0.2308 1. ] [1. 0.0769 0.5714]] 标准化后: [[-1.1767 -0.8227 0.8704] [-0.7845 1.6938 -1.5667] [ 0.7845 -0.242 0.8704] [ 1.1767 -0.6291 -0.1741]]归一化后所有值严格落在 [0,1]标准化后围绕 0 波动、量级统一。然后是关键实验加入体重 300kg 的异常样本data_outlier np.array([ [1.70, 67, 1.5], [1.71, 80, 0.8], [1.75, 70, 1.5], [1.76, 68, 1.2], [1.72, 300, 1.3], ])我的运行结果归一化后(正常样本的体重列): [0. 0.0558 0.0129 0.0043 1. ] 标准化后(正常样本的体重列): [-0.5458 -0.4039 -0.513 -0.5348 1.9975]一目了然一个异常点把归一化后正常样本的体重列压进了 0.004~0.056 的窄缝里特征区分度几乎归零标准化后正常样本仍在 -0.4~-0.55 之间保持原有排序和间隔。这就是优先标准化的完整证据链。四、案例鸢尾花分类鸢尾花数据集150 个样本、4 个特征花萼/花瓣的长宽单位 cm、3 个类别setosa / versicolor / virginica是 sklearn 自带的入门标准数据集。from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split, GridSearchCV from sklearn.preprocessing import StandardScaler from sklearn.neighbors import KNeighborsClassifier from sklearn.metrics import confusion_matrix, classification_report dataset load_iris() x_train, x_test, y_train, y_test train_test_split( dataset.data, dataset.target, test_size0.2, random_state22) scaler StandardScaler() x_train_s scaler.fit_transform(x_train) x_test_s scaler.transform(x_test) knn KNeighborsClassifier(n_neighbors5) knn.fit(x_train_s, y_train) print(knn.score(x_test_s, y_test))我的运行结果K5标准化后准确率0.933330 个测试样本错 2 个。一个诚实的意外发现值得单独说我在同一划分上跑了不做标准化的对照实验准确率反而是0.9667。原因不难解释鸢尾花 4 个特征本来就是同一量纲都是 cm、数值范围接近距离计算本来就没被支配——标准化不是无脑加分项它解决的是量纲问题量纲本来一致时收益有限。真正需要它的是特征单位混杂的数据比如房价数据的年收入 30 万和房龄 15。这个结论比预处理永远要做的教程套路更接近事实。五、交叉验证 网格搜索让模型自己调参K 不能拍脑袋选标准解法是两个工具的组合。交叉验证Cross Validation把训练集划分为 CV 份每次拿 1 份做验证集、其余 CV-1 份做训练轮换 CV 次取 CV 次评估的平均值作为模型得分。好处是评估不依赖某一次幸运/倒霉的划分结果更可信。网格搜索Grid Search把候选超参数排列组合每组参数都跑一遍交叉验证返回得分最高的参数组合。它俩在 sklearn 里被封装成一个 APIfrom sklearn.model_selection import GridSearchCV param_grid {n_neighbors: list(range(1, 21))} grid GridSearchCV(KNeighborsClassifier(), param_grid, cv5) grid.fit(x_train_s, y_train) print(grid.best_params_[n_neighbors]) print(grid.best_score_)我的运行结果网格搜索最优K: 6 交叉验证最高分: 0.9667 最优模型在测试集上的准确率: 0.9333流程完整走了一遍K 从 1 到 20 逐个试每组做 5 折交叉验证共训练 100 个模型选出 K6。注意最后一步选出最优 K 后要用全部训练数据重新训练模型再到测试集上做最终评估0.9333交叉验证分数只用来选参数不能代替测试集表现。六、分类评估混淆矩阵与三大指标6.1 准确率的盲区准确率预测对的 / 总数有一个致命盲区。癌症检测场景1000 人里只有 10 个患者模型把所有人全判为健康准确率 99%但一个患者都没抓到。准确率高不等于模型有用所以需要更细的评估体系。6.2 混淆矩阵以恶性肿瘤为正例四个格子的定义预测为正例预测为反例真实为正例TP 真正例FN 伪反例真实为反例FP 伪正例TN 真反例记忆技巧前一个字母T/F表示预测对没对后一个字母P/N表示预测成了什么。TP FN FP TN 总样本数。用课件的例子实测6 个恶性 4 个良性样本两个模型的预测from sklearn.metrics import confusion_matrix, accuracy_score from sklearn.metrics import precision_score, recall_score, f1_score y_true [恶性] * 6 [良性] * 4 model_a [恶性, 恶性, 恶性, 良性, 良性, 良性, 良性, 良性, 良性, 良性] model_b [恶性, 恶性, 恶性, 恶性, 恶性, 恶性, 良性, 良性, 良性, 恶性] pre precision_score(y_true, model_a, pos_label恶性) rec recall_score(y_true, model_a, pos_label恶性) f1 f1_score(y_true, model_a, pos_label恶性)我的运行结果指标模型 A模型 B准确率0.70000.9000精确率1.00000.8571召回率0.50001.0000F10.66670.9231模型 A判为恶性的 3 个全是真恶性精确率 100%但 6 个真恶性里只抓到 3 个召回率 50%它很准但不全。模型 B6 个患者全抓到召回率 100%代价是把 1 个良性误判为恶性精确率降到 85.7%它很全但牺牲了一点准。6.3 精确率、召回率、F1PrecisionTPTPFPRecallTPTPFNF12×P×RPRPrecision \frac{TP}{TP FP} \qquad Recall \frac{TP}{TP FN} \qquad F1 \frac{2 \times P \times R}{P R}PrecisionTPFPTP​RecallTPFNTP​F1PR2×P×R​精确率查准率预测为正例的样本里真对的有多少“我说的恶性有多少真是恶性”召回率查全率真实的正例里被抓到多少“所有恶性患者我抓到了几成”优先保谁场景癌症/诈骗检测优先召回率漏掉一个患者的代价远大于误报垃圾邮件拦截优先精确率误杀正常邮件比漏进一封垃圾邮件烦得多F1 为什么用调和平均算术平均会被高的一方兜底P1.0、R0.1 的模型算术平均还有 0.55看起来凑合调和平均是 2×1×0.1/1.10.18直接暴露短板。调和平均惩罚偏科只要有一项接近 0F1 就接近 0这符合评估模型要找明显短板的本意。手动算一遍课件练习P0.8、R0.6 时F1 2×0.48/1.4 ≈ 0.69。七、易错点预处理参数只能来自训练集scaler.fit_transform(x_train)之后测试集只能transform。我把这一步写错过一次对测试集重新 fit评估分数直接从 0.93 掉到 0.47教训是真的鸢尾花案例里标准化反而不加分特征量纲本来就一致时标准化的收益是零结论要结合数据本身判断交叉验证分数高 ≠ 测试集分数高交叉验证用于选参数最终表现以测试集为准混淆矩阵四格的命名T/F 看预测对没对P/N 看预测成了什么别背反了precision_score等默认pos_label1标签是字符串时要显式传pos_label恶性否则报错或算错八、知识清单KNN 分类 APIKNeighborsClassifier(n_neighbors5)回归KNeighborsRegressor交叉验证训练集分 CV 份轮流当验证集取平均分网格搜索超参数排列组合 交叉验证GridSearchCV(model, param_grid, cv5)正态分布N(μ,σ)N(\mu, \sigma)N(μ,σ)μ\muμ定位置、σ\sigmaσ定形状3σ 法则μ±3σ 覆盖 99.7% 的数据归一化受最大最小值支配鲁棒性差适合小数据精确场景标准化大样本下对异常值稳健优先选评估指标 APIconfusion_matrix/accuracy_score/precision_score/recall_score/f1_scoreF1 是精确率和召回率的调和平均惩罚偏科九、面试高频问答Q1K 值过大或过小会怎样K 太小模型复杂决策只看极小邻域容易被异常点带偏过拟合K 太大模型简单远处的非同类也参与投票欠拟合K 等于样本总数时永远预测多数类。实际用交叉验证 网格搜索选 K我实测鸢尾花上 K6 最优。Q2归一化和标准化的公式与选择归一化 (x-min)/(max-min) 缩放到 [0,1]受最大最小值支配一个异常点就能压垮正常样本的区分度标准化 (x-μ)/σ 转成均值 0 方差 1大样本下对异常值稳健。有异常值或配合梯度下降时优先标准化需要固定范围如图像像素时用归一化。我在体重数据里混入一个 300kg 异常样本做过对比归一化后正常样本被压进 0.004~0.056标准化后依然保持区分。Q3精确率和召回率的区别什么场景优先召回率精确率 TP/(TPFP)管预测为正例的有多少是真的召回率 TP/(TPFN)管真实正例抓到了几成。癌症检测、金融风控漏判代价极高优先召回率垃圾邮件拦截误杀代价高优先精确率。Q4F1 为什么用调和平均调和平均惩罚偏科P1.0、R0.1 的模型算术平均有 0.55调和平均只有 0.18。只要有一项接近 0F1 就接近 0符合评估要暴露短板的目的。
返回列表