深度学习笔记:07神经网络之手写数字识别的经典实现

神经网络之手写数字识别的经典实现

上一节完成了简单神经网络代码的实现,下面我们将进行最终的实现:输入一张手写图片后,网络输出该图片对应的数字。由于网络需要用0-9一共十个数字中挑选出一个,所以我们的网络最终输出层应该有十个节点编号为0-9,当网络读入一个图片进行识别时,如果网络认为它对应的数字应该是5所以他就会在5这个节点上输出一个高比率的值。–代表概率。

人工智能的有意思的点就在这里,他不和之前我们学习的普通的程序一样,给出确定的结果,他的结果有一定的犹豫性。他会输出若干个结果,每个结果都有一定的概率,我们取概率最大的那个。

下面我们应该把这个手写数字图片以及这个图片对应的数字关系传递给我们的神经元。

下面我们开始train接口的实现

import scipy.special
import numpy

class NeuralNetWork:
    def __init__(self,inputnodes,hiddennodes,outputnodes,learningrate):
        #初始化神经网络,设置输入层,中间层,和输出层
        self.inodes = inputnodes
        self.hnodes = hiddennodes
        self.onodes = outputnodes

        
        #设置学习率
        self.lr = learningrate
        '''
        初始化权重矩阵,我们有两个权重矩阵,一个是wih表示输入层和中间层节点间的链路权重形成的矩阵
        一个是who,表示中间层和输出层链路权重形成的矩阵
        '''
        self.wih = numpy.random.rand(self.hnodes, self.inodes) - 0.5
        self.who = numpy.random.rand(self.onodes, self.hnodes) - 0.5
        
        self.activation_function = lambda x:scipy.special.expit(x)
        
        pass
    def train(self, inputs_list, targets_list):
        #根据输入的训练数据更新节点链路权重,inputs_list输出结果,target_list训练结果
        '''
        把input_list,target_list转换成numpy支持的二维矩阵
        .T表示做矩阵的转置
        '''
        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)

        #输出层接收来自中间层的信号量
        final_inputs = numpy.dot(self.who,hidden_outputs)
        #输出层对信号量进行激活函数后得到最终输出信号
        final_outputs = self.activation_function(final_inputs)
        
        #计算误差
        output_errors = targets - final_outputs
        hidden_errors = numpy.dot(self.who.T,output_errors)
        #根据误差计算链路权重的更新量,然后把更新加在原来的权重上,transepose是转置。
        self.who += self.lr*numpy.dot((output_errors*final_outputs*(1 - final_outputs)),numpy.transpose(hidden_outputs))
        self.wih += self.lr*numpy.dot((hidden_errors*hidden_outputs*(1 - hidden_outputs)),numpy.transpose(inputs))
        pass
    def query(self,inputs):
        #根据输入数据计算并输出答案
        #计算中间层从输入层接收到的信号量
        hidden_inputs = numpy.dot(self.wih,inputs)
        #计算中间层经过激活函数后形成的输出信号量
        hidden_outputs = self.activation_function(hidden_inputs)
        #计算最外层接收到的信号量
        final_inputs = numpy.dot(self.who,hidden_outputs)
        #计算最外层神经元经过激活函数后输出的信号量
        final_outputs = self.activation_function(final_inputs)
        return final_outputs
    #灰度图,训练数据传入,第一个数字代表是什么数字
    #下面开始写怎么把这个接口完美实现

下面开始写,如何将我们的手写数字图片传给我们的神经元:

all_values[0]对应的是他最前面的数字,然后我们把这个targets队列中编号为int(all_values[0])的值设置为一个高比例数字0.99

#最外层有10个输出节点
onodes = 10
#构造一个含有十个元素的队列,然后我们把他们初始化为0,之后再每个加上0.01
targets = numpy.zeros(onodes) + 0.01
targets[int(all_values[0])] = 0.99
print(targets)
#这个的意思就是告诉这个神经网络你现在读到的数字是7

下面我们在传给神经网络时,我们得把这些数据都转换到0.01-0.99之间,这样才能保证数据足够精确,所以我们把所有数据都除以255,但是又有的数字比如是1/255,可能会变成零。所以我们需要把这种的数据再加一个0.01。因为你如果原来是0的话变成0.01影响不大,但是如果原来是1变成了0对计算精度还是有较大的影响的。

这样所有的数据都在0.01-0.99之间。然后得到这段数据以后再将其返回到传入trian函数中经过不断地训练改进。在改进的次数足够多的时候就可以进行手写判断了。
原本7的灰度图:

7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,185,159,151,60,36,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,222,254,254,254,254,241,198,198,198,198,198,198,198,198,170,52,0,0,0,0,0,0,0,0,0,0,0,0,67,114,72,114,163,227,254,225,254,254,254,250,229,254,254,140,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17,66,14,67,67,67,59,21,236,254,106,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,83,253,209,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,22,233,255,83,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,129,254,238,44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,249,254,62,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,133,254,187,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,205,248,58,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,126,254,182,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,75,251,240,57,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,221,254,166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,203,254,219,35,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,38,254,254,77,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31,224,254,115,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,133,254,254,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,61,242,254,254,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,121,254,254,219,40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,121,254,207,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

代码实现后:

scaled_input = image_array/255.0*0.99+0.01
print(scaled_input)

在这里插入图片描述

接下来我们初始化我们的神经网路:

#输入层我们的图片总共有28*28 = 784个像素点
input_nodes = 784
#中间的节点数目:太少了影响精确度,太多了并不会提高精确度反而会增加运行成本
hidden_nodes = 100
#输出层只会有十个结果0-9
output_nodes = 10
learning_rate = 0.3
n = NeuralNetWork(input_nodes,hidden_nodes,output_nodes,learning_rate)
#读入训练数据
#open函数里的路径根据数据存储的路径来设定---这个csv文件总共有1000张图
trainning_data_file = open("./mnist_test.csv")
#readline是按行读的意思
trainning_data_list = trainning_data_file.readlines()
print(len(trainning_data_list))
trainning_data_file.close()
#把数据依靠','区分,并分别读入
for record in trainning_data_list:
    all_values = record.split(',')
    inputs = (numpy.asfarray(all_values[1:]))/255.0 * 0.99 + 0.01
    #设置图片与数值的对应关系
    targets = numpy.zeros(output_nodes) + 0.01
    targets[int(all_values[0])] = 0.99
    n.train(inputs, targets)

下面我们看一下他的效果如何:

test_data_file = open("./mnist_test.csv")
test_data_list = test_data_file.readlines()
test_data_file.close()
import numpy
import matplotlib.pyplot
%matplotlib inline

#把数据依靠','区分,并分别读入
all_values = data_list[0].split(',')
#第一个值对应的是图片的表示的数字,所以我们要读取图片数据时要去掉第一个数值
image_array = numpy.asfarray(all_values[1:]).reshape((28,28))
matplotlib.pyplot.imshow(image_array,cmap = 'Greys',interpolation = 'None')

在这里插入图片描述

n.query(numpy.asfarray(all_values[1:])/255.0*0.99+0.01)

在这里插入图片描述

然后我们把这个图片额数据传入到这个神经网络的query接口里面去看一下他识别这个图片的效果怎么样:虽然概率都不大但是总体来说,可以看到到下标为7的概率是最大的9.96865733e-01
。这么说我们的神经网络还可以具备一点人工智能的能力了。

所以下面我们进一步走,我们把所有的图片都读进来,然后把所有的图片都让这个网络去判断。

scores = []
for record in test_data_list:
    all_values = record.split(',')
    correct_number = int(all_values[0])
    print("该图片对应的数字为:",correct_number)
    #预处理数字图片
    inputs = (numpy.asfarray(all_values[1:]))/255.0*0.99+0.01
    #让网络判断图片对应的数字
    outputs = n.query(inputs)
    #找到数值最大的神经元对应的编号
    label = numpy.argmax(outputs)
    print("out put reslut is :",label)
    if label == correct_number:
        scores.append(1)
    else:
        scores.append(0)
print(scores)

scores队列是如果识别正确的话就增加一个数字1,如果识别错误就增加一个数字0.,算一下我们的准确率:可以看到我们这个神经网络现在的准确率是0.9319

scores_array = numpy.asarray(scores)
print("perfermance = ",scores_array.sum()/scores_array.size)

打印输出:perfermance = 0.9319

然后我们训练一下我们的网络:

#初始化网络:
input_nodes = 784
hidden_nodes = 100
output_nodes = 10
learning_rate = 0.3
n = NeuralNetWork(input_nodes, hidden_nodes, output_nodes, learning_rate)
#读入训练数据
#open函数里的路径根据数据存储的路径来设定--这次是60000张图片
training_data_file = open("./mnist_train.csv")
trainning_data_list = training_data_file.readlines()
print(len(trainning_data_list))
training_data_file.close()
#把数据依靠','区分,并分别读入
for record in trainning_data_list:
    all_values = record.split(',')
    inputs = (numpy.asfarray(all_values[1:]))/255.0 * 0.99 + 0.01
    #设置图片与数值的对应关系
    targets = numpy.zeros(output_nodes) + 0.01
    targets[int(all_values[0])] = 0.99
    n.train(inputs, targets)
test_data_file = open("./mnist_train.csv")
test_data_list = test_data_file.readlines()
test_data_file.close()
scores = []
for record in test_data_list:
    all_values = record.split(',')
    correct_number = int(all_values[0])
    #预处理数字图片
    inputs = (numpy.asfarray(all_values[1:])) / 255.0 * 0.99 + 0.01
    #让网络判断图片对应的数字
    outputs = n.query(inputs)
    #找到数值最大的神经元对应的编号
    label = numpy.argmax(outputs)
    if label == correct_number:
        scores.append(1)
    else:
        scores.append(0)
scores_array = numpy.asarray(scores)
print("perfermance = ", scores_array.sum() / scores_array.size)

打印输出:perfermance = 0.9478666666666666
再看一下我们的准确率:提高到了百分之94.787

所以:我们给网络输入的训练数据越多,网络所识别的准确率越强。所以人工智能还是比较适合大企业的,因为大企业可以把很多高性能的计算机搭成一个集群,使劲跑训练数据就行了。

接下来介绍epochs

上面我们的训练的那个代码只进行了一次,epochs就是我们的训练流程要进行多少次,这边我们设置为7,就是跑7次

#初始化网络
input_nodes = 784
hidden_nodes = 100
output_nodes = 10
learning_rate = 0.3
n = NeuralNetWork(input_nodes, hidden_nodes, output_nodes, learning_rate)
#读入训练数据
#open函数里的路径根据数据存储的路径来设定
training_data_file = open("./mnist_train.csv")
trainning_data_list = training_data_file.readlines()
print(len(trainning_data_list))
training_data_file.close()
#加入epocs,设定网络的训练循环次数
epochs = 7
print("begin trainning")

for e in range(epochs):
    #把数据依靠','区分,并分别读入
    for record in trainning_data_list:
        all_values = record.split(',')
        inputs = (numpy.asfarray(all_values[1:]))/255.0 * 0.99 + 0.01
        #设置图片与数值的对应关系
        targets = numpy.zeros(output_nodes) + 0.01
        targets[int(all_values[0])] = 0.99
        n.train(inputs, targets)
   
        
print("trainning complete")

在这里插入图片描述

test_data_file = open("./mnist_test.csv")
test_data_list = test_data_file.readlines()
test_data_file.close()
scores = []
for record in test_data_list:
    all_values = record.split(',')
    correct_number = int(all_values[0])
    #预处理数字图片
    inputs = (numpy.asfarray(all_values[1:])) / 255.0 * 0.99 + 0.01
    #让网络判断图片对应的数字
    outputs = n.query(inputs)
    #找到数值最大的神经元对应的编号
    label = numpy.argmax(outputs)
    if label == correct_number:
        scores.append(1)
    else:
        scores.append(0)
scores_array = numpy.asarray(scores)
print("perfermance = ", scores_array.sum() / scores_array.size)

打印输出:perfermance = 0.9493
下面我们来看经过7轮训练以后,精确度提高到了百分之94.93

这就是我们这一节的全部代码啦。
我们所使用到的mnist_test.csv和mnist_train.csv在这个网站下载http://yann.lecun.com/exdb/mnist/
下载原始数据后,置于工程目录下,解压,运行以下代码即可。

def convert(imgf, labelf, outf, n):
    f = open(imgf, "rb")
    o = open(outf, "w")
    l = open(labelf, "rb")
 
    f.read(16)
    l.read(8)
    images = []
 
    for i in range(n):
        image = [ord(l.read(1))]
        for j in range(28 * 28):
            image.append(ord(f.read(1)))
        images.append(image)
 
    for image in images:
        o.write(",".join(str(pix) for pix in image) + "\n")
    f.close()
    o.close()
    l.close()
 
 
convert("./train-images.idx3-ubyte", "./train-labels.idx1-ubyte",
        "mnist_train.csv", 60000)
convert("./t10k-images.idx3-ubyte", "./t10k-labels.idx1-ubyte",
        "mnist_test.csv", 10000)
 
print("Convert Finished!")
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值