机器学习初探

从一个简单的问题开始

假设我们观察到这样一组数据:

xy
00
12
24
36
48

不难看出,x 和 y 的关系大概是 y = 2x。但如果是更复杂的数据,这个规律就不那么容易肉眼发现了。机器学习的本质,就是让程序自己从数据中找到这样的规律。

模型与参数

我们从一个最简单的模型开始:

y = w * x + b

其中:

  • w 是斜率,控制 x 对 y 的影响程度。
  • b 是偏置,让直线可以上下平移。

一开始我们不知道 wb 该取多少,可以随机给它们一个初始值,然后让程序自己不断调整。

成本函数:衡量预测的好坏

怎么知道当前的 wb 好不好?办法是拿预测值和真实值做比较。

对每个样本,误差可以这样计算:

d = (w * x + b) - y_true

把所有样本的误差平方后取平均,就得到了成本函数

cost(w, b) = (1 / n) * Σ(w * x_i + b - y_i)²

这个值越小,说明模型预测得越准。训练的目标,就是找到让 cost 最小的 wb

Tip:为什么叫成本函数? 可以把 cost 理解为“预测错误要付出的代价”。cost 为 0 表示完美预测,cost 越大表示错得越离谱。训练模型的过程,就是不断降低这个成本。

梯度下降:如何找到最优参数

现在问题变成了:怎么调整 wb,才能让 cost 不断下降?

我们需要知道 cost 对每个参数的变化率,也就是梯度。梯度指向 cost 增长最快的方向,所以我们沿着它的反方向走一小步。

更新公式是:

w = w - rate * ∂cost/∂w
b = b - rate * ∂cost/∂b

这里的 rate 就是学习率,控制每一步迈多大。

Tip:为什么叫梯度? 梯度的英文是 gradient,本意是“坡度”。在这个一维例子里,梯度就是斜率;参数更多时,梯度是一个向量,指向函数增长最快的方向。梯度下降,就是沿着最陡的下坡方向一步步往下走。

Tip:为什么需要学习率? 梯度只告诉你方向,没说可以走多远。步子太大可能直接跨过谷底,跑到对面更高的山坡上去,导致 cost 越来越大。学习率就是把步长限制在合理范围。

一段完整的 C 代码

#include <stdio.h>
#include <stdlib.h>

float train_set[][2] = {
    {0, 0},
    {1, 2},
    {2, 4},
    {3, 6},
    {4, 8}
};

float cost_function(float w, float b) {
    float result = 0.0;
    for (size_t i = 0; i < 5; i++) {
        float x = train_set[i][0];
        float y = train_set[i][1];
        float d = (w * x + b) - y;
        result += d * d;
    }
    return result / 5;
}

int main() {
    float w = 0.5;
    float b = 0.5;
    float rate = 1e-2;
    float eps = 1e-3;

    for (size_t i = 0; i < 1000; i++) {
        float dw = (cost_function(w + eps, b) - cost_function(w, b)) / eps;
        float db = (cost_function(w, b + eps) - cost_function(w, b)) / eps;

        w -= rate * dw;
        b -= rate * db;
    }

    printf("w = %f, b = %f\n", w, b);
    return 0;
}

运行后,程序会输出接近 w = 2, b = 0 的结果。

Tip:为什么要加偏置 b? 没有 b 时,模型 y = w * x 的直线必须过原点。但现实中很多数据并不过原点。加入 b 后,直线可以上下平移,模型能拟合更多情况。即使数据恰好过原点,b 也会学到接近 0 的值。

Tip:数值微分与解析梯度 上面的代码用 (cost(w + eps) - cost(w)) / eps 近似求导,这叫数值微分。它简单直观,但有微小误差。更精确的做法是直接推导出导数公式,称为解析梯度。对于复杂模型,解析梯度效率更高、更精确。

总结

这个小程序展示了机器学习的几个核心思想:

  • 模型:用 y = w * x + b 描述数据规律。
  • 成本函数:量化预测误差。
  • 梯度下降:沿着误差减小的方向调整参数。
  • 学习率:控制每次调整的幅度。
  • 偏置:增加模型的灵活性。

真实世界中的神经网络、深度学习,本质上也是这些思想的延伸:更复杂的模型、更多的参数、更高效的优化方法,但核心逻辑依然是从数据中不断学习,让成本越来越小。