原创

Java Deeplearning4j实现CNN(卷积神经网络)

1. 简述

在本篇文章中,我们将使用Java中的Deeplearning4j库构建并训练一个卷积神经网络模型。有关如何设置库的更多信息,请参阅deeplearning4j 入门j.

2. 图像分类

2.1. 问题陈述(Problem Statement)

假设我们有一组图像。每个图像代表一个特定类的对象。此外,图像上的对象属于唯一已知的类。所以,问题陈述是建立一个模型,它将能够识别给定图像上对象的类

例如,假设我们有一组有十个手势的图像。我们建立一个模型并训练它来分类。然后在训练之后,我们可以传递其他图像并对其上的手势进行分类。当然,给定的手势应该属于已知类。

2.2. 图像表示(Image Representation)

在计算机内存中,图像可以用数字矩阵表示。每个数字都是一个像素值,范围从0到255。

灰度图像是二维矩阵。类似地,RGB图像是具有宽度、高度和深度维度的3D矩阵。

正如我们所见,图像是一组数字。因此,我们可以建立多层网络模型来训练他们对图像进行分类。

3. 卷积神经网络CNN

卷积神经网络(CNN)是一种具有特定结构的多层网络模型。CNN的结构可分为两个块:卷积层和全连接(稠密)层。我们逐个来看看。

3.1. 卷积层

每个卷积层是一组平方矩阵,称为内核。最重要的是,我们需要他们对输入图像执行卷积。它们的数量和大小可能会有所不同,具体取决于给定的数据集。我们主要使用3×3或5×5内核,很少使用7×7内核。确切的大小和数量是通过反复试验选择的。

此外,我们在训练开始时随机选择核矩阵的变量。它们是网络的权重。

要执行卷积,我们可以使用内核作为滑动窗口。我们将内核权重乘以相应的图像像素并计算总和。然后我们可以使用stride(向右移动)和padding(向下移动)移动内核以覆盖图像的下一块。因此,我们将有一些值将用于进一步的计算。

简而言之,有了这个层,我们得到了一个卷积图像。有些变量可能小于零。这通常意味着这些变量不如其他变量重要。这就是为什么应用 ReLU 函数是进一步减少计算的好方法。

3.2. 子采样层(Subsampling Layer)

子采样(或池化)层是网络的一层,通常在卷积层之后使用。卷积后,我们得到很多计算变量但是,我们的任务是选择其中最有价值的

方法是应用滑动窗口算法到卷积的图像。在每个步骤中,我们将在预定义大小的方形窗口中选择最大值,通常在2×2和5×5像素之间。因此,我们的计算参数会更少。同是也将减少计算。

3.3. 稠密层(Dense Layer)

稠密(全连接)层是由多个神经元组成的层。我们需要这一层来执行分类。而且,可能有两个或更多这样的后续层。重要的是,最后一层的大小应等于要分类的类数。
网络的输出是图像属于每个类的概率。为了预测概率,我们将使用Softmax激活功能。

3.4. 优化技术

要进行训练,我们需要优化权重。请记住,我们最初随机选择这些变量。神经网络是一个很大的功能。而且,它有很多未知的参数,我们的权重。

当我们将图像传递给网络时,它会给我们答案。然后,我们可以建立一个损失函数,这将取决于这个答案。在监督学习方面,我们也有一个实际的答案-真实的班级。我们的任务是尽量减少这种损失函数。如果我们成功,那么我们的模型就会训练有素。

为了最小化功能,我们必须更新网络的权重。为此,我们可以针对这些未知参数中的每一个计算损失函数的导数。然后,我们可以更新每个权重。

我们可以增加或减少权重值,以找到损失函数的局部最小值,因为我们知道斜率。此外,这个过程是迭代的,称为梯度下降. 反向传播使用梯度下降来传播权重更新从网络的末尾到开始。

在本教程中,我们将使用随机梯度体面(SGD)优化算法。主要思想是我们在每一步随机选择一批火车图像。然后我们应用反向传播。

3.5. 评估指标

最后,在训练网络之后,我们需要获得有关模型执行情况的信息。
最常用的指标是准确性。这是正确分类的图像与所有图像的比率。同时,召回率,精确度和F1分数非常重要图像分类的指标以及。

4. 数据集准备

在本节中,我们将准备图像。让我们使用嵌入式CIFAR10本教程中的数据集。我们将创建迭代器来访问图像:

public class CifarDatasetService implements IDataSetService {

    private CifarDataSetIterator trainIterator;
    private CifarDataSetIterator testIterator;

    public CifarDatasetService() {
         trainIterator = new CifarDataSetIterator(trainBatch, trainImagesNum, true);
         testIterator = new CifarDataSetIterator(testBatch, testImagesNum, false);
    }

    // other methods and fields declaration

}

我们可以自己选择一些参数。TrainBatchtestBatch分别是每次训练和评估的图像数量。TrainImagesNumtestImagesNum是用于训练和测试的图像数量,单个epoch持续执行 trainImagesNum/trainBatch 步骤。这样,2048个训练图像分为32个批次,将导致2048/32=64的步骤。

5. Deeplearning4j中的CNN

5.1. 模型建立

接下来,让我们从头开始构建我们的CNN模型。要做到这一点,我们将使用卷积,子采样(池)和全连接(稠密)层

MultiLayerConfiguration configuration = new NeuralNetConfiguration.Builder()
  .seed(1611)
  .optimizationAlgo(OptimizationAlgorithm.STOCHASTIC_GRADIENT_DESCENT)
  .learningRate(properties.getLearningRate())
  .regularization(true)
  .updater(properties.getOptimizer())
  .list()
  .layer(0, conv5x5())
  .layer(1, pooling2x2Stride2())
  .layer(2, conv3x3Stride1Padding2())
  .layer(3, pooling2x2Stride1())
  .layer(4, conv3x3Stride1Padding1())
  .layer(5, pooling2x2Stride1())
  .layer(6, dense())
  .pretrain(false)
  .backprop(true)
  .setInputType(dataSetService.inputType())
  .build();

network = new MultiLayerNetwork(configuration);

在这里,我们指定学习率,更新算法,模型的输入类型和分层体系结构。我们可以尝试这些配置。因此,我们可以训练许多具有不同体系结构和训练参数的模型。此外,我们可以比较结果并选择最佳模型。

5.2. 模型训练

然后,我们将训练构建的模型。这可以通过几行代码来完成:

public void train() {
    network.init();    
    IntStream.range(1, epochsNum + 1).forEach(epoch -> {
        network.fit(dataSetService.trainIterator());
    });
}

epochs的数量是我们可以自己指定的参数。我们有一个小数据集,几百个epochs就足够了。

5.3. 评估模型

最后,我们可以评估现在训练的模型。借助Deeplearning4j库可以轻松完成:

public Evaluation evaluate() {
   return network.evaluate(dataSetService.testIterator());
}

评估是一个对象,包含训练模型后的计算指标。这些是准确性,精确度,召回率和F1分数。此外,它具有友好的可打印界面:

==========================Scores=====================
# of classes: 11
Accuracy: 0,8406
Precision: 0,7303
Recall: 0,6820
F1 Score: 0,6466
=====================================================

6. 总结

在本教程中,我们了解了CNN模型的体系结构,优化技术和评估指标。此外,我们使用Java中的Deeplearning4j库实现了该模型。

正文到此结束