基本模块搭建
模块化编程的思想非常重要,通过模块化编程可以大幅减少重复的敲代码过程,同时代码可读性也会增加。本章将讲述如何使用libtorch搭建一些MLP和CNN的基本模块。
MLP基本单元
首先是线性层的声明和定义,包括初始化和前向传播函数。代码如下:
1 | class LinearBnReluImpl : public torch::nn::Module{ |
在MLP的构造线性层模块类时,我们继承了torch::nn::Module类,将初始化和前向传播模块作为public,可以给对象使用,而里面的线性层torch::nn::Linear和归一化层torch::nn::BatchNorm1d被隐藏作为私有变量。
定义初始化函数时,需要将原本的指针对象ln和bn进行赋值,同时将两者的名称也确定。前向传播函数就和pytorch中的forward类似。
CNN基本单元
CNN的基本单元构建和MLP的构建类似,但是又稍有不同,首先需要定义的时卷积超参数确定函数。
1 | inline torch::nn::Conv2dOptions conv_options(int64_t in_planes, int64_t out_planes, int64_t kerner_size, |
该函数返回torch::nn::Conv2dOptions对象,对象的超参数由函数接口指定,这样可以方便使用。同时指定inline,提高Release模式下代码执行效率。
随后则是和MLP的线性模块类似,CNN的基本模块由卷积层,激活函数和归一化层组成。代码如下:
1 | class ConvReluBnImpl : public torch::nn::Module { |
简单MLP
在MLP的例子中,我们以搭建一个四层感知机为例,介绍如何使用cpp实现深度学习模型。该感知机接受in_features个特征,输出out_features个编码后的特征。中间特征数定义为32,64和128,其实一般逆序效果更佳,但是只是作为例子也无关紧要。
1 | class MLP: public torch::nn::Module{ |
每一层的实现均是通过前面定义的基本模块LinearBnRelu。
简单CNN
前面介绍了构建CNN的基本模块ConvReluBn,接下来尝试用c++搭建CNN模型。该CNN由三个stage组成,每个stage又由一个卷积层一个下采样层组成。这样相当于对原始输入图像进行了8倍下采样。中间层的通道数变化与前面MLP特征数变化相同,均为输入->32->64->128->输出。
1 | class plainCNN : public torch::nn::Module{ |
假定输入一个三通道图片,输出通道数定义为n,输入表示一个[1,3,224,224]的张量,将得到一个[1,n,28,28]的输出张量。
简单LSTM
最后则是一个简单的LSTM的例子,用以处理时序型特征。在直接使用torch::nn::LSTM类之前,我们先顶一个返回torch::nn::LSTMOptions对象的函数,该函数接受关于LSTM的超参数,返回这些超参数定义的结果。
1 | inline torch::nn::LSTMOptions lstmOption(int in_features, int hidden_layer_size, int num_layers, bool batch_first = false, bool bidirectional = false){ |
声明好LSTM以后,我们将内部的初始化函数和前向传播函数实现如下:
1 | LSTM::LSTM(int in_features, int hidden_layer_size, int out_size, int num_layers, bool batch_first){ |
代码见github