吴恩达机器学习笔记-第一部分

前置知识

什么是机器学习

一句话解释:机器学习就是让计算机“像人一样”通过经验学习,不是我们手把手地教它每一步,而是让它自己从数据中总结规律。

监督学习(Supervised Learning)

定义

监督学习是指,我们在训练模型的时候,会告诉它“答案”是什么,模型通过这些已有的“题目+答案”来学习,以便将来遇到新题目时也能给出正确答案。

举例

想象你是一位老师,要教学生区分苹果🍎和橘子🍊。

你给学生看一堆水果,每个水果下面都写着标签:“这是苹果”或者“这是橘子”。

学生通过观察颜色、形状、大小等特征来学习,因为每个水果都有标签(答案),这就是“监督学习”。

在机器学习中:

输入(特征) 输出(标签)
颜色红、圆、较大 苹果 🍎
颜色橙、圆、较小 橘子 🍊

常见模型

回归(Regression)

回归模型的任务是“预测一个数值”,结果是连续的,不是分类的。

输入 回归模型预测的结果
房子的面积、位置、装修情况 预测房价是:152.3 万元
一辆车的品牌、年份、里程数 预测二手车价格:7.5 万元
一个城市的气温、湿度、风速 预测明天温度:28.4°C

分类(Classification)

分类模型的任务是“选分类”:告诉你某个东西属于哪一类。

输入 分类模型预测的结果
一封电子邮件的内容 “是垃圾邮件” or “不是垃圾邮件”
一张动物照片 “是猫” or “是狗”
一位学生的学习数据 “能及格” or “不及格”

应用实例

  • 垃圾邮件识别(输入:邮件内容,输出:垃圾/非垃圾)
  • 图像识别(输入:照片,输出:狗🐶/猫🐱/人)
  • 疾病预测(输入:检查数据,输出:是否患病)

无监督学习(Unsupervised Learning)

定义

无监督学习是指,我们在训练模型的时候,不给出答案,模型自己去观察、归类、找规律。

举例

你是一位老师,给学生一堆没写标签的水果,他们不知道哪些是苹果,哪些是橘子。

但学生发现:有些水果颜色偏红,有些偏橙;有些大有些小……于是学生把水果自己分成几类。

这就像是无监督学习:自己找规律分组。

在机器学习中:

输入(特征) 没有输出标签,模型自己分组
颜色红、圆、较大 第1类
颜色橙、圆、较小 第2类

应用实例

  • 客户分群(银行/电商将用户分成不同群体)
  • 数据降维(去除冗余信息)
  • 异常检测(比如检测工厂里的异常机器)

总结

对比点 监督学习 无监督学习
是否有“正确答案” ✅ 有(带标签) ❌ 没有(无标签)
目的 预测结果 找结构、找规律
示例 判断水果种类(苹果/橘子) 自己分水果群组
常见算法 线性回归、逻辑回归、决策树、SVM 聚类(K-means)、主成分分析(PCA)

监督学习-线性回归

什么是线性回归?

线性回归(Linear Regression) 是机器学习中最基础也是最重要的一种监督学习模型,用来预测一个连续的数值

比如:

  • 用房子的面积来预测房价。
  • 用广告费用来预测销售额。

举个例子:

假设你是一个房产中介,你发现房子的价格(单位:万元)和面积(单位:平方米)之间有规律:

面积(x) 价格(y)
50 150
60 180
70 210

你希望找到一个公式,像这样的:

$ y = wx + b $

让你输入一个面积,就能预测价格。这个公式就是线性回归要学的目标。

线性回归的基本公式

线性回归的目标是学到一个函数(即模型):

$ \hat{y} = wx + b $

解释一下:

  • x 是输入(如房子的面积)
  • ŷ(y-hat) 是模型预测的结果
  • w 是斜率(权重,表示每增加一单位x,y增加多少)
  • b 是截距(当x=0时,y的值)

最终目标:让预测值 尽可能接近真实值 y

代价函数

公式

\(J(w, b) = \frac{1}{2m} \sum_{i = 1}^{m} (\hat{y}^{(i)} - y^{(i)})^2 = \frac{1}{2m} \sum_{i = 1}^{m} (f_{w,b}(x^{(i)}) - y^{(i)})^2\)

直观理解

参数\(w\)(只有一个)不同时,代价函数\(J\)的变化:

参数为\(w\)(只有一个)和\(b\)(只有一个):

代码示例(使用 Python 和 scikit-learn)

from sklearn.linear_model import LinearRegression
import numpy as np
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号

# 生成随机数据
np.random.seed(0)
X = 2 * np.random.rand(100, 1)
y = 4 + 3 * X + np.random.randn(100, 1)

# 创建线性回归模型
model = LinearRegression()

# 拟合模型
model.fit(X, y)

# 打印系数和截距
print("斜率 (m):", model.coef_[0][0])
print("截距 (b):", model.intercept_[0])

# 预测新数据
X_new = np.array([[1.5]])
y_pred = model.predict(X_new)
print("预测结果:", y_pred[0][0])

# 绘制散点图和拟合的直线
plt.scatter(X, y, color='blue')
plt.plot(X, model.predict(X), color='red', linewidth=3)
plt.xlabel("自变量")
plt.ylabel("因变量")
plt.title("简单线性回归")
plt.show()

运行结果:

斜率 (m): 2.968467510701019
截距 (b): 4.222151077447231
预测结果: 8.67485234349876

梯度下降算法

含义

梯度下降就是一个找最优解的过程。它一步一步地调整参数,直到代价函数的值最小为止。

直观理解

想象你站在一座山上, 任务是走到山谷底部(最低点) :

  • 你的位置(坐标)是$ (w,b) $。
  • 你脚下的坡度(梯度)告诉你:往哪个方向走,能最快下山(最陡的方向)。
  • 梯度的值会随着你位置的变化而变化,所以每走一步都需要重新计算梯度,决定下一步往哪走。

这个“走下去”的过程就是梯度下降(Gradient Descent)

公式

  • \({tmp_w} = w - \alpha \frac{\partial}{\partial w} J(w, b)=w - \alpha \frac{1}{m}\sum_{i = 1}^{m}(f_{w,b}(x^{(i)}) - y^{(i)})x^{(i)}\)
  • \({tmp_b} = b - \alpha \frac{\partial}{\partial b} J(w, b)=b - \alpha \frac{1}{m}\sum_{i = 1}^{m}(f_{w,b}(x^{(i)}) - y^{(i)})\)
  • \(w= tmp_w\)
  • \(b=tmp_b\)

\(\frac{\partial}{\partial w} J(w, b)\)看成代价函数\(J\)的斜率。

例如,只有\(w\)一个参数:

\(\alpha\)是学习率(learning rate),用来控制每次梯度下降时“走多远”。太小走得太慢,太大会错过最低点,需要找到合适的值。

示例代码(Python + NumPy 实现)

import numpy as np
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号

# 模拟训练数据(例如房子的面积和价格)
X = np.array([1, 2, 3, 4, 5])      # 特征(面积)
y = np.array([2, 4, 6, 8, 10])     # 标签(价格)

# 初始化参数
w = 0.0  # 斜率
b = 0.0  # 截距

# 学习率和迭代次数
alpha = 0.01
epochs = 100

# 存储损失记录(用于画图)
losses = []

# 梯度下降
for i in range(epochs):
    # 预测值
    y_pred = w * X + b

    # 误差
    error = y_pred - y

    # 损失(均方误差)
    loss = np.mean(error ** 2)
    losses.append(loss)

    # 计算梯度
    dw = 2 * np.mean(error * X)
    db = 2 * np.mean(error)

    # 更新参数(就是你图中的公式)
    w = w - alpha * dw
    b = b - alpha * db

    # 每10轮打印一次信息
    if i % 10 == 0:
        print(f"第{i}轮:w = {w:.4f}, b = {b:.4f}, loss = {loss:.4f}")

# 最终结果
print("\n训练完成:")
print(f"最终参数:w = {w:.4f}, b = {b:.4f}")

# 可视化结果
plt.scatter(X, y, label='原始数据')
plt.plot(X, w * X + b, color='red', label='拟合直线')
plt.legend()
plt.xlabel('X')
plt.ylabel('y')
plt.title('线性回归拟合结果')
plt.show()

输出结果:

第0轮:w = 0.4400, b = 0.1200, loss = 44.0000
第10轮:w = 1.7674, b = 0.4693, loss = 0.2435
第20轮:w = 1.8609, b = 0.4774, loss = 0.0430
第30轮:w = 1.8713, b = 0.4631, loss = 0.0393
第40轮:w = 1.8759, b = 0.4478, loss = 0.0367
第50轮:w = 1.8801, b = 0.4329, loss = 0.0343
第60轮:w = 1.8841, b = 0.4185, loss = 0.0321
第70轮:w = 1.8880, b = 0.4045, loss = 0.0300
第80轮:w = 1.8917, b = 0.3911, loss = 0.0280
第90轮:w = 1.8953, b = 0.3780, loss = 0.0262

训练完成:
最终参数:w = 1.8984, b = 0.3667

多元线性回归(Multiple Linear Regression)

多元线性回归是线性回归的扩展,它可以处理多个输入特征(变量),而不是只有一个特征。

基本形式

\(f_{\vec{w},b}(\vec{x}) = w_1x_1 + w_2x_2 + \cdots + w_nx_n + b = \vec{w} \cdot\ \vec{x} + b\)

  • \(\vec{w} = (w_1,w_2, \dots ,w_n)\):输入的特征向量,比如房子的信息:面积、卧室数、楼层数、地段评分等。
  • \(\vec{x} = (x_1,x_2, \dots ,x_n)\):模型的参数(权重),每个特征对应一个权重。

python代码实现点乘

f = np.dot(w, x) + b

举例

假设我们要预测房价:

特征
房子面积(㎡) $ x_1 = 100 $
卧室数 $ x_2 = 3 $
距离市中心(km) $ x_3 = 8 $

模型参数是:

\(\vec{w} = [3000, 10000, -2000]\)\(\ b = 50000\)

那么预测房价为:

\(f(\vec{x}) = 3000 \cdot 100 + 10000 \cdot 3 + (-2000) \cdot 8 + 50000 = 300000 + 30000 - 16000 + 50000 = 364000\)

示例代码

import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression

plt.rcParams['font.sans-serif'] = ['SimHei']  # 正常显示中文
plt.rcParams['axes.unicode_minus'] = False    # 正常显示负号

# 原始数据:面积(m²)、卧室数、距离市中心(km)
X = np.array([
    [100, 3, 8],
    [120, 2, 5],
    [80,  4, 10],
    [150, 3, 7],
    [200, 5, 2]
])
y = np.array([300, 320, 260, 390, 500])  # 房价,单位万元

# ✅ 标准化特征(Z-score 标准化)
X_mean = np.mean(X, axis=0)
X_std = np.std(X, axis=0)
X_scaled = (X - X_mean) / X_std

# 初始化参数
m, n = X_scaled.shape
w = np.zeros(n)
b = 0.0

# 超参数
alpha = 0.01
epochs = 1000
loss_list = []

# ✅ 梯度下降训练
for epoch in range(epochs):
    y_pred = np.dot(X_scaled, w) + b
    error = y_pred - y
    loss = np.mean(error ** 2)
    loss_list.append(loss)

    # 计算梯度
    dw = (2/m) * np.dot(X_scaled.T, error)
    db = (2/m) * np.sum(error)

    # 更新参数
    w -= alpha * dw
    b -= alpha * db

    # 每 100 轮打印一次
    if epoch % 100 == 0:
        print(f"第 {epoch:>4} 轮: loss = {loss:.4f}, w = {w}, b = {b:.4f}")

print("\n✅ 模型训练完成!")
print(f"最终参数:w = {w}, b = {b:.4f}")

# ✅ 可视化 Loss 曲线
plt.plot(range(epochs), loss_list)
plt.xlabel("训练轮数")
plt.ylabel("Loss(均方误差)")
plt.title("训练损失下降曲线")
plt.grid(True)
plt.show()

# ✅ 预测函数
def predict(new_X):
    new_X_scaled = (new_X - X_mean) / X_std
    return np.dot(new_X_scaled, w) + b

# 示例预测
new_house = np.array([130, 3, 6])
predicted_price = predict(new_house)
print(f"🏠 对面积130平米、3个卧室、距离6公里的房子预测价格为:{predicted_price:.2f} 万元")

# ✅ 与 sklearn 对比
reg = LinearRegression()
reg.fit(X_scaled, y)
print("\n📘 sklearn 线性回归模型:")
print(f"权重 w = {reg.coef_}")
print(f"偏置 b = {reg.intercept_:.4f}")

运行结果:

第    0 轮: loss = 132420.0000, w = [ 1.67809416  0.90997887 -1.46353821], b = 7.0800
第  100 轮: loss = 2440.6073, w = [ 44.4786325   17.43832645 -30.28374442], b = 307.9916
第  200 轮: loss = 209.7314, w = [ 50.89536614  15.44639964 -25.89241122], b = 347.8984
第  300 轮: loss = 126.3587, w = [ 55.84166938  14.08348652 -21.56379231], b = 353.1908
第  400 轮: loss = 93.3602, w = [ 59.9963053   13.04402769 -17.84495093], b = 353.8927
第  500 轮: loss = 70.2485, w = [ 63.50374323  12.18926644 -14.68980171], b = 353.9858
第  600 轮: loss = 53.7416, w = [ 66.46773844  11.47167583 -12.02029357], b = 353.9981
第  700 轮: loss = 41.9463, w = [68.97309129 10.8661047  -9.76319295], b = 353.9997
第  800 轮: loss = 33.5177, w = [71.09089519 10.35441161 -7.85510148], b = 354.0000
第  900 轮: loss = 27.4947, w = [72.88112516  9.92190737 -6.24211781], b = 354.0000

✅ 模型训练完成!
最终参数:w = [74.38054529  9.55966893 -4.89114575], b = 354.0000
🏠 对面积130平米、3个卧室、距离6公里的房子预测价格为:350.97 万元

📘 sklearn 线性回归模型:
权重 w = [82.66522249  7.55822433  2.57332822]
偏置 b = 354.0000

特征缩放(feature scaling)

特征缩放

公式

\(x' = \frac{x}{\text{max} }\)

其中:

  • \(x\)是原始特征值
  • \(max\)是该特征的最大值

直观理解

如果你想预测房价,现在有两个变量 x1 和 x2 来控制房子的价格。 x1 为房子的大小,范围在 0 到 2000,x2 为房子中卧室的数目,范围在 0 到 5,那么画出这个代价函数的轮廓图就是这个样子,一个扁扁的椭圆形。

对这个函数进行梯度下降,就是红线的过程,你会发现,这个路程很长很曲折,这样我们进行梯度下降所花费的时间就会很长。

这里就要用到特征缩放(Feature Scaling)。将变量 x1 和 x2 都缩放到一个范围中,我们将他们都缩放到 -1 到 1 这个范围内。最简单的方法就是将 x1 除以 2000(因为他的范围就是 0-2000), x2 除以 5。

均值归一化(Mean normalization)

\(x' = \frac{x - \mu}{\text{max} - \text{min}}\)
其中:
\(x\)是原始特征值
\(μ\)是该特征的平均值(mean)
\(max\)\(min\)是该特征的最大值与最小值

Z-score归一化

\(x' = \frac{x - \mu}{\sigma}\)
其中:
\(x\)是原始特征值
\(μ\)是该特征的平均值(mean)
\(\sigma\)是特征的标准差(standard deviation)

特征工程

含义

特征工程就是把原始数据变成机器学习模型能更好理解和利用的“特征”的过程

举例

原始数据表格(房价预测):

面积(m²) 建成年份 楼层信息 距离市中心(km)
120 2005 高楼层 8

经过特征工程后,你可能会变成:

面积(m²) 房龄(年) 是否高楼层(0/1) 距离市中心(km)
120 19 1 8

你看到了什么?

  • 把“建成年份”变成了“房龄” = 2024 - 2005
  • 把文字“高楼层”变成了数值 1(方便模型识别)
  • 去掉了冗余不必要的信息
  • 👉 这些就是特征工程的基本思想!

逻辑回归(Logistic Regression)

逻辑回归

含义

逻辑回归是用来做分类的模型,能判断样本属于某个类别的概率。

公式

\(z=\vec{w} \cdot \vec{x} + b\)

\(g(z) \ = \frac{1}{1 + e^{-z}}\)

\(f_{\vec{w},b}(\vec{x}) = g(\vec{w} \cdot \vec{x} + b) \ = \frac{1}{1 + e^{-(\vec{w} \cdot \vec{x} + b)}}\)

直观理解

目标:输出在 0 到 1 之间

  • 分类问题中,我们希望模型的输出表示“属于某一类的概率”。
  • 概率自然应该在区间 (0, 1) 之间,所以需要一种“压缩函数”。

Sigmoid 函数(Logistic 函数)

图中公式:

\(g(z) = \frac{1}{1 + e^{-z}}\)

  • \(z→+∞\)\(g(z)→1\)
  • \(z→-∞\)\(g(z)→0\)
  • \(z→0\)\(g(z)→0.5\)

决策边界(decision boundary)

含义

决策边界 是逻辑回归用来 把不同类别分开 的“分界线”

条件

\(z = \vec{w} \cdot \vec{x} + b = 0\)

举例

(1)

(2)

(3)

还有很多,如椭圆、不规则的。。。

逻辑回归的代价函数

公式

\(J(\vec{w}, b) = \frac{1}{m} \sum_{i = 1}^{m} L(f_{\vec{w}, b}(\vec{x}^{(i)}), y^{(i)})\)

损失函数

\(L(f_{\vec{w}, b}(\vec{x}^{(i)}), y^{(i)}) = \begin{cases} -\log(f_{\vec{w}, b}(\vec{x}^{(i)})) & \text{if } y^{(i)} = 1 \\ -\log(1 - f_{\vec{w}, b}(\vec{x}^{(i)})) & \text{if } y^{(i)} = 0 \end{cases}\)

其中:

  • \(f \in (0, 1)\):模型预测值(即 sigmoid 输出)
  • \(y \in \{0, 1\}\):真实标签
  • 我们希望\(f\)接近\(y\)的值

如果\(f\)\(y\)的值相差越大,损失就越大。

直观理解

\(-\log(f)\)

\(-\log(1-f)\)

简化公式

\(J(\vec{w}, b) = - \frac{1}{m} \sum_{i = 1}^{m} \left[ y^{(i)} \log(f_{\vec{w}, b}(\vec{x}^{(i)})) + (1 - y^{(i)}) \log(1 - f_{\vec{w}, b}(\vec{x}^{(i)})) \right]\)

\(L(f_{\vec{w}, b}(\vec{x}^{(i)}), y^{(i)}) = -y^{(i)} \log(f_{\vec{w}, b}(\vec{x}^{(i)})) - (1 - y^{(i)}) \log(1 - f_{\vec{w}, b}(\vec{x}^{(i)}))\)

梯度下降实现

重复{

\(w_j = w_j - \alpha \left[ \frac{1}{m} \sum_{i = 1}^{m} \frac{1}{2} (f_{\vec{w}, b}(\vec{x}^{(i)}) - y^{(i)}) x_j^{(i)} \right]\)

\(b = b - \alpha \left[ \frac{1}{m} \sum_{i = 1}^{m} \frac{1}{2} (f_{\vec{w}, b}(\vec{x}^{(i)}) - y^{(i)}) \right]\)

}

过拟合问题(Overfitting Problem)

直观理解

左边“欠拟合”,中间“恰到好处”,右边“过拟合”

解决过拟合方法

  1. 收集更多的数据
  2. 减少特征数量, 使用更简单的模型
  3. 使用正则化(Regularization)减小参数大小

正则化(Regularization)

正则化代价函数

\(\lambda\)称为正则化参数(Regularization Parameter)

线性回归

\(J(\vec{w}, b) = \frac{1}{2m} \sum_{i = 1}^{m} (f_{\vec{w}, b}(\vec{x}^{(i)}) - y^{(i)})^2 + \frac{\lambda}{2m} \sum_{j = 1}^{n} w_j^2\)

逻辑回归

\(J(\vec{w}, b) = - \frac{1}{m} \sum_{i = 1}^{m} \left[ y^{(i)} \log(f_{\vec{w}, b}(\vec{x}^{(i)})) + (1 - y^{(i)}) \log(1 - f_{\vec{w}, b}(\vec{x}^{(i)})) \right] + \frac{\lambda}{2m} \sum_{j = 1}^{n} w_j^2\)

正则化线性回归

重复{
\(w_j = w_j - \alpha \left[ \frac{1}{m} \sum_{i = 1}^{m} \left[ (f_{\vec{w}, b}(\vec{x}^{(i)}) - y^{(i)}) x_j^{(i)} \right] + \frac{\lambda}{m} w_j \right]\)
\(b = b - \alpha \frac{1}{m} \sum_{i = 1}^{m} (f_{\vec{w}, b}(\vec{x}^{(i)}) - y^{(i)})\)
}

正则化逻辑回归

重复{
\(w_j = w_j - \alpha \left[ \frac{1}{m} \sum_{i = 1}^{m} \left[ (f_{\vec{w}, b}(\vec{x}^{(i)}) - y^{(i)}) x_j^{(i)} \right] + \frac{\lambda}{m} w_j \right]\)
\(b = b - \alpha \frac{1}{m} \sum_{i = 1}^{m} (f_{\vec{w}, b}(\vec{x}^{(i)}) - y^{(i)})\)
}

虽然看上去和“正则化线性回归”相同,但是函数\(f\)不一样,这是应用于\(z\)的逻辑回归函数

posted @ 2025-05-20 17:17  Su1f4t3  阅读(36)  评论(0)    收藏  举报