沧海一声笑
滔滔两岸潮
浮沉随浪只记今朝
苍天笑
纷纷世上潮
谁负谁胜出天知晓
江山笑
烟雨遥
涛浪淘尽红尘俗事知多少
啦......
朋友圈的热点纷纷扰扰,转眼间满屏都是向Andrew Ng(吴恩达)同志学习,占领机器学习阵地的帖子。翻看一下Coursera的课程目录,默默从积灰的书堆底下翻出十多年前的《人工神经网络》教材,过上一把怀旧瘾。
金庸大侠笔下《笑傲江湖》一书中,既有正邪之判,复存门户之别,少林、武当、青城、五岳自诩正教与魔教(日月神教)誓不两立,出场人物的权谋武功高下各有不同。加之华山派气宗剑宗分野,嵩山派耗时数年搜集整理各派剑法遗存,葵花宝典化身辟邪剑法重现江湖……无疑加深了识别人物门派的难度,本文尝试BP神经网络算法(误差反向传播,Error Back Propagation)予以求解。
训练数据
输出结果
构造一个BP神经网络,根据人物的权谋、内功、剑法、轻功特征判断是否出自华山派。
l 神经元模型
神经网络中最基本的成分是神经元模型。取一组二进制输入值(附近的神经元),将每个输入值乘以一个连续值权重(每个附近神经元的突触强度),并设立一个阈值,如果这些加权输入值的和超过这个阈值,就输出1,否则输出0(同理于神经元是否放电)。
l BP算法的基本思想
通过计算输出结果和期望输出的误差来间接调整隐含层的权值,学习过程由信号的正向传播与误差的反向传播两个过程组成。
正向传播时,输入样本从输入层传入,经各隐含层逐层处理后,传向输出层。若输出层的实际输出与期望的输出不符,则转入误差的反向传播阶段。
-
反向传播时,将输出以某种形式通过隐含层向输入层逐层反传,并将误差分摊给各层的所有单元,作为修正各单元权值的依据。
Python代码解析
l 正向传播(1~5步)
设定输入数组X 和输出数组Y
初始化连接权值和阈值
wh 隐含层权值
bh 隐含层阈值
wout 输出层权值
bout 输出层阈值
- 计算输入数组与隐含层权值的点积,加上阈值(线性变换)
hidden_layer_input= matrix_dot_product(X,wh) + bh
- 采用Sigmoid激活函数进行非线性变换f(x)=1/(1 + exp(-x)).
hiddenlayer_activations = sigmoid(hidden_layer_input)
- 对隐含层激活函数的结果进行线性变换,求出与输出层权值的点积,再加上输出层阈值。通过Sigmoid函数预测输出值。
output_layer_input = matrix_dot_product (hiddenlayer_activations * wout ) + bout
output = sigmoid(output_layer_input)
l 反向传播(6~12步)
- 将预测结果与实际结果进行比较,其中误差损失函数表示为 ((Y-t)^2)/2
E = y – output
- 计算隐含层与输出层神经元的梯度
slope_output_layer = derivatives_sigmoid(output)
slope_hidden_layer = derivatives_sigmoid(hiddenlayer_activations)
- 将误差乘以输出层的梯度,得出输出层的调整因子
d_output = E * slope_output_layer
- 将误差反向传播到隐含层,计算输出层调整因子与隐含层至输出层连接权值的点积。
Error_at_hidden_layer = matrix_dot_product(d_output, wout.Transpose)
- 继续计算隐含层的调整因子,求出隐含层误差与隐含层梯度的点积。
d_hiddenlayer = Error_at_hidden_layer * slope_hidden_layer
- 借助前几步得出的调整因子,更新隐含层与输出层连接的权值
wout = wout + matrix_dot_product(hiddenlayer_activations.Transpose, d_output)*learning_rate
wh = wh + matrix_dot_product(X.Transpose,d_hiddenlayer)*learning_rate
- 最后更新隐含层和输出层的阈值
bias at output_layer =bias at output_layer + sum of delta of output_layer at row-wise * learning_rate
bias at hidden_layer =bias at hidden_layer + sum of delta of output_layer at row-wise * learning_rate
bh = bh + sum(d_hiddenlayer, axis=0) * learning_rate
bout = bout + sum(d_output, axis=0)*learning_rate
Python源代码
# -*- coding: utf-8 -*-
"""
Created on Sun Feb 11 22:42:30 2018
@author: vincentqiao
"""
import numpy as np
#Input array
X=np.array([[1,1,1,1],[1,1,1,0],[0,1,1,0],[1,0,1,1]])
#Output
y=np.array([[0],[1],[1],[0]])
#Sigmoid Function
def sigmoid (x):
return 1/(1 + np.exp(-x))
#Derivative of Sigmoid Function
def derivatives_sigmoid(x):
return x * (1 - x)
#Variable initialization
epoch=5000 #Setting training iterations
lr=0.1 #Setting learning rate
inputlayer_neurons = X.shape[1] #number of features in data set
hiddenlayer_neurons = 3 #number of hidden layers neurons
output_neurons = 1 #number of neurons at output layer
#weight and bias initialization
wh=np.random.uniform(size=(inputlayer_neurons,hiddenlayer_neurons))
bh=np.random.uniform(size=(1,hiddenlayer_neurons))
wout=np.random.uniform(size=(hiddenlayer_neurons,output_neurons))
bout=np.random.uniform(size=(1,output_neurons))
for i in range(epoch):
#Forward Propogation
hidden_layer_input1=np.dot(X,wh)
hidden_layer_input=hidden_layer_input1 + bh
hiddenlayer_activations = sigmoid(hidden_layer_input)
output_layer_input1=np.dot(hiddenlayer_activations,wout)
output_layer_input= output_layer_input1+ bout
output = sigmoid(output_layer_input)
#Backpropagation
E = y-output
slope_output_layer = derivatives_sigmoid(output)
slope_hidden_layer = derivatives_sigmoid(hiddenlayer_activations)
d_output = E * slope_output_layer
Error_at_hidden_layer = d_output.dot(wout.T)
d_hiddenlayer = Error_at_hidden_layer * slope_hidden_layer
wout += hiddenlayer_activations.T.dot(d_output) *lr
bout += np.sum(d_output, axis=0,keepdims=True) *lr
wh += X.T.dot(d_hiddenlayer) *lr
bh += np.sum(d_hiddenlayer, axis=0,keepdims=True) *lr
print (output)
输出结果
[[ 0.03964938]
[ 0.96135949]
[ 0.98159661]
[ 0.01767599]]