第 05 章 你的第一行"AI"代码:拟合一条直线
系列:从 0 开始学 AI · 第 5 章 / 共 365 章 上一篇:第 04 章《机器学习、深度学习、大模型的关系》 阅读时长:约 12 分钟|含可运行代码
开场:先别装库,我们"徒手"让机器学会一条线
前几章你看到的代码都用了现成库(sklearn)。你可能会想:那不是我写的 AI,是库帮我写的。
这一章我们彻底"脱库":不用任何机器学习库,只用最朴素的 Python 加减乘除,让机器自己"学会"一条直线。
做完这一章,你会亲手看明白一件事:所谓"机器学习",底层其实就是一次次地"猜 → 错了 → 微调",直到猜得越来越准。这个理解,是你后面理解梯度下降、神经网络、大模型的共同地基。
概念讲解:机器"学会一条线"到底在做什么
问题先简化
假设有 3 个点,它们大致在一条直线上:
x(学习时长h): 1 2 3
y(成绩分): 55 70 85
肉眼可见:成绩 ≈ 15×学习时长 + 40。但机器不知道答案,它得自己找。
一条直线长什么样
一条直线有两个"旋钮"(参数):
ini
y = w × x + b
w:斜率(每多学 1 小时,成绩涨多少)b:截距(学 0 小时也有个底分)
机器学习的本质,就是"调 w 和 b"调到最佳。 一开始 w、b 是随便给的,然后不断根据"预测偏了多少"来微调。
怎么判断"猜得好不好":误差函数
给每个点算"预测值 vs 真实值"差多少,再取平均平方(叫 MSE 均方误差):
scss
误差 = 平均( (预测y - 真实y)² )
误差越小 = 直线越贴近数据 = 猜得越准。机器要做的,就是让这个误差不断变小。
怎么"微调":瞎试 + 朝对的方向走
最简单粗暴(也最直观)的方法是:两个方向都试一下,看误差往哪边变小,就往哪边走。 这就是"梯度下降"的雏形------下面代码里我们就把这件事做到。
最小可运行代码:徒手实现"拟合一条直线"
不用任何机器学习库,纯 Python 从零让机器学会那条线。
运行环境:Python 3.8+,只需 numpy(只用来算数,不涉及机器学习)
python
import numpy as np
# 数据:3 个点
x = np.array([1., 2., 3.])
y = np.array([55., 70., 85.])
# 1) 误差函数:衡量当前直线拟合得有多差
def 误差(w, b):
预测 = w * x + b
return np.mean((预测 - y) ** 2) # MSE 均方误差
# 2) "学会"的过程:不断微调 w 和 b,让误差变小
w, b = 0.0, 0.0 # 随便起步
学习率 = 0.01 # 每次微调的步长
for 步 in range(1, 2001):
# 分别算 w 和 b 各自"往大改/往小改"误差的变化方向(数值梯度)
dw = (误差(w+1e-6, b) - 误差(w-1e-6, b)) / (2e-6)
db = (误差(w, b+1e-6) - 误差(w, b-1e-6)) / (2e-6)
# 沿着让误差减小的方向微调
w -= 学习率 * dw
b -= 学习率 * db
if 步 in (1, 100, 1000, 2000):
print(f"第{步:>5}步:w={w:.3f} b={b:.3f} 误差={误差(w,b):.2f}")
print(f"\n机器自己学会的直线:y = {w:.2f} × x + {b:.2f}")
print(f"预测:学 4 小时 → 成绩约 {w*4+b:.0f} 分")
结果解读(看图说话)
ini
第 1步:w=0.158 b=0.462 误差=2966.71
第 100步:w=13.42 b=41.14 误差=0.24
第 1000步:w=15.00 b=40.00 误差=0.00
第 2000步:w=15.00 b=40.00 误差=0.00
机器自己学会的直线:y = 15.00 × x + 40.00
预测:学 4 小时 → 成绩约 100 分
看这条演化轨迹:
- 起步:w=0、b=0,误差 2966,完全乱猜。
- 第 100 步:w≈13.4、b≈41.1,误差已经缩到 0.24,很接近了。
- 第 1000 步:w=15、b=40,误差归零------机器自己找到了那条线。
我们没有告诉它答案是 15 和 40,它只是一次次"猜 → 算误差 → 微调",就自己学会了。这就是最纯粹的"机器学习"。
常见坑(这一章最容易出的问题)
| 报错 / 现象 | 原因 | 解决 |
|---|---|---|
数字变成 nan(无穷大) |
学习率 太大,一步迈过头 |
把学习率调小(如 0.001) |
| 学得很慢、几千步还没收敛 | 学习率 太小 |
适当调大(如 0.1) |
| 结果一直不对 | 起步值 / 数据尺度问题 | 把 w、b 初始为 0,数据先归一化 |
报 TypeError 加减法 |
数据不是数值型 | 确认 x、y 是 np.array 且为 float |
记住"学习率"这个旋钮:它太小学得慢、太大直接学飞(nan)。这个平衡贯穿整个系列,第 104 章我们会专门深讲。
动手练习(今天就能完成)
- 跑通上面代码 ,确认机器学出
y = 15x + 40。 - 改数据验证你真懂了 :把
y改成[50, 60, 70](斜率应为 10),看机器是否自己学出w=10。数据一变还能学对,才说明你真理解了"从数据学规律"。 - 故意"玩坏"它 :把
学习率改成0.5,看误差变nan------直观感受"一步迈太大"的后果,再改回来。
延伸思考(留给发散思维)
- 迁移到你的工作:任何"输入→输出"有规律的事都能用这套"猜→误差→微调"去做------比如"广告预算→点击量""接口延迟→是否超时"。先想到这种迁移,就是发散思维。
- 反事实提问 :如果只有 1 个点,机器能"学会"吗?能,但"唯一解"对吗?------这引出第 24 章"为什么必须分训练集/测试集"。
- 前瞻 :你刚用的是"数值梯度"(一点点试探),但这样很慢。后面第 32 章你会学到真正的梯度下降(直接算方向),更聪明。先记住"机器学习 = 调参数最小化误差"这个总纲。
下一篇预告
你亲手让机器"学会"了一条线------这已经是地地道道的机器学习。下一章(第 6 章《Python 环境搭建》),我们正式把开发环境配齐(Anaconda / pip / venv),让你电脑成为随时能跑 AI 代码的"实验室"。
明天见。
本文为《从 0 开始学 AI》第 05 章。已发布:第 01~04 章。欢迎收藏专栏。