前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >人工神经网络学习笔记(4)

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

作者头像
twelvecoder
发布2021-12-22 10:05:46
3630
发布2021-12-22 10:05:46
举报
文章被收录于专栏:十二的树洞

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


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


准备数据:
  • 训练集and测试集:Mnist手写数字数据集(复制git链接克隆)MINST数据库是由米国机器学习大佬Yann提供的手写数字数据库文件,其官方下载地址Download Mnist。该数据集将会是神经网络的输入信号。

每一张图片像素都为 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

代码语言:javascript
复制
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

代码语言:javascript
复制
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
  1. (测试神经网络)输入命令:python network_test.py

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/09/01 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Python-numpy编码实现人工神经网络
    • 准备数据:
      • 编码实现
        • 运行程序
        相关产品与服务
        数据库
        云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档