监督学习
线性/逻辑回归、树、SVM。
40 分钟
监督学习
这一课你将能做到
- 用线性回归给题目估难度分,并解释每个系数的业务含义
- 用逻辑回归、决策树、随机森林预测用户是否掌握知识点,对比三者差异
- 说清随机森林(bagging)和 XGBoost(boosting)的原理区别,知道什么时候上哪个
为什么要学
监督学习是工业界用得最多的一类模型:你有「特征 + 答案」,让模型学出映射。本站两个核心场景全是监督学习——
- 回归:根据全站正确率、平均用时、平均尝试次数,给题目打一个 0-100 的难度分;
- 分类:根据用户的作答表现,预测「这个知识点掌握了没有」。
这一课一次过五个模型:线性回归 → 逻辑回归 → 决策树 → 随机森林 → XGBoost。它们不是并列的五个工具,而是一条「从简单到复杂、从可解释到高精度」的演进线,面试最爱沿这条线追问。
先建立图像
| 模型 | 一句话 | 强项 | 弱项 |
|---|---|---|---|
| 线性回归 | 加权求和拟合数值 | 可解释、快 | 只能学线性关系 |
| 逻辑回归 | 线性 + Sigmoid 出概率 | 概率输出、稳定 | 同上 |
| 决策树 | 一连串 if-else | 自动学交互、可读 | 深了就过拟合 |
| 随机森林 | 很多树投票(bagging) | 稳、准、几乎免调参 | 不如单树好解释 |
| XGBoost | 一棵接一棵纠错(boosting) | 表格数据精度天花板 | 超参数多、易过拟合 |
跟着做
步骤 1:造数据——题目难度(回归)
import numpy as np
from sklearn.model_selection import train_test_split
rng = np.random.default_rng(42)
n = 300
accuracy = rng.uniform(0.2, 0.95, n) # 全站正确率
avg_seconds = rng.uniform(30, 240, n) # 平均用时
avg_attempts = rng.uniform(1, 5, n) # 平均尝试次数
# 人为造一个「真实规律」+ 噪声:正确率高、用时短、尝试少 → 越简单(分数越低)
difficulty = 100 - 60*accuracy - 0.1*avg_seconds - 5*avg_attempts + rng.normal(0, 3, n)
X = np.column_stack([accuracy, avg_seconds, avg_attempts])
X_tr, X_te, y_tr, y_te = train_test_split(X, difficulty, test_size=0.2, random_state=42)
步骤 2:线性回归拟合并解释系数
from sklearn.linear_model import LinearRegression
reg = LinearRegression().fit(X_tr, y_tr)
print("R²:", reg.score(X_te, y_te).round(3)) # 通常 > 0.95
print("系数:", reg.coef_.round(2)) # ≈ [-60, -0.1, -5],和真实规律几乎一致
print("截距:", reg.intercept_.round(1)) # ≈ 100
系数读法:全站正确率每提高 0.1,难度分约降 6;平均用时每多 10 秒,难度分约降 1。模型把隐藏在数据里的规则「称」出来了——这是面试里「怎么给题目估难度」的完整答案雏形。
步骤 3:分类——预测用户是否掌握知识点
n = 600
X_user = np.column_stack([
rng.uniform(0, 1, n), # 个人正确率
rng.uniform(30, 240, n), # 平均用时
rng.uniform(1, 8, n), # 做题次数
])
mastery = ((X_user[:, 0] > 0.55) & (X_user[:, 2] > 3)).astype(int) # 造标签的「真实规则」
Xu_tr, Xu_te, yu_tr, yu_te = train_test_split(X_user, mastery, test_size=0.25,
random_state=42, stratify=mastery)