有源码提供:还在苦恼如何写CNN网络?看大神如何使用keras11行代码构建CNN网络
我曾经演示过如何使用TensorFlow创建卷积神经网络(CNN)来对MNIST手写数字数据集进行分类。TensorFlow是一款精湛的工具,具有强大的功能和灵活性。然而,对于快速原型制作工作,可能显得有些麻烦。Keras是一个运行在TensorFlow或者Theano的更高级别的库,旨在流线化构建深度学习网络的过程。事实上,在上一篇TensorFlow教程中,TensorFlow大约需要42行完成的内容,在Keras中只需11行就可以完成类似的功能。接下来我将向你展示如何通过Keras做到这一点。
该Keras教程将向你展示如何使用MNIST数据集构建CNN并实现> 99%的准确性。它与我之前的卷积神经网络教程中构建的结构完全相同,下图显示了网络的架构:
这个Keras教程的完整代码可以在这里找到。
Keras教程中的主要代码讲解:
下面的代码是在此Keras教程中使用的CNN结构的“胆量”
model = Sequential()model.add(Conv2D(32, kernel_size=(5, 5), strides=(1, 1),
接下来我们一步一步的来解释:
Model = Sequential()
Keras中的模型可以有两种——序贯和通过API函数。对于构建的大多数深度学习网络,序贯模型是最常用的。它允许你从输入到输出整个过程都能轻松地堆叠网络层(甚至循环层)。而API函数可以帮助你构建更复杂的网络体系结构,本教程将不介绍它。
第一行将模型类型声明为Sequential()。
model.add(Conv2D(32, kernel_size=(5, 5), strides=(1, 1),
接下来,我们添加一个2D卷积层来处理2D MNIST输入的图像。传递给Conv2D()函数的第一个参数是输出通道的数量。这里我们设置为我们有32个输出通道,下一个输入是kernel_size,我们选择了一个5×5移动窗口,其次是x和y方向(1,1)的步态。接着,激活函数是整流线性单元,最后我们必须与输入层的大小提供模型。
还要注意,我们不必声明任何权重或偏差变量,Keras会帮助我们进行完成。
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
接下来我们添加一个2D max pooling层。层的定义很简单。在这种情况下,我们只是简单地指定在x和y方向上的池的大小和(2,2)的步。
model.add(Conv2D(64, (5, 5), activation='relu'))model.add(MaxPooling2D(pool_size=(2, 2)))
接下来,我们添加另一个卷积层+最大池化层,具有64个输出通道。在Keras中Conv2D()函数的参数默认的步伐是(1,1),在Keras 中默认步伐是使它等于池的大小。
该层的输入张量是(batch_size,28,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,
Keras提供了许多损失函数(或者你可以建立自己的),这里可以看到的keras所有的损失函数。我们将使用标准交叉熵来进行分类(keras.losses.categorical_crossentropy)。Keras还提供了许多优化器,可以在这里看到。在这种情况下,我们使用Adam优化器(keras.optimizers.Adam)。最后,我们可以在模型上运行evaluate()时计算的度量。
接下来,我们要训练我们的模型。这可以通过在Keras中再次运行下面这个命令来完成:
model.fit(x_train, y_train,
该命令看起来类似于非常受欢迎的Python机器学习库中scikit learn使用的语法。我们首先传递我们的所有训练的数据,x_train和y_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%的准确度,你可以看到每个周期的准确性的改善如下图所示:
Kersa让事情很更加简单了,你不觉得吗?我希望这个Keras教程已经展示了它如何成为深度学习解决方案的有用框架。
作为一种附录,我会告诉你如何跟踪我们通过训练时期的准确性,这使我能够生成上面的图表。
在Keras中记录网络性能
Keras有一个实用的程序,名为“回调”,可用于跟踪训练期间的各种变量。你还可以使用它来创建检查点,将模型在训练的不同阶段进行保存,以帮助你避免工作结果丢失。整个结果会被传递到.fit()函数,如上所述。我会向你显示一个相当简单的用例,其中记录了准确性。
要创建一个回调,我们创建一个继承的类,它继承自keras.callbacks.Callback:
class AccuracyHistory(keras.callbacks.Callback):
上面代码继承的Callback超类有一些可以在我们的回调定义中覆盖的方法,例如 on_train_begin,on_epoch_end,on_batch_begin和on_batch_end。这些方法的名称就是代表了训练过程中我们可以“做事情”的时刻。在上面的代码中,在训练开始时,我们初始化一个列表self.acc = []来存储我们的精度结果。使用on_epoch_end ()方法,我们可以从日志中提取我们想要的变量,这是一个字典,默认情况下保留了训练过程中的丢失和准确性。然后我们实例化这样的回调:
history = AccuracyHistory()
现在我们可以使用回调参数名将历史记录传递给.fit()函数。请注意,.fit()需要一个回调参数的列表,所以你必须传递这样的历史:[history]。要访问我们在训练完成后创建的准确性列表,你可以简单地调用history.acc:
plt.plot(range(1,11), history.acc)
本文由@阿里云云栖社区组织翻译。
文章原标题《Keras tutorial – build a convolutional neural network in 11 lines》
作者:Andy译者:袁虎