python的优点是不太需要配置环境,不太需要注重变量的类型,有非常多优秀的库可以方便调用,对于没有志向深入学习编程语言以及编程小白入门非常友好。
首先实现的是普通神经网络,区别于卷积神经网络,也就是输入层-隐含层-输出层的NN。由于比较简单,只需要numpy这个库就可以。简单说一下为什么numpy这么强,主要是因为许多数学运算如矩阵点乘,自己写函数可以要用到多层循环结构,而直接调用np的dot函数不但运行速度快了十倍百倍,它也可以理解很多简单的运算如一个矩阵加一个实数为矩阵每一个元素加上这个实数,好用又高效。
首先定义一个类,叫neuralNetwork。
class neuralNetwork:
接下来定义初始化函数__init__。越复杂的网络结构其初始化的超参数越多,可能的参数有:gpu选项(训练的时候用cpu还是gpu),isTrain判断是训练还是测试阶段,save_dir保持训练的模型,optimizers选择优化器(SGD或者Adam等)。
最简单的NN需要的超参数只有四个:输入层结点数inputnodes,隐含层结点数hiddennodes,输出层结点数outputnodes和学习率learningrate。具体实现方法为:
def __init__(self,inputnodes,hiddennodes,outputnodes,learningrate):
self.inodes=inputnodes
self.hnodes=hiddennodes
self.onodes=outputnodes
self.wih=numpy.random.normal(0.0,pow(self.hnodes,-0.5),(self.hnodes,self.inodes))
self.who=numpy.random.normal(0.0,pow(self.onodes,-0.5),(self.onodes,self.hnodes))
self.lr=learningrate
self.activation_function=lambda x:scipy.special.expit(x)
pass
要注意在类中定义的函数第一个参数永远是 self,self的作用是指代实例。同时在类中函数相互调用要加 self ,如self.hnodes。numpy.random.normal生成一个高斯分布的概率密度随机数,三个参数分别是均值,方差和矩阵长宽。lambda x:scipy.special.expit(x)代表使用的激活函数是sigmoid,需要提前import scipy.special。
其次定义训练函数train。其思想就是输入*权重=输入层的输出=隐含层的输入。隐含层的输入*激活函数=隐含层的输出。隐含层的输出*权重=输出层的输入。输出层的输入*激活函数=最终输出。然后损失函数loss function就简单定义为目标-输出。这里说一下loss function和cost function的区别。前者只针对单一训练样本,后者是前者的求和,即对于所有训练样本。具体实现方法为:
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)
final_inputs=numpy.dot(self.who,hidden_outputs)
final_outputs=self.activation_function(final_inputs)