第十课 CS231N 动手实现反向传播

-------------------------

1.简单预测题

2.python代码

3.代码讲解

4.数学计算过程

-------------------------

想要更好的消化课程内容,不动手是不行的,所以写了这篇实验课程,课程内容也是参考了网络素材(很直观,也解释的很清楚),参考链接http://python.jobbole.com/82758/,我在这个基础之上加入了一些自己的理解,将程序执行的每个数学过程进行了梳理,方便记忆。整个代码使用python写的,需要一定的python基础。

一、简单预测题

1)题目

为了将原理表述清楚,本节拿一个简单的例子,并且用python进行编码实现。我们的训练数据只有4个,单个数据有3个维度,输入三个变量x1,x2,x3,然后输出1个结果数据y),如下图所示

考虑以上情形:给定三列输入,试着去预测对应的一列输出。 我们给的是比较少的训练数据,所以可以很容易就可以看出来里面的模型:第一列的输入和输出完全一致(在实际当中,有海量的数据 ,这个规则是很难发现出来)。

2)目标

我们的目标是建立一个分类方法y=f(x,w),通过上面的训练数据,结合反向传播算法,不断的优化,得到一个靠谱的w,这个w预测出来的值,要和实际值的误差尽量小,越小说明模型越精准。

3)方法

我们构建一个2层的神经网络,使用sigmoid函数进行计算,通过反向传播算法,不断优化和调整权重w的系数。

二、python代码

--------------------

import numpy as np

# 定义sigmoid function函数,deriv就可以得到它的导数

def nonlin(x,deriv=False):

if(deriv==True):

return x*(1-x)

return 1/(1+np.exp(-x))

# 数据数据集,每个数据集有三个变量,共4个数据实例

X = np.array([ [0,0,1],

[0,1,1],

[1,0,1],

[1,1,1] ])

# 定义输出数据集,为了方便编写,使用了转置T

y = np.array([[0,0,1,1]]).T

# 设定随机函数,随机种子为1

#初始化权重,是一个3行一列的向量

#进行训练

for iter in range(1000):

# forward propagation

l0 = X

#输出训练结果

l1 = nonlin(np.dot(l0,syn0))

#训练结果与真实结果比对,计算出损失值

l1_error = y - l1

# slope of the sigmoid at the values in l1

l1_delta = l1_error * nonlin(l1,True)

# 更新权重值

syn0 += np.dot(l0.T,l1_delta)

print("Output After Training:")

print(l1)

print(syn0)

-----------------------

下面是一次训练的结果(我们真实的结果是0,0,1,1,随机提取了一个训练结果)还是比较接近的

Output After Training:

三、代码讲解

1) 导入numpy 的线性代数工具库

import numpy as np

2) 定义sigmoid function函数,

如果deriv为true就可以得到它的导数,这个函数也可以为其他函数,这里我们选了sigmoid,他的特性是其倒数可以很容易起出来,若 Sigmoid 的输出值用变量 out 表示,则其导数值可简单通过式子 out *(1-out) 得到,这是非常高效的。

def nonlin(x,deriv=False):

if(deriv==True):

return x*(1-x)

return 1/(1+np.exp(-x))

3)初始化输入数据集和输出数据集

数据数据集,每个数据集有三个标量,共4个数据实例;# 定义输出数据集,为了方便编写,使用了转置T

X = np.array([ [0,0,1],

[0,1,1],

[1,0,1],

[1,1,1] ])

y = np.array([[0,0,1,1]]).T

4)设定随机函数,随机种子为1

我们的数字仍然会随机分布但是每次随机生成的方式都是一样的。这样就会让我们更容易的观察网络的改变。随机数种子对后面的结果一直有影响。同时,加了随机数种子以后,后面的随机数组都是按一定的顺序生成的。这个参数设置可以随意

5)初始化权重,权重初始值为随机数,是一个3行一列的向量

6)基于迭代的方式优化神经网络,进行训练

for iter in range(1000):

# 前向计算,我们的输入数据,记住X包含4个训练样例(4行)

l0 = X

7)输出训练结果

这一步用来进行预测。本质上来讲,我们首先让网络通过输入“尝试着”去预测输出。然后我们就研究怎么样每次循环都去逐步适应使得系统表现更好。这一行包含两个步骤。第一步用l0乘以syn0。第二步从sigmoid函数中获得输出

l1 = nonlin(np.dot(l0,syn0))

8)训练结果与真实结果比对,计算出损失值

现在l1对于每个输入有了一个“猜测”的输出。现在我们可以通过用真实值y减去猜测值l1来比较“猜测”的效果。l1_error是一个包含正数与负数的向量,揭示出当前的网络到底有多少误差。

l1_error = y - l1

# slope of the sigmoid at the values in l1

9)最关键部分,

l1_delta = l1_error * nonlin(l1,True)

先求出导数,之所以求出这个,前面的博文中已经讲明了,想象一下梯度的表达式

10)更新权重

syn0 += np.dot(l0.T,l1_delta)

print("Output After Training:")

syn0 =syn0+ np.dot(l0.T,l1_delta)

四、数学计算过程

实际优化过程中,会持续不断的进行,我们就选择其中一次优化过程进行分析

第一步,使用Sgmoid作为激活函数

第二步,定义输入矩阵x,输出矩阵y,权重矩阵syn0(这里的权重是随机选出来的)

第三步,将X赋给输入层l0

第四步,输入值是l0,通过sigmoid函数,计算出预测结果l1

第五步、计算预测输出和实际值偏差

第六步、计算预测输出的偏导(预测偏差*输入的偏导),这个结果

第七步,根据预测输出的偏导,调整syn0的值(反向传播)

计算出新的权重后,开始下一轮的优化,从权重调整的结果看,第一列的权重调整的是最多的,达到0.28,比其他两个0.03,0.12明显要搞出,这个也比较符合实际(理想模型就是第一列主要影响输出,其他2列影响结果)

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180930G21TMF00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

同媒体快讯

扫码关注云+社区

领取腾讯云代金券