适合人群:完全零基础的小白 阅读时间:约 30 分钟 核心目标:用最直白的语言,让你真正理解"机器怎么从数据中学习"
目录
- 什么是回归?先讲个故事
- 线性回归:用一条直线预测未来
- 损失函数:机器怎么知道自己猜得准不准?
- 梯度下降:机器学习的核心学习方法
- 实战:用线性回归预测房价
- 逻辑回归:从预测数字到预测类别
- Sigmoid 函数:把任何数字变成概率
- 决策边界:机器画的那条分界线
- 实战:用逻辑回归做垃圾邮件检测
- 多分类扩展:不止两个类别怎么办?
- 线性回归 vs 逻辑回归:一张表搞清区别
- 总结与下一步
1. 什么是回归?先讲个故事
想象你是一个卖西瓜的小贩。每天你都会记录:
- 今天的温度是多少度?
- 今天卖了多少个西瓜?
记录了一个月后,你发现:天越热,西瓜卖得越多。
现在天气预报说明天 35°C,你想猜一下明天能卖多少个西瓜——这就是回归。
回归 = 根据已有的数据,预测一个连续的数值
机器学习里的"回归"也是同样的道理,只不过让计算机来帮你做这个"猜测"的工作。
2. 线性回归:用一条直线预测未来
2.1 核心思想
线性回归的想法非常简单:找一条直线,尽可能穿过所有的数据点。
还是西瓜的例子。把温度放在横轴,销量放在纵轴,每一天的记录就是一个点:
销量(个)
|
40 | *
| *
30 | * *
| *
20 | * *
| *
10 | * *
| *
0 |_________________________ 温度(°C)
0 10 15 20 25 30 35
我们要做的就是画一条直线,让它尽可能"靠近"所有的点:
销量(个)
|
40 | * /
| * /
30 | * */
| * /
20 | * */
| * /
10 | * */
| * /
0 |__/______________________ 温度(°C)
0 10 15 20 25 30 35
这条斜线就是线性回归找到的"最佳直线"
2.2 数学表达(别怕,很简单)
这条直线的方程你在初中就学过:
y = kx + b
在机器学习里,我们换个写法(意思完全一样):
y = w * x + b
其中:
y = 预测值(比如西瓜销量)
x = 输入特征(比如温度)
w = 权重(weight),就是直线的斜率,表示 x 对 y 的影响有多大
b = 偏置(bias),就是直线的截距
举个例子:如果我们找到 w=1.2,b=-5,那么:
- 温度 30°C → 预测销量 = 1.2 × 30 + (-5) = 31 个
- 温度 35°C → 预测销量 = 1.2 × 35 + (-5) = 37 个
2.3 多个特征的情况
实际中,影响西瓜销量的不只是温度,可能还有:是不是周末?附近有没有活动?
y = w1 * x1 + w2 * x2 + w3 * x3 + b
比如:
y = 1.2 * 温度 + 5 * 是否周末 + 3 * 附近有活动 + (-10)
这就是多元线性回归,原理一模一样,只是从一条直线变成了一个"平面"(或者更高维度的"超平面")。
3. 损失函数:机器怎么知道自己猜得准不准?
3.1 什么是损失函数
机器要学习,首先得知道自己"学得好不好"。这就需要一个打分标准,在机器学习里叫做损失函数(Loss Function)。
损失函数 = 衡量"预测值"和"真实值"之间差距的一把尺子
差距越小,说明模型越好。
3.2 均方误差(MSE)
线性回归最常用的损失函数叫均方误差(Mean Squared Error,简称 MSE)。
翻译成大白话:
1. 对每个数据点,计算:预测值 - 真实值 = 误差
2. 把误差平方(这样负数也变正数了)
3. 把所有平方误差加起来
4. 除以数据点的个数,取平均
用数学公式写:
1 n
MSE = ──── × Σ (预测值ᵢ - 真实值ᵢ)²
n i=1
简化写法:
1 n
MSE = ──── × Σ (ŷᵢ - yᵢ)²
n i=1
为什么要平方? 两个原因:
- 预测多了(+5)和预测少了(-5)应该算一样的错误,平方后都是 25
- 平方后大的误差会被"放大",让模型更关注严重的错误
3.3 直观理解
销量
|
30 | * (真实值)
| |
| | ← 这个距离就是"误差"
| |
24 | ------●--------- (预测直线)
|
|________________________ 温度
MSE 就是所有这些"竖直距离"的平方的平均值
我们的目标:找到一组 w 和 b,让 MSE 尽可能小。
4. 梯度下降:机器学习的核心学习方法
4.1 爬山的比喻
想象你蒙着眼站在一座山上,你想走到山谷的最低点,但你看不见路。你会怎么做?
最聪明的办法:用脚感觉哪个方向是下坡,然后朝那个方向迈一步。 重复这个过程,你就会慢慢走到谷底。
这就是梯度下降(Gradient Descent)!
你在这里
↓
\ * /
\ /|\ /
\ / | \ /
\ | /
\ | /
\|/ ← 每一步都朝"最陡下坡方向"走
*
/|\
/ | \ ← 步子越来越小(因为越来越平了)
/ | \
______/ * \______ ← 到达谷底!(最优解)
纵轴 = 损失函数的值(MSE)
横轴 = 参数 w 的值
4.2 步骤详解
梯度下降的完整步骤:
第1步:随机初始化
给 w 和 b 随机赋一个值(比如 w=0, b=0)
第2步:计算损失
用当前的 w 和 b 计算预测值,然后算 MSE
第3步:计算梯度
梯度就是"当前位置的坡度"
- 梯度 > 0 → 说明往右是上坡,应该往左走(减小 w)
- 梯度 < 0 → 说明往右是下坡,应该往右走(增大 w)
第4步:更新参数
w_新 = w_旧 - 学习率 × 梯度
第5步:重复第2-4步
直到损失足够小,或者不再明显减小
4.3 学习率是什么?
学习率(Learning Rate)就是每一步迈多大:
学习率太大(步子太大): 学习率太小(步子太小):
\ /\ / \ /
\ / \ / \ /
\ / \/ ← 跳来跳去, \ /
X X 永远到不了谷底 \ /
/ \ /\ \ /
/ \ / \ \/
/ \/ \ *
终于到了...但好慢
学习率刚刚好:
\
\
\
\ ← 稳稳地走下去
\
\
* ← 很快就到了谷底!
通常学习率取 0.01 或 0.001 这样的小数。
4.4 梯度的数学推导(选看)
对于 MSE 损失函数:
∂MSE 2 n
────── = ──── × Σ (ŷᵢ - yᵢ) × xᵢ (对 w 求偏导)
∂w n i=1
∂MSE 2 n
────── = ──── × Σ (ŷᵢ - yᵢ) (对 b 求偏导)
∂b n i=1
看不懂也没关系,你只需要知道:梯度告诉我们参数应该往哪个方向调整、调整多少。
5. 实战:用线性回归预测房价
5.1 问题描述
假设我们有一组数据:房子的面积(平方米)和价格(万元)。
| 面积 (m²) | 价格 (万元) |
|---|---|
| 50 | 150 |
| 60 | 180 |
| 80 | 230 |
| 100 | 300 |
| 120 | 350 |
| 150 | 450 |
我们想根据面积预测价格。
5.2 Python 代码
import numpy as np
from sklearn.linear_model import LinearRegression
import matplotlib.pyplot as plt
# ========== 1. 准备数据 ==========
# 面积(单位:平方米)
X = np.array([50, 60, 80, 100, 120, 150]).reshape(-1, 1)
# 价格(单位:万元)
y = np.array([150, 180, 230, 300, 350, 450])
# ========== 2. 创建并训练模型 ==========
model = LinearRegression()
model.fit(X, y) # 一行代码完成训练!
# ========== 3. 查看模型学到了什么 ==========
print(f"斜率 w = {model.coef_[0]:.2f}")
print(f"截距 b = {model.intercept_:.2f}")
# 输出类似:斜率 w = 3.01, 截距 b = 1.36
# 意思是:价格 ≈ 3.01 × 面积 + 1.36
# ========== 4. 用模型进行预测 ==========
new_area = np.array([[90]]) # 预测 90 平方米的房子
predicted_price = model.predict(new_area)
print(f"90平米的房子预测价格:{predicted_price[0]:.1f} 万元")
# ========== 5. 可视化 ==========
plt.scatter(X, y, color='blue', label='真实数据')
plt.plot(X, model.predict(X), color='red', label='回归直线')
plt.xlabel('面积 (平方米)')
plt.ylabel('价格 (万元)')
plt.title('线性回归 - 房价预测')
plt.legend()
plt.show()
5.3 代码解读
整个过程可以总结为 4 步:
准备数据 训练模型 查看结果 做预测
┌─────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ X = 面积 │ --> │model.fit │ --> │ model. │ -->│ model. │
│ y = 价格 │ │ (X, y) │ │ coef_ │ │ predict │
└─────────┘ └──────────┘ │ intercept│ │ (新数据) │
└──────────┘ └──────────┘
5.4 评估模型好坏:R² 分数
from sklearn.metrics import r2_score
y_pred = model.predict(X)
r2 = r2_score(y, y_pred)
print(f"R² 分数 = {r2:.4f}")
# R² 接近 1 说明模型拟合得很好
# R² 接近 0 说明模型几乎没学到什么
R² 的直觉理解:R²=0.98 意味着模型能解释 98% 的数据变化,只有 2% 是它解释不了的。
6. 逻辑回归:从预测数字到预测类别
6.1 新的问题
到目前为止,线性回归帮我们预测的都是一个连续的数字(房价、销量)。
但生活中还有另一类问题:
- 这封邮件是不是垃圾邮件? → 是 / 不是
- 这个病人有没有糖尿病? → 有 / 没有
- 这张图片是猫还是狗? → 猫 / 狗
这些问题的答案不是一个数字,而是一个类别。这就是分类问题。
6.2 为什么不能直接用线性回归做分类?
假设我们用 0 表示"健康",1 表示"生病",然后用线性回归去拟合:
预测值
|
1.5| * (这是什么?1.5 不是 0 也不是 1!)
| /
1.0|---- - - - - - -*- - - - - - 生病的分界线
| / *
| /
0.5| /
| /*
0.0|--*------------ - - - - - - 健康的分界线
| / *
-0.5| * (这又是什么?-0.5?)
|________________________
某个指标
问题:线性回归的输出可以是任何数字(-∞ 到 +∞)
但我们只需要 0 或 1!
所以我们需要一种方法,把任意数字"压缩"到 0 和 1 之间——这就是 Sigmoid 函数的作用。
6.3 逻辑回归 = 线性回归 + Sigmoid
逻辑回归的两步走:
第 1 步(和线性回归一样): 第 2 步(新增的):
z = w * x + b P = Sigmoid(z) = 1 / (1 + e^(-z))
算出一个任意数字 z 把 z 变成 0~1 之间的概率 P
逻辑回归的输出是一个概率:比如 P=0.85 表示"有 85% 的可能性属于类别 1"
7. Sigmoid 函数:把任何数字变成概率
7.1 Sigmoid 的形状
Sigmoid 函数长这样——一条优美的 S 形曲线:
P(概率)
1.0 | ___________
| /
| /
0.8 | /
| /
| /
0.5 |- - - - - - -X- - - - - - - - - - - ← z=0 时,P=0.5
| /
| /
0.2 | /
| /
| /
0.0 |___/
|________________________________
-6 -4 -2 0 2 4 6 z
关键特点:
• z 很大 → P 接近 1(几乎确定是类别 1)
• z 很小 → P 接近 0(几乎确定是类别 0)
• z = 0 → P = 0.5(五五开,完全不确定)
7.2 Sigmoid 公式
1
Sigmoid(z) = ──────────
1 + e^(-z)
其中 e ≈ 2.718(自然常数,你不需要记住这个数字)
7.3 直觉理解
想象一个温度计:
确定是垃圾邮件 ← P=1.0
|
| 含有"中奖""免费""赶快点击"等词汇
|
大概率是垃圾邮件 ← P=0.8
|
|
不太确定 ← P=0.5 ← 分界线
|
|
大概率不是 ← P=0.2
|
| 正常的工作邮件
|
确定不是垃圾邮件 ← P=0.0
Sigmoid 函数就像这个温度计:不管输入的原始分数有多大或多小,它都能把结果"压"到 0 到 1 之间,变成一个概率。
7.4 逻辑回归的损失函数
线性回归用 MSE,但逻辑回归用的是交叉熵损失(Cross-Entropy Loss):
对于单个样本:
如果真实标签 y=1(比如确实是垃圾邮件):
Loss = -log(P)
→ P 越接近 1,Loss 越小(预测对了,损失小)
→ P 越接近 0,Loss 越大(明明是垃圾邮件,你说不是,惩罚大)
如果真实标签 y=0(比如不是垃圾邮件):
Loss = -log(1 - P)
→ P 越接近 0,Loss 越小(预测对了)
→ P 越接近 1,Loss 越大(预测错了,惩罚大)
合在一起写:
Loss = -[y × log(P) + (1-y) × log(1-P)]
不需要死记公式,只要记住核心思想:预测越自信且越错误,惩罚越大。
8. 决策边界:机器画的那条分界线
8.1 什么是决策边界
逻辑回归会在数据中间画一条"分界线",把两类数据分开:
特征2
|
| o o ← 类别 0(比如健康)
| o o
| o o \
| o \
| o o \
| *\* ← 类别 1(比如生病)
| * \*
| * \* *
| * * \ *
| * * \ *
| * * * \*
|____________________
特征1
那条斜线(\)就是"决策边界"
线左边 → 预测为类别 0
线右边 → 预测为类别 1
8.2 决策边界的数学含义
决策边界就是 P = 0.5 的那条线,也就是 z = 0 的地方:
w1 * x1 + w2 * x2 + b = 0
这就是一条直线方程!
在分界线上:模型说"我不确定,各 50%"
分界线一侧:P > 0.5 → 预测为类别 1
分界线另一侧:P < 0.5 → 预测为类别 0
8.3 决策边界的直觉
想象你是一个门卫,要判断来的人是不是本小区的住户:
打扮整洁度
|
| 住户 住户
| 住户 住户
| 住户 --------+------- ← 你心中的"分界线"
| 外人 外人
| 外人 外人
| 外人 外人
|________________________
熟悉程度
你根据"打扮整洁度"和"面熟程度"两个特征来做判断。
逻辑回归做的事情一模一样,只不过它的"分界线"是数学计算出来的。
9. 实战:用逻辑回归做垃圾邮件检测
9.1 问题描述
假设我们有一批邮件数据,对每封邮件统计了一些特征:
| 含"免费"次数 | 含"点击"次数 | 感叹号数量 | 是否垃圾邮件 |
|---|---|---|---|
| 0 | 0 | 1 | 0(不是) |
| 3 | 2 | 5 | 1(是) |
| 0 | 1 | 0 | 0(不是) |
| 5 | 4 | 8 | 1(是) |
| 1 | 0 | 2 | 0(不是) |
| 4 | 3 | 6 | 1(是) |
9.2 Python 代码
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, classification_report
# ========== 1. 准备数据 ==========
X = np.array([
[0, 0, 1], # 正常邮件
[3, 2, 5], # 垃圾邮件
[0, 1, 0], # 正常邮件
[5, 4, 8], # 垃圾邮件
[1, 0, 2], # 正常邮件
[4, 3, 6], # 垃圾邮件
[0, 0, 0], # 正常邮件
[6, 5, 9], # 垃圾邮件
[1, 1, 1], # 正常邮件
[3, 3, 7], # 垃圾邮件
])
y = np.array([0, 1, 0, 1, 0, 1, 0, 1, 0, 1])
# 0 = 正常邮件,1 = 垃圾邮件
# ========== 2. 划分训练集和测试集 ==========
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42
)
# ========== 3. 创建并训练逻辑回归模型 ==========
model = LogisticRegression()
model.fit(X_train, y_train)
# ========== 4. 进行预测 ==========
y_pred = model.predict(X_test)
# ========== 5. 查看预测概率 ==========
y_prob = model.predict_proba(X_test)
print("每封邮件的预测概率:")
print(" [正常邮件概率, 垃圾邮件概率]")
for i, prob in enumerate(y_prob):
print(f" 邮件{i+1}: [{prob[0]:.3f}, {prob[1]:.3f}] → 预测为 {'垃圾邮件' if y_pred[i]==1 else '正常邮件'}")
# ========== 6. 评估模型 ==========
accuracy = accuracy_score(y_test, y_pred)
print(f"\n模型准确率:{accuracy:.1%}")
print("\n详细评估报告:")
print(classification_report(y_test, y_pred,
target_names=['正常邮件', '垃圾邮件']))
9.3 预测新邮件
# 来了一封新邮件:含 4 个"免费",2 个"点击",7 个感叹号
new_email = np.array([[4, 2, 7]])
# 预测类别
prediction = model.predict(new_email)
print(f"预测结果:{'垃圾邮件 ⚠' if prediction[0]==1 else '正常邮件'}")
# 查看概率
prob = model.predict_proba(new_email)
print(f"是垃圾邮件的概率:{prob[0][1]:.1%}")
9.4 理解模型学到了什么
# 查看每个特征的权重
feature_names = ['含"免费"次数', '含"点击"次数', '感叹号数量']
for name, weight in zip(feature_names, model.coef_[0]):
print(f" {name}: 权重 = {weight:.3f}")
# 权重越大,说明该特征对"判断为垃圾邮件"的影响越大
理解权重的含义:
特征 权重 含义
────────────── ────── ────────────────────────────
含"免费"次数 +0.8 出现"免费"越多,越可能是垃圾邮件
含"点击"次数 +0.5 出现"点击"也是垃圾邮件的信号
感叹号数量 +0.3 感叹号多也有一定影响
如果权重为负数,说明这个特征反而降低了是垃圾邮件的概率
10. 多分类扩展:不止两个类别怎么办?
10.1 现实中的多分类问题
- 手写数字识别:0, 1, 2, ..., 9(10 个类别)
- 新闻分类:体育、科技、娱乐、财经(4 个类别)
- 图片分类:猫、狗、鸟、鱼(4 个类别)
逻辑回归本身是做二分类的(两个类别),但可以扩展为多分类。
10.2 策略一:One-vs-Rest(一对多)
假设要分 3 个类别:猫、狗、鸟
训练 3 个独立的逻辑回归模型:
模型1: 猫 vs 非猫 → P(猫) = 0.7
模型2: 狗 vs 非狗 → P(狗) = 0.2
模型3: 鸟 vs 非鸟 → P(鸟) = 0.1
最终选概率最高的:预测为 "猫"
图示:
┌──────────────┐
│ 模型1: 猫? │──→ P(猫) = 0.7 ← 最大!
└──────────────┘
┌──────────────┐
│ 模型2: 狗? │──→ P(狗) = 0.2
└──────────────┘ ↓
┌──────────────┐ 最终预测:猫
│ 模型3: 鸟? │──→ P(鸟) = 0.1
└──────────────┘
10.3 策略二:Softmax 回归
更优雅的方法是用 Softmax 函数,一次性输出所有类别的概率:
Softmax 的工作方式:
输入:z1=3.0, z2=1.0, z3=0.5 (三个类别的原始分数)
e^3.0
P(猫) = ──────────────── = 0.84
e^3.0 + e^1.0 + e^0.5
e^1.0
P(狗) = ──────────────── = 0.11
e^3.0 + e^1.0 + e^0.5
e^0.5
P(鸟) = ──────────────── = 0.05
e^3.0 + e^1.0 + e^0.5
注意:所有概率加起来 = 1.00(这很重要!)
10.4 Python 代码:多分类
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_iris
# 使用经典的鸢尾花数据集(3 种花)
iris = load_iris()
X = iris.data # 4 个特征:花萼长度、宽度,花瓣长度、宽度
y = iris.target # 3 个类别:0, 1, 2
# 训练多分类逻辑回归
model = LogisticRegression(max_iter=200)
model.fit(X, y)
# 预测新样本
new_flower = [[5.1, 3.5, 1.4, 0.2]]
prediction = model.predict(new_flower)
probabilities = model.predict_proba(new_flower)
print(f"预测类别:{iris.target_names[prediction[0]]}")
print(f"各类别概率:")
for name, prob in zip(iris.target_names, probabilities[0]):
print(f" {name}: {prob:.1%}")
输出类似:
预测类别:setosa
各类别概率:
setosa: 97.5%
versicolor: 2.4%
virginica: 0.1%
11. 线性回归 vs 逻辑回归:一张表搞清区别
┌────────────────┬────────────────────────┬────────────────────────┐
│ │ 线性回归 │ 逻辑回归 │
│ │ Linear Regression │ Logistic Regression │
├────────────────┼────────────────────────┼────────────────────────┤
│ 解决什么问题 │ 回归(预测数值) │ 分类(预测类别) │
├────────────────┼────────────────────────┼────────────────────────┤
│ 输出 │ 任意实数 │ 0~1 之间的概率 │
│ │ (-∞ ~ +∞) │ │
├────────────────┼────────────────────────┼────────────────────────┤
│ 激活函数 │ 无(直接输出) │ Sigmoid 函数 │
├────────────────┼────────────────────────┼────────────────────────┤
│ 损失函数 │ MSE(均方误差) │ 交叉熵(Cross-Entropy) │
├────────────────┼────────────────────────┼────────────────────────┤
│ 典型应用 │ 房价预测 │ 垃圾邮件检测 │
│ │ 销量预测 │ 疾病诊断 │
│ │ 温度预测 │ 客户流失预测 │
├────────────────┼────────────────────────┼────────────────────────┤
│ 评估指标 │ MSE、R² │ 准确率、精确率、召回率 │
├────────────────┼────────────────────────┼────────────────────────┤
│ 公式 │ y = w*x + b │ P = Sigmoid(w*x + b) │
└────────────────┴────────────────────────┴────────────────────────┘
12. 总结与下一步
12.1 本章知识地图
机器学习基础
│
├── 线性回归(预测数字)
│ ├── 原理:y = w*x + b
│ ├── 损失函数:MSE(均方误差)
│ ├── 优化方法:梯度下降
│ └── 应用:房价预测、销量预测
│
└── 逻辑回归(预测类别)
├── 原理:P = Sigmoid(w*x + b)
├── Sigmoid:把数字压缩到 0~1
├── 决策边界:P=0.5 的那条线
├── 损失函数:交叉熵
├── 二分类:是/否
└── 多分类:Softmax / One-vs-Rest
12.2 记住这些关键点
- 线性回归:找一条最佳直线来预测连续数值
- MSE:衡量预测值和真实值差距的"尺子"
- 梯度下降:像蒙眼下山一样,一步步找到最优解
- 逻辑回归:线性回归 + Sigmoid = 分类器
- Sigmoid:把任意数字变成 0~1 的概率
- 决策边界:概率 = 0.5 的地方,就是分界线
12.3 常见问题 FAQ
Q:逻辑回归明明是做分类的,为什么叫"回归"?
A:因为它的底层确实是做回归——回归出一个概率值,然后用这个概率来做分类。名字确实容易误导,但这是历史遗留问题。
Q:线性回归只能处理线性关系吗?
A:基础版本是的。但可以通过多项式特征(比如加入 x²、x³ 项)来处理非线性关系。这叫多项式回归。
Q:梯度下降一定能找到最优解吗?
A:对于线性回归——是的,因为 MSE 是一个"碗形"函数(凸函数),只有一个最低点。对于更复杂的模型则不一定。
Q:实际工作中,数据量要多大才够?
A:粗略的经验法则——样本数量至少是特征数量的 10 倍。比如你有 5 个特征,至少需要 50 条数据。当然,越多越好。
12.4 下一步学习建议
你现在在这里
↓
[线性回归 & 逻辑回归] → [决策树 & 随机森林] → [SVM 支持向量机]
↓
[特征工程与数据预处理] ← [模型评估与调参] ← [集成学习方法]
↓
[神经网络与深度学习]
12.5 动手练习建议
- 修改房价预测代码:加入更多特征(卧室数量、楼层),观察效果变化
- 用真实数据集练手:去 Kaggle 搜索 "house price prediction"
- 尝试调整学习率:用
SGDRegressor手动设置学习率,观察收敛速度 - 做一个自己的分类器:收集一些数据,用逻辑回归做分类
最后的最后:不要害怕数学公式。在这个阶段,你只需要理解公式背后的直觉。 随着你不断实践和学习,那些公式会自然而然地变得清晰起来。
记住:每一个机器学习大佬,都曾经是一个小白。
下一章预告:决策树与随机森林 —— 让机器像人类一样做判断