1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
import torch.nn as nn
import torch.nn.functional as F
import time
image_size = 28 # 图像总尺寸是28x28
num_classes = 10 # 标签总类数 1~10
num_epochs = 20 # 训练总周期
batch_size = 64 # 一个批次的大小,64张图片
# 定义一个卷积神经网络,4,8为指定两个卷积层厚度
# from MINIST.data import image_size, num_classes
depth = [4, 8]
class ConvNet(nn.Module):
# 复写构造函数
def __init__(self):
print('ConvNet 起始时间', time.strftime("%Y-%m-%d %H:%M:%S"))
# 该函数在创建一个ConvNet对象时即net=ConvNet()时就会被调用
# 首先调用父类的构造函数
super(ConvNet, self).__init__()
# 定义一个卷积层,输入通道为1,输出通道为4,窗口大小为5,padding为2\r\n
self.conv1 = nn.Conv2d(1, 4, 5, padding=2)
self.pool = nn.MaxPool2d(2, 2) # 定义一个池化层,一个窗口为2x2的池化运算、\r\n
# 第二层卷积 输入通道为depth[0],输入通道为depth[1],窗口为5,padding为2\r\n
self.conv2 = nn.Conv2d(depth[0], depth[1], 5, padding=2)
# 一个线性连接层,输入尺寸为最后一层立方体的线性平铺 输出层512个节点\r\n
self.fc1 = nn.Linear(image_size // 4 * image_size // 4 * depth[1], 512)
self.fc2 = nn.Linear(512, num_classes) # 最后一层线性分类单元输入为512,,输出为要做分类的类别数\r\n\r\n
def forward(self, x): # 该函数完成神经网络真正的前向运算,在这里把各个组件进行实际的拼装\r\n # x的尺寸 (batch_size,image_channels,image_width,image_height)\r\n
x = self.conv1(x) # 第一层卷积\r\n
x = F.relu(x) # 激活函数用ReLU,防止过拟合\r\n # 此时x的尺寸 (batch_size,num_filters,image_width,image_height)\r\n\r\n
x = self.pool(x) # 第二层是池化,将图片变小\r\n # x尺寸 (batch_size,depth[0],image_width/2,image_height/2)\r\n\r\n
x = self.conv2(x) # 第三层又是卷积,窗口为5,输入输出通道分别为depth[0]=4,depth[1]=8\r\n
x = F.relu(x) # 非线性函数\r\n # x尺寸 (batch_size,depth[1],image_width/2,image_height/2)\r\n\r\n
x = self.pool(x) # 第四层是池化,将图片缩小为原来的1/4\r\n # x尺寸 (batch_size,depth[1],image_width/4,image_height/4)\r\n\r\n # 将立体的特征图tensor压成一维向量\r\n
x = x.view(-1, image_size // 4 * image_size // 4 * depth[1]) # 该函数将x压成一维向量\r\n
# x尺寸 (batch_size,image_size//4*image_size//4*depth[1])\r\n\r\n
x = F.relu(self.fc1(x)) # 第五层为全连接,ReLUctant激活函数\r\n
# x的尺寸,(batch_size,512)\r\n\r\n # 以0.5的概率对这一层进行dropout操作,防止过拟合\r\n
x = F.dropout(x, training=self.training)
x = self.fc2(x) # 全连接\r\n # x的尺寸(batch_size,num_classes)\r\n\r\n # 输出层为log_softmax,即概率对数值log(p(x)),采用这个函数,可以使得后面交叉熵计算更快\r\n
x = F.log_softmax(x, dim=1)
return x
def retrieve_features(self, x): # 该函数用于提取网络的特征图,返回feature_map1,feature_map2为前两层卷积层的特征图\r\n
feature_map1 = F.relu(self.conv1(x)) # 完成第一次卷积\r\n
x = self.pool(feature_map1) # 完成第一次池化\r\n
feature_map2 = F.relu(self.conv2(x))
return (feature_map1, feature_map2)
|