不多说,直接上代码,自己边学边记录
下面展示一个CNN
。
import torch
import torch.nn as nn
import torch.nn.functional as F
#cnn框架,定义Net的初始化函数,这个函数定义了该神经网络的基本结构
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__() #复制并使用Net的父类的初始化方法,即先运行nn.Module的初始化函数
self.conv1 = nn.Conv2d(1, 6, 5) #定义conv1函数的是图像卷积函数:输入为图像(1个频道,即灰度图),输出为 6张特征图, 卷积核为5x5正方形
self.conv2 = nn.Conv2d(6, 16, 5) #定义conv2函数的是图像卷积函数:输入为6张特征图,输出为16张特征图, 卷积核为5x5正方形
self.fc1 = nn.Linear(16 * 5 * 5, 120) #定义fc1(fullconnect)全连接函数1为线性函数:y = Wx + b,并将16*5*5个节点连接到120个节点上。
self.fc2 = nn.Linear(120, 84) #定义fc2(fullconnect)全连接函数2为线性函数:y = Wx + b,并将120个节点连接到84个节点上。
self.fc3 = nn.Linear(84, 10) #定义fc3(fullconnect)全连接函数3为线性函数:y = Wx + b,并将84个节点连接到10个节点上。
#定义该神经网络的向前传播函数,该函数必须定义,一旦定义成功,向后传播函数也会自动生成(autograd)
def forward(self):
x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2)) #输入x->conv1->relu->2x2窗口的最大池化,输入x经过卷积conv1之后,经过激活函数ReLU,使用2x2的窗口进行最大池化Max pooling,然后更新到x。
x = F.max_pool2d(F.relu(self.conv2(x)), 2) #输入x->conv2->relu->2x2窗口的最大池化,输入x经过卷积conv2之后,经过激活函数ReLU,使用2x2的窗口进行最大池化Max pooling,然后更新到x。
x = x.view(-1, self.num_float_features(x)) #view函数将张量x变形成一维的向量形式,总特征数并不改变,为接下来的全连接作准备。
x = F.relu(self.fc1(x)) #输入x经过全连接1,再经过ReLU激活函数,然后更新x
x = F.relu(self.fc2(x)) #输入x经过全连接2,再经过ReLU激活函数,然后更新x
x = self.fc3(x) #输入x经过全连接3,然后更新x
return x
#使用num_flat_features函数计算张量x的总特征量(把每个数字都看出是一个特征,即特征总量),比如x是4*2*2的张量,那么它的特征总量就是16
def num_float_features(self, x):
size = x.size()[1:] #这里为什么要使用[1:],是因为pytorch只接受批输入,也就是说一次性输入好几张图片,那么输入数据张量的维度自然上升到了4维。[1:]让我们把注意力放在后3维上面
num_features = 1
for s in size:
num_features *= s
return num_features
net = Net()
print(net)
params = list(net.parameters())
print(len(params))
print(params[0].size())
这里面二维卷积nn.Conv2d用于图像数据,对宽度和高度都进行卷积。
运行截图如下:
nn.Conv2d定义:
class torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)
主要参数说明:
in_channels:在文本应用中,即为词向量的维度
out_channels:卷积产生的通道数,有多少个out_channels,就需要多少个一维卷积(也就是卷积核的数量)
kernel_size:卷积核的尺寸;卷积核的第二个维度由in_channels决定,所以实际上卷积核的大小为kernel_size * in_channels
padding:对输入的每一条边,补充0的层数