19、循环神经网络与卷积神经网络在不同任务中的应用

RNN与CNN在不同任务的应用分析

循环神经网络与卷积神经网络在不同任务中的应用

1. 循环神经网络在人类活动识别中的应用

1.1 LSTM模型表现

在人类活动识别(HAR)任务中,使用智能手机数据集训练的长短期记忆网络(LSTM)模型表现出色。仅经过几次迭代,LSTM就能够很好地收敛,并产生了较高的分类准确率,最高达到了94%。该模型能够将运动类型分为六个类别:步行、上楼梯、下楼梯、坐着、站立和躺着。

1.2 LSTM超参数调整

为了进一步提高准确率,可尝试调整以下LSTM超参数:
| 超参数 | 说明 | 当前值 | 可尝试值 |
| ---- | ---- | ---- | ---- |
| learningRate | 学习率 | 0.001f | - |
| trainingIters | 训练迭代次数 | trainingDataCount * 1000 | - |
| batchSize | 批次大小 | 1500 | 5000 |
| displayIter | 显示测试集准确率的迭代间隔 | 15000 | - |
| numLstmLayer | LSTM层数 | 3 | 5, 7, 9等 |

1.3 GRU单元介绍

门控循环单元(GRU)是LSTM单元的一种变体,由Kyunghyun Cho等人在2014年提出。它将单元状态和隐藏状态合并为一个向量h(t),并进行了一些其他更改。与标准LSTM模型相比,GRU模型更简单,并且越来越受欢迎。
GRU单元的工作原理如下:
- 一个单一的门控控制器同时控制遗忘门和输入门。当门控控制器输出为1时,输入门打开,遗忘门关闭;当输出为0时,情况相反。
- 每次存储记忆时,会先擦除存储位置。
- 由于每个时间步都会输出完整的状态向量,因此没有输出门。但引入了一个新的门控控制器,用于控制将上一状态的哪一部分显示给主层。

1.4 RNN成功的关键因素

LSTM和GRU单元是近年来循环神经网络(RNN)成功的主要原因之一,尤其是在自然语言处理(NLP)应用中。

2. 卷积神经网络在图像分类中的应用

2.1 传统DNN的局限性

传统的线性机器学习模型和深度神经网络(DNN),如多层感知器(MLP)或深度信念网络(DBN),在处理图像时存在局限性。对于小图像(如MNIST、CIFAR - 10),它们可以正常工作,但对于大图像,由于需要大量的参数,性能会下降。例如,一个100x100的图像有10,000个像素,如果第一层只有1,000个神经元,那么仅第一层就有1000万个连接。

2.2 CNN的优势

卷积神经网络(CNN)通过部分连接层解决了这个问题。由于连续层之间只是部分连接,并且大量重用权重,CNN的参数比全连接DNN少得多,这使得训练速度更快,减少了过拟合的风险,并且需要的训练数据也更少。此外,CNN学习到的特征可以在图像的任何位置检测到,而DNN学习到的特征只能在特定位置检测到。

2.3 CNN架构

典型的CNN架构由多个卷积层、整流线性单元(ReLU)层、池化层和全连接层组成。具体结构如下:

graph LR
    A[输入层] --> B[卷积层1]
    B --> C[ReLU层1]
    C --> D[池化层1]
    D --> E[卷积层2]
    E --> F[ReLU层2]
    F --> G[池化层2]
    G --> H[全连接层1]
    H --> I[ReLU层3]
    I --> J[全连接层2]
    J --> K[输出层]

每个卷积层的输出是一组特征图,由单个内核滤波器生成。池化层通常位于卷积层之后,用于对输入图像进行下采样,以减少计算负载、内存使用和参数数量。

2.4 卷积操作

卷积是一种数学操作,在信号处理中广泛使用。CNN中的卷积层实际上使用的是互相关操作,与卷积非常相似。CNN的第一个卷积层中的神经元只连接到输入图像中其感受野内的像素,而不是每个像素。这种架构允许网络在第一个隐藏层中专注于低级特征,然后在后续隐藏层中将它们组合成高级特征。

2.5 池化层和填充操作

池化层中的每个神经元连接到前一层中一个小矩形感受野内的有限数量的神经元。池化神经元没有权重,只是使用聚合函数(如最大值或平均值)对输入进行聚合。使用池化的目的是对输入图像进行下采样,以减少计算负载、内存使用和参数数量,避免过拟合,并使神经网络能够容忍图像的轻微偏移。
填充操作分为SAME和VALID两种类型:
- SAME:输出特征图的空间维度与输入特征图相同,通过在输入图的每一侧添加零来实现。
- VALID:不进行填充,只丢弃最右侧的列(或最底部的行)。

2.6 DL4j环境配置

在使用Deeplearning4j(DL4j)进行CNN开发之前,需要配置编程环境。可集成的库如下:
- DL4j:神经网络平台
- ND4J:JVM的NumPy
- DataVec:机器学习ETL工具
- JavaCPP:Java与本地C++的桥梁
- Arbiter:机器学习算法评估工具
- RL4J:JVM的深度强化学习

如果使用Maven在Eclipse或IntelliJ IDEA中开发,需要在pom.xml文件中添加以下依赖:

<dependency>
    <groupId>org.deeplearning4j</groupId>
    <artifactId>deeplearning4j-core</artifactId>
    <version>0.4-rc3.9</version>
</dependency>
<dependency>
    <artifactId>canova-api</artifactId>
    <groupId>org.nd4j</groupId>
    <version>0.4-rc3.9</version>
</dependency>
<dependency>
    <groupId>org.nd4j</groupId>
    <artifactId>nd4j-native</artifactId>
    <version>0.4-rc3.9</version>
</dependency>
<dependency>
    <groupId>org.nd4j</groupId>
    <artifactId>canova-api</artifactId>
    <version>0.0.0.17</version>
</dependency>

同时,需要注意以下几点:
- 确保安装并配置了Java(开发版本)1.8+(仅支持64位版本)。
- 使用Apache Maven进行自动化构建和依赖管理。
- 选择IntelliJ IDEA或Eclipse作为开发工具。
- 安装Git。
- 如果未配置本地系统BLAS,ND4J的性能会降低,可参考http://nd4j.org/getstarted.html#open进行安装和配置。

2.7 构建和训练简单CNN

以MNIST数据集为例,构建一个包含两个卷积层、两个下采样层、一个密集层和一个全连接输出层的CNN。具体代码如下:

import org.deeplearning4j.nn.conf.MultiLayerConfiguration
import org.deeplearning4j.nn.conf.NeuralNetConfiguration
import org.deeplearning4j.nn.conf.Updater
import org.deeplearning4j.nn.conf.layers.ConvolutionLayer
import org.deeplearning4j.nn.conf.layers.DenseLayer
import org.deeplearning4j.nn.conf.layers.OutputLayer
import org.deeplearning4j.nn.conf.layers.SubsamplingLayer
import org.deeplearning4j.nn.conf.layers.setup.ConvolutionLayerSetup
import org.deeplearning4j.nn.multilayer.MultiLayerNetwork
import org.deeplearning4j.nn.weights.WeightInit
import org.deeplearning4j.optimize.listeners.ScoreIterationListener
import org.nd4j.linalg.dataset.DataSet
import org.nd4j.linalg.dataset.api.iterator.DataSetIterator
import org.nd4j.linalg.lossfunctions.LossFunctions
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.deeplearning4j.datasets.iterator.impl.MnistDataSetIterator
import org.deeplearning4j.eval.Evaluation

object MNIST {
    val log: Logger = LoggerFactory.getLogger(MNIST.getClass)
    def main(args: Array[String]): Unit = {
        val nChannels = 1 // for grayscale image
        val outputNum = 10 // number of class
        val nEpochs = 10 // number of epoch
        val iterations = 1 // number of iteration
        val seed = 12345 // Random seed for reproducibility
        val batchSize = 64 // number of batches to be sent

        log.info("Load data....")
        val mnistTrain: DataSetIterator = new MnistDataSetIterator(batchSize, true, 12345)
        val mnistTest: DataSetIterator = new MnistDataSetIterator(batchSize, false, 12345)

        log.info("Network layer construction started...")
        //First convolution layer with ReLU as activation function
        val layer_0 = new ConvolutionLayer.Builder(5, 5)
          .nIn(nChannels)
          .stride(1, 1)
          .nOut(20)
          .activation("relu")
          .build()
        //First subsampling layer
        val layer_1 = new SubsamplingLayer.Builder(SubsamplingLayer.PoolingType.MAX)
          .kernelSize(2, 2)
          .stride(2, 2)
          .build()
        //Second convolution layer with ReLU as activation function
        val layer_2 = new ConvolutionLayer.Builder(5, 5)
          .nIn(nChannels)
          .stride(1, 1)
          .nOut(50)
          .activation("relu")
          .build()
        //Second subsampling layer
        val layer_3 = new SubsamplingLayer.Builder(SubsamplingLayer.PoolingType.MAX)
          .kernelSize(2, 2)
          .stride(2, 2)
          .build()
        //Dense layer
        val layer_4 = new DenseLayer.Builder()
          .activation("relu")
          .nOut(500)
          .build()
        // Final and fully connected layer with Softmax as activation function
        val layer_5 = new OutputLayer.Builder(LossFunctions.LossFunction.NEGATIVELOGLIKELIHOOD)
          .nOut(outputNum)
          .activation("softmax")
          .build()

        log.info("Model building started...")
        val builder: MultiLayerConfiguration.Builder = new NeuralNetConfiguration.Builder()
          .seed(seed)
          .iterations(iterations)
          .regularization(true).l2(0.0005)
          .learningRate(0.01)
          .weightInit(WeightInit.XAVIER)
          .optimizationAlgo(OptimizationAlgorithm.STOCHASTIC_GRADIENT_DESCENT)
          .updater(Updater.NESTEROVS).momentum(0.9)
          .list()
            .layer(0, layer_0)
            .layer(1, layer_1)
            .layer(2, layer_2)
            .layer(3, layer_3)
            .layer(4, layer_4)
            .layer(5, layer_5)
          .backprop(true).pretrain(false) // feedforward so no backprop

        // Setting up all the convlutional layers and initialize the network
        new ConvolutionLayerSetup(builder, 28, 28, 1) //image size is 28*28
        val conf: MultiLayerConfiguration = builder.build()
        val model: MultiLayerNetwork = new MultiLayerNetwork(conf)
        model.init()

        log.info("Model training started...")
        model.setListeners(new ScoreIterationListener(1))
        var i = 0
        while (i <= nEpochs) {
            model.fit(mnistTrain);
            log.info("*** Completed epoch {} ***", i)
            i = i + 1
        }

        var ds: DataSet = null
        var output: INDArray = null

        log.info("Model evaluation....")
        val eval: Evaluation = new Evaluation(outputNum)
        while (mnistTest.hasNext()) {
            ds = mnistTest.next()
            output = model.output(ds.getFeatureMatrix(), false)
        }
        eval.eval(ds.getLabels(), output)

        println("Accuracy: " + eval.accuracy())
        println("F1 measure: " + eval.f1())
        println("Precision: " + eval.precision())
        println("Recall: " + eval.recall())
        println("Confusion matrix: " + "\n" + eval.confusionToString())
        log.info(eval.stats())
        mnistTest.reset()
    }
}

通过以上步骤,我们可以构建、训练和评估一个简单的CNN模型,用于MNIST数据分类。在实际应用中,还可以根据需要调整超参数,以获得更好的分类结果。

2.8 模型训练与评估步骤总结

在使用上述代码构建和训练CNN模型时,可按照以下步骤进行:
1. 数据准备
- 指定灰度图像的通道数 nChannels = 1
- 确定分类的类别数 outputNum = 10
- 设置训练的轮数 nEpochs = 10 和迭代次数 iterations = 1
- 设定随机种子 seed = 12345 以确保结果可复现。
- 确定批次大小 batchSize = 64
- 使用 MnistDataSetIterator 加载MNIST训练集和测试集。
2. 网络层构建
- 构建第一个卷积层 layer_0 ,使用ReLU激活函数。
- 构建第一个下采样层 layer_1 ,采用最大池化。
- 构建第二个卷积层 layer_2 ,使用ReLU激活函数。
- 构建第二个下采样层 layer_3 ,采用最大池化。
- 构建密集层 layer_4 ,使用ReLU激活函数。
- 构建全连接输出层 layer_5 ,使用Softmax激活函数。
3. 模型配置与初始化
- 使用 NeuralNetConfiguration.Builder 配置神经网络。
- 设置随机种子、迭代次数、正则化、学习率、权重初始化方法等。
- 将各层添加到配置中,并设置反向传播和预训练参数。
- 使用 ConvolutionLayerSetup 设置卷积层。
- 构建配置并初始化模型。
4. 模型训练
- 设置迭代监听,每一轮迭代输出得分。
- 循环训练 nEpochs 轮,每轮使用训练集进行拟合。
5. 模型评估
- 使用 Evaluation 类对测试集进行评估。
- 遍历测试集,获取模型输出并进行评估。
- 输出准确率、F1值、精确率、召回率和混淆矩阵等评估指标。

2.9 CNN在图像分类中的优势总结

优势 说明
参数少 部分连接层和权重共享使得CNN的参数比全连接DNN少,训练速度更快,减少过拟合风险,所需训练数据更少。
特征泛化能力强 学习到的特征可以在图像的任何位置检测到,而不像DNN只能在特定位置检测到。
利用图像结构信息 架构嵌入了像素组织的先验知识,能更好地处理自然图像。

2.10 CNN架构可视化总结

graph LR
    A[输入层] --> B[卷积层1]
    B --> C[ReLU层1]
    C --> D[池化层1]
    D --> E[卷积层2]
    E --> F[ReLU层2]
    F --> G[池化层2]
    G --> H[全连接层1]
    H --> I[ReLU层3]
    I --> J[全连接层2]
    J --> K[输出层]

这个流程图展示了典型CNN架构的基本组成部分,包括卷积层、ReLU层、池化层和全连接层。输入图像经过一系列的卷积和池化操作,提取特征,最后通过全连接层进行分类。

2.11 后续优化方向

虽然我们已经构建并训练了一个简单的CNN模型,但在实际应用中,还可以通过以下方式进一步优化模型性能:
1. 调整超参数 :尝试不同的学习率、批次大小、迭代次数和LSTM层数等超参数,以找到最优的组合。
2. 增加数据量 :使用更多的训练数据可以提高模型的泛化能力,减少过拟合的风险。
3. 改进网络架构 :尝试不同的卷积核大小、池化方法和网络层数,以构建更复杂、更强大的CNN模型。
4. 数据增强 :对训练数据进行旋转、翻转、缩放等操作,增加数据的多样性,提高模型的鲁棒性。

通过不断地优化和改进,我们可以使CNN模型在图像分类任务中取得更好的性能,满足实际应用的需求。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值