1.1 序言——探索智能机器
千百年来,人类试图了解智能的机制,并将它复制到思维机器上。
人类从不满足于让机械或电子设备帮助做一些简单的任务,例如使用滑轮吊起沉重的岩石,使用计算器做算术。
人类希望计算机能够自动化执行更具有挑战性、相对复杂的任务,如对相似的照片进行分组、从健康细胞中识别出病变细胞,甚至是来一盘象棋博弈。这些任务似乎需要人类的智能才能完成,或至少需要人类思维中的某种更深层次、更神秘的能力来完成,而在诸如计算器这样简单的机器中找不到这种能力。
1997年,国际象棋卫冕世界冠军、国际象棋特级大师加里·卡斯帕罗夫被IBM“深蓝”计算机击败,人类在庆祝这一历史性成就的同时,也担心机器智能的潜力。
2016年3月,阿尔法围棋程序(AlphaGo)挑战世界围棋冠军李世石,以4比1的总比分取得了胜利。此事震惊世界,2016年因此被称为人工智能(Artificial Intelligence,AI)元年。
2022年11月,OpenAI公司发布了ChatGPT聊天机器人,成为历史上用户增长最快的消费者应用,并在世界范围内引起广泛关注。
ChatGPT 与人工智能发展史:从起源到未来
ChatGPT来了,人工智能时代,我们该如何应对?
ChatGPT 席卷全球,为什么会伴随恐慌?
为什么会引发这么大的轰动呢?
机器的学习能力,作为人工智能的核心要素,将会对人类社会的生产、生活、军事等活动产生难以估量的影响,极有可能是颠覆性、革命性的。
1.2 人工智能的新黄金时代
在20世纪50年代,人工智能这门学科正式成立,此时,人类雄心勃勃,对人工智能抱着非常乐观的态度。最初的成功,让人们看到了计算机可以进行简单的博弈、证明定理,因此,一些人相信,在十年左右的时间内,人类级别的人工智能将会出现。
但是,实践证明:发展人工智能困难重重,进展一度停滞不前。20 世纪70年代,人们在学术界挑战人工智能的雄心遭到了毁灭性的打击。
接下来,人们削减了人工智能研究经费,对人工智能的兴趣消失殆尽。
机器那冰冷的逻辑,绝对的1和0,看起来似乎永远不能够实现细致入微的、有机的,有时甚至模糊的生物大脑思维过程。
在一段时间内,人类无法更进一步,将机器智能探索带出其既定轨迹。
在此之后,研究人员灵光一现,是否可以通过复制生物大脑工作的机制来构建人工大脑?
真正的大脑具有神经元,具有更优雅更有机的推理,而不是冰冷的、非黑即白的、绝对的传统算法。
蜜蜂或鸽子大脑的简单性与其能够执行复杂任务的巨大反差,这一点启发了科学家。就是这零点几克的大脑,看起来就能够做许多事情,如导航、适应风向、识别食物和捕食者、快速地决定是战斗还是逃跑。
受到仿生智能计算的驱动,神经网络(Netural Network)出现了,并且神经网络从此成为在人工智能领域中最强大、最有用的方法之一。
今天,谷歌的Deepmind以神经网络为基础,能够做一些非常奇妙的事情,如让计算机学习如何玩视频游戏,并且在人类历史上第一次在极其变化多端的围棋博弈中击败了世界级的大师。如今,神经网络已经成为了日常技术的核心,例如自动车牌号码识别、解码手写的邮政编码。
本课程所探讨的就是神经网络,让大家了解神经网络如何工作,做出自己的神经网络,训练神经网络来完成特定任务。
1.3 深度学习的概念
先看一张图:
人工智能:是机器展现的人类智能,它的含义很广泛,是一个综合性系统。
机器学习:计算机利用已有的数据(经验),找出某种规律构建模型,并用它来解决实际问题。它是实现人工智能的一种方法,并非实现人工智能的唯一方法,但是近年来人工智能的研究一般使用机器学习。
深度学习:是机器学习的一个重要分支和延伸,是包含多隐层的神经网络结构。深度学习通过组合低层特征形成更加抽象的高层表示属性类别或特征,从而学习到数据本身最关键的特征。简单来说,深度学习就是更深、更加复杂的神经网络结构。
1.4 计算机和人类的特长
计算机的核心是计算器,这些计算器做算术非常快,对于执行与计算器相匹配的任务而言,非常擅长于对数字进行相加算出销售额、运用百分比算出税收、绘制现存数据的图表等。
计算机可以以相当快的速度,在1秒钟内进行4位数甚至10位数的相加,但是这不是人工智能。人类虽然很难快速地进行加法运算,但进行加法运算的过程不需要太多的智慧。简单说来,这只要求计算机拥有遵循基本指令的能力,而这正是计算机内的电子器件所做的事情。
观察下面的图片,看看能认出图片中包含哪些内容。
我们可以看到了人脸、猫和树的图片,并识别出了这些内容。事实上,人类可以以非常高的精确度快速地做到这一点。在这方面,人类通常不会出错。
人类可以处理图像中所包含的相当大量的信息,并且可以成功地识别图像中有哪些内容。但这种任务对计算机而言,并不是那么容易,实际上,是相当困难的。
问题 | 计算机 | 人类 |
---|---|---|
快速地对成千上万的大数字进行乘法运算 | 简单 | 困难 |
在一大群人的照片中查找面孔 | 困难 | 简单 |
科学家们怀疑图像识别需要人类智能,这正是机器所缺乏的。无论人类造出的机器多么复杂和强大,它依然不是人类。但是,由于计算机速度非常快,并且不知疲倦,人类恰恰希望计算机能更好地进行求解图像识别这类问题。人工智能所探讨的一切问题就是解决这种类型的难题。
1.有些任务,对传统的计算机而言很容易,对人类而言却很难。例如,对数百万个数字进行乘法运算。
2.另一方面,有些任务对传统的计算机而言很难,对人类而言却很容易。例如,从一群人的照片中识别出面孔。
当然,计算机将永远使用电子器件制造,因此研究人工智能的任务就是找到新方法或新算法,使用新的工作方式,尝试求解这类相对困难的问题。即使计算机不能完美地解决这些问题,只要计算机表现足够出色,依然可以给人们留下一种印象,觉得这是智能在起作用。
1.5 神经元——大自然的计算器
一些计算机拥有大量的电子计算元件、巨大的存储空间,并且运行频率比肉蓬蓬、软绵绵的生物大脑要快得多,但即使是像鸽子一样小的大脑,其能力也远远大于这些电子计算机,这使得科学家们对动物大脑迷惑不解。
传统的计算机按照严格的串行顺序,相当准确具体地处理数据。对于这些冰冷坚硬的计算机而言,不存在模糊性或不确定性。而另一方面,动物的大脑表面上看起来以慢得多的节奏运行,却似乎以并行方式处理信号,模糊性是其计算的一种特征。
下面是生物大脑中的基本单元——神经元。
虽然神经元有各种形式,但是所有的神经元都是将电信号从一端传输到另一端,沿着轴突,将电信号从树突传到树突。然后,这些信号从一个神经元传递到另一个神经元。这就是身体感知光、声、触压、热等信号的机制。来自专门的感觉神经元的信号沿着神经系统,传输到大脑,而大脑本身主要也是由神经元构成的。
需要多少个神经元才能执行相对复杂的有趣任务呢?
一般说来,能力非常强的人类大脑有大约1000亿个神经元!一只果蝇拥有约10万个神经元,能够飞翔、觅食、躲避危险、寻找食物以及执行许多相当复杂的任务。10万个神经元,这个数字恰好落在了现代计算机试图复制的范围内。一只线虫仅仅具有302个神经元,与今天的数字计算机资源相比,简直就是微乎其微!但是一只线虫能够完成一些相当有用的任务,而这任务对于尺寸大得多的传统计算机程序而言却难以完成。
那么,其中有什么秘密吗?生物的大脑要慢得多,并且比起现代计算机,其计算元件相对较少,但是为什么生物的大脑却有如此能力呢?
现在查看一个神经元是如何工作的。它接受了一个电输入,输出另一个电信号。
因此,是否可以考虑将神经元表示为线性函数?
生物神经元与简单的线性函数不一样,不能简单地对输入做出的响应,生成输出。也就是说,它的输出不能采用这种形式:输出=(常数×输入)+(也许另一常数)。
观察表明,神经元不会立即反应,而是会抑制输入,直到输入增强,强大到可以触发输出。可以这样认为,在产生输出之前,输入必须到达一个阈值。就像水在杯中——直到水装满了杯子,才可能溢出。神经元不希望传递微小的噪声信号,而只是传递有意识的明显信号。下图说明了这种思想,只有输入超过了阈值(threshold),足够接通电路,才会产生输出信号。
这个函数接受了输入信号,产生了输出信号,所以要将某种称为激活函数的阈值考虑在内。在数学上,有许多激活函数可以达到这样的效果。一个简单的阶跃函数可以实现这种效果。
可以看到,在输入值较小的情况下,输出为零。然而,一旦输入达到阈值,输出就一跃而起。具有这种行为的人工神经元就像一个真正的生物神经元。科学家所使用的术语实际上非常形象地描述了这种行为,当输入达到阈值时,神经元就激发了。
也可以继续改进阶跃函数。下图所示的 S S S形函数称为 S S S函数(sigmoid function)。这个函数,比起冷冰冰的阶跃函数要相对平滑,这使得这个函数更自然、更接近现实。
本课程将主要使用这种平滑的
S
S
S形函数制作神经网络。虽然人工智能研究人员还使用其他外形类似的函数,但是
S
S
S函数简单并且事实上非常常见。
S
S
S函数,有时也称为逻辑函数:
字母 e e e是数学常数2.71828 ……,出现在各种数学和物理学领域,使用省略号的原因是,它是一个无限不循环小数。
这个函数先对输入的 x x x取反,计算出 e e e的 − x -x −x次方,然后将所得到的结果加1,得到 1 + e − x 1 + e^{-x} 1+e−x;最后,对整个结果取倒数,也就是1除以 e − x e^{-x} e−x,做为输出值 y y y给出。
由于任何数的0次方都等于1,因此当 x x x为0时, e − x e^{-x} e−x为1。因此 y y y变成了 1 / ( 1 + 1 ) 1/(1 + 1) 1/(1+1),为1/2。此时,基本 S S S形函数在 y = 1 2 y = \frac{1}{2} y=21时,对 y y y轴进行切分。
在神经元的输出中使用 S S S形函数还有另一个非常重要的原因, S S S函数比起其他 S S S形函数计算得多,在后面的实践中,会看到为什么。
import matplotlib.pyplot as plt
import numpy as np
def sigmoid(x):
return 1 / (1 + np.exp(-x))
a = np.linspace(-5, 5, 100)
plt.plot(a,sigmoid(a))
运行结果如下:
现在回到神经元,思考如何建模人工神经。
现在要认识到的第一件事情是生物神经元可以接受许多输入,而不仅仅是一个输入。
对于所有这些输入,该做些什么呢?
只需要对它们进行相加,得到最终总和,作为 S S S函数的输入,然后输出结果。这实际上反映了神经元的工作机制。下图说明了这种组合输入,然后对最终输入总和使用阈值的思路。
如果组合信号不够强大,那么
S
S
S阈值函数的效果是抑制输出信号。如果总和
x
x
x足够大,
S
S
S函数的效果就是激发神经元。如果只有其中一个输入足够大,其他输入都很小,那么这也足够激发神经元。更重要的是,如果其中一些输入,单个而言一般大,但不是非常大,这样由于信号的组合足够大,超过阈值,那么神经元也能激发。这带来了一种直观的感觉,即这些神经元也可以进行一些相对复杂、在某种意义上有点模糊的计算。
树突收集了这些电信号,将其组合形成更强的电信号。如果信号足够强,超过阈值,神经元就会发射信号,沿着轴突,到达终端,将信号传递给下一个神经元的树突。
下图是使用这种方式连接的若干神经元。
注意,每个神经元接受来自其之前多个神经元的输入,并且如果神经元被激发了,它也同时提供信号给更多的神经元。
将这种自然形式复制到人造模型的一种方法是,构建多层神经元,每一层中的神经元都与在其前后层的神经元互相连接。下图详细描述了这种思想。
现在可以看到三层神经元,每一层有三个人工神经元或节点。还可以看到每个节点都与前一层或后续层的其他每一个节点互相连接。
这看起来很酷的体系架构,哪一部分能够执行学习功能呢?针对训练样本,应该如何调整做出反应呢?有没有和先前线性分类器中的斜率类似的参数进行调整呢?
最明显的一点就是调整节点之间的连接强度。在一个节点内,可以调整输入的总和或
S
S
S阈值函数的形状,但是比起简单地调整节点之间的连接强度,调整
S
S
S阀值函数的形状要相对复杂。
如果相对简单的方法可以工作,那么就可以坚持下去。下图再一次显示了连接的节点,但是这次在每个连接上显示了相关的权重。较小的权重将弱化信号,而较大的权重将放大信号。
此处需要解释一下权重符号旁边的有趣小数字(即下标)。简单说来,权重 w 2 , 3 w_{2,3} w2,3与前一层节点2传递给下一层的节点3的信号相关联。因此,权重 w 1 , 2 w_{1,2} w1,2减小或放大节点1传递给下一层节点2的信号。为了详细说明这种思路,下图突出显示了第一层和第二层之间的两条连接。
为什么神经网络一定是这种结构?
不采用其它方式,原因有两点,第一是这种一致的完全连接形式事实上可以相对容易地编码成计算机指令,第二是神经网络的学习过程将会弱化这些实际上不需要的连接(也就是这些连接的权重将趋近于0),因此对于解决特定任务所需最小数量的连接冗余几个连接,也无伤大雅。
随着神经网络学习过程的进行,神经网络通过调整优化网络内部的链接权重改进输出,一些权重可能会变为零或接近于零。零或几乎为零的权重意味着这些链接对网络的贡献为零,因为没有传递信号。零权重意味着信号乘以零,结果得到零,因此这个链接实际上是被断开了。
1.虽然比起现代计算机,生物大脑看起来存储空间少得多,运行速度比较慢,但是生物大脑却可以执行复杂的任务,如飞行、寻找食物、学习语言和逃避天敌。
2.相比于传统的计算机系统,生物大脑对损坏和不完善信号具有难以置信的弹性。
3.由互相连接的神经元组成的生物大脑是人工神经网络的灵感来源。
1.6 神经网络的数值传递
每个神经元都与其前后层的每个神经元相互连接的三层神经元图片,看起来让人相当惊奇。
但是,计算信号如何经过一层一层的神经元,从输入变成输出,这个过程有点令人生畏,看上去是个非常艰苦的工作。
现在尝试使用只有两层、每层两个神经元的较小的神经网络,来演示神经网络如何工作,如下图所示。
想象一下,两个输入值分别为1.0和0.5。这些值输入到这个较小的神经网络,如下图所示。
每个节点都使用激活函数,将输入转变成输出。使用先前的 S S S函数 y = 1 / ( 1 + e − x ) y = 1/(1 + e^{−x}) y=1/(1+e−x),其中神经元输入信号的总和为 x x x,神经元输出为 y y y。
权重是什么?权重的初始值应该为多少?一般使用随机权重:
-
w 1 , 1 = 0.9 w_{1,1} = 0.9 w1,1=0.9
-
w 1 , 2 = 0.2 w_{1,2} = 0.2 w1,2=0.2
-
w 2 , 1 = 0.3 w_{2,1} = 0.3 w2,1=0.3
-
w 2 , 2 = 0.8 w_{2,2} = 0.8 w2,2=0.8
随机初始值也是在先前简单的线性分类器中选择初始斜率值时采取的方案。随着分类器学习各个样本,随机值就可以得到改进。对于神经网络链接的权重而言也是一样的。
在这个小型的神经网络中,由于连接每一层中两个节点的组合就只有四种连接方式,因此只有四个权重。下图标出了当前所知的所有数字。
开始计算:
第一层节点是输入层,这一层不做其他事情,仅表示输入信号。也就是说,输入节点不对输入值应用激活函数。这没有什么其他奇妙的原因,就是这样的规定。神经网络的第一层是输入层,这层所做的所有事情就是表示输入,仅此而已。
第一层输入层很容易,此处,无需进行计算。
接下来的第二层需要做一些计算,对于这一层的每个节点需要算出组合输入。 S S S函数 y = 1 / ( 1 + e − x ) y = 1/(1 + e^{−x}) y=1/(1+e−x)中,这个函数中的 x x x表示一个节点的组合输入。此处组合的是所连接的前一层中的原始输出,但是这些输出得到了链接权重的调节。下图是先前所看到的一幅图,但是现在,这幅图包括使用链接权重调节输入信号的过程。
首先关注第二层的节点1。第一层输入层中的两个节点连接到了这个节点。这些输入节点具有1.0和0.5的原始值。来自第一个节点的链接具有0.9的相关权重,来自第二个节点的链接具有0.3的权重。因此,组合经过了权重调节后的输入,如下所示:
x = (第一个节点的输出 ∗ 链接权重) + (第二个节点的输出 ∗ 链接权重) x = (第一个节点的输出*链接权重)+(第二个节点的输出*链接权重) x=(第一个节点的输出∗链接权重)+(第二个节点的输出∗链接权重)
x = ( 1.0 ∗ 0.9 ) + ( 0.5 ∗ 0.3 ) x =(1.0 * 0.9)+(0.5 * 0.3) x=(1.0∗0.9)+(0.5∗0.3)
x = 0.9 + 0.15 x = 0.9 + 0.15 x=0.9+0.15
x = 1.05 x = 1.05 x=1.05
现在,得到 x = 1.05 x=1.05 x=1.05,这是第二层第一个节点的组合调节输入。使用激活函数 y = 1 / ( 1 + e − x ) y = 1/(1 + e^{−x}) y=1/(1+e−x)计算该节点的输出,可以使用计算器,答案为 y = 1 / ( 1 + 0.3499 ) = 1 / 1.3499 y = 1 /(1 + 0.3499)= 1 / 1.3499 y=1/(1+0.3499)=1/1.3499, y = 0.7408 y = 0.7408 y=0.7408。
现在得到了神经网络两个输出节点中的一个的实际输出。
继续计算剩余的节点,即第二层第二个节点。组合调节输入 x x x为:
x = (第一个节点的输出 ∗ 链接权重) + (第二个节点的输出 ∗ 链接权重) x = (第一个节点的输出*链接权重)+(第二个节点的输出*链接权重) x=(第一个节点的输出∗链接权重)+(第二个节点的输出∗链接权重)
x = ( 1.0 ∗ 0.2 ) + ( 0.5 ∗ 0.8 ) x =(1.0 * 0.2)+(0.5 * 0.8) x=(1.0∗0.2)+(0.5∗0.8)
x = 0.2 + 0.4 x = 0.2 + 0.4 x=0.2+0.4
x = 0.6 x = 0.6 x=0.6
继续使用 S S S激活函数 y = 1 / ( 1 + 0.5488 ) = 1 / 1.5488 y = 1/(1 + 0.5488) = 1/1.5488 y=1/(1+0.5488)=1/1.5488计算节点输出,得到 y = 0.6457 y = 0.6457 y=0.6457。下图显示了刚刚计算得到的网络输出。
从一个非常简化的网络得到两个输出值,这个工作量相对较小。对于一个相对较大的网络,是无法使用手工进行计算的。好在计算机在进行大量计算方面表现非常出色,并且不知疲倦和厌烦。
对于多于两层,每一层有4、8甚至100个节点的网络,我们也也不希望编写计算机指令来对这样的网络进行计算。即使只是写出所有层次和节点的计算指令,也会感到枯燥,甚至我犯错,更不用说手工进行这些计算了。
好在,即使是面对一个具有很多层、众多节点的神经网络,数学知道可以以非常简洁的方式写下计算出所有输出值的指令。由于这种简洁性,指令变得非常短,执行起来也更有效率,因此这种简洁性不仅仅对人类有益处,对计算机而言,也一样大有裨益。