17.AI大模型开发:机器学习--线性回归

开场白:今天咱们是"游戏数据分析师"

假设你现在是王者荣耀/英雄联盟的数据分析师。你发现,对局结束时的"总金币数" 是衡量玩家发育好坏的关键指标。

你想用机器学习预测:在游戏10分钟时,根据当前数据,最终全场能打多少钱?

影响金币的因素很多:击杀数、助攻数、补刀数、推塔数、甚至是游戏时长。

我们的任务:教机器从这些乱糟糟的数据中,找出一个万能公式!


第一部分:先搞定"机器学习世界观"(补全概述)

1. AI、ML、DL 是啥关系?(套娃理论)

  • AI(人工智能):终极目标。比如"让电脑像人一样会打游戏"。

  • ML(机器学习) :实现AI的一条路。让电脑自己看录像总结规律 ,而不是程序员写死代码 if 血量<10: 回城

  • DL(深度学习):ML里最火的一招。模仿人脑多层神经元,专门用来处理图像、语音这种超级复杂的数据(比如AI看小地图就知道对面打野在哪)。

2. 两种学习方式:告别"死记硬背"

  • 基于规则的学习(传统) :你写代码 if 补刀数 > 100: 判定为大神。这太死板了,万一对手疯狂针对,补刀少但人头多呢?

  • 基于模型的学习(ML) :你把成千上万局的数据(补刀、击杀、助攻、金币)扔给机器,它自己摸索出:"哦,一个人头大概值300块,一个补刀值20块"。这才是机器学习!

3. 核心黑话:样本、特征、标签(必须刻在脑子里)

我们造一张表,记录了游戏10分钟时的数据:

局号 游戏时长(分) 击杀数 死亡数 补刀数 最终总金币(标签y)
1 10 2 1 85 8500
2 15 5 3 120 12000
3 8 0 0 60 6000
  • 样本(Sample) :表中的一行数据(比如局号1)。这就是一个样本。

  • 特征(Feature / X) :表中的每一列(除最后一列) 。这里特征是:时长、击杀、死亡、补刀。记住:特征必须是数字!

  • 标签(Label / y) :我们想预测的那一列,这里是最终总金币

4. 训练集 vs 测试集(模拟考试)

不能把所有局的数据都拿来学,否则考试就没卷子了。

  • 8:2 分。80%的数据(训练集)给机器当课本学,20%(测试集)当考卷,检验它学没学明白。

  • 划重点测试集绝对不能参与训练! 否则就是作弊。

5. 机器学习四大门派(算法分类)

门派 核心特点 游戏案例
有监督学习 有标准答案(有标签y)。机器对着答案学。 预测金币(回归)、判断红蓝方胜负(分类)。
无监督学习 没答案(无标签)。让机器自己找规律。 把玩家自动分成"大神组"、"萌新组"、"人机组"(聚类)。
半监督学习 少量数据有标签,大量没有。 标注100张英雄头像让AI认,剩下9900张让AI自己猜,猜不准的再问人。
强化学习 只有奖惩机制。不断试错拿高分。 AI打王者,推塔给+10分,死了给-5分,靠这个自己练成了绝世高手。

6. 建模标准流程(6步走)

  1. 获取数据:从服务器拉取1万局游戏对局数据。

  2. 数据基本处理:把"异常数据"扔掉(比如一场比赛打了500分钟,这明显是挂机数据)。

  3. 特征工程(最耗头发的一步):把"红/蓝方"转成0/1,把"补刀数"和"击杀数"相乘得到新特征"经济转化率"。

  4. 模型训练:选个算法(比如线性回归),算出公式。

  5. 模型评估:拿测试集考一下,看看误差大不大。

  6. 上线服务:模型放服务器上,实时预测玩家10分钟后的经济走势。

7. 特征工程里面到底有啥?

  • 特征提取:把"玩家ID"这种文字,转换成向量数字。

  • 特征预处理 :击杀数是0~20,补刀数是0~200,数值范围差10倍!不做处理,算法会以为"补刀比击杀重要10倍"。我们必须做标准化(StandardScaler),把所有的特征压到同一个尺度(均值为0,方差为1)。

  • 特征降维:有100个特征算着太卡,压缩成10个新特征(信息有轻微损失,但速度起飞)。

  • 特征选择:发现"玩家今天穿什么颜色袜子"跟金币毫无关系,直接扔掉(数据不变,只砍列)。

  • 特征组合 :创造新特征 KDA = (击杀+助攻)/死亡,这往往比单独的击杀数更有预测力!

8. 救命!模型"翻车"了(拟合问题)

  • 欠拟合(太蠢了):训练集上误差就很大。

    • 原因:模型太简单。比如只用"游戏时长"预测金币。

    • 抢救:加特征!把击杀、补刀都加进去。

  • 过拟合(太精了):训练集误差0,测试集误差爆表。模型把"噪声数据"都背下来了。

    • 原因:模型太复杂,数据量太少。

    • 抢救加大数据量使用正则化(L1/L2)

  • 泛化 :模型在新数据(测试集) 上的表现。我们调参的一切目的,都是为了提高泛化能力

  • 奥卡姆剃刀 :如果两个模型效果差不多,选更简单的那个(简单即美)。


第二部分:重头戏!线性回归(找到那条"命运之线")

1. 什么是线性回归?(直觉理解)

我们假设"最终金币(y)"和"击杀数(x1)"、"补刀数(x2)"是线性关系(就是一次方的关系)。

数学公式长这样:

y = w1·x1 + w2·x2 + b

  • x:特征(输入)。

  • w(权重/系数) :这个特征每增加1个单位,y变化多少。比如 w1 = 300,代表多拿1个人头,金币多涨300。

  • b(偏置/截距):基础工资,哪怕你啥都不干,系统给的基础金币。

如果是只有一个特征,那就是一元线性回归(一条直线);如果有好几个特征,就是多元线性回归(一个超平面)。

2. 机器怎么判断这条线"好不好"?(损失函数 Loss)

机器得有个算账的尺子。我们预测的 y_pred 和真实的 y 肯定有差距。

最常用的尺子是 MSE(均方误差)

公式:

J(w)=m1​i=1∑m​(ypred(i)​−ytrue(i)​)2

  • m 是样本数量。

  • 为什么要平方?因为误差有正有负,平方可以防止正负抵消,而且能让大误差受到更严厉的惩罚

我们的目标 :调整 w 和 b,让这个 J(w) 越小越好

3. 怎么求这个"最小值"?(两条殊途同归的路)

方法A:正规方程(一步到位法)

直接对损失函数求导(求偏导),令导数等于0,直接算出最优解。

  • 优点:不需要循环,一步算出结果。

  • 缺点:如果特征数量巨大(比如上万),计算那个巨大的逆矩阵会把电脑算冒烟。

方法B:梯度下降(蒙眼下山法)【深度学习全靠它】

想象你蒙着眼站在山顶(损失函数最高点),你要下到山脚(最低点)。

  1. 你用脚探一下四周,哪个方向最陡(计算梯度)。

  2. 你朝着最陡的反方向 迈一步(因为要下山,所以是负梯度方向)。

  3. 反复循环,直到走到平地。

梯度下降更新公式(核心中的核心):

wj​:=wj​−α∂wj​∂​J(w)

  • α 是学习率(步长)

    • 太小:像蜗牛爬,死活到不了山脚(收敛极慢)。

    • 太大:像跳崖,一步跨过头,直接震荡发散(永远不收敛)。

梯度下降的三种"干饭"姿势

  • 全梯度下降(Batch GD) :看全部数据才迈一步。太慢了,数据量大直接卡死。

  • 随机梯度下降(SGD) :看1个数据就迈一步。快是快,但路径跟喝醉了一样晃荡。

  • 小批量梯度下降(Mini-batch GD) :看一小批(比如32个) 数据迈一步。工程界最常用!又快又稳!

4. 考试打分:怎么评价模型?(回归指标)

预测完了,怎么打分数?

指标 公式 大白话 特点
MAE MAE=n1​i=1∑n​∣yi​−y^​i​∣ 平均算下来,每局差了多少金币。 反应最真实的平均误差。
MSE MSE=n1​i=1∑n​(yi​−y^​i​)2 误差的平方再平均。 对离群点(异常值)极其敏感。偶尔一局炸了,MSE会崩。
RMSE RMSE=MSE​=n1​i=1∑n​(yi​−y^​i​)2​ 把MSE开根号。 让误差单位回到"金币",方便和真实值对比。

实战建议 :如果数据里有极个别"挂机送人头"的异常局,多看看MAE ;如果数据质量很高,用RMSE能帮你揪出细小的偏差。

5. 过拟合的克星------正则化(L1 vs L2)

如果发现模型过拟合了(训练集贼准,测试集贼烂),马上用正则化给模型戴上"紧箍咒"。

  • L1正则化(Lasso回归)------ 暴力裁员

    在损失函数后面加一项 λ∑∣wj​∣。

    效果:它看哪个特征不顺眼,直接把它的权重 w 锤成 0 !直接把这个特征砍掉,自带特征选择功能

  • L2正则化(岭回归 Ridge)------ 温柔降薪

    在损失函数后面加一项 λ∑wj2​。

    效果:它不砍人,但把所有人的工资(权重 w)都压得很小很小但不等于0。让模型整体变得平滑、抗干扰。

工程金句 :如果非要选一个,优先试L2(岭回归),因为它更稳定,不会因为误删有用特征而翻车。


第三部分:大口吃肉!全流程代码实战

场景 :我们模拟生成1000条《王者荣耀》10分钟时的数据,用 "击杀""补刀""推塔" 预测 "最终总金币"

1. 导入工具库 & 造数据

python 复制代码
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression, SGDRegressor, Ridge, Lasso
from sklearn.metrics import mean_squared_error, mean_absolute_error

# 设置随机种子,让你我跑出来的结果一模一样
np.random.seed(42)

# 模拟1000个样本
m = 1000
# 特征:击杀数(0~15),补刀数(10~200),推塔数(0~5)
kills = np.random.randint(0, 15, m)
cs = np.random.randint(10, 200, m)
towers = np.random.randint(0, 5, m)

# 真实公式(隐藏规律): 总金币 ≈ 300*击杀 + 15*补刀 + 500*推塔 + 5000基础 + 随机噪声
# 噪声让数据更真实,不至于完全拟合
gold = 300 * kills + 15 * cs + 500 * towers + 5000 + np.random.normal(0, 300, m)

# 组装成DataFrame
data = pd.DataFrame({
    '击杀': kills,
    '补刀': cs,
    '推塔': towers,
    '总金币': gold
})
print(data.head())

2. 切分数据 & 标准化(必做动作!)

python 复制代码
# X是特征,y是标签
X = data[['击杀', '补刀', '推塔']]
y = data['总金币']

# 1. 分割数据集 (训练集70%,测试集30%)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# 2. 标准化 (目的是让 击杀(0-15) 和 补刀(10-200) 处于同一量纲,梯度下降才跑得顺)
scaler = StandardScaler()
# 注意:用训练集的均值和方差去拟合,然后转换训练集和测试集
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)  # 测试集只用 transform,不用 fit!

3. 模型训练大乱斗(正规方程 VS 梯度下降 VS 正则化)

python 复制代码
# ----- A. 正规方程法 (LinearRegression) -----
lr_model = LinearRegression()
lr_model.fit(X_train_scaled, y_train)
y_pred_lr = lr_model.predict(X_test_scaled)

# ----- B. 随机梯度下降法 (SGDRegressor) -----
sgd_model = SGDRegressor(max_iter=1000, learning_rate='constant', eta0=0.01, random_state=42)
sgd_model.fit(X_train_scaled, y_train)
y_pred_sgd = sgd_model.predict(X_test_scaled)

# ----- C. L2正则化(岭回归 Ridge) 用来防止过拟合 -----
ridge_model = Ridge(alpha=1.0)  # alpha就是惩罚系数λ,越大惩罚越狠
ridge_model.fit(X_train_scaled, y_train)
y_pred_ridge = ridge_model.predict(X_test_scaled)

# ----- D. L1正则化(Lasso回归) 自带特征选择 -----
lasso_model = Lasso(alpha=0.1)
lasso_model.fit(X_train_scaled, y_train)
y_pred_lasso = lasso_model.predict(X_test_scaled)

4. 打印成绩单(评估与参数解读)

python 复制代码
print("="*50)
print("【模型性能对比 (MSE 越小越好)】")
print(f"正规方程 - 测试集MSE: {mean_squared_error(y_test, y_pred_lr):.2f}")
print(f"梯度下降 - 测试集MSE: {mean_squared_error(y_test, y_pred_sgd):.2f}")
print(f"岭回归L2 - 测试集MSE: {mean_squared_error(y_test, y_pred_ridge):.2f}")
print(f"Lasso回归 - 测试集MSE: {mean_squared_error(y_test, y_pred_lasso):.2f}")

print("\n【平均绝对误差 MAE】")
print(f"正规方程平均差了: {mean_absolute_error(y_test, y_pred_lr):.2f} 金币")

print("\n【模型的隐藏公式被挖出来了!】")
print(f"正规方程学到的权重 (w): {lr_model.coef_}")
print(f"正规方程学到的截距 (b): {lr_model.intercept_:.2f}")

print("\n【L1正则化(Lasso)的"裁员"效果】")
print(f"Lasso学到的权重 (很多被压成0了): {lasso_model.coef_}")

运行结果解读

  • 你会看到正规方程和梯度下降的MSE几乎一样,证明殊途同归。

  • 岭回归的MSE稍微大一点点(为了泛化牺牲了一点精度),但抗干扰能力更强。

  • Lasso回归的权重里,如果某个特征(比如推塔)权重变成了0,说明在Lasso眼里,这特征重要性不够,可以直接扔掉。

5. 可视化:看看预测值和真实值差多远

python 复制代码
# 取前50个测试样本画图
plt.figure(figsize=(10, 6))
plt.scatter(y_test[:50], y_pred_lr[:50], color='blue', label='预测值')
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'r--', linewidth=2, label='完美对角线 (预测=真实)')
plt.xlabel('真实总金币')
plt.ylabel('预测总金币')
plt.title('线性回归预测效果图 (点越贴紧红线说明越准)')
plt.legend()
plt.grid(True)
plt.show()

如果蓝点都密密麻麻贴在红虚线附近,说明你的模型修炼成功了!


总结:

  1. 机器学习世界观:记住有标签是监督,没标签是无监督;特征工程比调参重要一万倍;过拟合就上正则化。

  2. 线性回归本质 :就是求y=WX+b,通过损失函数(MSE) 算账,通过梯度下降找最低点(最优化)。

  3. 工具箱清单

    • 特征尺度不一?用 StandardScaler

    • 想一步到位?用 LinearRegression

    • 数据量大用梯度下降?用 SGDRegressor

    • 发现过拟合了?用 Ridge(L2)或 Lasso(L1)!