AutoCV第七课:ML基础

ML基础

注意事项

2023/5/29更新

新增逻辑回归内容,即第 3 节内容

前言

手写AI推出的全新保姆级从零手写自动驾驶CV课程,链接。记录下个人学习笔记,仅供自己参考。

本次课程主要学习复习 sqrt 函数和线性回归预测房价。

课程大纲可看下面的思维导图。

在这里插入图片描述

1. 复习sqrt函数

我们正式进入人工智能的学习,首先我们来回顾下之前求取 2 \sqrt 2 2 的例子

示例代码如下:

def sqrt(x):

    p  = x / 2  # 初始化
    
    lr = 0.01   # 学习率

    def forward(p, x):
        return (p * p - x) ** 2
    
    def backward(p, x, lr):
        delta_p = 4 * (p * p - x) * p
        return p - lr * delta_p

    while True:
        
        loss = forward(p, x)
        if loss < 1e-5:
            
            break
        
        p = backward(p, x, lr)

    return p

print(sqrt(2))

上述求解 2 \sqrt 2 2 的代码与我们之前讲解的有所不同

在这段代码中,函数 forward 计算了当前参数 p p p 的预测值与目标值 x x x 之间的误差,可以看作是神经网络中的损失函数

而函数 backward 则根据当前的误差以及学习率 l r lr lr,通过对参数 p p p 求梯度更新参数值,可以看作是神经网络中的后向传播过程

因此,可以把这段代码看作是一个简单的单层神经网络,使用梯度下降法来求解 2 \sqrt 2 2

2. 线性回归预测房价

我们从房价预测的案例入手来讲解线性回归

回归模型可以分为一元线性回归和多元线性回归

一元线性回归是指一个自变量与一个因变量之间的线性关系的回归模型。例如,本次讲解的例子中我们可以用一元线性回归模型来研究房价与时间之间的关系。一元线性回归模型的数学描述如下:
h θ ( x ) = θ 0 x 0 + θ 1 x 1 ( x 0 = 1 ) h_{\theta}(x)=\theta_0x_0+\theta_1x_1(x_0=1) hθ(x)=θ0x0+θ1x1(x0=1)
即利用一条直线来拟合房价与时间之间的关系:
y = k x + b y = kx+b y=kx+b
多元线性回归是指包含两个或两个以上自变量与一个因变量之间的线性关系的回归模型。例如,我们可以用多元线性回归模型来研究房屋售价与房屋面积、房间数量、地理位置等多个因素之间的关系。多元线性回归模型的数学描述如下:
h θ ( x ) = θ 0 x 0 + θ 1 x 1 + ⋯ + θ n x n = ∑ i = 0 n θ i x i = θ T X ( x 0 = 1 ) h_{\theta}(x)=\theta_{0}x_{0}+\theta_{1}x_{1}+\cdots+\theta_{n}x_{n}=\sum_{i=0}^{n}\theta_{i}x_{i}=\theta^{T}X(x_{0}=1) hθ(x)=θ0x0+θ1x1++θnxn=i=0nθixi=θTX(x0=1)

2.1 问题分析

问题描述:假设现在有一组数据,该数据描述了从 2008-2012 年上海的房价,现在请你根据该数据预测 2013 年的上海房价。

问题分析:房价预测问题就是一个典型的线性回归问题,我们的目的是建立一个数学模型来描述时间和房价之间的关系,由于自变量只有一个,因此这是一个一元线性回归模型,我们可以使用一条直线来对二者之间的关系进行拟合,即 y = k x + b y = kx + b y=kx+b

  • 特性1:若 b = 0 b = 0 b=0 y = k x y=kx y=kx 直线必过零点(模型表达能力会欠缺)
  • 特性2:当 x = 0 x = 0 x=0 时, y y y 值就是 b b b 即截距,而 k k k 是斜率(导数求斜率) k = d y d x = y 1 − y 0 x 1 − x 0 k = \frac{\mathrm{d} y}{\mathrm{d} x} = \frac{y_1-y_0}{x_1-x_0} k=dxdy=x1x0y1y0,若 x 1 = x 0 x_1=x_0 x1=x0 k k k 无意义即当直线与 y y y 轴垂直时 y y y 无意义,不能用 y = k x + b y=kx+b y=kx+b 表示

房价数据如下:

年份200820092010201120122013
价格6000800090001100015000?

可视化后如下:

在这里插入图片描述

图2-1 房价数据可视化

如何找到对应的直线呢?

我们可以先初始化一条直线 y = k x + b y=kx+b y=kx+b ,假设这就是我们要找的直线

如何衡量这条直线的好坏呢?

我们可以通过计算每个点到直线的距离,并求和取平均,使得总距离最短,如图 2-2 所示

如何去调整对应的直线使其能尽可能的符合预期呢?

我们需要根据总距离最短这个目的不断去更新直线的参数 k k k b b b

如何更新参数 k k k b b b

我们可以从求解 2 \sqrt 2 2 的例子中得到启发,定义损失函数 L L L 为总距离,利用梯度下降法 k k k b b b 沿着负梯度方向更新即可,如下所示,其中 l r lr lr 为学习率
k = k − l r ∗ ∂ L ∂ k k = k - lr * \frac{\partial L}{\partial k} k=klrkL

b = b − l r ∗ ∂ L ∂ b b = b - lr * \frac{\partial L}{\partial b} b=blrbL

在这里插入图片描述

图2-2 直线拟合房价数据

2.2 代码实现

我们先来简单实现,慢慢调试看有什么问题,代码如下:

import numpy as np
import matplotlib.pyplot as plt

data = np.array([
    [2008, 6000],
    [2009, 8000],
    [2010, 9000],
    [2011, 11000],
    [2012, 15000]
])


# 定义初始化的参数 k 和 b
k = np.random.random()
b = np.random.random()

X, Y = data.T

iter = 0    # 迭代次数
while True:
    
    iter += 1
    P = k * X + b   # 预测值
    L = np.mean(0.5 * (P - Y)**2)   # 定义损失函数

    print(f"{iter}. Loss: {L:.5f}, k = {k:.5f}, b = {b:.5f}")

    if L < 1e-5:    # 终止条件
        break

    delta_k = np.mean((P - Y) * X)  # 对 k 求偏导
    delta_b = np.mean(P - Y)        # 对 b 求偏导

    lr = 0.1
    k  = k - lr * delta_k   # k 更新
    b  = b - lr * delta_b   # b 更新

该代码实现了简单的线性回归预测,对一组房价和年份的数据进行拟合,以预测房价随时间的变化趋势。代码中首先随机初始化了 k k k b b b 两个参数,然后使用梯度下降算法不断迭代,通过损失函数计算预测值和真实值的误差,再根据误差反向传播来更新 k k k b b b,以期望使预测值更加接近真实值,最终得到一条直线,表示房价随时间的变化趋势。(from chatGPT)

输出如下:

1. Loss: 35297416.85023, k = 0.98189, b = 0.60411
2. Loss: 5000821078946638848.00000, k = 1573405.73810, b = 783.18369
3. Loss: 816251591822830492155922874368.00000, k = -635668580725.72083, b = -316252868.49308
4. Loss: 133231453522481572668586509982929722015744.00000, k = 256816018332930592.00000, b = 127769100099268.25000
...
59. Loss: nan, k = nan, b = nan
60. Loss: nan, k = nan, b = nan
61. Loss: nan, k = nan, b = nan
62. Loss: nan, k = nan, b = nan
63. Loss: nan, k = nan, b = nan
64. Loss: nan, k = nan, b = nan
65. Loss: nan, k = nan, b = nan
66. Loss: nan, k = nan, b = nan

可以看到直接跑飞了😂,可以看到一开始 L o s s Loss Loss 非常大,这意味着 Δ k \Delta k Δk Δ b \Delta b Δb 非常大,在下一次更新后 k k k b b b 非常大,最终没有迭代多少轮就放飞自我了。

根据输出结果,可以发现随着迭代次数的增加,损失函数的值呈现指数级别的增长,同时 k k k b b b 的值也变得异常巨大,最终导致损失函数的值变为 NaN。

我们可以将学习率 l r lr lr 设置的非常小来适配我们的 Δ k \Delta k Δk Δ b \Delta b Δb,但这似乎也不太好使,因为你不知道给多少合适,它本质上就是一个超参数,需要去调节,我们想固定 l r lr lr,能不能也得到一个比较好的效果呢?

当然是可以的,这个时候我们就要去限制 Δ k \Delta k Δk Δ b \Delta b Δb 了,而 Δ k \Delta k Δk Δ b \Delta b Δb 又是根据原始数据年份 X X X 和价格 Y Y Y 得来,那么我们可以考虑减小 X X X Y Y Y 的规模,对数据做缩放,让其在一个比较小的范围内

具体如何缩放呢?我们最容易想到的就是除以最大值,如下:

X = X / 2012
print(X)	# [0.99801193 0.99850895 0.99900596 0.99950298 1.        ]

但是又出现了新的问题,那就是缩放后的数据区分度太小了,所以我们对数据做预处理要满足两个条件:

  • 对数据做缩放,保证规模
  • 缩放时,确保数据具有区分性

我们可以使用最大最小值归一化方法

X = (X - X.min()) / (X.max() - X.min())
Y = (Y - Y.min()) / (Y.max() - Y.min())
print(X)	# [0.   0.25 0.5  0.75 1.  ]
print(Y)	# [0.         0.22222222 0.33333333 0.55555556 1.        ]

加入该方法后再来运行输出结果如下:

1. Loss: 0.32445, k = 0.93289, b = 0.75717
2. Loss: 0.24929, k = 0.89283, b = 0.67703
3. Loss: 0.19207, k = 0.85828, b = 0.60691
4. Loss: 0.14851, k = 0.82852, b = 0.54552
5. Loss: 0.11533, k = 0.80295, b = 0.49177
6. Loss: 0.09005, k = 0.78103, b = 0.44467
7. Loss: 0.07079, k = 0.76229, b = 0.40337
8. Loss: 0.05611, k = 0.74631, b = 0.36714
9. Loss: 0.04490, k = 0.73275, b = 0.33533
...

似乎没啥问题,也看不出来,我们来简单进行可视化下,代码如下所示:

import numpy as np
import matplotlib.pyplot as plt

data = np.array([
    [2008, 6000],
    [2009, 8000],
    [2010, 9000],
    [2011, 11000],
    [2012, 15000]
])


# 定义初始化的参数 k 和 b
k = np.random.random()
b = np.random.random()
X, Y = data.T

x_alpha = X.min()
x_beta  = X.max() - X.min()
y_alpha = Y.min()
y_beta  = Y.max() - Y.min()
X = (X - x_alpha) / x_beta
Y = (Y - y_alpha) / y_beta

iter = 0    # 迭代次数
while True:
    
    iter += 1
    P = k * X + b   # 预测值
    L = np.mean(0.5 * (P - Y)**2)   # 定义损失函数

    raw_x = X * x_beta + x_alpha    # x 复原
    raw_y = Y * y_beta + y_alpha    # y 复原
    raw_p = P * y_beta + y_alpha    # p 复原

    plt.cla()
    plt.xlim(2007, 2013)
    plt.ylim(0, 30000)
    plt.plot(X, Y, "b*")
    plt.plot(raw_x, raw_y, "b*")
    plt.plot(raw_x, raw_p, "r-")
    plt.pause(0.01)

    print(f"{iter}. Loss: {L:.5f}, k = {k:.5f}, b = {b:.5f}")

    if L < 1e-5:    # 终止条件
        break

    delta_k = np.mean((P - Y) * X)  # 对 k 求偏导
    delta_b = np.mean(P - Y)        # 对 b 求偏导

    lr = 0.1
    k  = k - lr * delta_k   # k 更新
    b  = b - lr * delta_b   # b 更新

可视化图如下所示:

在这里插入图片描述

图2-3 最大最小值归一化后直线拟合房价数据

好像是那么回事,我们再来分析下,最大最小值归一化是不是会出现 x = 0 x=0 x=0 y = 0 y=0 y=0 的情况,是不是意味着 y = k x + b y = kx+b y=kx+b 归零点,意味着 b = 0 b=0 b=0,我们可以看到输出中 b b b 是不断减小逼近于 0 的,因为减去 X m i n X_{min} Xmin Y m i n Y_{min} Ymin 相当于是把偏置 b b b 减掉了,相当于模型表达能力减弱了。

因此我们引入第二种归一化方法即正则化(对应正态分布)

  • X = ( X − m e a n ) / s t d X = (X - mean) / std X=(Xmean)/std
  • 能够更好更快的收敛,稳定性更强
  • 最大最小值归一化中当出现噪声点时(离散值),会严重影响归一化后的数据分布,稳定性差
x_alpha = X.mean()
x_beta  = X.std()
y_alpha = Y.mean()
y_beta  = Y.std()
X = (X - x_alpha) / x_beta
Y = (Y - y_alpha) / y_beta

可视化如下图:

在这里插入图片描述

图2-3 正则化后直线拟合房价数据

可以看到收敛更加稳定,对噪声带来的误差更小。

我们可以让其迭代到 200 次后退出循环,利用此时的 k k k b b b 做 2013 年的房价预测,代码如下所示:

import numpy as np
import matplotlib.pyplot as plt

data = np.array([
    [2008, 6000],
    [2009, 8000],
    [2010, 9000],
    [2011, 11000],
    [2012, 15000]
])


# 定义初始化的参数 k 和 b
k = np.random.random()
b = np.random.random()
X, Y = data.T

x_alpha = X.mean()
x_beta  = X.std()
y_alpha = Y.mean()
y_beta  = Y.std()
X = (X - x_alpha) / x_beta
Y = (Y - y_alpha) / y_beta

iter = 0    # 迭代次数
while True:
    
    iter += 1
    P = k * X + b   # 预测值
    L = np.mean(0.5 * (P - Y)**2)   # 定义损失函数

    raw_x = X * x_beta + x_alpha    # x 复原
    raw_y = Y * y_beta + y_alpha    # y 复原
    raw_p = P * y_beta + y_alpha    # p 复原

    plt.cla()
    plt.xlim(2007, 2013)
    plt.ylim(0, 30000)
    plt.plot(X, Y, "b*")
    plt.plot(raw_x, raw_y, "b*")
    plt.plot(raw_x, raw_p, "r-")
    plt.pause(0.01)

    print(f"{iter}. Loss: {L:.5f}, k = {k:.5f}, b = {b:.5f}")

    if L < 1e-5:    # 终止条件
        break

    delta_k = np.mean((P - Y) * X)  # 对 k 求偏导
    delta_b = np.mean(P - Y)        # 对 b 求偏导

    lr = 0.1
    k  = k - lr * delta_k   # k 更新
    b  = b - lr * delta_b   # b 更新
    
    if iter == 200:
        break

# 房价预测
year  = 2013
normalize_pred = k * (year - x_alpha) / x_beta + b
real_pred      = normalize_pred * y_beta + y_alpha
print(f"对于{year}年预测的房价是:{real_pred:.3f} 元")

输出如下:

对于2013年预测的房价是:16100.000

可以看到和我们猜想的预期是差不多的😀

2.3 总结

  • y = k x + b y = kx + b y=kx+b 能够表示一个线性模型
    • b = 0 b = 0 b=0 时,直线必定过 0 点,此时模型表达能力弱
    • b b b 是截距, k k k 是斜率,对于垂直于 y y y 轴的直线,无法表示
  • 对于 numpy 的矩阵,可以使用 x,y=data.T 在行方向上解包
  • 训练时,需要对数据进行预处理,目的是确保步长在比较小的范围内
  • 此时 l r lr lr 就相对比较固定,0.1 就行
  • 预处理的方法中,最大最小值归一化 x = (x - x.min()) / (x.max() - x.min())
  • 它会对异常数据比较敏感,不是一个好的做法
  • 预处理方法中,正则化:x = (x - x.mean()) / x.std()
  • 它考虑了所有数据的均值和方差,这是以后常见的方法,比较推荐

3. 逻辑回归分类

我们从苹果分类的案例入手来讲解逻辑回归(Logistic Regression)

3.1 问题1分析

问题1描述:根据苹果的大小将其分为大果、小果两类,如图1所示

问题1分析:我们需要构建一个自动分类器,让算法可以根据大小这个特征识别出当前的苹果属于哪个类别

在这里插入图片描述

图3-1 苹果分类问题1描述

定义 🍎 的大小为变量 x x x,则该分类问题可描述为:

  • a x + b ≥ 0 ax+b \ge 0 ax+b0 时,该苹果被分类为大果,对应的真值T为 1
  • a x + b < 0 ax+b<0 ax+b<0 时,该苹果被分类为小果,对应的真值T为 -1

这里的参数 a a a 用于将苹果的单位尺寸(例如克)转为一个无量纲的数值(去单位),参数 b b b 则用于平移数值,将线性方程的分界点设为 0

那你可能会问为什么不直接根据阈值来判断大小,比如苹果大于等于2.5则为大果,小于2.5则为小果,为什么要引入 a a a b b b 两个额外的参数,使问题变得复杂化?

使用 a x + b ax+b ax+b 的形式可以将问题进行数学统一化。通过调整参数 a a a b b b,可以在一个统一的数学表达式下灵活地调整分类的界限,适应不同地数据分布和问题需求。这种灵活性使得模型可以更好地拟合数据,并且可以通过优化算法自动学习合适的参数值。

接下来我们来构建模型
L = [ ( a x + b ) − T ] 2 = [ P − T ] 2 L = [(ax+b)-T]^2 = [P-T]^2 L=[(ax+b)T]2=[PT]2
我们来思考下上述 Loss 的定义合适吗?

我们当然希望说模型预测的数值越大越好,数值越大我们越有理由相信模型预测的结果,假设模型预测值为1000,那么我们有充足的理由相信说预测的苹果是大果,但是此刻我们计算 Loss 发现其数值非常大,这显然是不合理的,而我们发现只有当模型预测的结果为 ±1 时对应的 Loss 才为 0,也就是要求 不偏不倚,因此上述 Loss 的构建是不合适的

实际上我们需要的是:

    1. 当 T 是 +1 时,让 P 正向无限远离 0 即可,而不是接近 1
    1. 越远则信心越足,损失越小

在这里插入图片描述

图3-2 Loss曲线变化图

我们最终需要的效果如图2所示,假设真值 T 取 +1,当 P 越大时信心越足,当增加到一定程度后进入饱和区,此时损失越小,且减小到一定程度后也进入了饱和区

我们要引入一个新的函数帮我们达到上述效果,该函数定义如下:
s i g o m o d ( z ) = 1 1 + e − z sigomod(z) = \frac{1}{1+e^{-z}} sigomod(z)=1+ez1
其函数图像如下:

在这里插入图片描述

图3-3 sigmoid函数图像

该函数的性质是,当 z z z 值为 0 时,函数值为 0.5,当 z z z 趋近于无穷大时,函数值趋于 1,当 z z z 趋近于无穷小时,函数值趋于 0

现在我们来构建一个新的模型,如下所示:
L = − [ T ln ⁡ ( P ) + ( 1 − T ) ln ⁡ ( 1 − P ) ] P = s i g m o i d ( a x + b ) L = -[T\ln(P)+(1-T)\ln(1-P)] \\ P = sigmoid(ax+b) L=[Tln(P)+(1T)ln(1P)]P=sigmoid(ax+b)
其中真值 T 的标签变为了 0 和 1

  • 当 T = 0 时, L = − ln ⁡ ( 1 − P ) L = -\ln(1-P) L=ln(1P) ,1-P 的值域在 (0, 1)
    • P 要越接近 0 越好,Loss 越小,此时要求 ax+b 越趋近无穷小越好
  • 当 T = 1 时, L = − ln ⁡ ( P ) L = -\ln(P) L=ln(P) ,P 的值域在 (0, 1)
    • P 要越接近 1 越好,Loss 越小,此时要求 ax+b 越趋近无穷大越好

通过上述分析可知新构建的模型满足我们的需求

下面我们来了解几个概念

  • s i g m o i d ( z ) = 1 1 + e − z sigmoid(z)=\frac{1}{1+e^{-z}} sigmoid(z)=1+ez1 称为非线性函数,也叫 S 型函数
  • L = − [ T ln ⁡ ( P ) + ( 1 − T ) ln ⁡ ( 1 − P ) ] L = -[T\ln(P)+(1-T)\ln(1-P)] L=[Tln(P)+(1T)ln(1P)] 称为二元交叉熵损失(Binary Cross Entropy Loss,BCELoss),也叫 sigmoidCrossEntropyLoss
  • 可用伯努利分布进行推导,可参考https://blog.csdn.net/qq_40672115/article/details/130340572

3.2 问题1代码实现

示例代码如下:

import numpy as np
import matplotlib.pyplot as plt

data = np.array([
    [1, 0],
    [2, 0],
    [3, 1],
    [4, 1]
])

# 随机初始化a和b
a = 0.1
b = 0

# 解包
X, T = data.T

# 归一化
xmean = X.mean()
xstd  = X.std()
X = (X - xmean) / xstd

lr = 0.8
sigmoid  = lambda x : (1 / (1 + np.exp(-x)))

while True:
    P = sigmoid(a * X + b)
    L = np.mean(-(T * np.log(P) + (1 - T) * np.log(1 - P)))

    plt.cla()
    plt.plot(data[:, 0], data[:, 1], "b*") # 蓝色真值
    plt.plot(data[:, 0], P, "r*") # 红色预测值
    
    plt.pause(0.001)
    print(f"Loss: {L:.5f}, {a}, {b}")
    if L < 1e-5:
        break
    
    deltaA = np.mean((P - T) * X)
    deltaB = np.mean(P - T)

    a = a - lr * deltaA
    b = b - lr * deltaB

运行效果如下图所示:

在这里插入图片描述

图3-4 运行效果

3.3 问题2分析

问题2描述:根据苹果的大小和颜色将其分为两类,如图5所示

问题2分析:我们需要构建一个自动分类器,让算法可以根据大小和颜色这两特征识别出当前的苹果属于哪个类别

在这里插入图片描述

图3-5 苹果分类问题2描述

定义 🍎 的大小为变量 x x x,颜色为变量 y y y,则该分类问题可描述为:

  • a x + b y + c ≥ 0 ax+by+c \ge 0 ax+by+c0 时,该苹果被分类为好吃,对应的真值T为 1
  • a x + b y + c < 0 ax+by+c<0 ax+by+c<0 时,该苹果被分类为不好吃,对应的真值T为 0

这里的参数 a a a 用于将苹果的大小去单位化,参数 b b b 用于将苹果的颜色去单位化,参数 c c c 则用于平移数值,将线性方程的分界点设为 0

3.4 问题2代码实现

示例代码如下:

import numpy as np
import matplotlib.pyplot as plt

# 大小,颜色,标签
data = np.array([
    [5,  0.2, 0],
    [30, 0.1, 0],
    [5,  0.6, 1],
    [20, 0.9, 1]
])

# 随机初始化a和b
a = 0.1
b = 0.1
bias = 0

# 解包
# size, color, Truth
S, C, T = data.T

# 归一化
size_mean, color_mean = S.mean(axis=0), C.mean(axis=0)
size_std, color_std   = S.std(axis=0), C.std(axis=0)
S = (S - size_mean) / size_std
C = (C - color_mean) / color_std

sigmoid = lambda x : (1 / (1 + np.exp(-x)))

while True:
    P = sigmoid(S * a + C * b + bias)
    L = np.mean(-(T * np.log(P) + (1-T) * np.log(1-P)))
    
    plt.cla()
    plt.xlim(0, 35)
    plt.ylim(0, 1)

    xs = ([0, 35] - size_mean) / size_std
    ys = -(a * xs + bias) / b
    
    ys = ys * color_std + color_mean
    plt.plot([0, 35], ys, "r-", linewidth=3)

    for (x, y), p in zip(data[:, :2], P):
        if p < 0.5:
            p = (1 - p)
            size  = (p - 0.5) * 300
            color = (0, p, 0)
        else:
            size  = (p - 0.5) * 300
            color = (p, 0, 0)
        plt.plot(x, y, "*", color=color, markersize=size)
    
    plt.pause(0.1)
    print(f"Loss: {L:.5f}, {a}, {b}")
    if L < 1e-5:
        break

    deltaA = np.mean((P - T) * S, axis=0)
    deltaB = np.mean((P - T) * C, axis=0)
    deltaBias = np.mean(P - T)
    lr = 0.01
    a  = a - lr * deltaA
    b  = b - lr * deltaB
    bias = bias - lr * deltaBias

运行效果如下图所示:

在这里插入图片描述

图3-6 运行效果

⭐️ 的大小表示模型预测的信心程度,红线代表分类界线

那图中的直线是如何绘制的呢?其实分类问题是可以用直线定义

    1. 这个线称为分类线,线两侧为不同类
    1. 存在直线无法划分的情况(线性不可分)

直线的表达形式有以下两种:

  • 1.截距式 y = k x + b y=kx+b y=kx+b 无法表示 x = ? x=? x=?
  • 2.一般式 a x + b y + c = 0 ax+by+c=0 ax+by+c=0 (a 或 b ≠ 0)
    • 可改写为 ( − a b ) x + ( − c b ) = y (-\frac{a}{b})x + (-\frac{c}{b}) = y (ba)x+(bc)=y 或者 y = − a x + c b y = -\frac{ax+c}{b} y=bax+c

3.5 拓展-导数推导

现有
P = s i g m o i d ( z ) = s i g m o i d ( a x + b ) = 1 1 + e − ( a x + b ) L = − [ T ln ⁡ ( P ) + ( 1 − T ) ln ⁡ ( 1 − P ) ] P = sigmoid(z) = sigmoid(ax+b) = \frac{1}{1+e^{-(ax+b)}} \\ L = -[T\ln(P)+(1-T)\ln(1-P)] P=sigmoid(z)=sigmoid(ax+b)=1+e(ax+b)1L=[Tln(P)+(1T)ln(1P)]
最终我们要求 ∂ L ∂ a \frac{\partial L}{\partial a} aL ∂ L ∂ b \frac{\partial L}{\partial b} bL

我们先来求 ∂ P ∂ a \frac{\partial P}{\partial a} aP ∂ P ∂ b \frac{\partial P}{\partial b} bP
∂ P ∂ a = e − ( a x + b ) x ( 1 + e − a x + b ) 2 = ( 1 + e − ( a x + b ) ) x − x ( 1 + e − a x + b ) 2 = − 1 ( 1 + e − a x + b ) x − 1 ( 1 + e − a x + b ) 2 x = P x − P 2 x = P x ( 1 − P ) \begin{aligned} \frac{\partial P}{\partial a} &= \frac{e^{-(ax+b)}x}{(1+e^{-ax+b})^2} \\ &= \frac{(1+e^{-(ax+b)})x-x}{(1+e^{-ax+b})^2} \\ &= -\frac{1}{(1+e^{-ax+b})}x -\frac{1}{(1+e^{-ax+b})^2}x \\ &= Px-P^2x \\ &= Px(1-P) \end{aligned} aP=(1+eax+b)2e(ax+b)x=(1+eax+b)2(1+e(ax+b))xx=(1+eax+b)1x(1+eax+b)21x=PxP2x=Px(1P)

∂ P ∂ b = e − ( a x + b ) ( 1 + e − a x + b ) 2 = ( 1 + e − ( a x + b ) ) − 1 ( 1 + e − a x + b ) 2 = − 1 ( 1 + e − a x + b ) − 1 ( 1 + e − a x + b ) 2 = P − P 2 = P ( 1 − P ) \begin{aligned} \frac{\partial P}{\partial b} &= \frac{e^{-(ax+b)}}{(1+e^{-ax+b})^2} \\ &= \frac{(1+e^{-(ax+b)})-1}{(1+e^{-ax+b})^2} \\ &= -\frac{1}{(1+e^{-ax+b})} -\frac{1}{(1+e^{-ax+b})^2} \\ &= P-P^2 \\ &= P(1-P) \end{aligned} bP=(1+eax+b)2e(ax+b)=(1+eax+b)2(1+e(ax+b))1=(1+eax+b)1(1+eax+b)21=PP2=P(1P)

再来求 ∂ L ∂ a \frac{\partial L}{\partial a} aL ∂ L ∂ b \frac{\partial L}{\partial b} bL
∂ L ∂ a = − [ T × 1 P × ∂ P ∂ a + ( 1 − T ) × − 1 1 − P × ∂ P ∂ a ] = − [ T × 1 P × P x ( 1 − P ) + ( 1 − T ) × − 1 1 − P × P x ( 1 − P ) ] = − [ T x ( 1 − P ) − P x ( 1 − T ) ] = − [ T x − T P x − P x + T P x ] = ( P − T ) x \begin{aligned} \frac{\partial L}{\partial a} &= -[T \times \frac{1}{P} \times \frac{\partial P}{\partial a} + (1-T) \times \frac{-1}{1-P} \times \frac{\partial P}{\partial a}] \\ &= -[T \times \frac{1}{P} \times Px(1-P) + (1-T) \times \frac{-1}{1-P} \times Px(1-P)] \\ &= -[Tx(1-P) - Px(1-T)] \\ &= -[Tx-TPx-Px+TPx] \\ &= (P-T)x \end{aligned} aL=[T×P1×aP+(1T)×1P1×aP]=[T×P1×Px(1P)+(1T)×1P1×Px(1P)]=[Tx(1P)Px(1T)]=[TxTPxPx+TPx]=(PT)x

∂ L ∂ b = − [ T × 1 P × ∂ P ∂ b + ( 1 − T ) × − 1 1 − P × ∂ P ∂ b = − [ T × 1 P × P ( 1 − P ) + ( 1 − T ) × − 1 1 − P × P ( 1 − P ) ] = − [ T ( 1 − P ) − P ( 1 − T ) ] = − [ T − T P − P + T P ] = ( P − T ) \begin{aligned} \frac{\partial L}{\partial b} &= -[T \times \frac{1}{P} \times \frac{\partial P}{\partial b} + (1-T) \times \frac{-1}{1-P} \times \frac{\partial P}{\partial b}\\ &= -[T \times \frac{1}{P} \times P(1-P) + (1-T) \times \frac{-1}{1-P} \times P(1-P)] \\ &= -[T(1-P) - P(1-T)] \\ &= -[T-TP-P+TP] \\ &= (P-T) \end{aligned} bL=[T×P1×bP+(1T)×1P1×bP=[T×P1×P(1P)+(1T)×1P1×P(1P)]=[T(1P)P(1T)]=[TTPP+TP]=(PT)

3.6 总结

本次课程通过苹果分类案例来讲解逻辑回归问题,与线性回归不同的是逻辑回归主要解决的是分类问题,同时线性回归模型的损失函数并不适合于逻辑回归,为此我们通过引入了一个全新的函数-sigmoid函数,并重新定义了逻辑回归模型的损失函数即二元交叉熵损失即 BCELoss

个人总结

本次课程正式进入人工智能的学习,首先我们从一个不同的角度复习了 sqrt 函数,然后我们讲解了利用线性回归来进行房价预测,利用直线模型来对数据进行拟合,要注意的是我们需要对数据进行预处理,否则步长在一个很大的范围,无法完成收敛,常见预处理包括最大最小值归一化和正则化,前者对数据比较敏感,后者考虑了所有数据的均值和方差,收敛性更好,值得推荐。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱听歌的周童鞋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值