人工神经网络学习笔记(4)


Python-numpy编码实现人工神经网络


前面的几篇文章我们熟悉了人工神经网络的数学原理及其推导过程,但有道是‘纸上得来终觉浅’,是时候将理论变为现实了。现在我们将应用Python语言以及其强大的扩充程序库Numpy来编写一个简单的神经网络。


准备数据:

每一张图片像素都为 28 × 28 28\times 28 28×28,因此可作为一个 784 × 1 784\times 1 784×1的向量传入神经网络。

单个图片
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vOdOSJra-1580383064774)(/人工神经网络学习笔记(3)/20190607015526334.png)]

  • 初始花链接权重矩阵:使用正态概率分布采样权重,平均值为0,标准方差为结点传入链接数目的开方,即 1 i n p u t c o n n e c t s \frac{1}{\sqrt{inputconnects}} inputconnects 1

编码实现

下面的代码实现了一个双隐层的神经网络,但是它的表现并不好(最起码在Mnist数据集的表现上差强人意),我训练了5个小时(5世代)也只能达到%96.54的准确率。相比而言当隐层的神经网络在Mnist数据集上的表现更好,三个小时(5世代)可以达到%97.34的准确率。你可以注释掉下面的部分代码将其退回到单隐层结构甚至加到三隐层结构。虽然代码写的很乱但代码中每一句都有详细的注释,别介意哈哈哈。
包含两个源代码文件:

  • neural_network.py 包含神经网络主类用于训练神经网络
  • network_test.py 用于测试神经网络

neural_network.py

import numpy
import matplotlib.pyplot as plt
import scipy.special
import scipy.ndimage.interpolation
import time
import progressbar
import matplotlib.animation as anim

# 神经网络类定义
class neuralNetwork:
	# 初始化神经网络
	def __init__(self,inputnodes,hiddennodes,hiddennodes_2,outputnodes,learningrate):
		# 设置神经网络的输入层、隐藏层、输出层、的结点数和学习率
		self.inodes = inputnodes
		self.hnodes = hiddennodes                # 第一隐藏层结点数
		self.hnodes_2 = hiddennodes_2            # 第二隐藏层结点数
		#self.hnodes_3 = hiddennodes_3            # 第三隐藏层结点数
		self.onodes = outputnodes
		# 学习率
		self.lr = learningrate
		
		# (常规版)链接权重矩阵,随机权重在-0.5至0.5之间(三层神经网络)
		self.wih = (numpy.random.rand(hiddennodes,inputnodes)-0.5)            
		self.who = (numpy.random.rand(outputnodes,hiddennodes)-0.5)           
		# (进阶版)链接权重矩阵,随机权重在-0.5至0.5之间(三层神经网络)
		self.wih_ = numpy.random.normal(0.0,pow(self.hnodes,-0.5),(hiddennodes,inputnodes))          # 输入层到第一隐藏层权重矩阵
		self.wh12_ = numpy.random.normal(0.0,pow(self.hnodes_2,0.5),(hiddennodes_2,hiddennodes))     # 第一隐藏层到第二隐藏层权重矩阵
		#self.wh23_ = numpy.random.normal(0.0,pow(self.hnodes_3,0.5),(hiddennodes_3,hiddennodes_2))   # 第二隐藏层到第三隐藏层权重矩阵
		self.who_ = numpy.random.normal(0.0,pow(self.onodes,-0.5),(outputnodes,hiddennodes_2))         # 第三隐藏层到输出层权重矩阵

		#定义激活函数,由scipy库提供
		self.activation_function = lambda x : scipy.special.expit(x)


	# 训练神经网络
	def train(self,inputs_list,targets_list):
		# 将输入信号列表和目标信号列表转换成列向量
		inputs = numpy.array(inputs_list,ndmin=2).T
		targets = numpy.array(targets_list,ndmin=2).T

		# 第一隐藏层的输入信号:
		hidden_inputs = numpy.dot(self.wih_,inputs)
		# 第一隐藏层的输出信号(激活函数作用):
		hidden_outputs = self.activation_function(hidden_inputs)

		# 第二隐藏层的输入信号:
		hidden_inputs_2 = numpy.dot(self.wh12_,hidden_outputs)
		# 第二层隐藏层的输出信号:
		hidden_outputs_2 = self.activation_function(hidden_inputs_2)
		'''
		# 第三隐藏层的输入信号:
		hidden_inputs_3 = numpy.dot(self.wh23_,hidden_outputs_2)
		# 第三隐藏层的输出信号:
		hidden_outputs_3 = self.activation_function(hidden_inputs_3)
		'''
		# 输出层的输入信号:
		final_inputs = numpy.dot(self.who_,hidden_outputs_2)
		# 输出层的输出信号:
		final_outputs = self.activation_function(final_inputs)

		# 计算输出层误差向量
		output_errors = targets - final_outputs
		# 计算第三隐藏层误差向量
		#hidden_errors_3 = numpy.dot(self.who_.T,output_errors)
		# 计算第二隐藏层的误差向量
		hidden_errors_2 = numpy.dot(self.who_.T,output_errors)
		# 计算第一隐藏层的误差向量
		hidden_errors = numpy.dot(self.wh12_.T,hidden_errors_2)

		''' 优化链接权重值 '''
		# 第三隐藏层与输出层间的链接权重优化
		#self.who_ += self.lr * numpy.dot((output_errors * final_outputs * (1.0 - final_outputs)),numpy.transpose(hidden_outputs_3))
		# 第二隐藏层与第三隐藏层间的链接权重优化
		self.who_ += self.lr * numpy.dot((output_errors * final_outputs * (1.0 - final_outputs)),numpy.transpose(hidden_outputs_2))
		# 第一隐藏层与第二隐藏层间的链接权重优化
		self.wh12_ += self.lr * numpy.dot((hidden_errors_2 * hidden_outputs_2 * (1.0 - hidden_outputs_2)),numpy.transpose(hidden_outputs))
		# 输入层与第一隐藏层间的链接权重优化
		self.wih_ += self.lr * numpy.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)),numpy.transpose(inputs))
		
		
		#return self.query(inputs_list)

	# 查询
	def query(self,inputs_list):
		# 将输入列表转成numpy向量对象并转置为列向量
		inputs = numpy.array(inputs_list,ndmin=2).T
		# 第一隐藏层结点的输入信号:权重矩阵与输入信号向量的乘积
		self.hidden_inputs = numpy.dot(self.wih_,inputs)
		# 第一隐藏层结点的输出信号:经过S函数的加权求和值
		self.hidden_outputs = self.activation_function(self.hidden_inputs)

		# 第二隐藏层的输入信号:
		self.hidden_inputs_2 = numpy.dot(self.wh12_,self.hidden_outputs)
		# 第二层隐藏层的输出信号:
		self.hidden_outputs_2 = self.activation_function(self.hidden_inputs_2)
		'''
		# 第三隐藏层的输入信号:
		self.hidden_inputs_3 = numpy.dot(self.wh23_,self.hidden_outputs_2)
		# 第三隐藏层的输出信号:
		self.hidden_outputs_3 = self.activation_function(self.hidden_inputs_3)
		'''
		# 输出层结点的输入信号:
		self.final_inputs = numpy.dot(self.who_,self.hidden_outputs_2)
		# 输出层结点的最终输出信号:
		self.final_outputs = self.activation_function(self.final_inputs)

		# 返回最终输出信号
		return self.final_outputs
def test(Network,test_dataset_name):
	Network.wih_ = numpy.loadtxt('wih_file.csv')
	Network.wh12_ = numpy.loadtxt('wh12_file.csv')
	#Network.wh23_ = numpy.loadtxt('wh23_file.csv')
	Network.who_ = numpy.loadtxt('who_file.csv')

	# 准备测试数据
	test_data_file = open(test_dataset_name,'r')
	test_data_list = test_data_file.readlines()
	test_data_file.close()

	print('\n')
	print("Testing...\n")
	# 统计
	correct_test = 0
	all_test = 0
	correct = [0,0,0,0,0,0,0,0,0,0]
	num_counter = [0,0,0,0,0,0,0,0,0,0]

	#测试进度条
	p_test = progressbar.ProgressBar()
	p_test.start(len(test_data_list))

	# 动画显示
	#plt.figure(1)

	for imag_list in test_data_list:
		all_values = imag_list.split(',')
		lable = int(all_values[0])
		scaled_input = (numpy.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01
		imag_array = numpy.asfarray(scaled_input).reshape((28,28))
		'''
		plt.imshow(imag_array,cmap='Greys',animated=True)
		plt.draw()
		plt.pause(0.00001)
		'''
		net_answer = Network.query(scaled_input).tolist().index(max(Network.final_outputs))
		num_counter[lable] += 1
		
		if lable == int(net_answer):
			correct_test += 1
			correct[lable] += 1
		p_test.update(all_test + 1)
		all_test += 1

	p_test.finish()
	print("Finish Test.\n")

	# 网络性能
	performance = correct_test/all_test
	Per_num_performance = []
	for i in range(10):
		# 测试集可能不包含某些数字,故捕捉除以0异常
		try:
			Per_num_performance.append(correct[i]/num_counter[i])
		except ZeroDivisionError:
			Per_num_performance.append(0)

	print("The correctRate of per number: ",Per_num_performance)
	print("Performance of the NeuralNetwork: ",performance*100)
	return performance

# 定义网络规模与学习率
input_nodes = 784
hidden_nodes = 700
hidden_nodes_2 = 700
#hidden_nodes_3 = 100
output_nodes = 10
learningrate = 0.0001

if __name__ == "__main__":

	# 定义训练世代数
	epochs = 5

	#创建神经网络实例
	Net = neuralNetwork(input_nodes,hidden_nodes,hidden_nodes_2,output_nodes,learningrate)

	#plt.imshow(final_outputs,interpolation="nearest")

	# 准备训练数据
	data_file = open("mnist_train.csv",'r')
	data_list = data_file.readlines()
	N_train = len(data_list)
	data_file.close()
	# 动画显示
	#plt.figure(1)

	print("Training:", epochs, "epochs...")
	for e in range(epochs):
		# 训练进度条
		print('\nThe '+str(e+1)+'th epoch trainning:\n')
		p_train = progressbar.ProgressBar()
		p_train.start(N_train)
		i = 0

		for img_list in data_list:
			# 以逗号分割记录
			all_values = img_list.split(',')
			# 将0-255映射到0.01-0.99
			scaled_input = (numpy.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01
			imag_array = numpy.asfarray(scaled_input).reshape((28,28))
			#plt.imshow(imag_array,cmap='Greys',animated=True)
			#plt.draw()
			#plt.pause(0.00001)

			#旋转图像生成新的训练集
			input_plus_10imag = scipy.ndimage.interpolation.rotate(imag_array,10,cval=0.01,reshape=False)
			input_minus_10imag = scipy.ndimage.interpolation.rotate(imag_array,-10,cval=0.01,reshape=False)
			input_plus10 = input_plus_10imag.reshape((1,784))
			input_minus10 = input_minus_10imag.reshape((1, 784))
			# 根据标签创建目标值向量
			targets = numpy.zeros(output_nodes) + 0.01
			targets[int(all_values[0])] = 0.99

			# 用三个训练集训练神经网络
			Net.train(scaled_input,targets)
			Net.train(input_plus10,targets)
			Net.train(input_minus10,targets)

			#time.sleep(0.01)
			p_train.update(i+1)
			i+=1
		p_train.finish()
		
	print("\nTrainning finish.\n")

	# 将训练好的神经网络链接权重输出到csv文件中
	numpy.savetxt('wih_file.csv',Net.wih_,fmt='%f')
	numpy.savetxt('wh12_file.csv',Net.wh12_,fmt='%f')
	#numpy.savetxt('wh23_file.csv',Net.wh23_,fmt='%f')
	numpy.savetxt('who_file.csv',Net.who_,fmt='%f')

network_test.py

import neural_network as nk
import numpy
import matplotlib.pyplot as pl
import scipy.special
import scipy.ndimage.interpolation
import json
import time
import progressbar

# 测试神经网络
if __name__ == "__main__":
	input_nodes = nk.input_nodes
	hidden_nodes = nk.hidden_nodes
	hidden_nodes_2 = nk.hidden_nodes_2
	#hidden_nodes_3 = nk.hidden_nodes_3
	output_nodes = nk.output_nodes
	learningrate = nk.learningrate
	Network = nk.neuralNetwork(input_nodes,hidden_nodes,hidden_nodes_2,output_nodes,learningrate)
	nk.test(Network,"mnist_test.csv")
	

# hidden_nodes = 200 lr = 0.01 performance = 97.34


运行程序
  1. cd进入代码所在文件夹
  2. (训练神经网络)输入命令:python neural_network.py

Training

  1. (测试神经网络)输入命令:python network_test.py

Testing

[Warning] 运行时请确保训练集和测试集数据的.csv文件与源代码文件在同一个目录下,否则请修改源码中的文件路径

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
深度学习笔记v5是一本关于深度学习学习资料,下面我将用300字来回答有关这本笔记的内容。 深度学习是机器学习领域的一个重要分支,它主要研究模拟人脑神经网络的算法和模型,用于实现复杂的学习任务。深度学习在图像识别、语音识别和自然语言处理等领域取得了很多重要的突破,成为了人工智能领域的热点研究方向。 深度学习笔记v5中,首先介绍了深度学习的基本概念和原理。笔记详细解释了神经网络结构、前向传播、反向传播以及梯度下降等基本概念和算法。这些内容帮助读者理解深度学习的基本原理和工作机制。 接着,笔记介绍了常用的深度学习框架,如TensorFlow和PyTorch。这些框架提供了丰富的工具和函数,使得深度学习的开发变得更加简单和高效。笔记详细介绍了如何使用这些框架进行模型训练和评估。 此外,笔记还包含了一些深度学习的经典应用案例。这些案例涵盖了图像分类、目标检测、语音识别等多个领域。通过这些案例,读者可以深入了解深度学习在实际问题中的应用,并学习如何利用深度学习解决现实世界中的复杂任务。 最后,笔记还提供了大量的代码示例和练习题,帮助读者巩固所学的知识。通过实践,读者可以更好地理解深度学习的原理和应用。 总而言之,深度学习笔记v5是一本系统而全面的学习资料,适合对深度学习感兴趣的读者。通过阅读这本笔记,读者可以了解深度学习的基本概念和原理,掌握常用的深度学习框架,以及应用深度学习解决实际问题的方法。希望这本笔记能够对读者在深度学习领域的学习和研究有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值