ARTICLE DETAIL

资讯详情

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

机器学习期末题库:sklearn 核心算法与评估调参

机器学习期末题库:sklearn 核心算法与评估调参 简介这份机器学习期末复习题及答案资料包面向正在备考机器学习课程的高校学生与自学者帮助梳理考试高频考点、检验掌握程度。压缩包内共1个docx文档约20KB以文字版试题与解析为主便于打印或导入电子笔记反复翻阅。内容按单项选择题、多项选择题、名词解释、简答题等题型组织覆盖数据集划分、欠拟合与过拟合、K近邻、朴素贝叶斯、支持向量机核函数、聚类算法、决策树、回归评估指标、神经网络等核心知识点并配有答案与简要解析。读者可借助它进行考前自测快速定位易错概念理解模型评估与算法选择的常见考法也可作为课堂复习提纲的补充。目前已有1764人学习下载适合希望在有限时间内系统回顾机器学习基础、查漏补缺的期末备考者。1. 从一份期末题库看机器学习知识骨架期末前一周手里的复习资料通常就是一份带字母答案的题库选择题、名词解释、简答题再加两道编程题。背答案很快真正卡人的是编程题里的那几行——导入哪个库、X 要不要 reshape 成二维、评估指标到底挑哪一只。这份题库的知识点覆盖其实相当完整数据集划分、欠拟合与过拟合、KNN、朴素贝叶斯、决策树、SVM 核函数、回归评估指标、数据清洗与聚类还有两道用 sklearn 落地的编程题。骨架不等于肌肉下面按「概念为什么成立—代码怎么跑通—参数怎么调—哪里容易翻车」的顺序把这些得分点拆成能复现的实验。准备期末的人可以跟着走一遍想把 sklearn 常用接口系统过一遍的工程师也能拿它当检查清单。2. 训练集划分、欠拟合与过拟合判别口径与 sklearn 落地2.1 留出测试集是为了估一次泛化误差题库第一题问数据集分成训练集和什么答案是测试集。这个答案背后的理由值得展开模型在训练集上的误差叫经验误差它随模型复杂度单调下降真正关心的是模型在没见过的数据上的误差也就是泛化误差。测试集的价值在于提供一次近似无偏的估计——如果拿训练集自己评估自己模型只要把样本记下来就能拿满分这种分数没有任何信息量。常见做法是 7:3 或 8:2 划分类别不平衡时加分层参数保持标签比例。sklearn 的 train_test_split 一次就能完成from sklearn.model_selection import train_test_split # X 是特征矩阵y 是标签 X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.3, # 测试集占比样本量几百到几千时 20%~30% 都合适 random_state42, # 固定随机种子保证每次划分一致便于复现实验 stratifyy # 分类任务按标签分层抽样避免某类在测试集里为空 ) print(X_train.shape, X_test.shape)四个关键参数的作用需要分清test_size 控制切分比例样本量小于 200 时一般留 20% 到 30%random_state 保证可复现写实验报告时必填stratify 只对分类任务有意义回归任务传进去会直接报错shuffle 默认开启处理时间序列时要手动置为 False否则未来数据会被切进训练集。提示划分出测试集之后调参、选特征、挑模型都不能再碰它否则测试集就退化成了第二个验证集最终报出的分数会系统性偏乐观。调参的活应该交给交叉验证。不同划分方式的取舍可以对照下表划分方式适用场景代价留出法 train_test_split样本量大、快速验证单次估计方差大K 折交叉验证调参、小样本训练 K 次耗时为 K 倍分层 K 折类别不平衡的分类任务同上TimeSeriesSplit时序预测不能随机打乱顺序2.2 欠拟合与过拟合两条误差曲线的间距题库里「解决欠拟合」的选项给了四个增加训练数据量、对模型裁剪、增加迭代次数、正则化。在梯度下降训练的模型上答案是增加迭代次数其余三项里模型裁剪和正则化都是压过拟合的手段而增加数据量对欠拟合帮助有限——欠拟合的根源是模型容量不足或训练不充分喂更多同分布的数据也学不会新形状。判别二者有个不用画图的土办法同时看训练误差和验证误差。训练误差高、验证误差也高是欠拟合训练误差极低、验证误差明显高出一截是过拟合。用 learning_curve 可以把这条趋势算出来import numpy as np from sklearn.model_selection import learning_curve from sklearn.tree import DecisionTreeClassifier estimator DecisionTreeClassifier(random_state42) train_sizes, train_scores, val_scores learning_curve( estimator, X, y, train_sizesnp.linspace(0.1, 1.0, 5), # 训练样本从 10% 到 100%取 5 档 cv5, # 5 折交叉验证比单次留出法稳定 scoringaccuracy # 回归任务换成 neg_mean_absolute_error ) print(train_scores.mean(axis1)) print(val_scores.mean(axis1))learning_curve 返回三个数组train_sizes 是实际使用的训练样本数train_scores 与 val_scores 每一行对应一种训练规模、每一列对应一折。沿 axis1 求均值得到该规模下的平均分。若两条曲线都停在 0.7 附近且间距很小说明模型欠拟合该加特征或提高复杂度若训练分逼近 1.0 而验证分停在 0.7间距明显说明过拟合该减深度、加正则项或补样本。2.3 数据清洗与预处理流水线题库把数据清洗概括为缺失值处理和离群值检查落到工程里还要加上编码和标准化。缺失值最常见的是中位数或均值填充、直接删除整行离群值可以用 IQR 法则标记也就是超出 Q1-1.5×IQR 与 Q31.5×IQR 之外的样本或者用 z-score 绝对值大于 3 判定。把这些步骤串进 Pipeline 的好处是交叉验证时每一折的填充和标准化都只用该折的训练部分拟合不会把验证集的信息漏进来。from sklearn.pipeline import Pipeline from sklearn.impute import SimpleImputer from sklearn.preprocessing import StandardScaler from sklearn.neighbors import KNeighborsClassifier pipe Pipeline([ (imputer, SimpleImputer(strategymedian)), # 中位数填充比均值抗离群值 (scaler, StandardScaler()), # 标准化为均值 0、方差 1 (knn, KNeighborsClassifier(n_neighbors3)) ]) pipe.fit(X_train, y_train) print(pipe.score(X_test, y_test))Pipeline 按列表顺序执行最后一项必须是实现了 fit 与 predict 的估计器。SimpleImputer 的 strategy 可取 mean、median、most_frequent、constantStandardScaler 是距离类算法KNN、SVM、K-Means的必需品树模型则完全不需要因为树只比较阈值大小单调变换不改变分裂点。3. KNN 与朴素贝叶斯距离度量、概率判定式与分类题复现3.1 KNN 的 k 值、距离度量与特征缩放KNN 属于有监督学习题库第三题考的就是这一点。它的训练阶段几乎不做事只把样本存下来全部计算发生在预测时对待分类样本算出它与所有训练样本的距离取最近的 k 个按多数投票决定类别。因为依赖标签所以是有监督因为没有显式学习参数业内常称之为懒惰学习。距离度量默认是欧氏距离n 维下写成 sqrt(Σ(xi-yi)²)metric 参数还支持 manhattan曼哈顿p1和通用的 minkowskip 取 2 就等价于欧氏。k 值越大决策边界越平滑越容易欠拟合k 取 1 时边界紧贴每个样本点一个噪声点就能改变预测结果。常见做法是从 3 起步在 3 到 15 之间用交叉验证扫一遍。注意KNN 对量纲极其敏感。一个取值范围 0~10000 的收入特征会完全压过取值范围 0~1 的年龄特征距离计算就失去意义。用 KNN 之前先标准化属于必须动作。3.2 编程题复现KNeighborsClassifier 完整流程题库给出的编程题数据是十个二维点加对应标签可以原样照抄import numpy as np from sklearn.neighbors import KNeighborsClassifier # 特征矩阵必须是二维每行一个样本每列一个特征 X [[3, 2], [3, 1], [1, 3], [3, 4], [2, 2], [7, 4], [5, 3], [9, 2], [7, 3], [7, 0]] y [0, 0, 0, 0, 0, 1, 1, 1, 1, 1] clf KNeighborsClassifier( n_neighbors3, # k 值取 3 对局部噪声有一定容忍度 metriceuclidean # 距离度量二维数据用默认欧氏即可 ) clf.fit(X, y) # 训练阶段KNN 这里只做数据存储 print(clf.predict([[4, 4]])) # 预测单个样本仍要写成二维形式 print(clf.predict_proba([[4, 4]])) # 各类的投票比例 print(clf.score(X, y)) # 训练集上的准确率fit 接收的特征必须是二维数组predict 也一样所以单个样本要包一层方括号写成[[4, 4]]。predict_proba 返回 k 个邻居里各类所占比例k3 时只会出现 0、1/3、2/3、1 这几种取值用它反过来验证 k 是否真的生效很快。以 k3 预测[4, 4]两个近邻落在左半区类别 0、一个落在右半区类别 1输出 0换成[6, 3]三个近邻全部来自右半区输出 1。具体数值随 sklearn 版本和距离实现细节略有差异以本机运行结果为准。3.3 朴素贝叶斯的判定公式与三种变体题库考的是判定式 H(x) argmax P(Ci)∏P(ak|Ci)它来自贝叶斯定理外加一个「朴素」假设各特征在给定类别下相互独立。于是后验概率正比于先验 P(Ci) 乘以各特征条件概率的连乘取连乘结果最大的类别作为输出。分母 P(x) 对所有类别相同比较时可以省掉。连乘在特征维度高时容易下溢成 0工程实现一般在 log 空间里做加法。另一个必备动作是拉普拉斯平滑某个特征值在某类别下从未出现时条件概率算出来是 0连乘会把整个类别的后验一刀抹平给分子加 1、分母加上该特征的可能取值个数就能避免这种情况。sklearn 里对应 MultinomialNB 的 alpha 参数默认取值 1.0。变体适用特征关键参数GaussianNB连续值近似正态分布var_smoothingMultinomialNB计数类特征如词频alpha平滑系数BernoulliNB二值特征是否出现alpha、binarizeComplementNB类别不平衡的文本任务alpha独立假设在真实数据里几乎不成立但朴素贝叶斯在文本分类上常年可用原因是分类只需要 argmax 找对位置不需要概率值本身准确。这也是它与 KNN 的共性都是简单到几乎不用调参、适合先跑起来当基线的方案。4. 决策树划分标准与 SVM 核函数ID3/C4.5/CART 与线性不可分4.1 三种划分标准信息增益、信息增益率、基尼指数题库有两处考决策树算法的种类与划分依据指向 ID3、C4.5、CART 三种原题中出现的 ID4 是笔误教材里没有这个算法。决策树的生长过程就是不断选一个特征做测试、把数据切成更纯的子集直到节点足够纯或触发停止条件三种算法差的正是「怎么衡量一次切分好不好」。ID3 用信息增益即切分前后熵的下降量gain H(D) - Σ(|Dv|/|D|)·H(Dv)。它的偏袒很明显——取值多的特征比如样本编号天然能把每个样本单独分出去增益接近最大但学出来的树毫无泛化能力。C4.5 用信息增益率把这个偏差除掉分母是特征自身的分裂信息代价是取值少的特征又可能被过度惩罚实践中一般先筛出增益高于平均的特征再挑增益率最高的。CART 用基尼指数衡量随机抽两个样本、类别不一致的概率计算只涉及平方没有对数速度更快同时生成二叉树也是 sklearn 唯一实现的方案。4.2 sklearn 决策树的 criterion 与剪枝参数DecisionTreeClassifier 只提供两种 criteriongini 和 entropy分别对应基尼指数与信息增益C4.5 的增益率并没有内置选项。想控制树的复杂度靠的是下面这些剪枝参数参数作用取值思路max_depth限制树的最大深度3~10 起步配合交叉验证定值min_samples_split节点分裂所需最小样本数默认 2调到样本量的 5%~10%min_samples_leaf叶节点最少样本数调大能平滑预测抑制噪声分支max_features每次分裂考虑的特征数高维数据调小可降低方差ccp_alpha代价复杂度后剪枝阈值从 0 逐步增大找验证误差最低点from sklearn.tree import DecisionTreeClassifier, export_text clf DecisionTreeClassifier( criteriongini, # 也可换 entropy小数据集上差别通常不大 max_depth4, # 预剪枝主力参数先卡深度再看效果 min_samples_leaf2, # 每个叶子至少 2 个样本避免为单点建分支 random_state42 ) clf.fit(X_train, y_train) print(clf.score(X_test, y_test)) print(export_text(clf, feature_names[f0, f1])) # 文本形式打印这棵树 print(clf.feature_importances_) # 各特征的重要性分数export_text 输出的每一行是一个判断条件缩进层级就是树深度排查「为什么这个样本被判成那类」时比看图快得多。feature_importances_ 基于不纯度下降加权求和所有特征加起来等于 1可用于初步特征筛选但它对高基数特征有偏好别当成因果结论。max_depth 和 min_samples_leaf 是最该先动的两个参数先卡深度再卡叶子样本量通常能同时把训练集上 100% 的准确率拉下来、把测试集上的准确率提上去。4.3 SVM 核函数与线性不可分的维度直觉题库里 SVM 核函数的答案是高斯核sklearn 中对应 kernelrbf参数里还留了 linear、poly、sigmoid 三种。线性不可分听起来抽象本质只有一句不存在一个线性分类器能把两类点完全分开。一维空间里这个分类器是一个点二维里是一条直线三维里是一个平面n 维里就是超平面。题库第二套简答题把这个维度递进讲得很清楚。遇到线性不可分有两条路一是软间隔放宽约束、允许少量样本越界对应参数 CC 越大对错分越不能容忍越容易过拟合二是核技巧把样本隐式映射到更高维空间在那里原本纠缠的两类点就分得开了而计算量仍停留在原空间的内积上这也是高斯核最常用的原因。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, # 核宽度scale 等价于 1/(n_features * X.var()) probabilityTrue) # 需要 predict_proba 时打开训练会更慢 ) model.fit(X_train, y_train) print(model.score(X_test, y_test))C 与 gamma 是 RBF 核上必须一起调的一对C 管「允许多少错」gamma 管「每个样本的影响半径」。gamma 太大单个样本的影响半径很小决策边界会绕成一个个孤立小岛gamma 太小边界几乎退化成直线模型欠拟合。常见做法是在 C 取 0.1、1、10 与 gamma 取 0.001、0.01、0.1 的网格上做交叉验证数据量大时再换成对数均匀采样。5. 回归模型与评估指标MAE、RMSE、R² 的选择和编程题复现5.1 四个评估指标各自回答什么问题题库里回归评估的选择题给了 RMSE、MSE、MAE、R² 四个选项答案指向 MAE另一处又考均方差对应 RMSE。这四个指标经常被混着用但它们回答的问题并不一样指标计算要点单位对离群值的敏感度MAEmean(abs(yi - ŷi))与 y 相同低MSEmean((yi - ŷi)²)y 的平方高RMSEsqrt(MSE)与 y 相同高R²1 - SS_res / SS_tot无量纲中MSE 因为平方项会放大误差对离群值极其敏感好处是处处可导适合作为损失函数RMSE 开根号后回到原量纲是「平均错了多少」最直观的表述但同样怕离群点MAE 是误差绝对值的平均解释成平均偏差最不容易被少量极端值带偏代价是在零点不可导。R² 表示模型解释了目标变量多少比例的方差越接近 1 越好但它会随样本量增大而虚高当模型比「直接预测均值」还差时可以为负。报告结果时至少给两个MAE 配 R² 是通用组合。5.2 简单线性回归编程题的分步复现题库给出的解题步骤是导入库函数、导入数据集、建模、拟合、预测、模型评价六步数据集为 X[1,2,3,4,5]、y[3,4,6,8,9]。注意题库里写的from sklearn.linearn_model import LinearRegression是拼写错误正确模块名是 linear_model考场上写错就是直接扣分。import numpy as np from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score # 1. 导入数据集sklearn 要求特征为二维一维列表必须 reshape(-1, 1) X np.array([1, 2, 3, 4, 5]).reshape(-1, 1) y np.array([3, 4, 6, 8, 9]) model LinearRegression() # 2. 模型实例化 model.fit(X, y) # 3. 拟合解出残差平方和最小的系数 print(model.coef_, model.intercept_) # 斜率与截距 y_pred model.predict(np.array([[6]])) # 4. 预测 x6 print(y_pred) # 5. 评价MAE 与 RMSE 回到原量纲R² 看解释力度 y_train_pred model.predict(X) print(MAE, mean_absolute_error(y, y_train_pred)) print(MSE, mean_squared_error(y, y_train_pred)) print(RMSE, np.sqrt(mean_squared_error(y, y_train_pred))) print(R2, r2_score(y, y_train_pred))fit 内部解的是最小二乘问题对这组数据得到斜率 1.6、截距 1.2即 y 1.6x 1.2预测 x6 得 10.8。训练集上的 MAE 约 0.24RMSE 约 0.283R² 约 0.985数量级对得上就说明代码没问题。reshape(-1, 1) 里的 -1 表示该维度由 numpy 自行推算、1 表示一列写成 reshape(5, 1) 结果相同但换数据集就要改数字所以 -1 更通用。coef_ 与 intercept_ 是拟合之后才存在的属性顺序反了会抛 AttributeError。5.3 多元线性回归与正则化回归的边界特征只有一个时叫简单线性回归多个特征时叫多元线性回归模型形式一样只是系数从标量变成向量写成 y ω0 ω1x1 ... ωnxn。LinearRegression 通过 fit_intercept 控制是否拟合截距项默认 True正常情况下不要关掉。特征之间高度相关时最小二乘的解会变得极不稳定系数绝对值大得离谱。题库提到的岭回归、最小绝对收缩与选择算子Lasso和弹性网络就是针对这个问题岭回归在损失里加 L2 惩罚把系数整体压小Lasso 加 L1 惩罚会把一部分系数直接压成 0顺带完成特征选择弹性网络同时叠加两种惩罚用 l1_ratio 控制配比。使用它们的前提是先标准化因为惩罚项作用在系数上量纲不同的特征受到的惩罚力度并不公平。另一个常见误用是拿 R² 去比较不同数据集上训练的模型R² 依赖 y 的方差跨数据集没有可比性。6. 用交叉验证扫参数把复习题变成可验证的实验6.1 从 k 值扫描看有监督学习的证据背下来的结论只有跑一遍才算真的记住。以 KNN 那道题为例选择题说它是有监督学习这个判断可以直接用交叉验证的分数走势验证把标签打乱后模型分数掉到随机水平说明它确实在利用标签信息。import numpy as np from sklearn.model_selection import cross_val_score, StratifiedKFold from sklearn.pipeline import make_pipeline from sklearn.preprocessing import StandardScaler from sklearn.neighbors import KNeighborsClassifier X np.array([[3,2],[3,1],[1,3],[3,4],[2,2], [7,4],[5,3],[9,2],[7,3],[7,0]]) y np.array([0,0,0,0,0,1,1,1,1,1]) cv StratifiedKFold(n_splits5, shuffleTrue, random_state42) for k in range(1, 10): pipe make_pipeline( StandardScaler(), # 缩放放进 Pipeline避免数据泄漏 KNeighborsClassifier(n_neighborsk) ) scores cross_val_score(pipe, X, y, cvcv, scoringaccuracy) print(fk{k:2d} mean{scores.mean():.3f} std{scores.std():.3f})cross_val_score 返回每一折的分数mean 是平均表现std 反映稳定性。k1 时训练集上永远满分交叉验证分数却会随折的划分剧烈波动std 明显偏大k 增大到 5 以上边界变平滑std 收窄但 mean 可能开始下滑两者权衡的那个位置就是这组数据的合理 k。这里样本只有 10 个结论本身的参考价值有限但这段循环的写法可以原样搬到任何数据集上。6.2 数据泄漏最常出现的两个位置第一个位置是先对全量数据做标准化再划分训练测试集。StandardScaler 拟合时会记录全量的均值和方差测试集的统计信息就这样渗进了训练过程交叉验证分数会虚高几个百分点。正确顺序永远是先 split缩放放在 Pipeline 内部完成上面的 k 值扫描就是按这个写法来的。第二个位置是用测试集反复试参数。调一次、看一次测试分、再调一次这个循环跑上十几轮测试集就等同于被训练过了。留出一个独立的验证集或者全程用交叉验证选参只在最后把测试集用一次报告出来才站得住。6.3 复现实验的三个固定动作固定 random_state。无论是 train_test_split、StratifiedKFold 还是模型内部的随机性都要给同一个种子否则两次运行的分数对不上你无法判断是参数起了作用还是运气好。记录版本与形状。sklearn 各版本对默认参数和收敛行为有调整实验记录里写下sklearn.__version__与 X.shape比单独记住一个分数有用得多。样本量小的数据集固定种子前后分数差 0.1 是常态别把这种波动当成调参收益。固定评估口径。改模型时 scoring 参数不要中途换分类用 accuracy 就一路用 accuracy要用 f1 就从头到尾用 f1指标一换前面几轮的对比全部作废。本文还有配套的精品资源点击获取
返回列表