ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

机器学习算法模型地图:从回归到Transformer的完整梳理

机器学习算法模型地图:从回归到Transformer的完整梳理 简介这是一份集合20余种常用算法模型及代码实现的综合资源包面向数据挖掘、机器学习方向的学生、研究者和开发者帮助读者从算法原理、代码实现到结果应用形成完整认知缩短上手时间。资源共1234个文件压缩包大小约614.53MB文件类型覆盖PDF文档、Word/PPT讲义、MATLAB的m文件、SAS脚本、TXT说明、Excel数据表等其中PDF与Word偏重原理解析PPT便于快速把握算法框架m文件和SAS脚本提供可直接运行或修改的代码Excel和TXT多为示例数据与运行结果方便对照学习。资源内还包含图片、压缩包和其他辅助文件整体信息量大目录结构具有一定多样性可按模块或后缀快速定位所需内容。目前已有8577人学习下载内容对课程设计、论文实验及算法面试准备都有参考价值特别适合希望系统积累常用模型实现经验的学习者。 做机器学习这几年我最大的感受不是“算法学得不够多”而是“用的时候找不到合适的”。每次接一个新任务脑子里翻来覆去就那几个熟悉的模型一旦效果不行就卡住。后来我花了不少零散时间把自己代码库里高频使用、面试常问、论文里常见的20多种算法模型统一整理了一遍模型原理一句话概括、适用场景、核心代码实现、关键参数、避坑点。这篇就是那份整理内容的完整版希望能帮你建立一张清晰的“算法地图”不管你是刚入门还是做了几年都能直接拿来参考。整份整理我按“监督学习—无监督学习—集成学习—神经网络—评估与调参”五个维度来拆最后附上我在实际项目里踩过的坑和排查思路。所有代码都基于Python生态以scikit-learn为主部分深度学习用到PyTorch都是可以直接复制跑的版本。1. 算法模型地图先搞清每一类算法到底在解决什么问题1.1 从任务类型反推算法选型我在实际项目中从来不先想“我要用什么算法”而是先问自己三个问题我的数据有没有标签我的目标是预测数值还是判断类别我的数据量级和特征维度是多少这三个问题问完算法选型基本就收敛了。有标签、预测连续值线性回归、岭回归、Lasso、SVR、决策树回归、随机森林回归、XGBoost回归有标签、预测离散类别逻辑回归、KNN、决策树、SVM、朴素贝叶斯、随机森林、GBDT、XGBoost、LightGBM、神经网络无标签、想找内在结构KMeans、层次聚类、DBSCAN、GMM、PCA、t-SNE、Apriori有标签但数据是序列RNN、LSTM、GRU、Transformer数据是图像CNN及其各种变体这个表格看起来简单但非常实用。我见过太多人拿着一堆数据上来就调XGBoost结果业务问题其实是个聚类问题或者数据量只有几百条神经网络根本训不动。选型错了后面所有工作都是白费。1.2 算法复杂度与数据规模的匹配算法不是越复杂越好而是越匹配越好。我在一个风控项目里试过用深度学习做特征交叉效果反而不如逻辑回归加人工特征工程原因很简单样本只有两万条特征四十多个深度学习在这类稀疏场景下很容易过拟合而逻辑回归配合正则化反而稳健得多。这里给一个我常用的经验判断数据量小于一万条优先考虑线性模型、SVM、KNN、朴素贝叶斯数据量在万到百万之间树模型和集成模型是主力尤其XGBoost和LightGBM在表格数据上几乎是无敌的存在数据量百万级以上且特征复杂再上神经网络不迟。另外还要看硬件条件XGBoost在CPU上就能跑得很好而大型Transformer没有GPU基本是寸步难行。2. 监督学习主力算法从线性回归到SVM的代码实现2.1 线性回归与它的正则化兄弟们线性回归是入门第一个模型也可以说是整个监督学习的基石。它的核心假设是特征与目标之间存在线性关系目标函数是最小化均方误差。实际项目中裸的线性回归很少直接用因为特征一多就过拟合所以更常用的是加了L2正则的岭回归和加了L1正则的Lasso。from sklearn.linear_model import LinearRegression, Ridge, Lasso from sklearn.model_selection import train_test_split from sklearn.datasets import fetch_california_housing data fetch_california_housing() X_train, X_test, y_train, y_test train_test_split( data.data, data.target, test_size0.2, random_state42 ) lr LinearRegression().fit(X_train, y_train) ridge Ridge(alpha1.0).fit(X_train, y_train) lasso Lasso(alpha0.1).fit(X_train, y_train) print(fLinear R2: {lr.score(X_test, y_test):.4f}) print(fRidge R2: {ridge.score(X_test, y_test):.4f}) print(fLasso R2: {lasso.score(X_test, y_test):.4f})这套代码跑下来你会看到Ridge和Lasso的效果通常不会比Linear差太多但在特征维度很高时稳定性会好很多。Lasso还有一个额外好处它会自动把不重要的特征系数压成0所以可以直接用来做特征选择。我在一个营销响应率预测项目里用Lasso从120多个特征里筛出了30多个有效特征模型泛化能力反而提升了。2.2 逻辑回归分类问题的默认起点逻辑回归虽然名字里带“回归”但它解决的是分类问题。它在线性回归外面套了一个Sigmoid函数把输出压缩到0到1之间然后以概率形式做类别判断。为什么它如此常用因为它不仅效果稳定而且可以输出概率这在金融风控、医疗诊断这类对解释性要求高的场景里非常重要。from sklearn.linear_model import LogisticRegression from sklearn.metrics import accuracy_score, roc_auc_score model LogisticRegression(C1.0, max_iter1000) model.fit(X_train, y_train_binary) # 假设 y_train_binary 已转换为二分类标签 y_pred_prob model.predict_proba(X_test)[:, 1] print(fAccuracy: {accuracy_score(y_test_binary, model.predict(X_test)):.4f}) print(fAUC: {roc_auc_score(y_test_binary, y_pred_prob):.4f})逻辑回归需要特别注意的坑是特征共线性问题。如果两个特征高度相关模型系数会变得很不稳定正负号都可能会翻转。解决方案很简单训练前先算一下相关性矩阵把相关系数大于0.8的特征做去重或PCA降维。我在实际项目中还习惯把连续特征做标准化因为逻辑回归的梯度下降在特征尺度差异很大的时候收敛很慢。2.3 KNN、决策树与朴素贝叶斯三个“小而美”的分类器这三个算法都属于“原理简单但非常有用”的类型。KNN的核心思想是“物以类聚”新样本的类别由它最近的K个邻居投票决定。决策树则是通过一系列if-else规则把样本空间不断切分。朴素贝叶斯基于贝叶斯定理假设特征之间相互独立直接计算后验概率。from sklearn.neighbors import KNeighborsClassifier from sklearn.tree import DecisionTreeClassifier from sklearn.naive_bayes import GaussianNB knn KNeighborsClassifier(n_neighbors5, weightsdistance) tree DecisionTreeClassifier(max_depth5, random_state42) nb GaussianNB() for name, clf in [(KNN, knn), (DecisionTree, tree), (NaiveBayes, nb)]: clf.fit(X_train, y_train) print(f{name} Accuracy: {clf.score(X_test, y_test):.4f})这三个算法的适用场景差异非常大。KNN对特征尺度极其敏感用之前必须做标准化而且数据量大时预测速度会变得很慢适合小规模数据。决策树不需要特征标准化也不要求特征线性关系拟合能力非常强但参数max_depth不限制的话很容易过拟合到训练集务必配合剪枝参数使用。朴素贝叶斯虽然“朴素”到假设特征独立但在文本分类、垃圾邮件识别这类高维稀疏场景下表现意外地好而且训练速度极快。2.4 SVM从线性到非线性的边界划分SVM支持向量机的核心思想是找到一个超平面使得不同类别的样本间隔最大。当数据线性不可分时它通过核函数把数据映射到高维空间在高维空间寻找线性分割面。核函数的选择是整个SVM的灵魂。from sklearn.svm import SVC from sklearn.preprocessing import StandardScaler from sklearn.pipeline import make_pipeline svm_model make_pipeline( StandardScaler(), SVC(kernelrbf, C1.0, gammascale, probabilityTrue) ) svm_model.fit(X_train_small, y_train) print(fSVM Accuracy: {svm_model.score(X_test_small, y_test):.4f})这里我用make_pipeline把标准化和SVM串在一起这个习惯非常重要。SVM对特征尺度极其敏感因为它的间隔计算依赖特征间的距离度量。如果不做标准化量级大的特征会完全主导间隔计算。核函数方面RBF核是最常用的默认选择C控制对误分类的惩罚力度C越大越容易过拟合gamma控制单个样本的影响半径gamma越大拟合越精细但越容易过拟合。SVM在小样本、高维场景比如基因表达数据、文本分类表现非常好但样本量超过十万后训练速度会让人难以忍受。3. 无监督学习与降维算法从数据中挖掘隐藏结构3.1 KMeans与层次聚类最常用的两种聚类方式聚类是无监督学习的核心任务目标是把没有标签的数据按照相似度自动分组。KMeans是使用频率最高的聚类算法它的逻辑是随机初始化K个中心点然后迭代地把每个样本分配到最近的中心再重新计算中心位置直到收敛。层次聚类则不同它通过不断合并或分裂来构建一个树状的聚类结构。from sklearn.cluster import KMeans, AgglomerativeClustering from sklearn.preprocessing import StandardScaler X_scaled StandardScaler().fit_transform(X) kmeans KMeans(n_clusters4, random_state42, n_init10) labels_kmeans kmeans.fit_predict(X_scaled) hierarchical AgglomerativeClustering(n_clusters4, linkageward) labels_hier hierarchical.fit_predict(X_scaled)KMeans的一个大坑是K值要你自己定。我常用的方法有肘部法则和轮廓系数肘部法则看不同K值对应的SSE下降曲线拐点轮廓系数则综合衡量簇内紧密性和簇间分离度。我一般两个方法配合使用如果两者给出的K值不一致我会倾向于选轮廓系数更高但相差不大时更小的那个K因为聚类结果越少越容易解释。层次聚类的好处是不用预设K值可以通过树状图来判断分成几类合适但计算复杂度是O(n²)数据量超过几万就很吃力了。3.2 DBSCAN自动识别噪声的密度聚类DBSCAN是和KMeans完全不同的聚类思路。它不预设簇的数量而是基于密度来划分区域把样本密集的区域划分为簇把稀疏区域的点标记为噪声。这使得它在处理形状不规则的簇时比KMeans强得多而且天然能识别离群点。from sklearn.cluster import DBSCAN from sklearn.neighbors import NearestNeighbors # 先通过K距离图确定eps的合理范围 neighbors NearestNeighbors(n_neighbors5) neighbors.fit(X_scaled) distances, _ neighbors.kneighbors(X_scaled) distances np.sort(distances[:, 4]) dbscan DBSCAN(eps0.5, min_samples5) labels_db dbscan.fit_predict(X_scaled)DBSCAN的两个参数eps和min_samples决定了聚类结果的全部。eps是邻域半径min_samples是一个点成为核心点所需的最少邻居数。没有任何捷径这两个参数需要结合数据实际分布反复尝试。我在客户分群项目里就用DBSCAN识别出了KMeans看不到的异常行为群体——那些孤立的小簇往往对应着群体欺诈行为这个发现直接改变了项目的风控策略。需要注意DBSCAN对特征缩放非常敏感不同特征量级不同时eps的语义会变得难以解释。3.3 PCA与t-SNE降维的两个层次降维算法是我做数据可视化、特征压缩、去相关时最常用的工具。PCA通过线性变换把高维数据投影到方差最大的方向上属于线性降维计算快、可解释性强。t-SNE则是非线性降维非常擅长在二维平面上展示高维数据的局部结构但计算慢、结果不稳定。from sklearn.decomposition import PCA from sklearn.manifold import TSNE pca PCA(n_components2) X_pca pca.fit_transform(X_scaled) print(fExplained variance ratio: {pca.explained_variance_ratio_}) tsne TSNE(n_components2, perplexity30, random_state42) X_tsne tsne.fit_transform(X_scaled)PCA在工程上有个非常实用的进阶用法用PCA误差做异常检测。原理是正常样本能被前几个主成分很好地重构而异常样本重构误差会明显偏大。我有一次做传感器异常检测就用了这个方法把几十维的传感器读数降到10维重构误差超过3倍标准差的直接标红效果比直接建分类模型好得多因为根本不需要异常标签。t-SNE则几乎只用于可视化它不保留全局距离信息所以用t-SNE的图来下结论要格外谨慎。4. 集成学习与梯度提升练好这几个模型能打90%的表格数据4.1 随机森林并行集成的集大成者随机森林的原理是训练多棵决策树每棵树用从原始数据中有放回抽样得到的子集训练同时每次分裂只随机选取部分特征进行搜索。这种“样本随机特征随机”的双重随机机制让每棵树差异明显集成后大幅降低了方差。from sklearn.ensemble import RandomForestClassifier rf RandomForestClassifier( n_estimators300, max_depth12, min_samples_split10, min_samples_leaf4, max_featuressqrt, random_state42, n_jobs-1 ) rf.fit(X_train, y_train) importance rf.feature_importances_ print(fAccuracy: {rf.score(X_test, y_test):.4f})随机森林是我做过的最容易出效果且不需要太多调参的模型之一。它不需要特征标准化对缺失值有内置处理还能直接输出特征重要性。在特征重要性上我会再加一步稳定性验证在多个随机种子下跑多次看重要性的排序是否稳定而不是只依赖某一次的排序结果。另外n_estimators不是越大越好300棵树和1000棵树的效果差距通常很小但训练和推理时间翻了几倍实际使用300-500就足够了。4.2 GBDT、XGBoost与LightGBM梯度提升家族怎么选梯度提升树GBDT的思路和随机森林完全不同。它是串行的每一棵新树都学习之前所有树的预测残差逐步逼近真实值。XGBoost和LightGBM都是GBDT的高效实现前者在2015年前后屠榜各大机器学习竞赛后者则是前者的性能优化版本训练速度更快、内存占用更少。import xgboost as xgb import lightgbm as lgb xgb_model xgb.XGBClassifier( n_estimators500, max_depth6, learning_rate0.05, subsample0.8, colsample_bytree0.8, reg_alpha0.1, reg_lambda1.0, random_state42, eval_metriclogloss, early_stopping_rounds50 ).fit(X_train, y_train, eval_set[(X_test, y_test)], verboseFalse) lgb_model lgb.LGBMClassifier( n_estimators500, max_depth6, learning_rate0.05, subsample0.8, colsample_bytree0.8, reg_alpha0.1, reg_lambda1.0, random_state42 ).fit(X_train, y_train, eval_set[(X_test, y_test)]) print(fXGBoost Accuracy: {xgb_model.score(X_test, y_test):.4f}) print(fLightGBM Accuracy: {lgb_model.score(X_test, y_test):.4f})我的选型经验是如果数据量在中等规模、特征数量在几千以内XGBoost和LightGBM差距不大随便选一个就行如果特征维度非常稀疏比如高维分类特征one-hot后或者数据量超过几十万行LightGBM的leaf-wise生长策略会明显更快内存占用也更友好。但LightGBM在小数据集上更容易过拟合需要更小心地调小max_depth、调大min_data_in_leaf。这个细节我在好几个项目里帮数据科学团队省了半天调参时间。4.3 AdaBoost集成学习的鼻祖之一AdaBoost的核心思想是“三个臭皮匠顶个诸葛亮”。它串行地训练多个弱分类器每轮训练时加大被前一棵分错样本的权重这样后续的模型会越来越关注难分样本。不过说实话在XGBoost和LightGBM出现之后纯AdaBoost在表格数据上用得少了但它的思想非常重要是理解GBDT的前置知识面试也经常考。from sklearn.ensemble import AdaBoostClassifier from sklearn.tree import DecisionTreeClassifier adaboost AdaBoostClassifier( estimatorDecisionTreeClassifier(max_depth1), n_estimators200, learning_rate1.0, random_state42 ) adaboost.fit(X_train, y_train) print(fAdaBoost Accuracy: {adaboost.score(X_test, y_test):.4f})看到这里你会发现AdaBoost用max_depth1的决策树桩作为弱分类器就能取得不错的集成效果。这也解释了为什么基学习器的选择会极大影响集成效果。但AdaBoost对噪声数据非常敏感因为噪声样本在训练过程中会被反复加大权重导致模型被带偏。如果数据清洗质量一般我建议优先考虑随机森林它对噪声更加鲁棒。5. 神经网络与序列模型从MLP到Transformer的代码骨架5.1 MLP神经网络的基础积木多层感知机MLP就是最基础的神经网络结构输入层、隐藏层、输出层每层之间全连接。别觉得它简单所有深度网络的构建都建立在这一结构之上。我用PyTorch实现最小可用的MLP分类模型来演示核心代码结构。import torch import torch.nn as nn import torch.optim as optim class MLP(nn.Module): def __init__(self, input_dim, hidden_dim64, num_classes2): super().__init__() self.net nn.Sequential( nn.Linear(input_dim, hidden_dim), nn.ReLU(), nn.Dropout(0.3), nn.Linear(hidden_dim, hidden_dim), nn.ReLU(), nn.Dropout(0.3), nn.Linear(hidden_dim, num_classes) ) def forward(self, x): return self.net(x) model MLP(input_dim30, hidden_dim64, num_classes2) optimizer optim.Adam(model.parameters(), lr1e-3) criterion nn.CrossEntropyLoss() # 实际训练时需要手动构建 DataLoader这里展示核心逻辑 for epoch in range(100): model.train() optimizer.zero_grad() outputs model(x_batch) loss criterion(outputs, y_batch) loss.backward() optimizer.step()用MLP的时候我建议从2层隐藏层起步不要太深表格数据上太深的网络收益非常有限反而增加了过拟合风险。Dropout是标准配置尤其是在数据量不大的情况下。激活函数优先ReLU它在实践中稳定高效。学习率从1e-3起步通常比较稳妥如果loss震荡明显再降到1e-4。5.2 CNN与RNN的识别图像和序列的不同套路CNN卷积神经网络专门处理局部相关的结构数据最典型的就是图像。卷积操作通过滑动窗口提取局部特征然后在深层把局部特征组合成全局语义。RNN循环神经网络则处理时间序列和文本它让信息沿时间方向传递但梯度消失问题严重所以实际中更常使用LSTM或GRU。import torch.nn.functional as F class SimpleCNN(nn.Module): def __init__(self, num_classes10): super().__init__() self.conv1 nn.Conv2d(3, 32, kernel_size3, padding1) self.conv2 nn.Conv2d(32, 64, kernel_size3, padding1) self.pool nn.MaxPool2d(2, 2) self.fc nn.Linear(64 * 8 * 8, num_classes) def forward(self, x): x self.pool(F.relu(self.conv1(x))) x self.pool(F.relu(self.conv2(x))) x x.view(x.size(0), -1) return self.fc(x) class SimpleLSTM(nn.Module): def __init__(self, input_size, hidden_size, num_layers, num_classes): super().__init__() self.lstm nn.LSTM(input_size, hidden_size, num_layers, batch_firstTrue) self.fc nn.Linear(hidden_size, num_classes) def forward(self, x): out, _ self.lstm(x) return self.fc(out[:, -1, :])CNN这边BatchNorm几乎和卷积层绑定了我记得有一次模型在验证集上怎么都不收敛检查半天发现自己忘了加BatchNorm加上之后两个epoch就正常了。RNN这边对于序列数据输入格式必须整理成(batch, seq_len, input_size)输出取最后一个时间步的hidden state用于分类。LSTM的hidden_size和num_layers是两个最重要的超参数hidden_size默认64、num_layers默认2是我的标准起点。5.3 Transformer序列模型的新范式Transformer现在已经是NLP和很多序列建模任务的默认选择。它的核心机制是自注意力允许序列中任意两个位置直接交互彻底解决了RNN长距离依赖和无法并行的问题。虽然完整实现Transformer代码较长但工程上几乎都是加载预训练模型所以我这里给一个使用HuggingFace的最小示例属于高频复用的代码骨架。from transformers import pipeline classifier pipeline( sentiment-analysis, modeldistilbert-base-uncased-finetuned-sst-2-english ) result classifier(This project is going really well!) print(result) # 输出示例[{label: POSITIVE, score: 0.9998}]工程上70%以上的场景不需要从零训练Transformer而是加载预训练模型进行微调。这能省下天量的数据和算力。即便是微调也要注意学习率要调小通常1e-5到5e-5之间因为预训练模型的权重已经很好过大学习率会直接破坏已有特征。6. 模型评估与调参API调用背后必须掌握的三件事6.1 回归和分类的评估指标怎么选很多人拿到模型就打印accuracy但accuracy在很多场景下会骗人。我举个例子在信用卡欺诈检测里正样本只有1%一个把所有样本都预测为“正常”的模型accuracy也能有99%。这三个指标必须记住精确率、召回率、F1。from sklearn.metrics import ( precision_score, recall_score, f1_score, mean_squared_error, r2_score, confusion_matrix, classification_report ) # 分类指标 print(precision_score(y_test, y_pred)) print(recall_score(y_test, y_pred)) print(f1_score(y_test, y_pred)) print(confusion_matrix(y_test, y_pred)) # 回归指标 print(mean_squared_error(y_test, y_pred_reg)) print(r2_score(y_test, y_pred_reg))精确率高代表模型预测为正的样本里真正是正的占比高适合垃圾邮件过滤这种宁可不发也不能误发的场景。召回率高代表模型把真实正样本找回来的比例高适合疾病筛查这种宁可错查也不能漏查的场景。F1是二者的调和平均在正负样本不均衡时比accuracy可靠得多。回归方面MSE对离群值极其敏感一个离群点能把MSE拉爆如果数据里有离群点建议用MAE或Huber损失来评估。6.2 交叉验证小数据上评估模型的正确姿势数据集不够大的时候train_test_split一次划分得到的评估结果方差非常大也许换一个随机种子模型的排名就完全不同了。交叉验证是解决这个问题的标准方案把数据均分成K份每次用K-1份训练、1份验证轮流K次最后取平均成绩。K5是常用的默认值。from sklearn.model_selection import cross_val_score, StratifiedKFold cv StratifiedKFold(n_splits5, shuffleTrue, random_state42) scores cross_val_score(rf, X_train, y_train, cvcv, scoringf1) print(fCV F1: {scores.mean():.4f} ± {scores.std():.4f})注意拐点交叉验证保留下来的StratifiedKFold保证了每一折里正负样本比例和总体一致。如果不做分层抽样对于二分类这类问题很可能某一折里全是或几乎没有正样本导致验证集失效。交叉验证的std值要格外关注如果std过大比如F1均值0.85但标准差0.08说明模型在不同数据子集上表现差异很大更可能是特征不稳定或数据本身分布问题这时候调参解决不了本质问题。6.3 超参数调优网格搜索与随机搜索的正确用法调参是很多人最头疼的部分。网格搜索是穷举所有参数组合样本维度高时几乎不可行。随机搜索是在参数范围内随机采样效率和效果都更好。还有贝叶斯优化近年越来越常用但工程上先掌握前两种就够了。from sklearn.model_selection import GridSearchCV, RandomizedSearchCV from scipy.stats import randint, uniform param_grid { n_estimators: [200, 300, 500], max_depth: [6, 8, 10, 12], min_samples_split: [10, 20], min_samples_leaf: [2, 4] } random_search RandomizedSearchCV( RandomForestClassifier(random_state42), param_distributions{ n_estimators: randint(100, 500), max_depth: randint(4, 16), min_samples_split: randint(5, 30), min_samples_leaf: randint(2, 10), }, n_iter30, cv5, scoringf1, random_state42, n_jobs-1 ) random_search.fit(X_train, y_train) print(fBest params: {random_search.best_params_})我的调参原则是少调参数优先只调最关键的有限几个。不同模型的参数重要性不同树模型里max_depth、min_samples_leaf往往比n_estimators更影响效果GBDT里learning_rate和n_estimators是联动关系的两者要一起看不能只调其中一个。任何搜索都要配合交叉验证否则调出来也是过拟合的参数。7. 常见问题与排查技巧实录7.1 模型效果差的排查清单在我自己的项目经历里模型效果差九成不是模型本身的问题而是数据出的问题。我给自己整理了一个排查清单按顺序过一遍基本能定位问题。数据泄露目标变量或被预测后的信息在训练时被不小心用进去了。这是一个无声的杀手没有报错、没有警告效果在训练集上特别好测试集上崩得离谱。正负样本极度不均衡先试class_weightbalanced再考虑过采样、欠采样或SMOTE。特征尺度不一致树模型可以不管但线性模型、KNN、SVM必须做标准化。特征里有太多missing value或者全是常数这两种情况树模型容易迭代出奇怪的分支直接删掉可能更好。训练集和测试集分布不一致检查一下时间切片如果不是随机切分而是按时间切分要考虑数据时效性衰减的问题。7.2 数据泄露的经典案例与检查办法数据泄露这个问题几乎是所有刚接触机器学习的工程师最容易踩且最难察觉的坑。我见过最典型的一个例子是当时做客户流失预测把“最近三个月是否联系客服”作为特征模型效果好得惊人。结果上线之后发现跑预测的时候根本没有“未来三个月”的数据因为客户是先流失然后才产生客服记录这个特征本身就是未来信息的偷看。检查数据泄露我常用的办法是观察特征重要性排序是否合理是否出现了一个在业务逻辑上“太完美”的特征。再就是做时间切分验证用前80%时间训练后20%验证如果效果比随机切分差很多大概率存在和时间相关的信息泄露。7.3 过拟合与欠拟合的动态诊断训练集效果极好、测试集效果很差过拟合。训练集和测试集效果都很差欠拟合。这个诊断人人会做但实操里更推荐看学习曲线来动态判断。from sklearn.model_selection import learning_curve import numpy as np train_sizes, train_scores, val_scores learning_curve( rf, X_train, y_train, cv5, train_sizesnp.linspace(0.1, 1.0, 10), scoringf1, n_jobs-1 )训练分数很高但验证分数差距很大典型过拟合解决方向是加正则、减深度、加数据。两条曲线都低且差距不大那是欠拟合例如模型容量不足、特征太少或数据量根本不够。这里有一种特殊情况是模型容量太小但数据量很大这时加特征、加深模型、减少正则约束比增加数据量更有效。8. 最后分享一点算法工程化的心得整理这份A到Z的算法笔记对我来说不仅仅是一次知识的梳理更是一个“重建决策流程”的过程。现在拿到一个项目我不会再凭感觉选模型而是先在纸上画一遍数据流业务要什么指标、数据长什么样、允许的延迟和算力预算是多少、解释性有没有硬要求。这套流程走完后适合的算法往往只剩下两三个再通过交叉验证对比一把挑出最优就足够稳妥了。最后的建议是这篇整理里的每段代码都值得自己动手跑一遍改一改参数、换一换数据集踩一些报错这才是把这些模型真正变成你自己的工具的路径。算法库不在于多而在于你真正理解每个模型在什么条件下能发挥出它的价值。本文还有配套的精品资源点击获取
返回列表