前言

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

代码及工具箱

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

正文

判断豆豆的毒性

判断一个人是否擅长打篮球,不能只看身高,还得考虑体重、灵活性,以及训练的刻苦程度等因素。同样,我们之前用豆豆的大小来预测它的毒性,这在现实中太简单了。现实中,豆豆的毒性不仅和大小有关,还和颜色有关。

三维空间中的预测模型

如果只用大小来预测,我们可以画在一个平面图上,横轴是大小,纵轴是毒性。但现在我们还得考虑颜色,所以需要一个三维图,其中第三根轴代表颜色深浅。这样,我们就可以在这个三维空间中,看到不同大小和颜色的豆豆对应的毒性了。只有那些大小和颜色都符合特定条件的豆豆才有毒。简单来说,就像在一个立体图中找到特定的有毒豆豆点一样。

神经网络与决策曲面

当我们在预测模型中增加了一个新的特征,比如豆豆的颜色深浅,我们的神经元需要接收两个输入:大小和颜色。这意味着预测函数的线性部分从简单的一元一次函数变成了更复杂的二元一次函数。

想象一下,在三维空间中,二元一次函数会形成一个平面,就像在二维空间中一元一次函数形成一条直线一样。这个平面的两个轴分别代表豆豆的大小和颜色深浅,而平面上的每一点则代表了一个特定的线性组合结果。

当这个线性结果通过神经元的非线性激活函数时,平面会被扭曲成一个曲面。这个曲面代表了在不同的大小和颜色深浅下,模型对豆豆毒性概率的预测结果。

如果我们在这个曲面上找到所有预测值恰好为0.5的点,并将这些点连接起来,就形成了一条分界线。这条分界线就像地理中的等高线一样,它将三维空间分成了两部分:一部分预测结果大于0.5(预测为有毒),另一部分预测结果小于0.5(预测为无毒)。

简而言之,通过增加颜色深浅这一特征并结合大小,我们的神经网络能够创建出一个复杂的决策曲面,这个曲面能够帮助我们更准确地区分哪些豆豆是有毒的,哪些是无毒的。

特征与模型复杂度

当我们增加更多的特征来预测结果时,比如豆豆的大小和颜色深浅,我们的模型需要能够捕捉这些特征间的复杂关系。在二维空间中,一个简单的线性模型(只有一个特征)可能会有一个0.5的等高线,它是一个点,可以作为分类的阈值。但在三维空间中,我们需要一个平面来表示这个关系,而这个平面上的0.5等高线则成为了一个类型分割线。

然而,如果豆豆的毒性不仅与大小和颜色有关,还可能涉及更复杂的非线性关系,那么单一的神经元和线性模型就不够用了。这就是所谓的线性不可分问题。在这种情况下,即使我们调整权重和偏置,得到的决策边界(0.5等高线)仍然是直线,无法适应弯曲的实际边界。

隐藏层神经元与非线性决策边界

为了解决这个问题,我们需要引入隐藏层神经元。隐藏层的神经元可以学习数据中的复杂模式,它们可以创建出非线性的决策边界,比如曲线,来更好地分割数据。通过在网络中添加多个隐藏层神经元,并让这些神经元通过梯度下降算法进行学习,我们可以组合出不同的形状,从而形成复杂的决策边界,以适应数据的实际分布。

当我们处理二元输入的情况,比如同时考虑豆豆的大小和颜色深浅,引入隐藏层神经元后,神经网络就可以在三维空间中创建出更复杂的曲面。这些曲面能够适应数据的实际分布,使得0.5的分割线(决策边界)不再是简单的直线,而是可以被扭曲成曲线,以适应更复杂的分类任务。

你提到的“直点”和“曲点”的概念是一个有趣的类比。在一元输入的二维预测函数模型中,加入隐藏层后,模型可以创建出更复杂的曲线,这些曲线可以被视为二维空间中的“曲点”。这表明,通过增加神经元和层数,神经网络能够学习和模拟出更复杂的决策边界。

至于你留下的小问题,如果豆豆的有毒概率分布呈现为一个圆形,即圈内的豆豆有毒而圈外的无毒,要实现这样的分类,隐藏层至少需要一个神经元。这是因为即使是单个神经元,只要给予合适的参数,也能够模拟出圆形的决策边界。当然,这通常需要非线性激活函数的帮助,比如Sigmoid或ReLU等。

这个问题也引出了神经网络中的一个核心概念:通用近似定理。该定理表明,一个具有足够数量隐藏层神经元的前馈神经网络,只要给予适当的训练,理论上可以近似任何复杂的函数。这意味着,无论数据分布如何复杂,只要网络足够大,都能找到合适的决策边界来实现分类。

高维空间的理解

随着数据特征的增加,比如在豆豆的例子中,除了大小和颜色深浅,我们还考虑外壳硬度,我们的预测模型需要在更高维度的空间中进行操作。这在直观上可能难以想象,因为我们生活在三维世界中,难以直接可视化四维或更高维度的空间。

然而,数学提供了一种强大的工具,可以帮助我们处理这种情况。在数学中,增加一个特征意味着在模型中增加一个维度。不管我们有多少特征,数学都能够处理,因为增加维度仅仅是一个抽象的概念。每个特征都被视为一个独立的维度,而神经网络能够在这些高维空间中找到数据间的复杂关系。

  • 数据维度:每个特征都是数据的一个维度,无论这个特征是数字、颜色、形状还是其他任何可量化的属性。

  • 抽象表示:尽管我们无法在高维空间中直观地可视化数据,数学模型可以抽象地表示这些维度,并通过计算来分析和理解数据。

  • 神经网络的能力:神经网络通过在高维特征空间中学习权重和偏置,能够捕捉特征间的复杂关系,即使这些关系在低维空间中不可见。

  • 决策边界的复杂性:随着维度的增加,决策边界(即分类面)可以变得更加复杂,神经网络能够适应这些复杂性,创建出适合数据分布的决策边界。

当我们收集豆豆的更多特征,比如它的长度、颜色,甚至硬度时,我们就能从不同的角度来了解它,这样预测它是否有毒就更加准确。就像评价一个人,不能只看外表,还要看他的内在品质和能力。

随着考虑的特征变多,模型需要学习的参数也会变多,手动去设置每一个参数会很复杂。幸运的是,我们有现代的机器学习工具,它们可以自动帮我们处理这些复杂的计算,让我们能够轻松地应对这些挑战。

在接下来的课程中,我们会介绍向量和矩阵,这些是处理多维度数据的关键数学工具。在机器学习和神经网络中,能否熟练运用向量和矩阵非常重要。

我们会开始使用keras这样的深度学习框架来构建神经网络。使用框架的好处是,我们不需要自己从头编写前向传播和反向传播的代码,梯度下降等细节也被框架自动处理。不过,无论我们是做工程实现还是参数调整,都离不开对矩阵和向量的使用。

好消息是,向量和矩阵的概念实际上并不复杂。从工科的角度看,它们是数学中相对容易理解的部分。在我们的课程中,只会用到最基础的向量和矩阵知识,所以不需要担心它们会很难掌握。只要掌握了这些基础知识,就能在机器学习和神经网络的学习和应用中游刃有余。

编程实验

本节课的编程实现就只实现【两个输入特征,一个神经元】的神经网络。【两个输入特征,两个以上神经元】的网络留待下节课,直接使用keras框架进行创建和训练。(不然手写反向传播会累死>︿<)

训练数据集

## Create a dataset
n = 100
xs, ys = dataset.get_beans5(n)

开始训练(后续可以改成向量形式)

w1 = 0.1
w2 = 0.1
b = 0.1
x1s = xs[:, 0]
x2s = xs[:, 1]

# 开始训练
def forward_propgation(x1s, x2s):
    z = w1*x1s+w2*x2s+b
    a = 1/(1+np.exp(-z))
    return a

for _ in range(500):
    for i in range(n):
        x = xs[i]
        y = ys[i]

        x1=x[0]
        x2=x[1]

        # 前向传播
        a = forward_propgation(x1, x2)
        e = (y-a)**2
        # 反向传播
        deda = -2*(y-a)
        dedz = deda*a*(1-a)
        dzdw1 = x1
        dzdw2 = x2
        dzdb = 1

        dedw1 = dedz*dzdw1
        dedw2 = dedz*dzdw2
        dedb = dedz*dzdb

        # 梯度下降

        w1 = w1-0.01*dedw1
        w2 = w2-0.01*dedw2
        b = b-0.01*dedb

plot_utils.show_scatter_surface(xs, ys, forward_propgation)

训练结果