前言

本文教程均来自b站【小白也能听懂的人工智能原理】,感兴趣的可自行到b站观看。

代码及工具箱

本专栏的代码和工具函数已经上传到GitHub:1571859588/xiaobai_AI: 零基础入门人工智能 (github.com),可以找到对应课程的代码

正文

智能体的分类思考

在前面的学习中,我们了解到通过梯度下降算法和前向、反向传播的训练,可以让一个智能体(如小蓝)从直觉出发,自动学习并调整其认知以符合现实。然而,我们发现这种精确拟合的方式并不完全符合智能体(无论是人类还是机器)的思考模式。人类在面对问题时,往往倾向于进行分类而非进行精确的数值估计。

例如,面对馒头,我们不会去计算馒头的大小与饱腹感之间的精确函数关系,而是简单地将其分为“能吃饱”和“吃不饱”两类。同样,对于一只小狗的眼睛,我们可能会将其分类为“可爱”、“不可爱”或“吓人”,而不是去构建一个眼睛大小与可爱程度之间的精确数学模型。

对于小蓝这样的智能体,如果它具备一定的抗毒性,比如能承受最大0.8的毒性,那么它更可能采用简单的分类方法来判断豆豆是否有毒,而不是去精确估算豆豆的毒性大小。这种分类方法更符合智能体的本能和实际应用需求。

引入激活函数

因此,智能体的思考和决策过程往往是基于分类而非精确拟合,这提示我们在设计智能系统时,应考虑引入分类机制,以更贴近智能体的自然思考方式。

在处理豆豆是否有毒的分类问题时,我们面对的是二分类任务,即结果只有两种可能性:有毒或无毒。在这种情况下,我们之前的神经元预测模型,一个基于线性函数的模型,不再适用,因为它的输出可以是任意实数,而我们需要的输出是离散的0或1。

为了解决这个问题,我们需要引入激活函数,它能够将线性函数的连续输出转换为离散的分类结果。具体来说,我们希望当线性函数的输出大于某个阈值时,激活函数的输出为1(表示有毒),而当输出小于或等于阈值时,激活函数的输出为0(表示无毒)。这种分段函数的引入,正是激活函数的作用。

激活函数的作用

激活函数的引入,使我们的模型能够更好地处理分类问题,它通过非线性变换,将连续的输入空间划分为不同的类别,从而使得模型能够进行有效的分类决策。这种处理方式更符合人类在面对分类任务时的直觉思维,也使得机器学习模型更加灵活和强大。

罗森布拉特感知器与激活函数

在讨论罗森布拉特感知器时,我们提到了激活函数的概念。罗森布拉特感知器是一种早期的神经网络模型,它通过将线性函数的输出传递给一个符号函数来实现二分类。这个符号函数,也就是我们所说的阶跃函数,是一个简单的分段函数,当输入大于0时输出1,小于0时输出0。

然而,阶跃函数作为激活函数存在一些问题,尤其是在梯度下降算法中。阶跃函数在输入为0时不可导,这会导致在训练过程中梯度的计算变得困难。

为了解决这个问题,我们引入了逻辑斯特函数,也就是Sigmoid函数,作为激活函数。标准的逻辑斯特函数形式为[ $\sigma(x) = \frac{1}{1 + e^{-x}} $],它将输入值压缩到0和1之间,非常适合用于二分类问题。Sigmoid函数不仅连续可导,而且其导数也易于计算,这使得它在梯度下降算法中非常受欢迎。

通过使用Sigmoid函数,我们能够构建一个更加完善的感知器模型,它可以更平滑、更有效地进行学习和分类。这也标志着我们对罗森布拉特感知器的理解达到了一个新的高度,为后续更复杂的神经网络模型奠定了基础。

Sigmoid函数的特性

Sigmoid激活函数因其S形曲线而得名,其输出值始终介于0和1之间,这使得它非常适合用于逻辑判断和分类任务。它的一个重要特性是它的平滑性,即函数在整个定义域内都是连续且可导的,这为梯度下降算法提供了便利。

尽管Sigmoid函数在分界点附近的变化不够尖锐,看起来似乎不够果断,但正是这种平滑性使得它在梯度下降中非常有用。与阶跃函数相比,后者在分界点处导数是无穷大,而在其他地方导数为零,这会导致梯度下降算法难以应用,因为梯度(即导数)在大多数情况下为零,无法提供有效的信息来更新权重。

Sigmoid函数的导数是其本身与(1减去本身)的乘积,这使得在梯度下降过程中,即使在分界点附近,也能提供非零的梯度值,从而有助于网络参数的调整和学习过程的进行。

因此,尽管Sigmoid函数看起来没有阶跃函数那样直接,但它的平滑和连续性使其成为训练神经网络时梯度下降算法的理想选择。这种特性使得Sigmoid函数在深度学习和机器学习中得到了广泛的应用。

梯度下降与参数调整

Sigmoid激活函数因其平滑连续且在整个定义域内可导的特性,成为神经网络中一个受欢迎的选择。它帮助模型,比如小蓝的神经元,做出更符合逻辑的决策。

在处理豆豆分类问题时,小蓝首先通过线性函数处理输入数据得到中间结果z。这个z随后输入到Sigmoid函数中,经过非线性变换,得到最终的预测输出a。

对于数学基础好的人来说,理解z、a与输入x之间的关系是直观的。z是x的一元一次函数结果,而a是z经过Sigmoid函数后的输出。调整线性函数的参数w和b会影响z,进而影响a。

关键在于,无论w和b如何变化,Sigmoid函数始终保持其S形曲线,将z映射到0和1之间。这意味着对于固定的z,a是确定的,不受w和b的影响。

然而,a与x之间的关系会随着w和b的调整而变化,反映了模型如何响应输入数据的变化。

总的来说,Sigmoid函数增加了模型的非线性,这对于准确分类至关重要,同时也保持了梯度下降算法所需的数学特性,使得模型训练成为可能。

复合函数的链式法则

在神经网络的世界里,权重(w)和偏置(b)是调整模型预测的两个关键参数。想象一下,我们有一个简单的线性函数 ( z = wx + b ),它就像一个转换器,把输入(x)变成输出(z)。通过改变w和b的值,我们可以改变这个转换器的工作方式。

举个例子,如果我们设w为5,b为-5,那么当输入x为1时,输出z就会是0。然后,我们把这个z值送到Sigmoid函数里,它会给我们一个介于0和1之间的输出a,这个a就是模型的预测结果。如果我们把w增加到10,而b保持不变,那么为了得到同样的z值,输入x就需要改变。这样,随着x的增加,z的增长速度会加快,这就像是把Sigmoid函数输出的S形曲线在x轴上压缩了。

这个转换过程其实是一个复合函数的例子。输入x首先通过线性函数变成z,然后z再通过Sigmoid函数变成a。通过梯度下降算法,我们可以不断调整w和b,让预测结果a更接近我们想要的目标。

梯度下降算法的工作原理是计算损失函数对w和b的梯度,然后沿着梯度告诉我们的方向更新w和b,让模型的预测越来越准确。通过不断迭代这个过程,我们可以训练出一个能够准确预测新数据的模型。

总的来说,神经网络通过学习输入和输出之间的复杂关系,能够做出智能的决策。这个过程不仅展示了神经网络的强大能力,也是我们能够构建智能系统的基础。

当我们面对神经网络中复杂的函数时,求导并进行梯度下降算法更新参数似乎很困难。一开始,我们可能会想用定义法求导,但这非常繁琐。幸运的是,我们有一个更巧妙的方法,那就是利用复合函数的链式法则。

让我们回顾一下,我们有一个由内层函数和外层函数组成的复合函数。内层函数可能只是一个简单的一次函数,而外层函数可能是一个二次函数。在这种情况下,我们不需要知道内层函数的因变量h具体是什么,我们只需要知道它如何依赖于我们的参数w。在外层函数中,h就像是一个普通的自变量。

为了求导,我们可以将这个过程想象成剥洋葱,从外层开始,逐步向内层求导。首先,我们对最外层的函数求导,得到它对h的导数。然后,我们对内层函数求导,得到它对w的导数。最后,我们将这两个导数相乘,得到最外层函数对最内层自变量w的导数。

这种方法不仅简化了求导过程,而且使得梯度下降算法在神经网络中的参数更新变得可行。通过这种方式,我们可以有效地调整网络中的权重w和偏置b,以最小化损失函数,提高模型的预测性能。

简而言之,复合函数的链式法则为我们提供了一种强大而直观的方式来求解神经网络中参数的梯度,这是现代神经网络优化不可或缺的一部分。

在神经网络的世界里,我们用一种叫做Sigmoid的神奇函数来帮助模型做出决策。想象一下,我们有一个模型,它需要决定一件事情是“对”还是“错”,Sigmoid函数就能帮它做出这个决定。

当我们训练这个模型时,我们会给它很多数据,然后它会尝试找出数据中的规律。这个过程叫做梯度下降,它帮助模型通过不断尝试和错误来找到最好的规律。而复合函数求导就像是这个过程的加速器,它让梯度下降变得更快更有效。

想象一下,我们的模型就像一个多层的蛋糕,每一层都有很多小小的决策者(神经元)。如果我们想要知道这个蛋糕(模型)哪些部分做得好,哪些需要改进,我们就需要用到一种叫做反向传播的技术。它就像是蛋糕师傅检查每一层蛋糕是否完美一样。

反向传播和梯度下降一起工作,帮助我们找出模型中每个小决策者(神经元)需要改进的地方。这样,我们的模型就可以学习得更好,做出更准确的预测。

在很久以前,人们认为如果每个小决策者都只是做一些简单的计算,那么不管我们的模型有多大,它都只能做一些简单的事情。但是,有了激活函数,就像是给每个小决策者一个超级大脑,让他们可以一起解决非常复杂的问题。

这就是为什么我们现在的人工智能可以做得这么好,它们可以识别图片中的猫和狗,可以和我们聊天,甚至可以开车。所有这些都是因为有了这些聪明的函数和算法,它们让我们的机器变得智能。

这个现在看起来平平无奇的利用本科一年级就学过的复合函数的链式求导法则的反向传播算法,却是在罗森布拉特感知器发明的,27年后才被提出。正如深度学习领域的另一位巨头人物Angel说的那样,很多看似显而易见的想法,只有在事后才变得显而易见

编程实验​

好了,同学们我们开始做本节课的编程实验,本次编程实验呢我们主要来做两件事情,首先把sigmoid激活函数代入到预测模型中,然后我们知道代入激活函数的预测模型的代价函数是一个比较复杂的复合函数,所以我们使用复合函数的链式求导法则,求出代价函数在w和b上的导数,然后再进行梯度下降进行参数调整。

import utils.dataset as dataset
import numpy as np
import matplotlib
from matplotlib import pyplot as plt
import matplotlib.animation as animation
# 设置matplotlib正常显示中文和负号
matplotlib.rcParams['font.sans-serif']=['SimHei']   # 用黑体显示中文
matplotlib.rcParams['axes.unicode_minus']=False  

# define the function
def sigmoid(x):
    return 1/(1+np.exp(-x))
def f(x):
    return x*w+b

# 为了制作动画
ims=[]
fig = plt.figure()


# 初始化参数
w = np.random.randn(1)
b = np.random.randn(1)
alpha =0.05

# 有了sigmoid的训练过程
for _ in range(1000):
    for i in range(n):
        x=xs[i]
        y=ys[i]

        # 使用复合函数的链式求导法则,求出代价函数在w和b上的导数
        z = x*w+b
        a = 1/(1+np.exp(-z))
        e = (y-a)**2

        deda=-2*(y-a)
        dadz=a*(1-a)
        dzdw=x
        dzdb=1

        dedw = deda*dadz*dzdw
        dedb = deda*dadz*dzdb

        # 进行梯度下降,参数调整
        w = w - alpha*dedw
        b = b - alpha*dedb

预测动画