zoukankan      html  css  js  c++  java
  • 神经网络的后续改进

      针对前几次做的笔记,发现训练集太少的情况下,识别率太低。有可能降到50%的情况。后做了几次改进,不过这几次改进还是在训练集只有100个,测试集10个的情况下,识别率有了一点提高,能稳定在60%,70%。可能如果加大训练集的话,识别率会有很大提升。

      具体的改进有以下几点:

    (1)增加训练次数:

        即把整个训练集运行多次,保持学习率不变。这是值得的,原因是通过提供更多的爬下斜坡的机会,有助于梯度在下降过程中进行权重更新。直觉告诉我们,训练的次数越多,所得到的性能可能就越好。实际上,太多的训练实际上会过犹不及,这是由于神经网络过度拟合训练数据,因此,网络会在先前没有见到过的新数据上表现不佳。过度拟合现象是需要注意的。改进的代码如下:

     1 #训练四次
     2 i = 4
     3 for e in range(i):
     4     #训练神经网络
     5     for record in training_data_list:
     6         #根据逗号,将文本数据进行拆分
     7         all_values = record.split(',')
     8         #将文本字符串转化为实数,并创建这些数字的数组。
     9         inputs = (numpy.asfarray(all_values[1:])/255.0 * 0.99) + 0.01
    10         #创建用零填充的数组,数组的长度为output_nodes,加0.01解决了0输入造成的问题
    11         targets = numpy.zeros(output_nodes) + 0.01
    12         #使用目标标签,将正确元素设置为0.99
    13         targets[int(all_values[0])] = 0.99
    14         n.train(inputs,targets)
    15         pass
    16 pass

    (2)改变网络结构

      尝试改变中间隐藏层节点的数目。

      隐藏层是发生学习过程的地方。输入层只引进了输入信号,输出层只送出神经网络的答案,是隐藏层可以进行学习,将输入转化为答案,这是学习发生的场所。事实上,隐藏层节点前后的链接权重具有学习能力。

      如果隐藏层节点太少,比如说3个,这就没有足够的空间让网络学习任何知识,并将所有输入转换为正确的输出,就像用5座车去装载10个人,你不可能将那么多人塞进去,科学家称这种限制为学习容量。

      但是,如果有10000个隐藏层节点,会发生什么情况呢?虽然我们不会缺少学习容量,但是由于目前有太多的路径进行学习选择,因此可能难以训练网络。

           运行结果显示,隐藏层节点为10个的时候,正确率某次运行结果可能低于30%,整体上不会高于60%,当隐藏层节点到50个的时候,所达到的性能其实和具有100个隐藏层节点所达到的性能差不多。所以可能到达某个阈值后,随着隐藏层节点的数量增加,结果会有所改善,但是不显著。由于增加隐藏层节点意味着增加了到前后层的每个节点的新网络链接,这一切都会产生额外的计算,因此训练神经网络所用的时间也增加了!

    (3)改变学习率

      改变学习率,就是改变梯度下降的速度。

      如果过高的提高学习率,可能得到的结果更糟。好像大的学习率导致了梯度下降过程中有一些来回跳动和超调。

      如果选择好的学习率,在性能上会有所改善。如果在不改变隐藏层节点数目的情况下,好的学习率可能会达到隐藏层节点数目最优时的性能,来借此以少胜多。

      如果选择过低的学习率,性能可能并不变好,过小的学习率也是有害的,这是因为由于限制了梯度下降的速度,使用的步长太小了,因此对性能造成了损害。运行速度也变慢。

    (4)同时增加训练次数和减少学习率

      有专家的经验指出,在更多的训练次数情况下,减少学习率确实能够得到更好的性能。

    改进后的代码:

      1 import numpy
      2 import scipy.special
      3 import matplotlib.pyplot as plt
      4 import pylab
      5 # 神经网络类定义
      6 class NeuralNetwork():
      7     # 初始化神经网络
      8     def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate):
      9         # 设置输入层节点,隐藏层节点和输出层节点的数量
     10         self.inodes = inputnodes
     11         self.hnodes = hiddennodes
     12         self.onodes = outputnodes
     13         # 学习率设置
     14         self.lr = learningrate
     15         # 权重矩阵设置 正态分布
     16         self.wih = numpy.random.normal(0.0, pow(self.hnodes, -0.5), (self.hnodes, self.inodes))
     17         self.who = numpy.random.normal(0.0, pow(self.onodes, -0.5), (self.onodes, self.hnodes))
     18         # 激活函数设置,sigmod()函数
     19         self.activation_function = lambda x: scipy.special.expit(x)
     20         pass
     21 
     22     # 训练神经网络
     23     def train(self,input_list,target_list):
     24         # 转换输入输出列表到二维数组
     25         inputs = numpy.array(input_list, ndmin=2).T
     26         targets = numpy.array(target_list,ndmin= 2).T
     27         # 计算到隐藏层的信号
     28         hidden_inputs = numpy.dot(self.wih, inputs)
     29         # 计算隐藏层输出的信号
     30         hidden_outputs = self.activation_function(hidden_inputs)
     31         # 计算到输出层的信号
     32         final_inputs = numpy.dot(self.who, hidden_outputs)
     33         final_outputs = self.activation_function(final_inputs)
     34 
     35         output_errors = targets - final_outputs
     36         hidden_errors = numpy.dot(self.who.T,output_errors)
     37 
     38         #隐藏层和输出层权重更新
     39         self.who += self.lr * numpy.dot((output_errors*final_outputs*(1.0-final_outputs)),
     40                                         numpy.transpose(hidden_outputs))
     41         #输入层和隐藏层权重更新
     42         self.wih += self.lr * numpy.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)),
     43                                         numpy.transpose(inputs))
     44         pass
     45     # 查询神经网络
     46     def query(self, input_list):
     47         # 转换输入列表到二维数组
     48         inputs = numpy.array(input_list, ndmin=2).T
     49         # 计算到隐藏层的信号
     50         hidden_inputs = numpy.dot(self.wih, inputs)
     51         # 计算隐藏层输出的信号
     52         hidden_outputs = self.activation_function(hidden_inputs)
     53         # 计算到输出层的信号
     54         final_inputs = numpy.dot(self.who, hidden_outputs)
     55         final_outputs = self.activation_function(final_inputs)
     56         return final_outputs
     57 
     58 # 设置每层节点个数
     59 input_nodes = 784
     60 hidden_nodes = 100
     61 output_nodes = 10
     62 # 设置学习率为0.3
     63 learning_rate = 0.3
     64 # 创建神经网络
     65 n = NeuralNetwork(input_nodes, hidden_nodes, output_nodes, learning_rate)
     66 
     67 #读取训练数据集 转化为列表
     68 training_data_file = open("D:/mnist_train_100.csv",'r')
     69 training_data_list = training_data_file.readlines();
     70 training_data_file.close()
     71 
     72 #训练四次
     73 i = 2
     74 for e in range(i):
     75     #训练神经网络
     76     for record in training_data_list:
     77         #根据逗号,将文本数据进行拆分
     78         all_values = record.split(',')
     79         #将文本字符串转化为实数,并创建这些数字的数组。
     80         inputs = (numpy.asfarray(all_values[1:])/255.0 * 0.99) + 0.01
     81         #创建用零填充的数组,数组的长度为output_nodes,加0.01解决了0输入造成的问题
     82         targets = numpy.zeros(output_nodes) + 0.01
     83         #使用目标标签,将正确元素设置为0.99
     84         targets[int(all_values[0])] = 0.99
     85         n.train(inputs,targets)
     86         pass
     87 pass
     88 
     89 
     90 #读取测试文件
     91 test_data_file = open("D:/mnist_test_10.csv",'r')
     92 test_data_list = test_data_file.readlines()
     93 test_data_file.close()
     94 
     95 # all_values = test_data_list[2].split(',')
     96 # print(all_values[0])  #输出目标值
     97 
     98 # image_array = numpy.asfarray(all_values[1:]).reshape((28,28))
     99 # print(n.query((numpy.asfarray(all_values[1:])/255.0*0.99)+0.01))#输出标签值
    100 # plt.imshow(image_array,cmap='Greys',interpolation='None')#显示原图像
    101 # pylab.show()
    102 
    103 #进行统计 如果期望值和输出的值相同,就往score[]数组里面加1,否则加0 进而算准确率
    104 score = []
    105 for record in test_data_list:
    106     #用逗号分割将数据进行拆分
    107     all_values = record.split(',')
    108     #正确的答案是第一个值
    109     correct_values = int(all_values[0])
    110     print(correct_values,"是正确的期望值")
    111     #做输入
    112     inputs = (numpy.asfarray(all_values[1:])/255.0 * 0.99) + 0.01
    113     #测试网络 作输入
    114     outputs= n.query(inputs)
    115     #找出输出的最大值的索引
    116     label = numpy.argmax(outputs)
    117     print(label,"是网络的输出值
    ")
    118     #如果期望值和网络的输出值正确 则往score 数组里面加1 否则添加0
    119     if(label == correct_values):
    120         score.append(1)
    121     else:
    122         score.append(0)
    123     pass
    124 pass
    125 print(score)
    126 score_array = numpy.asfarray(score)
    127 print("正确率是:",(score_array.sum()/score_array.size)*100,'%')

    测试结果:

  • 相关阅读:
    ASP.NET MVC基于标注特性的Model验证:DataAnnotationsModelValidator
    TDD个人实践体会
    客户端调用Spring.Net发布的WebService
    XML自动解析器开源
    Javascript MVVM模式前端框架—Knockout 2.1.0系列
    定时执行SQL存储过程
    orchard之lucene.net索引生成
    并发编程学习总结
    python开发总结
    Thrift
  • 原文地址:https://www.cnblogs.com/carlber/p/9748305.html
Copyright © 2011-2022 走看看