跟着这个教程一步步理解反向传播算法
欢迎关注天善智能,我们是专注于商业智能BI,人工智能AI,大数据分析与挖掘领域的垂直社区,学习,问答、求职一站式搞定!
对商业智能BI、大数据分析挖掘、机器学习,python,R等数据领域感兴趣的同学加微信:tstoutiao,邀请你进入数据爱好者交流群,数据爱好者们都在这儿。
作者:张小鸡 人工智能爱好者社区专栏作者
知乎ID:https://www.zhihu.com/people/mr.ji
个人公众号:鸡仔说
每一个认真生活的人,都应该认真学一下机器学习。骄傲者从中获得谦卑,浮躁者从中获得平静,就犹如体验过波涛风浪或生死洗礼一样。从此,便真真地知道了:自己是个弱鸡。
哔哔完了,进入正题,在此之前,希望你已经对基础的神经网络有一个了解,而反向传播算法,其实是一个寻求最优解的过程。包括我在内的很多人,一开始都认为其中的原理很难,但其实不是,反向传播算法之所以被广泛应用,除了有效性外,私以为还得益于它的容易理解。看过《土拨鼠之日》的人,一定希望拥有和男主一样的奇特经历。因为它的奇妙之处,是可以一次次地返回去实验,如果失败了,则得到反馈,再优化。相应的,反向传播算法也是如此,一次次的返回去重来,得到最优解。
下面咱们从从最简单三层神经网络开始,即输入层,隐含层和输出层。输入层包含两个神经元i1, i2,隐含层包含两个神经元h1, h2,输出层同样是两个神经元o1, o2,输入层和隐含层的偏置项分别为b1, b2,**函数默认为sigmod函数。
现在我们对它们附上初始值,如下图所示:
其中:
输入数据 i1=0.05,i2=0.10;
输出数据 o1=0.01,o2=0.99;
初始权重 w1=0.15,w2=0.20,w3=0.25,w4=0.30;
w5=0.40,w6=0.45,w7=0.50,w8=0.55
还记得我们的最终目标吧?给出初始值i1,i2,求出使得离目标输出最接近的系数值,即(wi, bi)
一步步的推导过程我再次不赘述,可以参考下原文,传送门在文末参考
我说一下具体的代码实现部分的一些细节。Matt Mazur大佬的代码清晰易读,而且分类特别赞,我们回顾一下上面的结构,发现整个神经网络系统就分为两个部分:神经元和连接神经元的线(即权重和偏置项),分工也很清晰明了。神经元负责的有:
向前传播:加权和,**函数,输出函数,误差
反向传播:误差偏导,输出函数到**函数的偏导,**层到加权和的偏导
它们之间的连线,也就是网络层,负责对神经元的操控,它只需要负责向前传播和得到输出的结果。有了如上的结构,便可以来搭建整个网络了,黑喂狗~~
首先编写神经元:
1classNeuron():
2
3def__init__(self, bias):
4self.bias = bias
5self.weights = []
6
7defcalculate_output(self, inputs):
8self.inputs = inputs
9self.out_put =self.activate(self.calculate_total_net_input())
10returnself.out_put
11
12defcalculate_total_net_input(self):
13total =0
14foriinrange(len(self.inputs)):
15total +=self.weights[i] *self.inputs[i]
16returntotal +self.bias
17
18defactivate(self, total_net_input):
19return1/(1+math.exp(-total_net_input))
20
21defcalculate_error(self, target_output):
22return0.5* (target_output -self.out_put) **2
23
24# ∂E/∂yⱼ
25defcalculate_pd_error_wrt_output(self, target_output):
26return- (target_output -self.out_put)
27
28# dyⱼ/dzⱼ = yⱼ * (1 - yⱼ)
29defcalculate_pd_active_wrt_total_net_input(self):
30returnself.out_put * (1-self.out_put)
31
32# ∂zⱼ/∂wᵢ = wᵢ
33defcalculate_pd_total_net_input_wrt_weight(self, index):
34returnself.inputs[index]
35
36# δ = ∂E/∂zⱼ = ∂E/∂yⱼ * dyⱼ/dzⱼ
37defcalculate_pd_error_wrt_total_net_input(self, target_output):
38returnself.calculate_pd_error_wrt_output(target_output) *self.calculate_pd_active_wrt_total_net_input()
接下来我们编写网络层部分的代码:
1classNeuronLayer():
2
3def__init__(self, num_neurons, bias):
4self.bias = bias
5self.neurons = []
6foriinrange(num_neurons):
7self.neurons.append(Neuron(bias))
8
9deffeed_forward(self, inputs):
10outputs = []
11forneuroninself.neurons:
12outputs.append(neuron.calculate_output(inputs))
13returnoutputs
14
15defget_outs(self):
16outputs = []
17forneuroninself.neurons:
18outputs.append(neuron.out_put)
19returnoutputs
最后,我们由它们来组合我们的整个网络结构:
1classNeuralNetwork():
2LEARNING_RATE =0.5
3
4def__init__(self, num_inputs, num_hiddens, num_outputs, hidden_layer_weights=None, hidden_layer_bias=None, output_layer_weights=None, output_layer_bias=None):
5self.num_inputs = num_inputs
6
7self.hidden_layer = NeuronLayer(num_hiddens, hidden_layer_bias)
8self.output_layer = NeuronLayer(num_outputs, output_layer_bias)
9
10self.init_weights_from_inputs_to_hidden_layer_neurons(hidden_layer_weights)
11self.init_weights_from_hidden_layer_neurons_to_output_layer_neurons(output_layer_weights)
12
13definit_weights_from_inputs_to_hidden_layer_neurons(self, hidden_layer_weights):
14weight_num =0
15forhinrange(len(self.output_layer.neurons)):
16foriinrange(self.num_inputs):
17ifnothidden_layer_weights:
18self.hidden_layer.neurons[h].weights.append(random.random())
19else:
20self.hidden_layer.neurons[h].weights.append(hidden_layer_weights[weight_num])
21weight_num +=1
22
23definit_weights_from_hidden_layer_neurons_to_output_layer_neurons(self, output_layer_weights):
24weight_num =0
25foroinrange(len(self.output_layer.neurons)):
26forhinrange(len(self.hidden_layer.neurons)):
27ifnotoutput_layer_weights:
28self.output_layer.neurons[o].weights.append(random.random())
29else:
30self.output_layer.neurons[o].weights.append(output_layer_weights[weight_num])
31weight_num +=1
32
33deffeed_forward(self, inputs):
34hidden_layer_outputs =self.hidden_layer.feed_forward(inputs)
35returnself.output_layer.feed_forward(hidden_layer_outputs)
36
37deftrain(self, train_inputs, train_outputs):
38self.feed_forward(train_inputs)
39
40pd_errors_wrt_output_neuron_total_net_input = [0]*len(self.output_layer.neurons)
41foroinrange(len(self.output_layer.neurons)):
42pd_errors_wrt_output_neuron_total_net_input[o] =self.output_layer.neurons[o].calculate_pd_error_wrt_total_net_input(train_outputs[o])
43
44pd_errors_wrt_hidden_neuron_total_net_input = [0] * len(self.hidden_layer.neurons)
45forhinrange(len(self.hidden_layer.neurons)):
46d_error_wrt_hidden_neuron_output =0
47foroinrange(len(self.output_layer.neurons)):
48d_error_wrt_hidden_neuron_output += pd_errors_wrt_hidden_neuron_total_net_input[o] *self.output_layer.neurons[o].weights[h]
49
50pd_errors_wrt_hidden_neuron_total_net_input[h] += d_error_wrt_hidden_neuron_output *self.hidden_layer.neurons[h].calculate_pd_active_wrt_total_net_input()
51
52foroinrange(len(self.output_layer.neurons)):
53forw_hoinrange(len(self.output_layer.neurons[o].weights)):
54
55pd_error_wrt_weight = pd_errors_wrt_output_neuron_total_net_input[o] *self.output_layer.neurons[o].calculate_pd_total_net_input_wrt_weight(w_ho)
56
57self.output_layer.neurons[o].weights[w_ho] -=self.LEARNING_RATE * pd_error_wrt_weight
58
59forhinrange(len(self.hidden_layer.neurons)):
60forw_ihinrange(len(self.hidden_layer.neurons[h].weights)):
61# ∂Eⱼ/∂wᵢ = ∂E/∂zⱼ * ∂zⱼ/∂wᵢ
62pd_error_wrt_weight = pd_errors_wrt_hidden_neuron_total_net_input[h] *self.hidden_layer.neurons[
63h].calculate_pd_total_net_input_wrt_weight(w_ih)
64
65# Δw = α * ∂Eⱼ/∂wᵢ
66self.hidden_layer.neurons[h].weights[w_ih] -=self.LEARNING_RATE * pd_error_wrt_weight
以上便是通过简单的网络结构,理解反向传播算法的相关细节。从我学习和理解的过程来看,其实真正花耐心去理解,是不难的,往往真正击败我们的,真正击败我们的,往往是浮躁。道长且阻,一起加油~
GitHub地址:
https://github.com/hacksman/simple_neural_network
参考:
A Step by Step Backpropagation Example(原文):
https://mattmazur.com/2015/03/17/a-step-by-step-backpropagation-example/
推荐阅读:
2018年终精心整理|人工智能爱好者社区历史文章合集(作者篇)
2018年终精心整理 | 人工智能爱好者社区历史文章合集(类型篇)
公众号后台回复关键词学习
回复 免费 获取免费课程
回复 直播 获取系列直播课
回复 Python 1小时破冰入门Python
回复 人工智能 从零入门人工智能
回复 深度学习 手把手教你用Python深度学习
回复 机器学习 小白学数据挖掘与机器学习
回复 贝叶斯算法 贝叶斯与新闻分类实战
回复 数据分析师 数据分析师八大能力培养
回复 自然语言处理 自然语言处理之AI深度学习