【神经网络】 之 神经网络基础(一)

1.人与机器,各有所长

有些任务,对传统的计算机而言很容易,对人类而言却很难。例如,对数百万个数字进行乘法运算。
另一方面,有些任务对传统的计算机而言很难,对人类而言却很容易。例如,从一群人的照片中识别出面孔。

2.一个简单的预测机 

人的思考过程:

我们忽略机器处理的细节,可将神经网络的处理过程简化为下图(处理机)。

让我们稍微增加一点难度,举一个进度转换的例子。

现在想象一下,假设我们不知道千米和英里之间的转换公式,但知道它们直接是线性关系:“英里=千米×C”,其中C为常数。

现在,我们有一个真实的例子

【100千米 = 62.137英里】

我们试着设C=0.5,看看会发生什么情况。

这样,我们按C=0.5计算,得结果ans = 50,这与真实示例是有差距的,我们称之为【误差值】,

误差值=真实值-计算值 = 62.137-50 = 12.137。

我们知道错了,那应该做些什么呢?——上调C的值:我们将C稍微增加到0.6,得出ans=60,现在误差变小了,为2.137。如果对这个误差满意,计算就到此结束了。但如果还想继续缩小误差,那么我们再继续增大C的值,这次我们设C=0.7,得出ans=70。糟糕!过犹不及,误差值变成了-7.863。

改怎么解决这个问题呢?

我们尝试适度的调整C值,由0.6上调至0.61,得ans=61,误差值为1.137,误差更小了,说明这个方法奏效了。

我们来总结一下:

  • 所有有用的计算机系统都有一个输入和一个输出,并在输入和输出之间进行某种类型的计算。神经网络也是如此。
  • 当我们不能精确知道一些事情如何运作时,我们可以尝试使用模型来估计其运作方式,在模型中,包括了我们可以调整的参数。如果我们不知道如何将千米转换为英里,那么我们可以使用线性函数作为模型,并使用可调节的梯度值作为参数。
  • 改进这些模型的一种好方法是,基于模型和已知真实示例之间的比较,得到模型偏移的误差值,调整参数。

3.分类器与预测器并无太大差别

因为上述的简单机器接受了一个输入,并做出应有的预测,输出结果,所以我们将其称为预测器。我们根据结果与已知真实示例进行比较所得到的误差,调整内部参数,使预测更加精确。

现在,我们来看看测量得到的花园中小虫子的宽度和长度。

 在上图中,你可以清楚地看到两群小虫。毛虫细而长,瓢虫宽而短。

你还记得给定千米数,预测器试图找出正确的英里数这个示例吗?这台预测器的核心有一个可调节的线性函数。当你绘制输入输出的关系图时,线性函数输出的是直线。可调参数C改变了直线的斜率。

如果我们在这幅图上画上一条直线,会发生什么情况呢?

虽然我们不能使用先前将千米数转换成英里数时的同样方式,但是我们也许可以使用直线将不同性质的事物分开。

   

我们通过调整斜率,找到了一条合适的直线来将小虫分开。

设想一下,下一次,计算机使用机器手臂抓起一只新的小虫,测量其宽度和长度,然后它可以使用上面的分界线,将小虫正确归类为毛虫或瓢虫。(这就是一个预测器

但是,我们忽略了一个至关重要的因素。我们如何得到正确的斜率呢?我们如何改进不能很好划分这两种小虫的分界线呢?(请继续向下看)

4.训练简单的分类器

现在,我们有两个实例。

我们知道这组实例是正确的。这些实例帮助我们调整分类函数的斜率。用来训练预测器或分类器的真实实例,我们称为训练数据

让我们使用一条随机的分界线开始我们的讨论。回顾一下,在千米转换为英里预测器的实例中,我们有一个调整了参数的线性函数。此处,由于分界线是一条直线,因此我们也可以进行相同的处理:y =Ax

由于严格来说,此处的直线不是一台预测器,因此我们有意使用名称y和x ,而不使用名称长度和宽度。与先前我们将千米转换为英里不一样,这条直线不将宽度转换为长度。相反,它是一条分界线,是一台分类器。

之前,我们看到参数A控制着直线的斜率。较大的A对应着较大的斜率。

让我们尝试从A = 0.25开始,分界线为y = 0.25x 。在与训练数据的同一张图中,我们绘制这条直线,观察一下这是一种什么情况。

无需任何计算,我们可以观察到直线y = 0.25x 不是一台很好的分类器。这条直线未将两种类型的小虫区分开来。由于瓢虫也处在直线之上,因此我们不能说“如果小虫在直线之上,则这是一条毛虫”。

直观上,我们观察到需要将直线向上移动一点,但是我们要抵制诱惑,不能通过观察图就画出一条合适的直线。我们希望能够找到一种可重复的方法,也就是用一系列的计算机指令来达到这个目标。计算机科学家称这一系列指令为算法(algorithm)。

让我们观察第一个训练样本数据:宽度为3.0和长度为1.0瓢虫。如果我们使用这个实例测试函数y =Ax ,其中x 为3.0,我们得到:y =0.25*3.0= 0.75在这个函数中,我们将参数A设置为初始随机选择的值0.25,表明对于宽度为3.0的小虫,其长度应为0.75。但是,由于训练数据告诉我们这个长度必须为1.0,因此我们知道这个数字太小了。

现在,我们有了一个误差值。正如先前将千米转换为英里的预测器实例一样,我们可以利用这个误差值来搞清楚如何调整参数A。

但是,在我们调整参数A之前,让我们考虑y 应该是什么值。如果y 为1.0,那么直线就会恰好经过瓢虫所在的坐标点(x ,y )=(3.0,1.0)。这是一个非常微妙的点,但是实际上,我们并不希望出现这种情况。我们希望直线处于这个点上方。为什么呢?因为我们希望所有瓢虫的点处于直线下方,而不是在直线上。这条直线需要成为瓢虫和毛虫之间的一条分界线,而不是给定小虫宽度、预测小虫长度的一个预测器。

因此,当x = 3.0时,我们尝试使用y =1.1的目标值。这只是比1.0大一点的数。我们也可以选择1.2甚至1.3,但是我们不希望使用10或100这样较大的数字,因为这很可能会使得直线在瓢虫和毛虫上方,导致这个分类器没有一点作用。
因此,期望的目标值是1.1,误差值E为,误差值=(期望目标值 - 实际输出值),这样,E = 1.1-0.75 = 0.35。


让我们暂停下来提醒一下自己,将误差值、期望的目标值和计算值的意义在图上表示出来。

现在,我们需要对这个E做些什么,才能更好地指导我们调整参数A呢?这是一个重要的问题。

在这个任务中,让我们退一步再想一想。我们希望用y 中称为E的误差值,来搞清楚参数A所需改变的值。要做到这一点,我们需要知道两者的关系。A与E是如何关联的呢?如果我们知道了这一点,那么我们就可以理解更改一个值如何影响另一个值。

我们先从分类器的线性函数开始:y =Ax
我们知道,A的初始猜测值给出了错误的y 值,y 值应该等于训练数据给定的值。我们将正确的期望值t 称为目标值。为了得到t 值,我们需要稍微调整A的值。数学家使用增量符号Δ表示“微小的变化量”。下面我们将这个变化量写出来:
                                                                 t = (A + ΔA)x
让我们在图中将其画出来,以使其更容易理解。在图中,你可以看到新的斜率(A+ΔA)。

请记住,误差值E是期望的正确值与基于A的猜测值计算出来的值之间的差值。也就是说,E等于t -y 。

我们将这个过程写出来,这样就清楚了:t -y = (A + ΔA)x - Ax

展开表达式并化简:
         E =t -y = (A + ΔA)x - Ax
         E = (ΔA)x

这是多么美妙啊!误差值E与ΔA存在着一种简单的关系。这种关系如此简单,以至于我认为这是错的,但实际上这是正确的。无论如何,这种简单的关系让我们的工作变得相对容易。

我们很容易沉迷于代数,或由于代数而分心。让我们提醒自己,我们所希望的是摆脱这些代数,用一些简明的语言达到我们的目标。根据误差值E,我们希望知道需要将A调整多少,才能改进直线的斜率,得到一台更好的分类器。要做到这一点,我们只要重新调整上一个方程,将 ΔA算出:
                                                           ΔA= E / x
这就可以了!这就是我们一直在寻找的神奇表达式。我们可以使用误差值E,将所得到的ΔA作为调整分界线斜率A的量。
让我们开始吧 ——更新最初的斜率

误差值为0.35,x 为3.0。这使得ΔA = E / x = 0.35 / 3.0 = 0.1167。这意味着当前的A = 0.25需要加上0.1167。这也意味着,修正后的A值为(A+ΔA),即0.25 + 0.1167 = 0.3667。当A=0.3667时,使用这个A值计算得到的y 值为1.1,正如你所期望的,这就是我们想要的目标值。

唷!我们做到了!我们找到了基于当前的误差值调整参数的方法。
让我们继续前进吧!

现在,我们已经完成了一个实例训练,让我们从下一个实例中学习。此时,我们已知正确值对为x = 1.0和y = 3.0。当线性函数使用更新后的A = 0.3667,并把x = 1.0代入到线性函数中时,让我们观察会发生什么情况。我们得到y = 0.3667 * 1.0 = 0.3667。这与训练样本中y = 3.0相去甚远。

基于与先前同样的推理,我们希望直线不要经过训练数据,而是稍微高于或低于训练数据,我们将所需的目标值设置为2.9。这样,毛虫的训练样本就在直线上方,而不是在直线之上。误差值E为2.9-0.3667= 2.5333。

比起先前,这个误差值更大,但是如果仔细想想,迄今为止,我们只使用一个单一的训练样本对线性函数进行训练,很明显,这使得直线偏向于这个单一的样本。

与我们先前所做的一样,让我们再次改进A。ΔA为E / x ,即2.5333 /1.0 = 2.5333。这意味着较新的A为0.3667 + 2.5333 = 2.9。这也意味着,对于x = 1.0,函数得出了2.9的答案,这正是所期望的值。

这个训练量有点大了,因此,让我们再次暂停,观察我们已经完成的内容。下图显示出了初始直线、向第一个训练样本学习后的改进直线和向第二个训练样本学习后的最终直线。

等等,这是什么情况啊!看着这幅图,我们似乎并没有做到让直线以我们所希望的方式倾斜。这条直线没有整齐地划分出瓢虫和毛虫。

好了,我们理解了先前的诉求。改进直线,以得出各个所需的y 值。这种想法有什么错误呢?如果我们继续这样操作,使用各个训练数据样本进行改进,那么我们所得到的是,最终改进的直线与最后一次训练样本非常匹配。实际上,最终改进的直线不会顾及所有先前的训练样本,而是抛弃了所有先前训练样本的学习结果,只是对最近的一个实例进行了学习。

如何解决这个问题呢?

其实很简单!在机器学习中,这是一个重要的思路。我们应该进行适度改进(moderate)。也就是说,我们不要使改进过于激烈。我们采用ΔA几分之一的一个变化值,而不是采用整个ΔA,充满激情地跳跃到每一个新的A值。使用这种方法,我们小心谨慎地向训练样本所指示的方向移动,保持先前训练迭代周期中所得到的值的一部分。在先前相对简单的千米转换为英里的预测器中,我们就已经观察到这种有节制的调整,我们小心翼翼地调整参数C,使其只是实际误差值的几分之几

这种自我节制的调整,还带来了一个非常强大、行之有效的“副作用”。当训练数据本身不能确信为完全正确并且包含在现实世界测量中普遍出现的错误或噪声这两种情况时,有节制的调整可以抑制这些错误或噪声的影响。这种方法使得错误或噪声得到了调解和缓和。

好吧,让我们重新使用这种方法。但是这一次,在改进公式中,我们将添加一个调节系数:
ΔA= L(E / x )
调节系数通常被称为学习率(learning rate),在此,我们称之为L。

我们就挑L = 0.5作为一个合理的系数开始学习过程。简单说来,这就意味着我们只更新原更新值的一半。再一次重复上述过程,我们有一个初始值A = 0.25。使用第一个训练样本,我们得到y = 0.25 * 3.0 = 0.75,期望值为1.1,得到了误差值0.35。ΔA =
L(E / x )= 0.5 * 0.35 / 3.0 = 0.0583。更新后的A值为0.25 + 0.0583 =0.3083。

尝试使用新的A值计算训练样本,在x = 3.0时,得到y = 0.3083 * 3.0 =0.9250。现在,由于这个值小于1.1,因此这条直线落在了训练样本错误的一边,但是,如果你将这视为后续的众多调整步骤的第一步,则这个结果不算太差。与初始直线相比,这条直线确实向正确方向移动了。

我们继续使用第二个训练数据实例,x = 1.0。使用A = 0.3083,我们得到y = 0.3083 * 1.0 = 0.3083。所需值为2.9,因此误差值是2.9-0.3083=2.5917。ΔA = L(E / x ) = 0.5 * 2.5917 / 1.0 = 1.2958。当前,第二个更新的值A等于0.3083 + 1.2958 = 1.6042。

让我们再次观察初始直线、改进后的直线和最终直线,观察这种有节制的改进是否在瓢虫和毛虫区域之间是否得到了更好的分界线。

 结果真的很不错!
即使使用这两个简单的训练样本,利用带有调节学习速率的一种相对简单的改进方法,我们也非常迅速地得到了一条很好的分界线y =Ax ,其中A为1.6042。

让我们先放下已经取得的成就。我们已经实现了自动化的学习方法,虽然方法非常简单,但卓有成效地对若干实例进行分类。

这太棒了!

我们再简单总结一下。

  • 我们使用简单的数学,理解了线性分类器输出误差值和可调节斜率参数之间的关系。也就是说,我们知道了在何种程度上调整斜率,可以消除输出误差值。
  • 使用朴素的调整方法会出现一个问题,即改进后的模型只与最后一次训练样本最匹配,“有效地”忽略了所有以前的训练样本。解决这个问题的一种好方法是使用学习率,调节改进速率,这样单一的训练样本就不能主导整个学习过程。
  • 来自真实世界的训练样本可能充满噪声或包含错误。适度更新有助于限制这些错误样本的影响。

【参考资料】:Python神经网络编程~[英]塔里克·拉希德(Tariq Rashid)著,林赐 译.

猜你喜欢

转载自blog.csdn.net/Aibiabcheng/article/details/106911064