机器学习分类作业:KNN、决策树、随机森林与逻辑回归对比

分类器对比实验的六个评估维度

机器学习作业代写 里,分类器对比是最常见的题型,也是最容易只拿到及格分的题型——因为多数人把四个模型跑一遍、贴一张准确率表就交了,而评分重心在「为什么这个模型在这个数据上更好」以及「评估指标选得对不对」。

分类器对比实验的六个评估维度

评估指标:准确率为什么常常不够

准确率在类别不均衡时会严重高估模型性能——当负类占 95% 时,一个「永远预测负类」的模型准确率就有 95%。

from sklearn.metrics import (accuracy_score, precision_score, recall_score,
                             f1_score, roc_auc_score, confusion_matrix)

y_pred = model.predict(X_test)
y_prob = model.predict_proba(X_test)[:, 1]

print('准确率 :', accuracy_score(y_test, y_pred))
print('精确率 :', precision_score(y_test, y_pred, zero_division=0))
print('召回率 :', recall_score(y_test, y_pred, zero_division=0))
print('F1     :', f1_score(y_test, y_pred, zero_division=0))
print('AUC    :', roc_auc_score(y_test, y_prob))
print('混淆矩阵:n', confusion_matrix(y_test, y_pred))

四个指标各自的含义要说清:

  • 精确率(Precision):预测为正的样本里,真正为正的比例。关心「误报代价」时用它——把正常邮件判成垃圾邮件。
  • 召回率(Recall):真正为正的样本里,被找出来的比例。关心「漏报代价」时用它——把生病判成健康。
  • F1:两者的调和平均,适用于两者都重要且类别不均衡的场景。
  • AUC:与阈值无关的排序能力,反映「正样本得分高于负样本的概率」。

报告里必须说明「为什么选这个指标」,而不是全列一遍。如果业务场景是「筛查」(宁可多报不可漏报),主指标应是召回率;如果是「拦截」(误报会伤害用户),主指标应是精确率。

四个模型的核心差异

四个模型的本质区别在于「决策边界的形状」与「可解释性」——KNN 是局部投票、决策树是轴平行切分、随机森林是多树集成、逻辑回归是线性加权。

KNN(K 近邻)

from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler

# KNN 对量纲极其敏感,必须先标准化
scaler = StandardScaler()
X_train_s = scaler.fit_transform(X_train)
X_test_s  = scaler.transform(X_test)     # 注意:只用训练集 fit

knn = KNeighborsClassifier(n_neighbors=5)
knn.fit(X_train_s, y_train)

特点:无需训练(惰性学习),但预测慢(要算到所有训练样本的距离);必须有标准化,否则量纲大的特征会主导距离;K 太小易过拟合,K 太大欠拟合。

决策树

from sklearn.tree import DecisionTreeClassifier, export_text

tree = DecisionTreeClassifier(max_depth=4, min_samples_leaf=10,
                              random_state=42)
tree.fit(X_train, y_train)
print(export_text(tree, feature_names=list(X.columns)))   # 可读的规则

特点:可解释性最强(能打印成 if-else 规则);不需要标准化;但单棵树方差大、易过拟合,必须限制深度或用剪枝。

随机森林

from sklearn.ensemble import RandomForestClassifier

rf = RandomForestClassifier(n_estimators=300, max_depth=None,
                            min_samples_leaf=2, n_jobs=-1, random_state=42)
rf.fit(X_train, y_train)

# 特征重要性
for name, imp in sorted(zip(X.columns, rf.feature_importances_),
                        key=lambda x: -x[1])[:10]:
    print(f'{name:24s} {imp:.3f}')

特点:通过「自助采样 + 随机特征子集」降低方差,通常开箱即用表现最好;不需要标准化;但可解释性比单棵树弱很多(特征重要性不等于因果,且对相关特征会互相稀释)。

逻辑回归

from sklearn.linear_model import LogisticRegression

lr = LogisticRegression(max_iter=1000, class_weight='balanced')
lr.fit(X_train_s, y_train)     # 同样建议标准化,便于系数比较

# 系数方向可直接解释
for name, coef in sorted(zip(X.columns, lr.coef_[0]), key=lambda x: -abs(x[1]))[:10]:
    print(f'{name:24s} {coef:+.3f}')

特点:系数可直接解释为「该特征每增加一个单位,对数几率变化多少」;训练快;但只能拟合线性边界,需要人工构造交互项才能捕捉非线性。

交叉验证:单次划分不可信

单次训练/测试划分的结果受随机种子影响很大,K 折交叉验证通过多次划分给出均值和方差,才谈得上「模型 A 优于模型 B」。

from sklearn.model_selection import StratifiedKFold, cross_val_score

cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
for name, model in [('KNN', knn), ('Tree', tree), ('RF', rf), ('LR', lr)]:
    scores = cross_val_score(model, X_train_s, y_train, cv=cv,
                             scoring='roc_auc')
    print(f'{name:6s} AUC = {scores.mean():.4f} ± {scores.std():.4f}')

必须用分层(Stratified)而非普通 K 折——分层保证每折的正负比例与整体一致,类别不均衡时尤其重要。报告里要报「均值 ± 标准差」,只报均值无法判断差异是否显著。

超参数调优:别在测试集上调

from sklearn.model_selection import GridSearchCV

param_grid = {'n_neighbors': [3, 5, 7, 11, 15]}
gs = GridSearchCV(KNeighborsClassifier(), param_grid, cv=cv,
                  scoring='f1', n_jobs=-1)
gs.fit(X_train_s, y_train)
print('最优 K:', gs.best_params_, ' 交叉验证 F1:', gs.best_score_)

调参必须在训练集内部做(用交叉验证),测试集只在最后评估一次。如果用测试集选超参数,报告的指标会虚高,属于方法性错误。

偏差与公平性:报告里该有的一节

模型整体指标好,不代表对每个子群体都好——分组评估是发现系统性偏差的必要步骤。

# 按受保护属性分组,比较各组的召回率
for group in df_test['group'].unique():
    mask = df_test['group'] == group
    r = recall_score(y_test[mask], y_pred[mask], zero_division=0)
    print(f'{group:12s} 样本数={mask.sum():5d}  召回率={r:.3f}')

如果某组召回率显著低于其它组,说明模型对该群体系统性失效。报告里应该讨论三点:差异有多大、可能的原因(训练样本不足?特征本身有偏?)、以及缓解方向(重采样、去掉受保护属性、分组阈值)。

常见扣分点

  • 只报准确率,类别不均衡时不报精确率/召回率/AUC。
  • KNN 或逻辑回归没做标准化(或先标准化再划分,造成数据泄漏)。
  • 用测试集调超参数。
  • 只做单次划分,没有交叉验证或没有报标准差。
  • 交叉验证用普通 K 折而非分层。
  • 混淆矩阵只贴图不解读(哪些类互相混淆、为什么)。
  • 把特征重要性解释为因果关系。
  • 缺少分组公平性讨论。
  • 决策树不限制深度,训练集 100% 测试集很差却不分析。

常见问题

四个模型里应该选哪个?

看数据规模和可解释性要求。小数据、需要解释给非技术受众 → 逻辑回归或浅层决策树;中等数据、追求准确率 → 随机森林;样本量很大且特征维度高 → KNN 会变慢,不合适。报告里应该给出选择理由,而不是「随机森林最好所以选它」。

标准化应该在哪一步做?

用训练集 fit,用同一个 scaler 去 transform 测试集。如果先对全量数据标准化再划分,测试集的均值方差信息就泄漏进了训练过程,评估结果虚高。这个错误很常见,作业里会被专门检查。

AUC 0.85 算好吗?

取决于领域。信用评分、欺诈检测里 0.85 已经不错;医学影像里 0.85 可能偏低。判断标准是与基线对比:随机猜测是 0.5,简单规则(比如只用最相关的一个特征)能到多少?报告里给出基线才有参照。

类别不均衡怎么处理?

三条路径:重采样(对少数类过采样 SMOTE,或对多数类欠采样)、类别权重(class_weight='balanced')、调整判定阈值(不用 0.5,按业务需求选)。重采样只能在训练集内做,在划分前做会污染测试集。

特征重要性可以说明因果吗?

不能。特征重要性只反映「这个特征对预测有用」,可能因为它与真实原因相关(混淆变量),也可能因为模型利用了数据中的偏差。要讨论因果需要实验设计或因果推断方法,不是分类模型的产出。

报告需要画决策边界吗?

如果特征只有两个维度,画决策边界非常直观,能一眼看出线性 vs 非线性的差异。高维数据可以先用 PCA 降到二维再画,但要注明「这是投影,可能失真」。这项不是必需,但做了是加分点。

代写Pro 的机器学习作业服务

  • 指标选得对:按业务场景说明主指标选择理由,不只报准确率。
  • 流程无泄漏:标准化、重采样、调参全部在训练集内完成。
  • 对比有统计意义:分层交叉验证,报均值 ± 标准差。
  • 解释到位:混淆矩阵解读、特征重要性的正确表述、分组公平性讨论。
  • 可复现:固定随机种子,Notebook 含完整流程与依赖声明。

需要 机器学习作业代写 支持,可以联系我们,或查看 人工智能代写 与 数据分析作业代写 的服务范围。

相关案例与服务

需要有人帮你把这门作业做完?

把作业要求直接发过来,通常 10 分钟内回复给出报价与交付时间。不满意不接单。

每天 09:00 – 24:00(北京时间) | hecrereed@163.com

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

需要代写帮助?

通常 10 分钟内回复

邮箱 hecrereed@163.com 填写需求,免费报价 →
每天 09:00 – 24:00(北京时间)