如何使用深度学习实现CNN4j-Java快速进阶教程
1. 概述
在本教程中,我们将使用 Java 中的 Deeplearning4j 库构建和训练卷积神经网络模型。
有关如何设置库的更多信息,请参阅我们的Deeplearning4j 指南。
2. 图像分类
2.1. 问题陈述
假设我们有一组图像。每个图像表示特定类的对象。此外,图像上的对象属于唯一已知的类。因此,问题陈述是构建能够识别给定图像上对象的类的模型。
例如,假设我们有一组包含十个手势的图像。我们构建一个模型并对其进行训练以对其进行分类。然后经过训练后,我们可以传递其他图像并对它们的手势进行分类。当然,给定的手势应该属于已知的类。
2.2. 图像表示
在计算机内存中,图像可以表示为数字矩阵。每个数字都是一个像素值,范围从 0 到 255。
灰度图像是 2D 矩阵。同样,RGB 图像是具有宽度、高度和深度维度的 3D 矩阵。
正如我们所看到的,图像是一组数字。因此,我们可以构建多层网络模型来训练它们对图像进行分类。
3. 卷积神经网络
卷积神经网络 (CNN) 是一种具有特定结构的多层网络模型。CNN的结构可以分为两个块:卷积层和全连接(或密集)层。让我们逐一看一下。
3.1. 卷积层
每个卷积层都是一组方形矩阵,称为核。最重要的是,我们需要它们对输入图像执行卷积。它们的数量和大小可能会有所不同,具体取决于给定的数据集。我们主要使用 3×3 或 5×5 个内核,很少使用 7×7 个内核。确切的大小和数量是通过反复试验选择的。
此外,我们在训练开始时随机选择核矩阵的变量。它们是网络的权重。
要执行卷积,我们可以将内核用作滑动窗口。我们将内核权重乘以相应的图像像素并计算总和。然后,我们可以使用步幅(向右移动)和填充(向下移动)移动内核以覆盖图像的下一个块。因此,我们将拥有将在进一步计算中使用的值。
简而言之,通过这一层,我们得到了一个卷积图像。某些变量可能小于零。这通常意味着这些变量不如其他变量重要。这就是为什么应用ReLU函数是进一步减少计算的好方法。
3.2. 子采样层
子采样(或池化)层是网络的一个层,通常在卷积层之后使用。卷积后,我们得到了很多计算变量。但是,我们的任务是在其中选择最有价值的。
方法是将滑动窗口算法应用于卷积图像。在每一步中,我们将在方形窗口中选择预定义大小的最大值,通常在 2×2 到 5×5 像素之间。因此,我们将拥有更少的计算参数。因此,这将减少计算。
3.3. 密集层
密集(或全连接)层是由多个神经元组成的层。我们需要这一层来执行分类。此外,可能有两个或更多这样的后续层。重要的是,最后一层的大小应等于要分类的类数。
网络的输出是图像属于每个类的概率。为了预测概率,我们将使用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
}
我们可以自己选择一些参数。TrainBatch和testBatch分别是每个训练和评估步骤的图像数量。TrainImagesNum 和 testImagesNum是用于训练和测试的图像数量。一个epoch持续trainImagesNum/trainBatch步骤。因此,拥有 2048 张批量大小 = 32 的火车图像将导致每个时期 2048 / 32 = 64 步。
5. 深度学习中的卷积神经网络4j
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());
});
}
周期数是我们可以自己指定的参数。我们有一个小数据集。结果,几百个epoch就足够了。
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库实现了该模型。