记一次全连接神经网络识别手写数字

全连接神经网络识别手写数字

先放代码链接: https://github.com/EricEricEricJin/Written-Number-Recogonizice

目录

  • 搭建神经网络
  • 下载手写数字数据集
  • 训练模块
    • 读取和处理数据集
    • 初始化神经网络类
    • 训练
  • 测试模块
    • 导入 处理数据集(和前文的类似)
    • 初始化和加载权重矩阵
    • 测试

搭建神经网络

算法,实现 略
我参照了《Python神经网络编程》一书。书中的3层神经网络的示例代码:https://github.com/makeyourownneuralnetwork/makeyourownneuralnetwork/blob/master/part2_neural_network.ipynb
我在其基础上改为了多层,并增加了存储、加载权重矩阵的函数 SaveWeightLoadWeight。代码:https://github.com/EricEricEricJin/multi-layer-neuralnetwork

import numpy
import scipy.special

class neuralnetwork:
    def __init__(self, nodes_list, learningrate, layer):
        #变量初始化
        self.weights_list = [] #i-1个
        self.nodes_list = nodes_list #i个
        self.lr = learningrate
        self.layer = layer
        #初始化权重
        for i in range (self.layer - 1):
            self.weights_list.append (numpy.random.rand(self.nodes_list[i + 1], self.nodes_list[i]) - 0.5)
        #激活函数
        self.activation_function = lambda x: scipy.special.expit(x)

    def train(self, inputs, targets):
        inputs_list = [] #i个
        outputs_list = [] #i-1个
        errors_list = [] #i-1个
        #第0层的输入
        inputs_list.append (numpy.array(inputs, ndmin = 2).T)
        #目标
        targets_list = numpy.array(targets, ndmin = 2).T
        #输入输出计算
        inputs_list.append (numpy.dot(self.weights_list[0], inputs_list[0]))
        outputs_list.append (self.activation_function (inputs_list[1]))
        for i in range (self.layer - 2):
            inputs_list.append (numpy.dot(self.weights_list[i+1], outputs_list[i])) #
            outputs_list.append (self.activation_function(inputs_list[i+2]))
        #误差计算   从后往前
        #error是反的!!!
        errors_list.append (targets_list - outputs_list[self.layer - 2]) 
        for i in range (self.layer - 2):
            errors_list.append (numpy.dot(self.weights_list[self.layer - 2 - i].T, errors_list[i]))
        #权重更新
        for i in range (self.layer - 2):
            self.weights_list[self.layer - 2 - i] += self.lr * numpy.dot((errors_list[i] * outputs_list[self.layer - 2 - i] * (1 - outputs_list[self.layer - 2 - i])), numpy.transpose(outputs_list[self.layer - 3 - i]))
        self.weights_list[0] += self.lr * numpy.dot((errors_list[self.layer - 2] * outputs_list[0] * (1 - outputs_list[0])), numpy.transpose(inputs_list[0])) 

    def SaveWeight(self, filepath):
        m = numpy.array(self.weights_list)
        numpy.save(filepath, m)

    def LoadWeight(self, filepath):
        self.weights_list = numpy.load(filepath)

    def query(self, inputs):   
        inputs_list = []
        outputs_list = []
        inputs_list.append (numpy.array(inputs, ndmin = 2).T)
        inputs_list.append (numpy.dot(self.weights_list[0], inputs_list[0]))
        outputs_list.append (self.activation_function(inputs_list[1]))
        for i in range (self.layer - 2):
            inputs_list.append (numpy.dot(self.weights_list[i + 1], outputs_list[i]))
            outputs_list.append (self.activation_function(inputs_list[i+2]))
        return outputs_list[self.layer - 2]

下载手写数字数据集

我用的阿里天池数据集 原链接忘记存了 可以从我的GitHub上下载:https://github.com/EricEricEricJin/Written-Number-Recogonizice/blob/master/train.zip
是个CSV文件 长这个样子:
在这里插入图片描述

训练模块

读取和处理数据集

使用python内置的csv模块, 把数据集读为二维列表TrainingData
代码:

import csv

TrainFile = open("train.csv", "r")

TrainingData = []
Reading = csv.reader(TrainFile)
for row in Reading:
    TrainingData.append(row)

对于每一条(也就是CSV里的一行)数据我们这样处理:
通过Label对应写Target(这里对应如下表),并且把TrainingData里的Input归一

LabelTarget
0[1,0,0,0,0,0,0,0,0,0]
1[0,1,0,0,0,0,0,0,0,0]
2[0,0,1,0,0,0,0,0,0,0]
3[0,0,0,1,0,0,0,0,0,0]
4[0,0,0,0,1,0,0,0,0,0]
8[0,0,0,0,0,0,0,0,1,0]
9[0,0,0,0,0,0,0,0,0,1]

代码:

Targets = []
for i in range(len(TrainingData) - 1):
    cond = int(TrainingData[i+1][0])
    if cond == 0:
        Targets.append([1,0,0,0,0,0,0,0,0,0])
    elif cond == 1:
        Targets.append([0,1,0,0,0,0,0,0,0,0])
    elif cond == 2:
        Targets.append([0,0,1,0,0,0,0,0,0,0])
    elif cond == 3:
        Targets.append([0,0,0,1,0,0,0,0,0,0])
    elif cond == 4:
        Targets.append([0,0,0,0,1,0,0,0,0,0])
    elif cond == 5:
        Targets.append([0,0,0,0,0,1,0,0,0,0])
    elif cond == 6:
        Targets.append([0,0,0,0,0,0,1,0,0,0])
    elif cond == 7:
        Targets.append([0,0,0,0,0,0,0,1,0,0])
    elif cond == 8:
        Targets.append([0,0,0,0,0,0,0,0,1,0])
    elif cond == 9:
        Targets.append([0,0,0,0,0,0,0,0,0,1])
      
    for j in range(len(TrainingData[0]) - 1):
        TrainingData[i+1][j+1] = int(TrainingData[i+1][j+1]) / 255
初始化神经网络类

文件头上要导入之前(<搭建神经网络>里)写的神经网络代码

NL = [len(TrainingData[1]) - 1, int((len(TrainingData[1]) - 1) / 1.5), int((len(TrainingData[1]) - 1)/2.5), 10]
LR = 0.1
L = len(NL)

ann = mla.neuralnetwork(NL, LR, L)

NL: Network Layer, 描述神经网络每层的节点数。如:[1,2,3]意为三层,第一层1个节点,第二层2个节点,第三层3个节点
LR: Learning Rate, 学习率 决定神经网络的学习速度

训练

有的时候我们可能需要在之前训练的权重的基础上再训练,所以这里我写了:

LW = input("load weight?        yes/no")
if LW == "yes":
    ann.LoadWeight("new_a.npy")

注意:如果放在服务器上不挂起的跑的话,无法接受键盘标准输入,是否加载权重要写死

然后开始训练:

for num in range(5): # 训练5次
    for i in range(len(TrainingData) - 1):
        ann.train(TrainingData[i+1][1:], Targets[i])
        #print("---", num+1, "---", i+1, "---")
    ann.SaveWeight("new_a.npy")
    print("Training:    time(s):", num+1)

这样你训练过的权重矩阵就被存到new_a.npy里了。文件名根据个人喜好和规范设定, 扩展名.npy是numpy数组的格式

测试模块

Good. 现在开始测试训练的模型的准确率。

导入 处理数据集 (和前文的差不多)

由于我用的test.csv里没有label(???鬼知道为什么),此处使用train.csv(之前用来训练的数据集)来测试(这样做是不正确的,可能会导致测试准确率偏高)

import csv

TrainFile = open("train.csv", "r")

TrainingData = []
Reading = csv.reader(TrainFile)
for row in Reading:
    TrainingData.append(row)

for i in range(len(TrainingData) - 1):
    TrainingData[i+1][0] = int(TrainingData[i+1][0])
    for j in range(len(TrainingData[0]) - 1):
        TrainingData[i+1][j+1] = int(TrainingData[i+1][j+1]) / 255
初始化神经网络和计数变量,并且加载之前训练好的权重矩阵 (和前文的差不多)
NL = [len(TrainingData[1]) - 1, int((len(TrainingData[1]) - 1) / 1.5), int((len(TrainingData[1]) - 1)/2.5), 10]
LR = 0.1
L = len(NL)

nn = mla.neuralnetwork(NL, LR, L)
nn.LoadWeight("new_a.npy")

right = 0
wrong = 0
测试

由于我们之前设置Targets的方法(可以回去康一眼),我们现在看输出列表中最大的数字的index就是图片里的数字。

for i in range(len(TrainingData) - 1):
	output = nn.query(TrainingData[i + 1][1:])
	output_index = 0
	for j in range(10):
		if (output[j] > output[output_index]):
			output_index = j
	if output_index == TrainingData[i + 1][0]:
		right += 1
		#print("#", i+1, " correct!")
	else:
		wrong += 1
		#print("#", i+1, " wrong!")
	#print("R: ", right, "	W: ", wrong)
print("\n\nRate: ", right / (right + wrong))

打印出来的就是你的准确率了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值