「周末AI课堂」神经网络综观(代码篇)机器学习你会遇到的“坑”

「周末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就像迈出左脚再迈右脚一样自然。

「周末AI课堂」神经网络综观(代码篇)机器学习你会遇到的“坑”

图为在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库,将模型可视化。

「周末AI课堂」神经网络综观(代码篇)机器学习你会遇到的“坑”

读芯君开扒

课堂TIPS

• 很多人都会认为keras作为一个容易上手的框架,是把很多运算隐藏,所以包装太多,灵活性一定很差。但是需要注意,keras使用了tensorflow、Theano和CNTK的backend,我们完全使用其后端来进行创新设计,灵活性事实上非常高,前提是一定要清楚深度学习和机器学习很多理论。

• keras的模型搭建方式有两种,本文介绍了其中一种,叫做函数式模型,另外一种叫做序列式,序列式搭建简单模型更快,但函数式更加灵活。此文仅展示了keras的基本功能,还有很多功能将在具体的任务中使用。

「周末AI课堂」神经网络综观(代码篇)机器学习你会遇到的“坑”

作者:唐僧不用海飞丝

如需转载,请后台留言,遵守转载规范

相关推荐