「周末AI课堂」神经网络综观(代码篇)机器学习你会遇到的“坑”
在前面的《神经网络综观(理论篇)》中,我们到目前已经对神经网络的设计有了具体的了解,主要基于获得更好的表示和更好的优化,从宏观上,层与层的连接方式,每层神经元的数量,层的类别和个数,以及如何将不同种类的层组合起来,微观上则包含了隐层神经元和输出单元的种类。对神经网络的设计要考虑具体面对的问题,比如面对我们在前面课程中反复使用的iris分类数据,一个普通的全连接网络就可以解决,如果解决图片识别的问题,那么带有卷积层的神经网络可能会适应的更好,如果面对语音识别,一个双向添加LSTM结构的循环神经网络可能是必要的,但无一例外,在具体实践中,我们需要根据理论对上述的组件进行更新。
我们前面曾经使用numpy自行搭建了一个简单的感知机:
class NeuralNetwork:
def__init__(self, x, y):
self.input = x
self.weights = np.random.rand(x.shape[1],1)
self.weights1 = np.random.rand(1)
self.y = y
self.output = np.zeros(self.y.shape)
def feedforward(self):
self.output = sigmoid(np.dot(self.input, self.weights)+self.weights1)
def backprop(self):
d_weights = np.dot(self.input.T,(2*(self.y -self.output) * sigmoid_derivative(self.output)))
d_weights1 =np.dot(2*(self.y -self.output).reshape(4),sigmoid_derivative(self.output).reshape(4))
self.weights += d_weights
self.weights1 += d_weights1
如果将隐层的数目和神经元的拓展是非常容易的,我们在初始化的时候可以很方便的添加:
......
self.weights2 = np.random.rand(10,1)
......
这样就获得了一个10个神经元的隐层。
但如果涉及到更大型更深的网络,这样的拓展就不再容易,所以我们必须掌握专门用于深度学习的框架,让我们快速的搭建模型并检验效果。所以在这里,我推荐使用keras来作为深度学习的入门工具,目前深度学习的框架非常之多,比如tensorflow,caffe,CNTK,torch,theano,paddlepaddle,mxnet等等,但keras搭建模型的速度非常快,这意味着创新性的想法可以被很快的实现,同时具有一定的灵活性,运行速度也不慢,也可以很方便在GPU上运行,最重要的是,在掌握理论的基础上,学习keras就像迈出左脚再迈右脚一样自然。
图为在google各个深度学习框架的搜索次数,一定程度上可以反映出用户对深度学习框架的感兴趣程度,可以看到keras增长迅猛,仅次于tensorflow。
在统计学习中,虽然经常使用sklearn,但我并未做简单介绍,因为统计学习更强调的是数学和模型,sklearn包含的内容太多,一个严重的后果是使得一部分读者还没有入门就已经放弃,所以在开始使用keras做任务之前,本文的主要目的就是向大家介绍神经网络在keras中的体现,以及keras的简单使用,你大概只需要花几分钟的时间就可以上手它。
首先,一个神经网络必须有输入输出,在keras中,我们要先定义好一个模型:
from keras.models import Model
from keras.layers import Input
inputs=Input(shape=(100,))
model=Model(inputs=inputs,outputs=inputs)
我们创建了一个输入有100维的神经元模型,但注意到我们的输入和输出都是一样的,这意味着我们只是创建了一个没有任何用处的100个神经元,放在inputs层里。keras.layers类中提供了很多种层,我们接下来添加全连接层,只需要:
from keras.models import Model
from keras.layers import Input,Dense
inputs=Input(shape=(100,))
x=Dense(32)(inputs)
model=Model(inputs=inputs,outputs=x)
全连接的意思是,前一层所有的神经元与后一层的神经元均存在权重连接。接下来,我们需要激活函数,需要激活函数来调整神经网络,我们使用了ReLU作为激活函数提取出来,让其单独成为一层。并添加到原来的模型中:
from keras.models import Model
from keras.layers import Input,Dense,ReLU
inputs=Input(shape=(100,))
x=Dense(32)(inputs)
y=ReLU()(x)
model=Model(inputs=inputs,outputs=y)
通过这样的添加,我们已经获得了一个两层的神经网络,输出的值就为激活函数的处理之后的输出,准确的说,这只是一个输入为100维,输出为32维的感知机,我们要继续添层加使其能够处理非线性问题,紧接着,我们添加一个用于输出的层,并采用softmax函数作为激活函数,添加到上述模型中:
from keras.models import Model
from keras.layers import Input,Dense,ReLU,softmax
inputs=Input(shape=(100,))
x=Dense(32)(inputs)
y=ReLU()(x)
out=Dense(10)(y)
out=softmax()(out)
model=Model(inputs=inputs,outputs=out)
我们最终的模型就是处理100维特征的10分类数据。需要注意的是,隐藏单元和输出单元功能并不一样,输出单元一般都可以作为隐藏单元,但隐藏单元只有少数几种可以成为输出单元,这与我们使用的损失函数有关。为了达到同样的效果,激活函数可以在层内事先指定好,比如:
x=Dense(32)(inputs)
y=ReLU()(x)
还可以把激活函数和层放在一起写作:
y=Dense(32,activation='relu')(inputs)
两种方法没有什么特别的区别。模型搭建完成后,我们完成了表示的任务,我们在开始优化之前,人们经常忘记的一点就是,在进行的优化的时候我们需要初始化参数,keras提供了参数初始化类,我们在对一个网络进行优化的时候会使用到它,比如我们想进行正态分布的随机初始化:
from keras importinitializers
rn=initializers.RandomNormal(mean=0,stddev=1,seed=42)
我们设置好了一个均值为零,标准差为1。随机数种子为42的正态分布随机初始化器。我们在搭建网络中通过kernel_initializer参数传递初始化方法:
from keras importinitializers
from keras.models import Model
from keras.layers import Input,Dense,ReLU,softmax
rn=initializers.RandomNormal(mean=0,stddev=1,seed=42)
inputs=Input(shape=(100,))
x=Dense(32,kernel_initializer=rn)(inputs)
y=ReLU()(x)
out=Dense(10,kernel_initializer=rn)(y)
out=softmax()(out)
model=Model(inputs=inputs,outputs=out)
同时,我们需要知道损失函数、优化算法和评估标准,他们分别可以从以下代码获得:
from keras import losses
loss=losses.categorical_crossentropy
from keras importoptimizers
sgd=optimizers.SGD(lr=0.1,decay=1e-10,momentum=0.9,nesterov=True)
from keras import metrics
performance=metrics.categorical_accuracy
其中,我们指定损失函数的交叉熵,优化算法为带有nesterov动量的随机梯度下降,评估标准为准确率。就可以用损失函数、优化算法以及评估标准编译好我们的模型:
model.compile(loss=loss, optimizer=sgd,metrcis=[performance])
接下来我们使用模型的fit方法开始训练数据:
model.fit(x=X, y=y, batch_size=32, epochs=1,verbose=1)
其中X,y是我们的数据,特别需要注意的是,batch_size就是指每次用于梯度更新的样本数量,epochs是指整体数据被迭代的次数,与iteration不同,iteration是指进行的梯度更新的次数。verbose是一个显示日志的开关,如果设置为1,在训练过程中,会出现一个萌萌的进度条,不知道多少人因为这个可爱的进度条,陷入keras无法自拔。
训练完成后,我们可以方便的将keras模型保存为HDF5文件(需要安装python库:h5py):
model.save('duxinshu.h5')
就保存到了当前面文件夹,当我们在其他地方使用这个模型时,只需要:
from keras.model import load_model
model = load_model('my_model.h5')
除此之外,我们还可以将上述的模型打印出来,使用:
model.summary()
就可以在解释器中看到模型的状态,同时我们还可以安装ann_visualizer库,将模型可视化。
读芯君开扒
课堂TIPS
• 很多人都会认为keras作为一个容易上手的框架,是把很多运算隐藏,所以包装太多,灵活性一定很差。但是需要注意,keras使用了tensorflow、Theano和CNTK的backend,我们完全使用其后端来进行创新设计,灵活性事实上非常高,前提是一定要清楚深度学习和机器学习很多理论。
• keras的模型搭建方式有两种,本文介绍了其中一种,叫做函数式模型,另外一种叫做序列式,序列式搭建简单模型更快,但函数式更加灵活。此文仅展示了keras的基本功能,还有很多功能将在具体的任务中使用。
作者:唐僧不用海飞丝
如需转载,请后台留言,遵守转载规范