2021-06-13

本文以通俗易懂的方式介绍了神经网络的基础概念,包括人工智能简史、训练原理和反向传播过程。通过线性实例演示如何计算权重和偏导数,以及梯度下降方法的单变量和双变量应用。重点讲解了损失函数,特别是均方差和交叉熵。
摘要由CSDN通过智能技术生成

@第一章神经网络
第一步 概论与基本概念

摘要

在这一步中,我们将针对零基础的初学者们,用通俗易懂的语言,讲述神经网络的基本概念。

在概论与基本概念中,首先对人工智能的发展简史、定义、以及科学范式的演化进行介绍,并列举了一些有趣的实例,让大家对人工智能的世界观方法论形成一个基本的认识。

然后讲解一下神经网络基本的训练和工作原理,因为基本上各种教程里都没有提到这一点,以至于笔者在刚开始学习神经网络时一头雾水,不得要领,不知从何处开始下手。

再后面是反向传播和梯度下降,我们先从简单的线性方式说起(只有加法和乘法),而且用代入数值的方式来消除对公式的恐惧心理。然后会说到分层的复杂(非线性)函数的反向传播,同样用数值代入方式手推反向过程。

梯度下降是神经网络的基本学习方法,我们会用单变量和双变量两种方式说明,配以可视化的图解。再多的变量就无法用可视化方式来解释了,所以我们力求用简单的方式理解复杂的事物。

本部分最后是损失函数的讲解,着重说明了神经网络中目前最常用的均方差损失函数(用于回归)和交叉熵损失函数(用于分类)。

2.1 线性反向传播

2.1.1 正向计算的实例

假设有一个函数:

z = x ⋅ y (1) z = x \cdot y \tag{1} z=xy(1)

其中:

x = 2 w + 3 b (2) x = 2w + 3b \tag{2} x=2w+3b(2)

y = 2 b + 1 (3) y = 2b + 1 \tag{3} y=2b+1(3)

计算图如图2-4。

图2-4 简单线性计算的计算图

注意这里 x , y , z x,y,z x,y,z 不是变量,只是中间计算结果; w , b w,b w,b 才是变量。因为在后面要学习的神经网络中,要最终求解的目标是 w w w b b b 的值,所以在这里先预热一下。

w = 3 , b = 4 w = 3, b = 4 w=3,b=4 时,会得到图2-5的结果。

图2-5 计算结果

最终的 z z z 值,受到了前面很多因素的影响:变量 w w w,变量 b b b,计算式 x x x,计算式 y y y

2.1.2 反向传播求解 w w w

w w w 的偏导

目前 z = 162 z=162 z=162,如果想让 z z z 变小一些,比如目标是 z = 150 z=150 z=150 w w w 应该如何变化呢?为了简化问题,先只考虑改变 w w w 的值,而令 b b b 值固定为 4 4 4

如果想解决这个问题,最笨的办法是可以在输入端一点一点的试,把 w w w 变成 3.5 3.5 3.5 试试,再变成 3 3 3 试试…直到满意为止。现在我们将要学习一个更好的解决办法:反向传播。

z z z 开始一层一层向回看,图中各节点关于变量 w w w 的偏导计算结果如下:

因为 z = x ⋅ y z = x \cdot y z=xy,其中 x = 2 w + 3 b , y = 2 b + 1 x = 2w + 3b, y = 2b + 1 x=2w+3b,y=2b+1

所以:

∂ z ∂ w = ∂ z ∂ x ⋅ ∂ x ∂ w = y ⋅ 2 = 18 (4) \frac{\partial{z}}{\partial{w}}=\frac{\partial{z}}{\partial{x}} \cdot \frac{\partial{x}}{\partial{w}}=y \cdot 2=18 \tag{4} wz=xzwx=y2=18(4)

其中:

∂ z ∂ x = ∂ ∂ x ( x ⋅ y ) = y = 9 \frac{\partial{z}}{\partial{x}}=\frac{\partial{}}{\partial{x}}(x \cdot y)=y=9 xz=x(xy)=y=9

∂ x ∂ w = ∂ ∂ w ( 2 w + 3 b ) = 2 \frac{\partial{x}}{\partial{w}}=\frac{\partial{}}{\partial{w}}(2w+3b)=2 wx=w(2w+3b)=2

图2-6 对 w w w 的偏导求解过程

图2-6其实就是链式法则的具体表现, z z z 的误差通过中间的 x x x 传递到 w w w。如果不是用链式法则,而是直接用 z z z 的表达式计算对 w w w 的偏导数,会怎么样呢?我们来试验一下。

根据公式1、2、3,我们有:

z = x ⋅ y = ( 2 w + 3 b ) ( 2 b + 1 ) = 4 w b + 2 w + 6 b 2 + 3 b (5) z=x \cdot y=(2w+3b)(2b+1)=4wb+2w+6b^2+3b \tag{5} z=xy=(2w+3b)(2b+1)=4wb+2w+6b2+3b(5)

对上式求 w w w 的偏导:

∂ z ∂ w = 4 b + 2 = 4 ⋅ 4 + 2 = 18 (6) \frac{\partial z}{\partial w}=4b+2=4 \cdot 4 + 2=18 \tag{6} wz=4b+2=44+2=18(6)

公式4和公式6的结果完全一致!所以,请大家相信链式法则的科学性。

w w w 的具体变化值

公式4和公式6的含义是:当 w w w 变化一点点时, z z z 会产生 w w w 的变化值18倍的变化。记住我们的目标是让 z = 150 z=150 z=150,目前在初始状态时是 z = 162 z=162 z=162,所以,问题转化为:当需要 z z z 162 162 162 变到 150 150 150 时, w w w 需要变化多少?

既然:

Δ z = 18 ⋅ Δ w \Delta z = 18 \cdot \Delta w Δz=18Δw

则:

Δ w = Δ z 18 = 162 − 150 18 = 0.6667 \Delta w = {\Delta z \over 18}=\frac{162-150}{18}= 0.6667 Δw=18Δz=18162150=0.6667

所以:

w = w − 0.6667 = 2.3333 w = w - 0.6667=2.3333 w=w0.6667=2.3333
x = 2 w + 3 b = 16.6667 x=2w+3b=16.6667 x=2w+3b=16.6667
z = x ⋅ y = 16.6667 × 9 = 150.0003 z=x \cdot y=16.6667 \times 9=150.0003 z=xy=16.6667×9=150.0003

我们一下子就成功地让 z z z 值变成了 150.0003 150.0003 150.0003,与 150 150 150 的目标非常地接近,这就是偏导数的威力所在。

2.1.3 反向传播求解 b b b

b b b 的偏导

这次我们令 w w w 的值固定为 3 3 3,变化 b b b 的值,目标还是让 z = 150 z=150 z=150。同上一小节一样,先求 b b b 的偏导数。

注意,在上一小节中,求 w w w 的导数只经过了一条路:从 z z z x x x w w w。但是求 b b b 的导数时要经过两条路,如图2-7所示:

  1. z z z x x x b b b
  2. z z z y y y b b b

图2-7 对b的偏导求解过程

从复合导数公式来看,这两者应该是相加的关系,所以有:

∂ z ∂ b = ∂ z ∂ x ⋅ ∂ x ∂ b + ∂ z ∂ y ⋅ ∂ y ∂ b = y ⋅ 3 + x ⋅ 2 = 63 (7) \frac{\partial{z}}{\partial{b}}=\frac{\partial{z}}{\partial{x}} \cdot \frac{\partial{x}}{\partial{b}}+\frac{\partial{z}}{\partial{y}}\cdot\frac{\partial{y}}{\partial{b}}=y \cdot 3+x \cdot 2=63 \tag{7} bz=xzbx+yzby=y3+x2=63(7)

其中:

∂ z ∂ x = ∂ ∂ x ( x ⋅ y ) = y = 9 \frac{\partial{z}}{\partial{x}}=\frac{\partial{}}{\partial{x}}(x \cdot y)=y=9 xz=x(xy)=y=9
∂ z ∂ y = ∂ ∂ y ( x ⋅ y ) = x = 18 \frac{\partial{z}}{\partial{y}}=\frac{\partial{}}{\partial{y}}(x \cdot y)=x=18 yz=y(xy)=x=18
∂ x ∂ b = ∂ ∂ b ( 2 w + 3 b ) = 3 \frac{\partial{x}}{\partial{b}}=\frac{\partial{}}{\partial{b}}(2w+3b)=3 bx=b(2w+3b)=3
∂ y ∂ b = ∂ ∂ b ( 2 b + 1 ) = 2 \frac{\partial{y}}{\partial{b}}=\frac{\partial{}}{\partial{b}}(2b+1)=2 by=b(2b+1)=2

我们不妨再验证一下链式求导的正确性。把公式5再拿过来:

z = x ⋅ y = ( 2 w + 3 b ) ( 2 b + 1 ) = 4 w b + 2 w + 6 b 2 + 3 b (5) z=x \cdot y=(2w+3b)(2b+1)=4wb+2w+6b^2+3b \tag{5} z=xy=(2w+3b)(2b+1)=4wb+2w+6b2+3b(5)

对上式求b的偏导:

∂ z ∂ b = 4 w + 12 b + 3 = 12 + 48 + 3 = 63 (8) \frac{\partial z}{\partial b}=4w+12b+3=12+48+3=63 \tag{8} bz=4w+12b+3=12+48+3=63(8)

结果和公式7的链式法则一样。

b b b 的具体变化值

公式7和公式8的含义是:当 b b b 变化一点点时, z z z 会发生 b b b 的变化值 63 63 63 倍的变化。记住我们的目标是让 z = 150 z=150 z=150,目前在初始状态时是 162 162 162,所以,问题转化为:当我们需要 z z z 162 162 162 变到 150 150 150 时, b b b 需要变化多少?

既然:

Δ z = 63 ⋅ Δ b \Delta z = 63 \cdot \Delta b Δz=63Δb

则:

Δ b = Δ z 63 = 162 − 150 63 = 0.1905 \Delta b = \frac{\Delta z}{63}=\frac{162-150}{63}=0.1905 Δb=63Δz=63162150=0.1905

所以:
b = b − 0.1905 = 3.8095 b=b-0.1905=3.8095 b=b0.1905=3.8095
x = 2 w + 3 b = 17.4285 x=2w+3b=17.4285 x=2w+3b=17.4285
y = 2 b + 1 = 8.619 y=2b+1=8.619 y=2b+1=8.619
z = x ⋅ y = 17.4285 × 8.619 = 150.2162 z=x \cdot y=17.4285 \times 8.619=150.2162 z=xy=17.4285×8.619=150.2162

这个结果也是与 150 150 150 很接近了,但是精度还不够。再迭代几次,直到误差不大于 1e-4 时,我们就可以结束迭代了,对于计算机来说,这些运算的执行速度很快。

这个问题用数学公式倒推求解一个二次方程,就能直接得到准确的b值吗?是的!但是我们是要说明机器学习的方法,机器并不会解二次方程,而且很多时候不是用二次方程就能解决实际问题的。而上例所示,是用机器所擅长的迭代计算的方法来不断逼近真实解,这就是机器学习的真谛!而且这种方法是普遍适用的。

2.1.4 同时求解 w w w b b b 的变化值

这次我们要同时改变 w w w b b b,到达最终结果为 z = 150 z=150 z=150 的目的。

已知 Δ z = 12 \Delta z=12 Δz=12,我们不妨把这个误差的一半算在 w w w 的账上,另外一半算在 b b b 的账上:

Δ b = Δ z / 2 63 = 12 / 2 63 = 0.095 \Delta b=\frac{\Delta z / 2}{63} = \frac{12/2}{63}=0.095 Δb=63Δz/2=6312/2=0.095

Δ w = Δ z / 2 18 = 12 / 2 18 = 0.333 \Delta w=\frac{\Delta z / 2}{18} = \frac{12/2}{18}=0.333 Δw=18Δz/2=1812/2=0.333

  • w = w − Δ w = 3 − 0.333 = 2.667 w = w-\Delta w=3-0.333=2.667 w=wΔw=30.333=2.667
  • b = b − Δ b = 4 − 0.095 = 3.905 b = b - \Delta b=4-0.095=3.905 b=bΔb=40.095=3.905
  • x = 2 w + 3 b = 2 × 2.667 + 3 × 3.905 = 17.049 x=2w+3b=2 \times 2.667+3 \times 3.905=17.049 x=2w+3b=2×2.667+3×3.905=17.049
  • y = 2 b + 1 = 2 × 3.905 + 1 = 8.81 y=2b+1=2 \times 3.905+1=8.81 y=2b+1=2×3.905+1=8.81
  • z = x × y = 17.049 × 8.81 = 150.2 z=x \times y=17.049 \times 8.81=150.2 z=x×y=17.049×8.81=150.2

容易出现的问题:

  1. 在检查 Δ z \Delta z Δz 时的值时,注意要用绝对值,因为有可能是个负数
  2. 在计算 Δ b \Delta b Δb Δ w \Delta w Δw 时,第一次时,它们对 z z z 的贡献值分别是 1 / 63 1/63 1/63 1 / 18 1/18 1/18,但是第二次时,由于 b , w b,w b,w 值的变化,对 z z z 的贡献值也会有微小变化,所以要重新计算。具体解释如下:

∂ z ∂ b = ∂ z ∂ x ⋅ ∂ x ∂ b + ∂ z ∂ y ⋅ ∂ y ∂ b = y ⋅ 3 + x ⋅ 2 = 3 y + 2 x \frac{\partial{z}}{\partial{b}}=\frac{\partial{z}}{\partial{x}} \cdot \frac{\partial{x}}{\partial{b}}+\frac{\partial{z}}{\partial{y}}\cdot\frac{\partial{y}}{\partial{b}}=y \cdot 3+x \cdot 2=3y+2x bz=xzbx+yzby=y3+x2=3y+2x
∂ z ∂ w = ∂ z ∂ x ⋅ ∂ x ∂ w + ∂ z ∂ y ⋅ ∂ y ∂ w = y ⋅ 2 + x ⋅ 0 = 2 y \frac{\partial{z}}{\partial{w}}=\frac{\partial{z}}{\partial{x}} \cdot \frac{\partial{x}}{\partial{w}}+\frac{\partial{z}}{\partial{y}}\cdot\frac{\partial{y}}{\partial{w}}=y \cdot 2+x \cdot 0 = 2y wz=xzwx+yzwy=y2+x0=2y
所以,在每次迭代中,要重新计算下面两个值:
Δ b = Δ z 3 y + 2 x \Delta b=\frac{\Delta z}{3y+2x} Δb=3y+2xΔz
Δ w = Δ z 2 y \Delta w=\frac{\Delta z}{2y} Δw=2yΔz

以下是程序的运行结果。

没有在迭代中重新计算 Δ b \Delta b Δb 的贡献值:

single variable: b -----
w=3.000000,b=4.000000,z=162.000000,delta_z=12.000000
delta_b=0.190476
w=3.000000,b=3.809524,z=150.217687,delta_z=0.217687
delta_b=0.003455
w=3.000000,b=3.806068,z=150.007970,delta_z=0.007970
delta_b=0.000127
w=3.000000,b=3.805942,z=150.000294,delta_z=0.000294
delta_b=0.000005
w=3.000000,b=3.805937,z=150.000011,delta_z=0.000011
delta_b=0.000000
w=3.000000,b=3.805937,z=150.000000,delta_z=0.000000
done!
final b=3.805937

在每次迭代中都重新计算 Δ b \Delta b Δb 的贡献值:

single variable new: b -----
w=3.000000,b=4.000000,z=162.000000,delta_z=12.000000
factor_b=63.000000, delta_b=0.190476
w=3.000000,b=3.809524,z=150.217687,delta_z=0.217687
factor_b=60.714286, delta_b=0.003585
w=3.000000,b=3.805938,z=150.000077,delta_z=0.000077
factor_b=60.671261, delta_b=0.000001
w=3.000000,b=3.805937,z=150.000000,delta_z=0.000000
done!
final b=3.805937

从以上两个结果对比中,可以看到三点:

  1. factor_b第一次是63,以后每次都会略微降低一些
  2. 第二个函数迭代了3次就结束了,而第一个函数迭代了5次,效率不一样
  3. 最后得到的结果是一样的,因为这个问题只有一个解

对于双变量的迭代,有同样的问题:

没有在迭代中重新计算 Δ b , Δ w \Delta b,\Delta w Δb,Δw 的贡献值(factor_bfactor_w每次都保持6318):

double variable: w, b -----
w=3.000000,b=4.000000,z=162.000000,delta_z=12.000000
delta_b=0.095238, delta_w=0.333333
w=2.666667,b=3.904762,z=150.181406,delta_z=0.181406
delta_b=0.001440, delta_w=0.005039
w=2.661628,b=3.903322,z=150.005526,delta_z=0.005526
delta_b=0.000044, delta_w=0.000154
w=2.661474,b=3.903278,z=150.000170,delta_z=0.000170
delta_b=0.000001, delta_w=0.000005
w=2.661469,b=3.903277,z=150.000005,delta_z=0.000005
done!
final b=3.903277
final w=2.661469

在每次迭代中都重新计算 Δ b , Δ w \Delta b,\Delta w Δb,Δw 的贡献值(factor_bfactor_w每次都变化):

double variable new: w, b -----
w=3.000000,b=4.000000,z=162.000000,delta_z=12.000000
factor_b=63.000000, factor_w=18.000000, delta_b=0.095238, delta_w=0.333333
w=2.666667,b=3.904762,z=150.181406,delta_z=0.181406
factor_b=60.523810, factor_w=17.619048, delta_b=0.001499, delta_w=0.005148
w=2.661519,b=3.903263,z=150.000044,delta_z=0.000044
factor_b=60.485234, factor_w=17.613053, delta_b=0.000000, delta_w=0.000001
w=2.661517,b=3.903263,z=150.000000,delta_z=0.000000
done!
final b=3.903263
final w=2.661517

这个与第一个单变量迭代不同的地方是:这个问题可以有多个解,所以两种方式都可以得到各自的正确解,但是第二种方式效率高,而且满足梯度下降的概念

def target_function(w,b):
    x = 2*w+3*b
    y=2*b+1
    z=x*y
    return x,y,z

def single_variable(w,b,t):
    print("\nsingle variable: b ----- ")
    error = 1e-5
    while(True):
        x,y,z = target_function(w,b)
        delta_z = z - t
        print("w=%f,b=%f,z=%f,delta_z=%f"%(w,b,z,delta_z))
        if abs(delta_z) < error:
            break
        delta_b = delta_z /63
        print("delta_b=%f"%delta_b)
        b = b - delta_b

    print("done!")
    print("final b=%f"%b)

def single_variable_new(w,b,t):
    print("\nsingle variable new: b ----- ")
    error = 1e-5
    while(True):
        x,y,z = target_function(w,b)
        delta_z = z - t
        print("w=%f,b=%f,z=%f,delta_z=%f"%(w,b,z,delta_z))
        if abs(delta_z) < error:
            break
        factor_b = 2*x+3*y
        delta_b = delta_z/factor_b
        print("factor_b=%f, delta_b=%f"%(factor_b, delta_b))
        b = b - delta_b

    print("done!")
    print("final b=%f"%b)


# this version has a bug
def double_variable(w,b,t):
    print("\ndouble variable: w, b -----")
    error = 1e-5
    while(True):
        x,y,z = target_function(w,b)
        delta_z = z - t
        print("w=%f,b=%f,z=%f,delta_z=%f"%(w,b,z,delta_z))
        if abs(delta_z) < error:
            break
        delta_b = delta_z/63/2
        delta_w = delta_z/18/2
        print("delta_b=%f, delta_w=%f"%(delta_b,delta_w))
        b = b - delta_b
        w = w - delta_w
    print("done!")
    print("final b=%f"%b)
    print("final w=%f"%w)

# this is correct version
def double_variable_new(w,b,t):
    print("\ndouble variable new: w, b -----")
    error = 1e-5
    while(True):
        x,y,z = target_function(w,b)
        delta_z = z - t
        print("w=%f,b=%f,z=%f,delta_z=%f"%(w,b,z,delta_z))
        if abs(delta_z) < error:
            break

        factor_b, factor_w = calculate_wb_factor(x,y)
        delta_b = delta_z/factor_b/2
        delta_w = delta_z/factor_w/2
        print("factor_b=%f, factor_w=%f, delta_b=%f, delta_w=%f"%(factor_b, factor_w, delta_b,delta_w))
        b = b - delta_b
        w = w - delta_w
    print("done!")
    print("final b=%f"%b)
    print("final w=%f"%w)

def calculate_wb_factor(x,y):
    factor_b = 2*x+3*y
    factor_w = 2*y
    return factor_b, factor_w

if __name__ == '__main__':
    w = 3
    b = 4
    t = 150
    single_variable(w,b,t)
    single_variable_new(w,b,t)
    double_variable(w,b,t)
    double_variable_new(w,b,t)

在这里插入图片描述

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值