用“Keras”11行代码构建CNN

    xiaoxiao2021-04-18  206

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


    我曾经演示过如何使用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), 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移动窗口,其次是x和y方向(1,1)的步态。接着,激活函数是整流线性单元,最后我们必须与输入层的大小提供模型。

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

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

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

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

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

    该层的输入张量是(batch_size28,28,3228×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行代码。现在让我们来训练模型并执行预测。

    训练和评估卷积神经网络

    我们已经开发了KerasCNN架构,但是我们还没有指定损失函数,或者告诉框架使用哪种类型的优化器(即梯度下降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%的准确度,你可以看到每个周期的准确性的改善如下图所示:

    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 译者:袁虎 审阅:

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

    相关资源:七夕情人节表白HTML源码(两款)

    最新回复(0)