KNN配合鸢尾花数据集几乎是每个做机器学习的人都会跑通的第一组项目。我第一次跑完的时候说实话有点失望——代码就那么几行准确率却高得吓人以至于很长一段时间里我都觉得这玩意儿太“玩具”了。直到后来碰了几个真实业务场景里的分类问题才发现越是简单的算法越考验你对数据的基本功是否扎实。这篇就从KNN在鸢尾花分类上的完整实践讲起数据集是怎么回事、KNN的原理怎么理解、一套能直接抄走的流程长什么样、调参和排查有哪些实用技巧。适合刚接触机器学习、想动手跑通第一个分类项目的读者也适合想回头把KNN和鸢尾花这对组合彻底吃透的人。我可以保证这里面每一个坑我都亲自踩过每一个结论都是实测出来的。1. 先说为什么鸢尾花成了机器学习界的“Hello World”1.1 一份来自1936年的经典数据集鸢尾花数据集最早由统计学家Ronald Fisher在1936年引入用来展示线性判别分析。近一百年过去它依然是使用频率最高的入门数据集这不是偶然。数据集本身非常朴素150条样本、3个类别、每个类别50条每条样本有4个数值特征分别对应鸢尾花的花萼长度、花萼宽度、花瓣长度、花瓣宽度单位都是厘米。三个类别分别是Setosa、Versicolor和Virginica你可以简单理解成三种不同的鸢尾花品种。特征取值范围区分度感受花萼长度sepal length4.3 ~ 7.9三类有重叠单独用会混淆花萼宽度sepal width2.0 ~ 4.4区分力一般噪声较大花瓣长度petal length1.0 ~ 6.9区分度最强Setosa一眼可辨花瓣宽度petal width0.1 ~ 2.5区分度强两类边界有交集为什么说它适合入门第一150条样本规模小任何一个算法几秒钟就能跑完你可以在本地反复折腾不需要上GPU不用考虑分布式连内存占用都可以忽略不计。第二数据已经整理得干干净净没有缺失值没有异常值连字符串都不用处理——你甚至不需要设计特征工程拿raw数据直接喂给算法就能得到一个看得过去的结果。第三类别是均衡的每类恰好50条不存在“多数类碾压少数类”这类让人头疼的类别不平衡问题。我经常跟新人说新手阶段遇到一个“乖得不像话”的数据集是好事。它让你可以把全部注意力放在理解算法本身而不是被各种脏数据问题打断思路。等你把KNN真正吃透了再回头去处理那些残留值、乱编码、分布失衡的问题心里才有底。1.2 为什么偏偏是KNN鸢尾花分类这个任务能用的算法很多。逻辑回归能跑决策树能跑支持向量机也能跑。头歌那套练习题里就有一道是用决策树做鸢尾花分类我在带新人时也常拿这两个算法对比。但你如果去看所有入门教程的默认选择大概率还是KNN原因足够充分。决策树学的是“轴对齐”的if-else规则它找的是特征阈值划分出来的边界永远跟坐标轴平行在数据分布稍微复杂一点的任务里树的结构会变得很深解释起来也费劲。KNN学的是另一套逻辑——距离近的就是一类。它不需要显式的规则表边界天然是不规则的Voronoi区域能贴合任意形状的类簇这让它在新手阶段异常友好。更关键的是KNN被称为“懒惰学习”算法。它的训练阶段什么事都没干只是把数据原封不动地存下来真正的工作量全在预测阶段——预测的时候才去挨个计算新样本和所有训练样本的距离选最近的K个邻居来投票。这个特性让它几乎没有“训练成本”也让它的每一步决策都透明可解释。你可以指着任何一个预测结果说“看它就是根据这K个邻居得出来的。”这在真实业务场景里价值很大老板问你“为什么判定这个用户是高价值客户”的时候你能直接从训练集里拎出几个样本当证据。应用层面KNN的思路远不止于教科书。推荐系统里找相似用户、风控系统里识别异常交易、金融领域做量化信号的初筛分类底层逻辑都是“物以类聚”这四个字。鸢尾花项目就是这条路上最平缓的第一阶台阶。2. KNN三要素K值、距离、决策规则2.1 核心思想物以类聚KNN的全称是K-Nearest NeighborsK近邻算法。一句话概括给你一个新样本找到训练集中离它最近的K个样本看这K个样本里哪一类最多新样本就属于那一类。这个思想在生活里太常见了。你想判断一个人的音乐口味最快的办法不是去翻他几百页的歌单而是看他平时最常待在一起的那几个朋友都喜欢什么歌。KNN干的事就是这个——每次做判断之前先去把“朋友圈”翻出来看看。从数理角度看KNN做的就是一种非参数分类。所谓非参数意思是它不对数据的分布做任何假设不认为数据要服从某个高斯分布也不需要你提前设定一个函数形式。它完全是靠数据本身“按需判决”。这带来一个直接的好处它对复杂的、非线性的边界天然兼容。你可能很难用一条直线把两个类别干净地分开但只要它们在局部空间里扎堆存在KNN就能把边界划得歪歪扭扭地贴着数据走。不过“懒惰学习”的代价就是预测阶段的复杂度。训练阶段是O(1)预测阶段却需要计算新样本和全部训练样本的距离复杂度O(n)。样本量小的时候无所谓到百万级数据量时每一次预测都要等上一阵子。这也是为什么KNN通常更适合中小规模的数据场景。2.2 K值怎么定尖峰和平滑的权衡K值的选择是整个KNN里最核心的超参数没有之一。我见过太多人一上来直接填K5跑出个不错的结果就再也不管了。鸢尾花数据集确实好说话K5能跑出高分是常态但这不是你忽略调参的理由。K值小意味着你只参考极少数几个邻居。极端情况K1此时模型只看最近的一个样本完全跟着单个样本走。训练集上这个模型几乎永远满分——因为每个训练样本的最近邻居就是它自己。但测试集上很容易翻车离群点、噪声数据都会直接带偏预测方差极大。这是个典型过拟合信号。K值大则会引入远处样本的干扰。极端情况K150直接把全部样本都拉进来投票那每个新样本的预测结果都等于全局多数类更像是无脑猜模型的局部区分能力彻底没了。K越大决策边界越平滑但如果大到淹没局部结构就是欠拟合。我常用的经验区间是3到15。选奇数主要是为了避开平票——3个邻居最多出现“2比1”不可能出现“1比1比1”。但真要细究平票在sklearn里也有内部处理逻辑不用过于纠结。真正靠谱的做法是把K当超参用交叉验证去搜索这个后文会展开。关于K值和准确率我在鸢尾花上实测过一个有意思的现象随着K从1增加到30测试集准确率并不总是平滑下降而是会有一段抖动——某个K值下准确率突然就低了一截下一个K值又弹回来。这说明单次划分里存在“边界样本”的影响某个具体的邻居点可能正好落在临界位置。因此评估K值的好坏一定要看交叉验证的平均结果而不是单独看某一次划分的准确率。2.3 距离度量不止一种话事方式KNN里“近”这个词需要量化。最常用的是欧氏距离也就是多维空间里两点间的直线距离公式就不再重复了。在sklearn里KNeighborsClassifier默认用的就是闵可夫斯基距离参数p2时等价于欧氏距离p1时等价于曼哈顿距离。距离度量公式特点适用场景欧氏距离各维度差的平方求和再开方对大差异维度更敏感特征连续、量纲一致时最常用曼哈顿距离各维度绝对差求和高维噪声大时更稳对离群点不敏感余弦距离看向量方向不看长度文本、稀疏特征场景常用实践里怎么选鸢尾花这种低维连续数据欧氏和曼哈顿的差别其实不大最终准确率可能只有一两个百分点的浮动。但在高维数据或某些业务场景下差异就会被放大。比如用户行为特征动辄上百维很多值还是稀疏的0/1此时曼哈顿距离往往比欧氏更抗噪——欧氏距离会把个别维度的突出差异平方放大几维偏差很大的点会主导整个距离计算曼哈顿则是每个维度等权累加差值更加平均主义。对高维稀疏特征比如文本向量我会优先考虑余弦距离因为它看的是方向一致性而不是绝对长度。不过这类场景KNN本来就少用文本分类有更适合的算法。对鸢尾花来说默认的欧氏距离就已经够用了可以调参但别指望出现质变。2.4 为什么要给特征做标准化这是KNN实践里公认的关键一步也是新人最不容易想通的一步。KNN计算距离时每个特征默认被平等对待。但特征之间的数值范围往往不一样鸢尾花的花萼长度大致在4.3到7.9厘米之间花瓣宽度则在0.1到2.5厘米之间。虽然这两个特征的绝对值范围都只有个位数不够极端但放到真实业务场景里有的特征在0到1之间有的特征直接上万此时计算欧氏距离全靠量级大的那个特征“带节奏”量级小的特征贡献几乎可以被忽略。这件事的数学本质很简单欧氏距离是各维度差的平方和维度自身的量级直接决定它对总距离的贡献权重。量级大的特征动辄相差几千平方后总量轻松碾压其他特征。所以标准化能把所有特征拉到同一套尺度均值为0方差为1让距离计算时每个特征保持“公平发言权”。更准确地说真正影响KNN距离的是各特征的方差。某个特征方差越大它在这个样本集中的“分歧度”就越大对距离的贡献也越大。如果业务上我们认为这四个特征同等重要那就应该通过标准化把方差对齐。StandardScaler做的正是这件事——减去均值除以标准差把所有特征统一到相同尺度。在鸢尾花上标准化不一定带来翻天覆地的提升数据集太友好但这一步养成的肌肉记忆会在你以后处理真实数据时替你挡掉很多雷。3. 环境准备与数据探索3.1 装好依赖一分钟上手动手之前先把环境准备好。这个项目只需要Python和一个能跑Jupyter的编辑器我用得最多的是VSCode加Jupyter插件你也可以直接用Jupyter Notebook或者PyCharm哪个顺手用哪个。依赖库四个scikit-learn提供机器学习算法pandas负责数据处理matplotlib和seaborn负责可视化。在终端里运行pip install scikit-learn pandas matplotlib seaborn如果你是在Anaconda环境下操作这些库通常已经预装好了可以直接跳过。版本方面不用太纠结scikit-learn只要是1.0以上版本跑这个项目就没有任何问题。装好之后在Python里import一遍确认没报错就可以开工了。3.2 先别急着建模把数据看清楚很多人跑机器学习有个毛病导入数据之后直接就开始训练连数据长什么样都没看过。做技术可以硬核但不要盲目自信。先花两分钟把数据结构摸清楚后面每一步都会顺畅得多。加载鸢尾花数据集有两种方式。我更喜欢直接用scikit-learn内置的加载器from sklearn.datasets import load_iris import pandas as pd iris load_iris() X iris.data # 特征矩阵shape是(150, 4) y iris.target # 标签0/1/2分别对应三个品种 df pd.DataFrame(X, columnsiris.feature_names) df[target] y print(df.head())输出结果里前四列是花萼和花瓣的尺寸最后一列是类别编码。注意一个细节target是整数编码0、1、2对应的实际名字可以从iris.target_names里取——这就是那些网络教程里经常写的“setosa”“versicolor”“virginica”。接着看整体统计信息print(df.describe()) print(df[target].value_counts())describe会给出每个特征的均值、标准差、最小值和分位数value_counts则确认每个类别恰好50条。类别均衡这件事看似不起眼其实很关键——如果三个类别数量相差悬殊准确率指标就会有欺骗性你拿到的所谓高分可能只是“什么都预测成多数类”的结果。3.3 画图看分布三类的“分家”边界数据探索的最后一步用图把分布画出来。这一步能让你提前预判后面模型的表现。import seaborn as sns import matplotlib.pyplot as plt sns.pairplot(df, huetarget, paletteSet1) plt.show()pairplot会把任意两个特征的组合都画成一张散点图对角线是单特征的密度分布这一张图足以覆盖四个特征的所有两两组合。至少能得出三个结论第一Setosa这个类别在所有特征组合的散点图里都跟另外两类明显分离也就是说它和另外两类在特征空间里几乎不重叠。这意味着分类器区分Setosa会非常轻松几乎没有难度。第二Versicolor和Virginica这两个类在“花萼”相关的特征组合下大量重叠单靠花萼尺寸极容易混淆。只有在涉及花瓣长度或花瓣宽度的时候两个类别才显示出比较清晰但仍有部分交错的分界。第三越看越明白这个数据集的分类难点全集中在Versicolor和Virginica在部分特征空间里的重叠区域。后续做的标准化、调参、评估本质上都是在拿这几个边界样本做文章。你会发展出对数据真实结构的直觉而不是只盯着最终输出的准确率数字。4. 实操从数据划分到模型评估的一整套流程4.1 数据划分训练集与测试集怎么切模型训练之前必须先把手里的数据分成训练集和测试集。规矩很简单在一部分数据上训练模型在另一部分模型从未见过的数据上评估效果这样才能检验模型是不是真的学到了规律而不是把数据死记硬背下来。这一步我直接用train_test_splitfrom sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, stratifyy, random_state42 )test_size0.2表示拿20%的样本当测试集也就是150条里分30条做测试剩下120条训练。stratifyy用来做分层抽样确保划分出来的训练集和测试集里三个类别的比例和原始数据一致——每一类在测试集里都恰好是10条。如果忽略这个参数随机划分可能导致测试集中某个类别特别多或特别少影响评估的公平性。random_state42则是固定随机种子。不设这个参数每次运行切出的数据都不同模型结果也随之漂移你很难判断效果波动到底是调参引起的还是随机性引起的。固定种子是保证实验可复现的基本习惯。还有一点值得注意train_test_split默认shuffleTrue也就是划分前会打乱数据顺序。这背后有个具体的坑——鸢尾花数据集在原始文件里就是按类别顺序排列的前50条全是Setosa中间50条全是Versicolor后50条全是Virginica。如果不打乱直接按比例切分测试集里可能只有某一个类别的样本训练出来的模型在这个“残缺”的测试集上评分会完全失真。sklearn默认帮你避开这个坑但如果你是用pandas手动切数据一定要记得自己做shuffle。4.2 标准化训练集fit测试集只transform数据划分完成之后标准化的正确姿势是紧接着就做。先看代码from sklearn.preprocessing import StandardScaler scaler StandardScaler() X_train_scaled scaler.fit_transform(X_train) X_test_scaled scaler.transform(X_test)关键就在最后两行训练集用的是fit_transform测试集只用了transform没有fit。fit这一步是让scaler去计算训练集每个特征的均值和标准差。fit_transform在训练集上完成了“计算参数并转换数据”这两件事。而测试集上的transform是直接使用训练集计算出来的均值和标准差去转换测试集数据。为什么要这么做因为测试集在真实场景中代表“未来到达的新数据”模型训练时不应该接触到它们的信息。如果对全量数据一起fitscaler就提前看到了测试集的统计量这属于一种数据泄露。虽然泄露的只是均值方差这类统计信息影响可能不像标签泄露那么致命但你在真实项目中一旦养成这个坏习惯后果会很难收拾。一套正确、严格的数据处理流程应该是从划分之后就开始隔离训练集和测试集的信息流。这个位置是看代码最容易忽略但最该养成习惯的地方我将它视为一种“卫生习惯”。等你在公司里处理真正的业务数据测试集可能要每周滚动更新一次如果每次都要拿全量数据重新计算均值和方差流程会变得混乱不堪模型评估也失去说服力。4.3 建模、预测与评估做好了前两步剩下的建模部分反而最轻松。实例化一个KNeighborsClassifier指定K5训练预测评估from sklearn.neighbors import KNeighborsClassifier from sklearn.metrics import accuracy_score, classification_report, confusion_matrix knn KNeighborsClassifier(n_neighbors5) knn.fit(X_train_scaled, y_train) y_pred knn.predict(X_test_scaled) print(Accuracy:, accuracy_score(y_test, y_pred)) print(confusion_matrix(y_test, y_pred)) print(classification_report(y_test, y_pred, target_namesiris.target_names))这套代码跑下来准确率通常在0.93以上。我手上的多次实验里标准化后K5的分类准确率稳定在0.97附近。confusion_matrix的30乘30正确说法是3×3矩阵每一行代表测试集中真实的类别每一列代表模型预测的类别对角线上的数字就是被正确分类的样本数。如果看到非对角线有数字就是模型把某个样本错分到了其他类别——在这个数据集里错分基本都发生在Versicolor和Virginica之间跟前面可视化的观察完全对得上。classification_report提供了每个类别的精确率、召回率、F1值。其中F1分数对理解“模型在那个类别上到底行不行”特别直观。我习惯先看整体准确率再看混淆矩阵里哪两个类别容易混淆最后落到classification_report里的单项指标上三步定位问题。这个排查顺序跟看体检报告的思路差不多先看总评再看异常指标最后定位到具体项目。到这里第一版模型已经完成了整个流程不到10行核心代码。能用简单方法解决的问题不值得一开始就上复杂模型。但在你确定K5是最优选择之前这个模型还不能算完工。5. 调参实战K值搜索与交叉验证5.1 手动试K肉眼观察曲线第一件事把K从1到30挨个跑一遍画出测试集准确率随K变化的曲线。这个操作很朴素但能建立起“K值如何影响结果”的直观感受。import matplotlib.pyplot as plt k_range range(1, 31) scores [] for k in k_range: knn KNeighborsClassifier(n_neighborsk) knn.fit(X_train_scaled, y_train) scores.append(knn.score(X_test_scaled, y_test)) plt.plot(k_range, scores, markero) plt.xlabel(K value) plt.ylabel(Accuracy) plt.title(KNN Accuracy vs K) plt.show()在这条曲线上我会重点观察几个现象。曲线在某个区间内到达峰值再往后会缓慢下降甚至出现抖动这个抖动就是前文提到的“边界样本效应”。你还会发现K1的训练集准确率确实可以达到100%但测试集分数不一定最高——训练集得分高不意味着泛化好这是无数次实验中反复出现的经典教训。只看K的话常见结果是K3到K7之间有一个“平台期”峰值的具体位置会随着随机种子变化而有微小偏移。所以仅靠单次划分去判断K值好坏是不够的应该交叉验证。5.2 交给GridSearchCV参数搜索的工业做法手动循环只能给一个粗略直觉真正靠谱的调参方式是用网格搜索加交叉验证。交叉验证的大致意思把训练集再切成多份轮流拿其中几份训练、一份验证最后综合多轮的分数取平均。这样做的好处是模型不再依赖某一次幸运的划分评估结果更稳定也更有代表性。from sklearn.model_selection import GridSearchCV param_grid { n_neighbors: range(1, 31), weights: [uniform, distance], p: [1, 2] } grid GridSearchCV( KNeighborsClassifier(), param_grid, cv5, scoringaccuracy ) grid.fit(X_train_scaled, y_train) print(Best params:, grid.best_params_) print(Best CV accuracy:, grid.best_score_) print(Test accuracy:, grid.score(X_test_scaled, y_test))这段代码会遍历所有超参数组合30个K值乘以2种投票权重乘以2种距离一共120组每一组在5折交叉验证里跑5次训练和验证。对鸢尾花这个体量来说整个搜索过程也就几秒钟纵深感很强。我实测下来的结果里最佳参数通常落在K5到K9之间weightsuniform或distance都能有不错表现p2也就是欧氏距离略微占优。weightsdistance的含义是按距离加权投票距离更近的邻居话语权更大这在理论上比一律平权更合理但在鸢尾花这种小数据集上差异不大。我还是建议两组都放进网格里搜索反正成本很低。从GridSearchCV拿到的best_params_严格来说还需要注意它是在交叉验证里选出来的最优参数最终评估还是要用训练集整体重新拟合一次再到测试集上评分。上面代码里grid.score(X_test_scaled, y_test)返回的就是在最优参数下重训模型的测试集得分。这条流程走到位调参才算是闭环。5.3 特征选取实验只有两个特征怎么玩调完超参之后我想再加一个特征实验帮你理解“特征多不等于模型好”。在鸢尾花数据里花瓣长度和花瓣宽度这两个特征的区分能力最强。做个对比实验只保留这两列跑一遍同样的流程再对比全特征的结果。X_petal X[:, 2:4] # petal length和petal width X_train_p, X_test_p, y_train_p, y_test_p train_test_split( X_petal, y, test_size0.2, stratifyy, random_state42 ) scaler_p StandardScaler() X_train_p_scaled scaler_p.fit_transform(X_train_p) X_test_p_scaled scaler_p.transform(X_test_p) knn_p KNeighborsClassifier(n_neighbors5) knn_p.fit(X_train_p_scaled, y_train_p) print(2 features accuracy:, knn_p.score(X_test_p_scaled, y_test_p))实际跑下来两个特征的准确率跟四个特征的版本非常接近有时甚至并列或者反超。乍看有点反直觉但想想前面可视化那一步就明白了花萼特征本身在Versicolor和Virginica之间重叠严重属于“噪声偏大”的特征。加进模型后反而可能干扰距离计算让边界样本的预测不稳定。这个实验提醒我的是建模前先做特征分析比事后调参更有收益。6. 常见问题与排查技巧实录6.1 结果不可复现的坑random_state最容易被忽视的坑是随机性。跑同一个模型第一次准确率0.97第二次变成0.93你可能会以为是代码写错了其实只是数据划分的随机种子没固定。排查方法很简单train_test_split和GridSearchCV里都设置random_state让整个流程可复现。我在自己的环境里固定用的是42没有特别原因就好记。如果你希望看到划分随机性对结果的影响可以故意多换几个种子跑对比但要明确记住——实验比较的前提是控制变量其他条件不变时随机种子不同导致的波动恰恰说明了评估结果具有不确定性。用交叉验证取平均也是对抗这种随机性的手段。6.2 “先标准化再划分”是数据泄露这是代码顺序的经典错误。见过不少新人写的是scaler StandardScaler() X_scaled scaler.fit_transform(X) # 全量数据一起fit X_train, X_test, y_train, y_test train_test_split(X_scaled, y, ...)从结果上看在鸢尾花数据集上这样做往往也“看不出大问题”因为泄露的只是特征统计量。但由此形成的错误习惯放到真实业务场景里就是灾难。比如你在做信贷违约预测时先在全量数据上算均值和方差模型评估会偏乐观上线后效果却明显缩水。数据泄露这个坑隐蔽但影响深远早养成正确习惯早受益。正确的顺序我再说一遍先划分再在训练集上fit_transform然后在测试集上只transform一步都不能乱。6.3 准确率100%的陷阱鸢尾花上偶尔会有人跑出100%的“完美”准确率这里头有真有假。假的100%最典型的是fit完之后直接拿训练集去评估。KNeighborsClassifier有一个特性当K1时每个训练样本的最近邻居就是它自己在训练集上打分必然全对。但训练集上的得分说明不了泛化能力直接拿来宣布模型完美会显得很不专业。另外一个容易出问题的地方是数据顺序。鸢尾花数据集按类别顺序排列如果你手动切分时没有shuffle又不小心把同类数据都塞进测试集比如测试集里只有Setosa模型在这个“简单模式”的测试集上跑出高分甚至满分完全可能。所以一定要确认train_test_split里shuffleTrue并且用stratify做分层才能保证测试集的真实性。6.4 距离度量的数学陷阱最后一个坑是关于距离计算的。如果没有做标准化KNN的距离会被数值范围大的特征主导。我试过把一个业务数据集直接喂给KNN里面有年龄20到60和年收入几万到几百万两个特征结果分类结果几乎完全由收入决定年龄的作用被淹没。这个现象对鸢尾花影响不算致命但会造成边界偏移、个别样本错分。另一个容易被忽视的点是sklearn的KNeighborsClassifier默认p2但如果特征维度升高或者数据变得稀疏调整p值甚至换metric都会有明显效果。我自己的建议是先把标准化做好再谈距离度量的选择多数常规项目里标准化的收益远大于调metric的收益。还有性能层面的问题。KNN预测阶段要逐个计算距离当训练集样本量增大到几十万甚至更高时每次预测都变得很慢。如果业务场景要求毫秒级响应KNN就不合适了要么用KD树或Ball Tree这类加速结构要么考虑换模型。scikit-learn里algorithm参数可以指定kd_tree或ball_tree但加速效果取决于数据维度。作为入门实践先知道这个瓶颈存在心里有个数就行。写在最后的几句实在话就鸢尾花这个项目本身而言技术含量确实不高它真正值钱的地方在于帮你建立一套完整的建模直觉先看数据长什么样再想用什么算法原理去匹配然后严格区分训练集和测试集的信息流最后用交叉验证代替拍脑袋调参。我后来带新人、评审项目代码发现大部分低级错误都出在这一套基本功上而不是模型选得不够时髦。我自己再上手这个项目时最喜欢留作扩展的方向是换一个真实数据集把流程重新跑一遍比如UCI上的葡萄酒数据集或者手写数字数据集你会立刻体会到标准化、K值搜索、特征选择这些步骤的真实分量。KNN这套思路在商品推荐、用户分群、金融量化信号初筛等场景里都有用武之地原理就是我前面说的“物以类聚”四个字。最后分享一个小技巧每次建模前把数据集的shape、特征名、类别分布贴到笔记最前面模型跑完后再把最佳参数和测试集准确率记在最后。一来方便自己排查二来这份记录就是你后面写实验报告、发技术文章的第一手素材。我这些年写了不少技术分享从没想过素材管理这件事后来才意识到迭代记录本身就是最好的学习资产。
