Python实现人工神经网络(反向传播算法)

来源:互联网 发布:135端口可以关闭吗 编辑:程序博客网 时间:2024/05/22 00:08

注意:本程序使用Python3编写,额外需要安装numpy工具包用于矩阵运算,未测试python2是否可以运行。


本程序实现了《机器学习》书中所述的反向传播算法训练人工神经网络,理论部分请参考我的读书笔记。

在本程序中,目标函数是由一个输入x和两个输出y组成,

x是在范围【-3.14, 3.14】之间随机生成的实数,而两个y值分别对应 y1 = sin(x),y2 = 1。


随机生成一万份训练样例,经过网络的学习训练后,再用随机生成的五份测试数据验证训练结果。

调节算法的学习速率,以及隐藏层个数、隐藏层大小,训练新的网络,可以观察到参数对于学习结果的影响。



算法代码如下:


#!usr/bin/env python3# -*- coding:utf-8 -*-import numpy as npimport math# definition of sigmoid funtion# numpy.exp work for arrays.def sigmoid(x):return 1 / (1 + np.exp(-x))# definition of sigmoid derivative funtion# input must be sigmoid function's resultdef sigmoid_output_to_derivative(result):return result*(1-result)# init training setdef getTrainingSet(nameOfSet):setDict = {"sin": getSinSet(),}return setDict[nameOfSet]def getSinSet():x = 6.2 * np.random.rand(1) - 3.14x = x.reshape(1,1)# y = np.array([5 *x]).reshape(1,1)# y = np.array([math.sin(x)]).reshape(1,1)y = np.array([math.sin(x),1]).reshape(1,2)return x, ydef getW(synapse, delta):resultList = []# 遍历隐藏层每个隐藏单元对每个输出的权值,比如8个隐藏单元,每个隐藏单元对两个输出各有2个权值for i in range(synapse.shape[0]):resultList.append((synapse[i,:] * delta).sum())resultArr = np.array(resultList).reshape(1, synapse.shape[0])return resultArrdef getT(delta, layer):result = np.dot(layer.T, delta)return resultdef backPropagation(trainingExamples, etah, input_dim, output_dim, hidden_dim, hidden_num):# 可行条件if hidden_num < 1:print("隐藏层数不得小于1")return# 初始化网络权重矩阵,这个是核心synapseList = []# 输入层与隐含层1synapseList.append(2*np.random.random((input_dim,hidden_dim)) - 1)# 隐含层1与隐含层2, 2->3,,,,,,n-1->nfor i in range(hidden_num-1):synapseList.append(2*np.random.random((hidden_dim,hidden_dim)) - 1)# 隐含层n与输出层synapseList.append(2*np.random.random((hidden_dim,output_dim)) - 1)iCount = 0lastErrorMax = 99999# while True:for i in range(10000):errorMax = 0for x, y in trainingExamples:iCount += 1layerList = []# 正向传播layerList.append(sigmoid(np.dot(x,synapseList[0])))for j in range(hidden_num):layerList.append(sigmoid(np.dot(layerList[-1],synapseList[j+1])))# 对于网络中的每个输出单元k,计算它的误差项deltaList = []layerOutputError = y - layerList[-1]# 收敛条件errorMax = layerOutputError.sum() if layerOutputError.sum() > errorMax else errorMaxdeltaK = sigmoid_output_to_derivative(layerList[-1]) * layerOutputErrordeltaList.append(deltaK)iLength = len(synapseList)for j in range(hidden_num):w = getW(synapseList[iLength - 1 - j], deltaList[j])delta = sigmoid_output_to_derivative(layerList[iLength - 2 - j]) * wdeltaList.append(delta)# 更新每个网络权值w(ji)for j in range(len(synapseList)-1, 0, -1):t = getT(deltaList[iLength - 1 -j], layerList[j-1])synapseList[j] = synapseList[j] + etah * tt = getT(deltaList[-1], x)synapseList[0] = synapseList[0] + etah * tprint("最大输出误差:")print(errorMax)if abs(lastErrorMax - errorMax) < 0.0001:print("收敛了")print("####################")breaklastErrorMax = errorMax# 测试训练好的网络for i in range(5):xTest, yReal = getSinSet()layerTmp = sigmoid(np.dot(xTest,synapseList[0]))for j in range(1, len(synapseList), 1):layerTmp = sigmoid(np.dot(layerTmp,synapseList[j]))yTest = layerTmpprint("x:")print(xTest)print("实际的y:")print(yReal)print("神经元网络输出的y:")print(yTest)print("最终输出误差:")print(np.abs(yReal - yTest))print("#####################")print("迭代次数:")print(iCount)if __name__ == '__main__':import datetimetStart = datetime.datetime.now()# 使用什么样的训练样例nameOfSet = "sin"x, y = getTrainingSet(nameOfSet)# setting of parameters# 这里设置了学习速率。etah = 0.01# 隐藏层数hidden_num = 2# 网络输入层的大小input_dim = x.shape[1]# 隐含层的大小hidden_dim = 100# 输出层的大小output_dim = y.shape[1]# 构建训练样例trainingExamples = []for i in range(10000):x, y = getTrainingSet(nameOfSet)trainingExamples.append((x, y))# 开始用反向传播算法训练网络backPropagation(trainingExamples, etah, input_dim, output_dim, hidden_dim, hidden_num)tEnd = datetime.datetime.now()print("time cost:")print(tEnd - tStart)


1 0
原创粉丝点击