摘要: 还在苦恼如何写自己的CNN网络?看大神如何使用keras11行代码构建CNN网络,有源码提供。

更多深度文章,请关注:https://yq.aliyun.com/cloud


用“Keras”11行代码构建CNN

我曾经演示过如何使用TensorFlow创建卷积神经网络(CNN)来对MNIST手写数字数据集进行分类。TensorFlow是一款精湛的工具,具有强大的功能和灵活性。然而,对于快速原型制作工作,可能显得有些麻烦。Keras是一个运行在TensorFlow或者Theano的更高级别的库,旨在流线化构建深度学习网络的过程。事实上,在上一篇TensorFlow教程中  ,TensorFlow大约需要42行完成的内容,在Keras中只需11行就可以完成类似的功能。接下来我将向你展示如何通过Keras做到这一点。

该Keras教程将向你展示如何使用MNIST数据集构建CNN并实现> 99%的准确性。它与我之前的卷积神经网络教程中构建的结构完全相同 ,下图显示了网络的架构:

用“Keras”11行代码构建CNN

这个Keras教程的完整代码可以在这里找到。

Keras教程中的主要代码讲解:

下面的代码是在此Keras教程中使用的CNN结构的“胆量”

 

model = Sequential()
model.add(Conv2D(32, kernel_size=(5, 5), strides=(1, 1),
                 activation='relu',
                 input_shape=input_shape))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
model.add(Conv2D(64, (5, 5), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(1000, activation='relu'))
model.add(Dense(num_classes, activation='softmax'))

 

接下来我们一步一步的来解释:

 

Model  =  Sequential()

 

Keras中的模型可以有两种——序贯和通过API函数。对于构建的大多数深度学习网络,序贯模型是最常用的。它允许你从输入到输出整个过程都能轻松地堆叠网络层(甚至循环层)。而API函数可以帮助你构建更复杂的网络体系结构,本教程将不介绍它。

第一行将模型类型声明为Sequential()。

 

model.add(Conv2D(32, kernel_size=(5, 5), strides=(1, 1),
                 activation='relu',
                 input_shape=input_shape))

 

接下来,我们添加一个2D卷积层来处理2D MNIST输入的图像。传递给Conv2D()  函数的第一个参数是输出通道的数量。这里我们设置为我们有32个输出通道,下一个输入是kernel_size,我们选择了一个5×5移动窗口,其次是xy方向(1,1)的步态。接着,激活函数是整流线性单元,最后我们必须与输入层的大小提供模型。

还要注意,我们不必声明任何权重或偏差变量,Keras会帮助我们进行完成。

 

model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))

 

接下来我们添加一个2D max pooling层。层的定义很简单。在这种情况下,我们只是简单地指定在xy方向上的池的大小 和(2,2)的步。

 

model.add(Conv2D(64, (5, 5), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

 

接下来,我们添加另一个卷积层+最大池化层,具有64个输出通道。在Keras中Conv2D()函数的参数默认的步伐是(1,1),在Keras 中默认步伐是使它等于池的大小。

 

该层的输入张量是(batch_size28,28,32)28×28是图像的大小,32是来自上一层的输出通道数。但是,我们不必明确说明输入的形状是什么,Keras也能自动识别。这样可以快速组合网络架构,而不用担心网络周围张量的大小。

 

model.add(Flatten())
model.add(Dense(1000, activation='relu'))
model.add(Dense(num_classes, activation='softmax'))

 

现在我们已经在Keras中构建了卷积层,我们希望将这些输出平坦化,以完全进入我们的连接层。在TensorFlow中,我们为了平坦化必须弄清楚卷积层的输出张量的大小,还要明确我们的权重和偏差变量的大小。

接下来的两行声明了我们的完全连接层,使用Keras中的Dense()层。首先我们指定大小,根据我们的架构,我们指定了1000个节点,每个节点都是由ReLU功能激活。第二个是我们softmax分类或输出层,这是我们类数量的大小。就这样 - 我们已经成功地开发了CNN的架构,只有8行代码。现在让我们来训练模型并执行预测。

训练和评估卷积神经网络

 

我们已经开发了Keras的CNN架构,但是我们还没有指定损失函数,或者告诉框架使用哪种类型的优化器(即梯度下降,Adam optimiser等)。在Keras中,这些可以在一个命令中执行:

 

model.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.SGD(lr=0.01),
              metrics=['accuracy'])

 

Keras提供了许多损失函数(或者你可以建立自己的),这里可以看到的keras所有的损失函数。我们将使用标准交叉熵来进行分类(keras.losses.categorical_crossentropy)。Keras还提供了许多优化器,可以在这里看到。在这种情况下,我们使用Adam优化器(keras.optimizers.Adam)。最后,我们可以在模型上运行evaluate()时计算的度量。

接下来,我们要训练我们的模型。这可以通过在Keras中再次运行下面这个命令来完成:

 

model.fit(x_train, y_train,
          batch_size=batch_size,
          epochs=epochs,
          verbose=1,
          validation_data=(x_test, y_test),
          callbacks=[history])

 

该命令看起来类似于非常受欢迎的Python机器学习库中scikit learn 使用的语法。我们首先传递我们的所有训练的数据,x_trainy_train,下一个参数是批量大小,我们不必在Keras训练期间明确我们数据的批量处理,而是指定批量大小。在这种情况下,我们使用的批量大小为128。接下来我们设置训练周期(在这种情况下为10)。详细标志在此处设置为1,指定设定是否要在控制台中打印详细信息以了解训练进度。

3328/60000 [>.............................] - ETA: 87s - loss: 0.2180 - acc: 0.9336
3456/60000 [>.............................] - ETA: 87s - loss: 0.2158 - acc: 0.9349
3584/60000 [>.............................] - ETA: 87s - loss: 0.2145 - acc: 0.9350
3712/60000 [>.............................] - ETA: 86s - loss: 0.2150 - acc: 0.9348

最后,我们将验证或测试数据传递给拟合函数,因此Keras知道在模型上运行evaluate()时,会测量指标的数据。

一旦模型被训练,我们可以评估它并打印结果:

score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])

 

在上述模型培训10个周期之后,我们实现了99.2%的准确度,你可以看到每个周期的准确性的改善如下图所示:

用“Keras”11行代码构建CNN

Kersa让事情很更加简单了,你不觉得吗?我希望这个Keras教程已经展示了它如何成为深度学习解决方案的有用框架。

作为一种附录,我会告诉你如何跟踪我们通过训练时期的准确性,这使我能够生成上面的图表。

在Keras中记录网络性能

Keras有一个实用的程序,名为“回调”,可用于跟踪训练期间的各种变量。你还可以使用它来创建检查点,将模型在训练的不同阶段进行保存,以帮助你避免工作结果丢失。整个结果会被传递到.fit()函数,如上所述。我会向你显示一个相当简单的用例,其中记录了准确性。

 

要创建一个回调,我们创建一个继承的类,它继承自keras.callbacks.Callback:

 

class AccuracyHistory(keras.callbacks.Callback):
    def   on_train_begin(self, logs={}):
        self.acc = []
    def  on_epoch_end(self, batch, logs={}):
        self.acc.append(logs.get('acc'))

 

上面代码继承的Callback超类有一些可以在我们的回调定义中覆盖的方法,例如  on_train_beginon_epoch_endon_batch_beginon_batch_end这些方法的名称就是代表了训练过程中我们可以“做事情”的时刻。在上面的代码中,在训练开始时,我们初始化一个列表self.acc = []来存储我们的精度结果。使用on_epoch_end ()方法,我们可以从日志中提取我们想要的变量这是一个字典,默认情况下保留了训练过程中的丢失和准确性。然后我们实例化这样的回调:

 

history = AccuracyHistory()

 

现在我们可以使用回调参数名将历史记录传递给.fit()函数。请注意,.fit()需要一个回调参数的列表,所以你必须传递这样的历史:[history]。要访问我们在训练完成后创建的准确性列表,你可以简单地调用history.acc:

 

plt.plot(range(1,11), history.acc)
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.show()

 

本文由@阿里云云栖社区组织翻译。

文章原标题《Keras tutorial – build a convolutional neural network in 11 lines》

作者:Andy 译者:袁虎 审阅:

 

 

 

文章为简译,更为详细的内容,请查看原文

 

 

 

 

 

 

本文由用户为个人学习及研究之目的自行翻译发表,如发现侵犯原作者的版权,请与社区联系处理yqgroup@service.aliyun.com