卷积神经网络之手撕代码
1、计算卷积神经网络的输出尺寸
n = \dfrac{W-F+2P}{S}+1其中:N 代表输出尺寸,W 代表输入尺寸,F 代表卷积核大小,P 代表填充尺寸,S 代表步长
2、网络参数量的计算
对于CNN而言,每个卷积层的参数量如下:
params = C_{o} \times(C_{i}\times k_{w} \times k_{h}+1)其中, C_{i} 代表输入特征的通道数,也即是每个卷积核的通道数,k_{w}, k_{h} 分别代表卷积核的宽和高,C_{o} 代表输出特征的通道数,也即是卷积核的个数。+1 代表偏置项。
对于全连接层而言,每个全连接层的参数量如下:
parames = I\times O+O其中,I 代表输入神经元的个数,O 代表输出神经元的个数,+O 代表偏置项
3、网络运算量(Flops)
FLOPs 是英文 floating point operations 的缩写,表示浮点运算量,中括号内的值表示卷积操作计算出 feature map 中一个点所需要的运算量(乘法和加法)。
对于CNN而言,每个卷积层的运算量如下:
FLOPs = [(C_{i} \times k_{w} \times k_{h}) + (C_{i} \times k_{w} \times k_{h} -1)+1]\times C_{o} \times W \times H其中,C_{i} 表示输入特征图的通道,k_{w},k_{h} 分别代表卷积核的宽和高,C_{o} 代表输出特征的通道数,H,W 分别代表输出特征向量的宽和高。由于输出特征的每个像素都是由卷积核元素与输入特征向量对应位置一一相乘然后再相加得到的,因此乘法计算量为:(C_{i} \times k_{w} \times k_{h})\times C_{o} \times W \times H,加法计算量为:(C_{i} \times k_{w} \times k_{h} -1)\times C_{o} \times W \times H,因为如果乘了9次,只做了8次加法运算,偏置的计算量为:C_{o} \times W \times H,所以总的 FLOPs 如上所示。
对于全连接网络而言,每个全连接层的FLOPs如下:
FLOPs = [I + (I-1) + 1] \times O其中,I 代表每个输出神经元的乘法运算量,I-1 代表每个输出神经元的加法运算量,+1 代表偏置。
4、CNN中感受野的计算
在卷积神经网络中, 感受野(Receptive Field)是指特征图上的某个点能看到的输入图像的区域,即特征图上的点是由输入图像中感受野大小区域的计算得到的,计算如下:
RF_{i+1} = RF_{i}+(k-1) \times S_{i}其中,RF_{i+1} 和 RF_{i} 分别表示第 i+1 和第 i 层的感受野大小,k 表示卷积核的大小,S_{i} 表示之前所有层的步长的乘积(不包括本层)。
5、CNN中上采样的方法
双三次插值:其根据离待插值最近的4*4=16个已知值来计算待插值,每个已知值的权重由距离待插值距离决定,距离越近权重越大。
k = nn.Upsample(scale_factor=2, mode='bicubic', align_corners=True) # 创建双三次插值实例 Output = k(Input)
反卷积:该方式将引入许多‘0’的行和‘0’的列,导致实现上非常的低效。并且,反卷积只能恢复尺寸,并不能恢复数值,因此经常用在神经网络中作为提供恢复的尺寸,具体的数值往往通过训练得到。
Input = torch.arange(1,10,dtype=torch.float32).view(1,1,3,3) Transposed = nn.ConvTranspose2d(1,1,3,stride=2, padding = 1) Output = Transposed(Input)
亚像素上采样:假设原始输入为 [C,H,W],需要变成 [C,sH,sW] 的大小,那么亚像素上采样分两步走:
- [C,H,W] ==> [s^{2}C, H, W],通过卷积实现通道的扩充
- [s^{2}C, H, W] ==> [C,sH,sW],通过 PixelShuffle 的方式实现长宽的增加
class Net(nn.Module): def __init__(self, upscale_factor): super(Net, self).__init__() self.conv1 = nn.Conv2d(1, 64, (5, 5), (1, 1), (2, 2)) self.conv2 = nn.Conv2d(64, 32, (3, 3), (1, 1), (1, 1)) self.conv3 = nn.Conv2d(32, 1 * (upscale_factor ** 2), (3, 3), (1, 1), (1, 1)) # 最终将输入转换成 [32, 9, H, W] self.pixel_shuffle = nn.PixelShuffle(upscale_factor) # 通过 Pixel Shuffle 来将 [32, 9, H, W] 重组为 [32, 1, 3H, 3W] def forward(self, x): x = torch.tanh(self.conv1(x)) x = torch.tanh(self.conv2(x)) x = torch.sigmoid(self.pixel_shuffle(self.conv3(x))) return x
6、Softmax函数
Softmax 函数:将激活值与所有神经元的输出值联系在一起,所有神经元的激活值加起来为1。第L层(最后一层)的第j个神经元的激活输出为:
a_{j}^{L}=\frac{e^{Z_{j}^{L}}}{\sum_{k} e^{Z_{t}^{L}}}def softmax(x): shift_x = x - np.max(x)#防止输入增大时输出为nan exp_x = np.exp(shift_x) return exp_x / np.sum(exp_x)
7、手写一个卷积神经网络的训练模板
import torch import torch.nn as nn class Network(nn.Module): def __init__(self): super().__init__() self.head = nn.Senquential( nn.Conv2d(1,20,5), nn.ReLU(), nn.Conv2d(20,64,5), nn.ReLU()) self.tail = nn.Senquential( nn.Conv2d(64,20,5), nn.ReLU(), nn.Conv2d(20,3,5), nn.ReLU()) def forward(self, x): x = self.head(x) x = self.tail(x) return x import torch.optimal optimal = torch.optimal.Adam() MSE = nn.MSELoss() model = Network() Input = torch.floatTensor(1,3,32,32) for i in range(epochs): out = model(Input) loss = MSE(out, label) loss.backward() loss.step()
- 手撕卷积神经网络CNN【附代码】
- 卷积神经网络(CNN)讲解及代码
- 卷积神经网络(CNN)代码实现(MNIST)解析
- 卷积神经网络(CNN)的训练及代码实现
- 1700X + GTX950 跑 CNN卷积神经网络面部表情识别实例代码
- Deep Learning论文笔记之(五)CNN卷积神经网络代码理解
- Coursera deeplearning.ai 深度学习笔记4-1-Foundations of Convolutional Neural Networks-卷积神经网络基础及代码实现
- 深度学习之卷积神经网络CNN及tensorflow代码实现示例详细介绍(转载)
- 利用卷积神经网络(VGG19)实现火灾分类(附tensorflow代码及训练集)
- 深度学习(五)CNN卷积神经网络代码理解
- 深度学习之卷积神经网络CNN及tensorflow代码实现示例
- 卷积神经网络的前向传播、反向传播及其代码实现
- Matlab deep learning toolbox CNN 卷积神经网络代码改进
- Deep Learning论文笔记之(五)CNN卷积神经网络代码理解
- 代码实例讲解:卷积神经网络程序细节(附完整代码)
- 一文带你理解卷积神经网络(CNN),附代码实现与CNN网络训练基本概念讲解
- 深度学习之卷积神经网络CNN及tensorflow代码实现示例详细介绍
- DeepLearning tutorial(4)CNN卷积神经网络原理简介+代码详解
- 小白_从0开始学习_FashionMNIST_深度学习_卷积神经网络_pytorch代码详解
- 深度学习(五)CNN卷积神经网络代码理解