很多刚开始学机器学习的朋友应该都有过这种体验:教材和网课一口气抛出感知机、逻辑回归、SVM、决策树、KNN五个分类算法,每个都单独看觉得懂了,可真拿到一份数据,却完全不晓得该先跑哪个模型。我当年踩了一年坑之后才算想明白一件事——这几个基础分类算法不是彼此割裂的知识点,而是同一件事的不同解法和取舍,把它们放在同一个框架里对照着学,才是最快的内化路径。
所以这篇东西不打算按教科书方式一个个“介绍”算法,而是直接用 scikit-learn 把这五类模型全部串起来,从原理本质、适用边界、代码实现到调参陷阱,一次性讲透。不管你是刚装好 Scikit-Learn 还在啃 API 的新手,还是已经跟着实验做过决策树收入预测、KNN 红酒分类这类练手项目、想补原理短板的进阶同学,这篇文章的定位都很明确:看完你会有一张清晰的选型地图,同时拿到一套可以直接抄作业的对比实验模板。
1. 环境和实验设计:为什么把五个模型放在一起跑
先花两分钟把实验环境准备好。老手可以直接跳到 1.2 节,新手建议整个流程跟一遍,因为你会发现后面所有代码都依赖这套固定的 fit/predict/score 结构。
1.1 安装 scikit-learn 与版本选择
安装本身没什么玄学,官方推荐的现代方式是直接用 pip 装:
pip install scikit-learn如果用的是 Anaconda 发行版,通常自带 scikit-learn,没有的话敲一行:
conda install scikit-learn装完强烈建议顺手装两个辅助库,后面做数据操作和可视化都会用到:
pip install pandas matplotlib版本问题上我多说一句。scikit-learn 从 0.22 开始弃用了一些老 API,1.0 之后又统一了大部分接口,目前主流教程都是基于 1.x。装好后可以在 Python 里确认一下:
import sklearn print(sklearn.__version__)只要输出是 1.0 以上,下面所有代码都能直接跑。我本机用的版本比较新,文中的参数名称和写法在 1.0 到 1.3 之间都是稳定的,完全不用担心过时问题。
注意:安装时容易踩的第一个坑是 NumPy 版本冲突。scikit-learn 对 NumPy 版本有最低要求,如果你以前装过老版本 NumPy,建议用
pip install -U numpy scikit-learn一并升级,别单独装 sklearn,否则很容易出现导入时报错。
1.2 一个模型训练的最小完整流程
学习 scikit-learn 最重要的一件事是:它的绝大部分模型都长得一模一样。任何分类器,几乎都是下面这套三段式操作:
from sklearn.svm import SVC model = SVC() # 1. 创建模型,设置超参数 model.fit(X_train, y_train) # 2. 喂训练数据,拟合模型 acc = model.score(X_test, y_test) # 3. 在测试集上评估这段代码里的X_train是训练特征矩阵,y_train是标签向量。你只要接受这套统一接口,感知机、逻辑回归、SVM、决策树、KNN 这些完全不同的算法,在代码层面只是换了第一行的类名而已。这也是我一开始就选择 scikit-learn 作为学习框架的原因——它可以把你从“背每个算法各自的 API”里解放出来,让你把注意力全部放在“算法本身在解决什么问题”。
后面所有代码都遵循这套三段式,唯一变化的是模型名和参数。宏观上用一句话概括整个实验流程:
- 加载数据
- 拆分训练集和测试集
- 做特征缩放
- 用五个模型分别训练并评估
- 针对每个模型做基本的超参数调优
这个流程本身就是工业界做 baseline 的标准动作,不是教学专用,这点你往后做项目会越来越有体会。
2. 五个分类算法的原理本质与适用边界
这里我不会给你堆公式,而是用最直白的方式说清楚每个算法的“决策思路”,因为只有理解了思路,你才知道什么时候该用它、什么时候它一定会翻车。
2.1 感知机:理解“让错误推动学习”的起点
感知机(Perceptron)可以说是所有神经网络和线性模型的祖师爷,1957 年由 Frank Rosenblatt 提出。它的核心思路极度简单:找一条直线(在二维空间中)把两类点分开。怎么找呢?随机初始化一条线,然后逐个看样本点,如果某个点被分错了,就调整线的位置,让这条线往错误点的方向“拉一拉”。一直重复这个过程,直到所有点都被分对(或者达到最大迭代次数)。
在 scikit-learn 里代码是:
from sklearn.linear_model import Perceptron perceptron = Perceptron(max_iter=1000, random_state=42) perceptron.fit(X_train, y_train)注意“线性可分”这四个字,这是感知机的命门。如果两类数据在特征空间里本身就是你中有我、我中有你,感知机永远不会收敛。还有一个容易被忽略的点:默认的 Perceptron 只能用二分类,处理多分类其实是 sklearn 在内部帮你做了 OvR(一对多)策略。
实操心得:你可能会问,既然感知机这么简单,为什么现在没人直接用它?因为它在可训练性和稳定性上不如逻辑回归——感知机对于落在决策边界附近的点极其敏感,轻微扰动就会让模型在学习过程中震荡。但它的意义在于,它是理解“迭代式学习”“误差驱动”的最佳入门素材,神经网络全连接层的本质就是一个带激活函数的多层感知机。
2.2 逻辑回归:线性分类器里最实用的那个
逻辑回归(Logistic Regression)名字里带“回归”,干的却是正儿八经的分类活。它和线性回归很像,都是算一条加权线性的分数:( z = w_1x_1 + w_2x_2 + ... + b )。不同之处在于,它把这个分数再塞进一个 Sigmoid 函数,把连续值压到 0 到 1 之间,当作“样本属于某一类”的概率。
比如分数 z 算出来是 3,经过 Sigmoid 变成 0.95,那模型就认为这个样本有 95% 的概率属于正类。默认情况下,sklearn 把概率大于 0.5 的判成正类,小于 0.5 判成负类。这个“概率输出”能力是逻辑回归最大的价值——你可以拿它做排序(比如根据点击率排序)、风险评级,而不仅仅是一个 yes/no 的分类器。
from sklearn.linear_model import LogisticRegression lr = LogisticRegression(max_iter=1000, random_state=42) lr.fit(X_train, y_train) proba = lr.predict_proba(X_test) # 得到每类的概率为什么逻辑回归这么常用?因为它训练快、内存小、可解释性强(权重 w 直接告诉你每个特征对结果的正向或负向影响),而且不管数据量是几千条还是几百万条,都能表现得不错。它的短板也很明确——特征与标签之间的关系如果高度非线性,逻辑回归的边界就是一条直线或一个超平面,很难拟合出复杂形状。
2.3 SVM:用“最大化间隔”寻找最稳健的分割线
支持向量机(Support Vector Machine,简称 SVM)和逻辑回归一样也是线性分类器,但它选分界线的标准与众不同:不只找一条能正确分类的线,而是要找到离两侧最近样本点都最远的那条线。这些决定边界的最近样本点,就叫“支持向量”,它们像夹住一根杆子两侧的支撑点一样,把决策边界的位置“撑”出来。
这条最大间隔线的优势是泛化能力通常更好——因为分类边界离两侧数据都足够远,新样本落在模糊地带的概率就低。sklearn 里的实现还会引入一个惩罚参数 C,用来控制“对误分类样本的容忍度”。C 越大,模型越想把每个样本都分对,主导者是严格追求训练集正确率,但也更容易过拟合;C 越小,模型允许一定数量的错误,换取更平滑的边界和更强的泛化能力。
from sklearn.svm import SVC svm_linear = SVC(kernel='linear', C=1.0, random_state=42) svm_rbf = SVC(kernel='rbf', C=1.0, gamma='scale', random_state=42)SVM 真正的杀手锏是“核技巧”(kernel trick)。简单说,如果数据在原始空间里乱七八糟没法用一条直线分开,我可以把它们映射到更高维的空间——在低维空间里拧成一团的数据,升维之后往往能用一个平面轻轻切开。核技巧高明在哪里?你不用真的做那次升维计算,只需要在低维空间里算一个核函数(比如高斯 RBF 核),就能得到高维空间点积的结果,计算成本大大降低。
代价是什么呢?SVM 的时间复杂度在小数据集上很友好,但样本量一旦超过几万条,训练速度会明显下降。所以在中小型数据集上,非线性 SVM 常常是最强分类器之一,但放到百万级数据场景,人们通常会转向逻辑回归或树模型。
2.4 决策树:把 if-else 规则自动学到极致
决策树(Decision Tree)大概是这五个模型里最直观的一个了。它的思路就是自动从数据里学习一套 if-else 规则:如果年龄小于 35 且收入大于 5000,就预测可以贷款;否则继续判断其他特征。每一步分裂都会选择一个特征和一个阈值,目标是让分裂之后的数据类别“纯度”更高。
衡量纯度的指标有两个:Gini 不纯度(基尼系数)和信息增益(基于信息熵)。sklearn 中默认用 Gini,计算方式是 ( Gini = 1 - \sum p_i^2 ),其中 ( p_i ) 是每个类别的占比。假如一个集合里两类各占一半,Gini 是 0.5,说明混乱程度高;如果全部是同一类,Gini 是 0,说明纯度拉满。决策树就不断挑选特征和阈值,让 Gini 下降最多。
from sklearn.tree import DecisionTreeClassifier, plot_tree dt = DecisionTreeClassifier(max_depth=3, random_state=42) dt.fit(X_train, y_train) import matplotlib.pyplot as plt plt.figure(figsize=(15, 8)) plot_tree(dt, filled=True, feature_names=feature_names, class_names=class_names) plt.show()决策树的优点有两个。第一是可解释性无与伦比,画出来就是一棵树,业务人员也能看懂。第二是不需要特征缩放,因为它每次只在一个特征上找阈值,数值大小对结果没有影响。缺点是单棵决策树极其容易过拟合——如果不限制深度,它会为训练集的每一个特殊样本生成分支,看着训练精度很高,测试集上一塌糊涂。解决办法就是预剪枝参数:限制max_depth、min_samples_split、min_samples_leaf等,这个后面实战会演示。
2.5 KNN:不学习也能分类的“懒惰选手”
K 近邻(K-Nearest Neighbors,简称 KNN)完全打破了前面几个模型的训练范式。感知机、逻辑回归、SVM、决策树都有“训练”阶段,KNN 没有,它在训练时什么都不做,只是把数据记下来,等到你做预测时,才把新样本拉到特征空间里,找距离最近的 K 个已知样本,然后让这些邻居投票决定新样本属于哪一类。
from sklearn.neighbors import KNeighborsClassifier knn = KNeighborsClassifier(n_neighbors=5, metric='minkowski', p=2) knn.fit(X_train, y_train)K 值的选择是 KNN 最关键的超参数。K 太小,模型对噪声极其敏感,比如 K=1 时只要最近的一个邻居被标错类,预测就错了;K 太大,会把离得很远的样本也拉进来,导致边界过平滑。一个常见的初始参考值取样本数的平方根左右,但更靠谱的方式是画学习曲线,逐个测试 K 从 1 到 20 的表现。
我知道很多人会混淆 KNN 和 KMeans,因为名字里都是“K”。这里必须说清楚:KNN 是监督学习,做分类或回归,本质是“看邻居投票”;KMeans 是无监督学习,做聚类,本质是“迭代找质心、不停重新分配样本”。两者唯一的共同点只是都依赖距离度量。如果你在做分类任务,脑子里应该出现 KNN;在做数据分群任务,才轮到 KMeans。
注意:KNN 对特征缩放极其敏感。因为它算的是欧氏距离,如果一个特征是“年龄”(0-100),另一个特征是“年收入”(0-10 万),收入维度会直接主导距离计算,年龄等于被无视了。所以任何基于距离的学习器,用之前必须做标准化或归一化。
3. 实战:一份数据同时跑通五个模型
原理说过一遍,现在上真家伙。我选的数据集是 scikit-learn 内置的红酒数据集(load_wine),178 个样本,13 个特征,3 个类别,规模小但包含了完整的特征工程和模型调优流程,特别适合做多模型对比实验。
3.1 数据加载与预处理:标准化是必选项吗
先加载数据并拆分成训练集和测试集:
import pandas as pd from sklearn.datasets import load_wine from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler wine = load_wine() X = pd.DataFrame(wine.data, columns=wine.feature_names) y = wine.target X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42, stratify=y ) scaler = StandardScaler() X_train_scaled = scaler.fit_transform(X_train) X_test_scaled = scaler.transform(X_test)这里有几个细节请你留意,都是实战里肉眼可见踩过坑的地方:
random_state=42保证每次实验数据划分完全一致,你复现出的结果能和我的对上。如果不固定随机种子,模型性能的差异里就混入了数据划分的随机性,你根本没法判断算法调优有没有效果。stratify=y是分层抽样参数,让训练集和测试集里三个类别的比例保持一致,避免某类样本恰好都分到测试集导致结果失真。尤其类别不均衡时,这一步能救你命。- 缩放器用
fit_transform处理训练集后,测试集只能用transform,这个区别千万不能混。如果对测试集单独fit,就相当于让模型提前看到了测试集的统计信息,这叫做“数据泄露”,会让评估结果虚高。
3.2 五个模型统一训练与评分
我把五个模型写在一个循环里对比:
from sklearn.linear_model import Perceptron, LogisticRegression from sklearn.svm import SVC from sklearn.tree import DecisionTreeClassifier from sklearn.neighbors import KNeighborsClassifier from sklearn.metrics import accuracy_score, classification_report, confusion_matrix models = { 'Perceptron': Perceptron(max_iter=1000, random_state=42), 'LogisticRegression': LogisticRegression(max_iter=1000, random_state=42), 'SVM(RBF)': SVC(kernel='rbf', C=1.0, random_state=42), 'DecisionTree': DecisionTreeClassifier(max_depth=3, random_state=42), 'KNN(k=5)': KNeighborsClassifier(n_neighbors=5) } X_train_use = X_train_scaled X_test_use = X_test_scaled # 决策树单独用原始特征,其余用标准化后的特征 results = {} for name, model in models.items(): if name == 'DecisionTree': model.fit(X_train, y_train) y_pred = model.predict(X_test) acc = accuracy_score(y_test, y_pred) else: model.fit(X_train_use, y_train) y_pred = model.predict(X_test_use) acc = accuracy_score(y_test, y_pred) results[name] = acc print(f'{name}: {acc:.4f}')我在决策树上单独使用了未缩放的数据,原因是特征缩放不会改变决策树的分裂规则,它对每个特征独立寻找阈值,数据是否标准化完全不影响结果。这也是我做对比实验时比较讲究的地方——不要让模型迁就我的统一流程,而是要根据模型特性单独安排数据输入。
在我本机上的结果大致是:
| 模型 | 准确率 | 备注 |
|---|---|---|
| Perceptron | 0.8611 | 线性模型,红酒数据基本线性可分,表现尚可但略不稳 |
| LogisticRegression | 0.9722 | 标准线性分类器,默认 L2 正则化效果稳定 |
| SVM(RBF) | 0.9722 | 非线性核,小数据集上的强力选手 |
| DecisionTree(max_depth=3) | 0.9444 | 剪枝后有一定泛化能力 |
| KNN(k=5) | 0.9722 | 缩放后表现优秀,距离度量充分发挥作用 |
看到没,逻辑回归、SVM、KNN 在这个数据集上分数接近,都是 0.97 左右,感知机最弱,决策树居中。这其实说明一件事:数据集简单时,几个主流分类器的天花板都很接近,真正的差异体现在数据变复杂、噪声变多、类别不均衡之后。所以别一上来就追求复杂模型,先跑这几个 baseline 拿准确率,是最高效的策略。
3.3 交叉验证和 GridSearchCV 调参实操
只跑一次 train/test split 说服力不够。更严谨的做法是交叉验证——把训练数据分成 5 份,轮流拿 4 份训练、1 份验证,最终结果取平均。这样能极大减小划分随机性带来的方差。
from sklearn.model_selection import cross_val_score, GridSearchCV # 5 折交叉验证看稳定性 for name, model in models.items(): scores = cross_val_score(model, X_train_use, y_train, cv=5) print(f'{name}: mean={scores.mean():.4f}, std={scores.std():.4f}')调参上我强烈推荐直接用 GridSearchCV,把它理解成“参数组合自动试错机”。它会把你要搜索的参数列表逐项组合,跑交叉验证选最好的组合。以 SVM 为例:
param_grid = { 'C': [0.1, 1, 10, 100], 'gamma': ['scale', 0.01, 0.1, 1], 'kernel': ['rbf'] } svm_search = GridSearchCV(SVC(random_state=42), param_grid, cv=5) svm_search.fit(X_train_scaled, y_train) print(svm_search.best_params_) print(svm_search.best_score_)KNN 的调 K 也照葫芦画瓢:
knn_search = GridSearchCV( KNeighborsClassifier(), {'n_neighbors': range(1, 21)}, cv=5 ) knn_search.fit(X_train_scaled, y_train) print(knn_search.best_params_)实操心得:调参前先想清楚要优化哪个指标。分类任务的默认评分是 accuracy,但如果你的数据类别不平衡,accuracy 会骗人。比如 95% 都是负类,你把所有样本预测为负类,accuracy 就能有 0.95,这显然是假象。这时候 GridSearchCV 的
scoring参数可以换成'f1'、'roc_auc'或'precision',根据业务目标来选。
4. 从红酒扩展到实际场景:收入预测和鸢尾花分类的关键细节
如果你已经跟着第一节做完了头歌平台上的“决策树收入预测-sklearn版”或者“KNN 红酒分类”,你会发现在线实验和真正的项目实战之间还差着一层东西——不是代码能力,而是“拿到原始数据后怎么把它变成模型能吃的样子”。我们来把完整链路补齐。
4.1 决策树做收入预测:数据清洗是真正的老大难
收入预测通常用的数据是成人收入数据集(Adult Income),核心任务是判断一个人的年收入是否超过 5 万美元。特征包含年龄、工作类别、教育程度、婚姻状况、职业、种族、性别、每周工作时长等,标签是 >50K 或 <=50K。这数据的特点是:
- 缺失值用
?表示,需要先清洗。 - 类别型特征占了大半,要把文本变成数值。
- 类别比例接近 75:25,有轻度不均衡。
决策树在这类结构化表格数据上特别吃香,因为它的分裂过程自动处理了类别和数值的混合。核心流程大概是:
import pandas as pd from sklearn.model_selection import train_test_split from sklearn.preprocessing import LabelEncoder from sklearn.tree import DecisionTreeClassifier df = pd.read_csv('adult.csv') # 把 ? 替换成 NaN,再删除或填充 df = df.replace('?', pd.NA).dropna() # 类别型特征用 LabelEncoder for col in df.select_dtypes(include=['object']).columns: df[col] = LabelEncoder().fit_transform(df[col].astype(str)) X = df.drop('income', axis=1) y = df['income'] X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42, stratify=y ) dt = DecisionTreeClassifier(max_depth=5, min_samples_leaf=10, random_state=42) dt.fit(X_train, y_train) print(f'Accuracy: {dt.score(X_test, y_test):.4f}')值得注意的是,这个任务里用了min_samples_leaf=10,意思是每个叶子节点至少要有 10 个样本。这个参数比单纯限制深度往往更有效,因为它同时限制了树的分支规模,能让树更平滑地泛化。我在做收入预测时发现,深树很容易记住单一用户的中奖特征,剪枝之后准确率虽然略降,但业务上的稳定性会明显好很多。
4.2 KNN 做鸢尾花分类:先做特征可视化判断距离度量是否合理
鸢尾花分类是 KNN 最理想的入门数据集——150 个样本、4 个数值特征、3 个品种。但它隐含着一个坑:花萼长度和花瓣长度的量纲差异不大,所以很多人不缩放也能得到不错的效果。这会让你产生“KNN 不缩放也行”的错误印象。
更稳妥的做法是先用散点图或 pairplot 快速观察数据分布,判断特征之间的物理意义差异有多大:
import seaborn as sns from sklearn.datasets import load_iris iris = load_iris() df_iris = pd.DataFrame(iris.data, columns=iris.feature_names) df_iris['species'] = iris.target sns.pairplot(df_iris, hue='species') plt.show()画出图之后你会看到,不同鸢尾花品种的花瓣长宽差异非常明显,几乎可以线性分开,这就是为什么简单 KNN 就能到 0.95+ 的准确率。但如果换成包含时间戳、金额、计数值的业务数据,特征之间单位可能差出几个数量级,不缩放的 KNN 大概率会被数值最大的特征牵着鼻子走。所以养成“凡是用 KNN,先用 StandardScaler”的条件反射,是最省心的做法。
5. 踩坑记录:Scikit-Learn 分类实战的常见问题清单
下面这些坑,都是我在实际跑模型时真实遇到过、并且不止一次帮朋友排查过的,按出现频率从高到低罗列出来,建议你复制下来当速查表。
5.1 ConvergenceWarning:模型没训练完就罢工
实践中最常见的警告是ConvergenceWarning: Maximum number of iterations reached。逻辑回归和感知机默认最大迭代次数有限,当数据没做标准化时,特征间量纲差异大,梯度下降收敛速度会非常慢,程序跑满迭代上限后直接停下来,模型还没真正学到位。解决方式有两层:
- 第一层,把
max_iter调大到 10000,治标。 - 第二层,对特征做
StandardScaler标准化,让所有特征的尺度统一在均值 0、方差 1 附近,让优化过程跑得更顺,这才是治本。
我自己的习惯是默认就写LogisticRegression(max_iter=10000),如果数据量特别大,可以结合标准化避免无意义的计算浪费。
5.2 特征缩放的时间点错误
特征缩放最大的误区,就是把scaler.fit_transform用在全部数据上,然后再做 train_test_split。这会导致测试集的统计信息在训练之前就被模型“偷看”了。正确顺序是:先拆分数据集,再单独对训练集fit_transform,然后对测试集只做transform。如果你把顺序搞反,评估结果会偏乐观,模型上线后表现和实验差距很大,排查起来特别诡异。
5.3 评估指标的维度太单一
很多新手只看 accuracy 一个指标。在类别均衡的数据集上问题不大,但一旦正负样本比例失衡,比如 95:5,accuracy 就会变成“全猜多数类”都能拿 95 分的垃圾指标。真正靠谱的评估要同时看查准率(Precision)、召回率(Recall)和 F1 分数。分类报告可以一次性给出这些值:
from sklearn.metrics import classification_report y_pred = lr.predict(X_test) print(classification_report(y_test, y_pred))结合混淆矩阵一起看:
from sklearn.metrics import confusion_matrix print(confusion_matrix(y_test, y_pred))混淆矩阵的每一行是真实类别,每一列是预测类别。对角线上的数字越大越好,非对角线是“错分样本”的实际分布,能让你看清楚模型到底混淆了哪两个类别。比如在红酒数据集上,如果类别 1 和类别 2 经常互相误判,说明这两个品种在特征上高度相似,可能需要为此收集更多特征或换非线性模型。
5.4 决策树过拟合:用预剪枝控制模型复杂度
决策树过拟合几乎是我的入门期必然踩的坑。不设任何限制的决策树可以把训练集准确率跑到 1.0,但测试集表现很拉胯。解决办法是在训练前就把树“剪掉”。常用预剪枝参数有三个:最大深度max_depth、叶子节点最小样本数min_samples_leaf、内部节点最小样本数min_samples_split。我个人的经验做法是先用默认参数跑一次,观察训练准确率和测试准确率差距。如果差距超过 10%,说明过拟合明显,再逐步减小max_depth或增大min_samples_leaf,直到差距收敛到 5% 以内。
5.5 随机性和可复现性:为什么你的结果和别人的不一样
有朋友经常跑来问我:同一个数据集、同一个模型,为什么我跑出来的结果跟教程差很多?十次里有九次是因为没设random_state。决策树和 SVM 等模型的训练可能涉及随机初始化和随机抽样,不设随机种子,每次跑的结果都会轻微变动。规范做法很简单,但凡有random_state参数,都设成 42 或任意固定整数。多模型对比实验里,这一步不做会严重影响调参判断。
6. 模型选型法则:遇到新任务到底该用哪个
最后这部分价值含量不低。很多人问“哪个分类器最牛”,但真实答案永远是“看数据”。我把这些年做分类的经验浓缩成一套快速选型思路,可以直接对照套用。
6.1 一张表选好模型
| 任务特点 | 推荐模型 | 理由 |
|---|---|---|
| 数据线性可分,需要快速 baseline | 逻辑回归或线性 SVM | 训练快、稳定、可解释 |
| 高维稀疏特征,比如文本分类 | 逻辑回归 | 正则化方便,内存占用小 |
| 中小型数据、特征高度非线性 | RBF 核 SVM | 核技巧能捕捉复杂边界 |
| 需要向业务解释预测依据 | 决策树 | 可画出树结构,规则透明 |
| 训练时间几乎为零,预测时只查邻居 | KNN | 非参数、实现简单,适合快速原型 |
| 样本量极大(百万级) | 逻辑回归或 SGDClassifier | 线性模型训练复杂度低,能扛住大数据 |
| 非常在意准确率,可接受黑盒模型 | 集成方法(随机森林、XGBoost) | 多个基础模型叠加,精度通常更高 |
注意,这张表的主角还是那五个基础模型。集成学习只是把决策树这种弱学习器组合起来,你如果连单个模型的原理都没吃透,跑再多集成模型也只是在开盲盒。
6.2 一套可以复用到所有分类任务的流程
我这几年做任何分类项目,几乎都按这套流程走,推荐给你:
- 清洗数据:处理缺失值、重复值、异常值。
- 特征工程:把类别变量编码,把连续变量标准化。
- 切分数据:固定
random_state,必要时stratify保类比例。 - 先跑逻辑回归作为 baseline,记录准确率、F1 等指标。
- 按数据量级从基础五个模型里选两三个,在同一个数据集上对比。
- 对表现最好的模型做超参数调优,用 GridSearchCV 或 RandomizedSearchCV。
- 用测试集做最终验证,并详细看混淆矩阵,定位错误样本的模式。
- 上线前再想想,评估指标是否匹配业务目标,是否需要处理类别不均衡。
这流程听起来不刺激,但极其有效。大多数人模型效果差,不是缺什么炫技算法,而是前面三步没做好。
最后再分享一个我自己的体会:刚开始学 sklearn 时,我也喜欢把每个模型的参数都背得很熟,甚至收藏了各种花哨的调参模板,但真到了项目里根本用不上。后来想明白,真正重要的不是记住参数,而是理解每个模型假设的本质——SVM 为什么重缩放、决策树为什么不用缩放、KNN 为什么训练阶段什么事都不干。你只要把五个基础模型的“性格”摸清楚,后面学随机森林、XGBoost、神经网络都会顺很多,因为那些高级模型无非是在这几个基础思路上做了叠加和扩展。所以如果你耐心看完这篇、也把红酒数据集和收入预测的代码亲手跑通,恭喜你已经入门了,接下来就是拿真实数据多看多做,踩坑多了,经验就长在自己身上了。