全连接神经网络FC(Full Connection)
FC的准则很简单:神经网络中除输入层之外的每个节点都和上一层的所有节点有连接。例如下面这个网络结构就是典型的全连接:
神经网络的第一层为输入层,最后一层为输出层,中间所有的层都为隐藏层。在计算神经网络层数的时候,一般不把输入层算做在内,所以上面这个神经网络为2层。其中输入层有3个神经元,隐层有4个神经元,输出层有2个神经元。
用PyTorch完成手写数字识别
简单的FC
from torch
import nn
class simpleNet(nn
.Module
):
"""
定义了一个简单的三层全连接神经网络,每一层都是线性的
"""
def __init__(self
, in_dim
, n_hidden_1
, n_hidden_2
, out_dim
):
super(simpleNet
, self
).__init__
()
self
.layer1
= nn
.Linear
(in_dim
, n_hidden_1
)
self
.layer2
= nn
.Linear
(n_hidden_1
, n_hidden_2
)
self
.layer3
= nn
.Linear
(n_hidden_2
, out_dim
)
def forward(self
, x
):
x
= self
.layer1
(x
)
x
= self
.layer2
(x
)
x
= self
.layer3
(x
)
return x
加激活函数的FC
class Activation_Net(nn
.Module
):
"""
在上面的simpleNet的基础上,在每层的输出部分添加了激活函数
"""
def __init__(self
, in_dim
, n_hidden_1
, n_hidden_2
, out_dim
):
super(Activation_Net
, self
).__init__
()
self
.layer1
= nn
.Sequential
(nn
.Linear
(in_dim
, n_hidden_1
), nn
.ReLU
(True))
self
.layer2
= nn
.Sequential
(nn
.Linear
(n_hidden_1
, n_hidden_2
), nn
.ReLU
(True))
self
.layer3
= nn
.Sequential
(nn
.Linear
(n_hidden_2
, out_dim
))
"""
这里的Sequential()函数的功能是将网络的层组合到一起。
"""
def forward(self
, x
):
x
= self
.layer1
(x
)
x
= self
.layer2
(x
)
x
= self
.layer3
(x
)
return x
加激活函数和批标准化的FC
class Batch_Net(nn
.Module
):
"""
在上面的Activation_Net的基础上,增加了一个加快收敛速度的方法——批标准化
"""
def __init__(self
, in_dim
, n_hidden_1
, n_hidden_2
, out_dim
):
super(Batch_Net
, self
).__init__
()
self
.layer1
= nn
.Sequential
(nn
.Linear
(in_dim
, n_hidden_1
), nn
.BatchNorm1d
(n_hidden_1
), nn
.ReLU
(True))
self
.layer2
= nn
.Sequential
(nn
.Linear
(n_hidden_1
, n_hidden_2
), nn
.BatchNorm1d
(n_hidden_2
), nn
.ReLU
(True))
self
.layer3
= nn
.Sequential
(nn
.Linear
(n_hidden_2
, out_dim
))
def forward(self
, x
):
x
= self
.layer1
(x
)
x
= self
.layer2
(x
)
x
= self
.layer3
(x
)
return x
导入包
除了之前常用的torch, nn, Variable之外,还导入了DataLoader用于加载数据,使用了torchvision进行图片的预处理,然后,导入了上面所定义的三个模型。
import torch
from torch
import nn
, optim
from torch
.autograd
import Variable
from torch
.utils
.data
import DataLoader
from torchvision
import datasets
, transforms
定义一些超参数
batch_size
= 64
learning_rate
= 0.02
num_epoches
= 20
数据预处理
在torchvision中提供了transforms用于帮我们对图片进行预处理和标准化。其中我们需要用到的有两个:ToTensor()和Normalize()。前者用于将图片转换成Tensor格式的数据,并且进行了标准化处理。后者用均值和标准偏差对张量图像进行归一化:给定均值:
(
M
1
,
.
.
.
,
M
n
)
(M_1,...,M_n)
(M1,...,Mn) 和标准差:
(
S
1
,
.
.
,
S
n
)
(S_1,..,S_n)
(S1,..,Sn) 用于 n 个通道, 该变换将标准化输入
t
o
r
c
h
.
∗
T
e
n
s
o
r
torch.*Tensor
torch.∗Tensor 的每一个通道。其处理公式为:
i
n
p
u
t
[
c
h
a
n
n
e
l
]
=
(
i
n
p
u
t
[
c
h
a
n
n
e
l
]
−
m
e
a
n
[
c
h
a
n
n
e
l
]
)
/
s
t
d
[
c
h
a
n
n
e
l
]
input[channel] = (input[channel] - mean[channel])/std[channel]
input[channel]=(input[channel]−mean[channel])/std[channel]
而Compose函数可以将上述两个操作合并到一起执行。
data_tf
= transforms
.Compose
(
[transforms
.ToTensor
(),transforms
.Normalize
([0.5], [0.5])]
)
加载数据
PyTorch提供了一些常用数据集,所以我们定义数据集下载器如下:
train_dataset
= datasets
.MNIST
(
root
='./data', train
=True, transform
=data_tf
, download
=True)
test_dataset
= datasets
.MNIST
(root
='./data', train
=False, transform
=data_tf
)
train_loader
= DataLoader
(train_dataset
, batch_size
=batch_size
, shuffle
=True)
test_loader
= DataLoader
(test_dataset
, batch_size
=batch_size
, shuffle
=False)
选择模型
然后选择相应的神经网路模型来进行训练和测试,我们这里定义的神经网络输入层为
28
∗
28
28*28
28∗28,因为我们处理过的图片像素为
28
∗
28
28*28
28∗28,两个隐层分别为300和100,输出层为10,因为我们识别0~9十个数字,需要分为十类。损失函数和优化器这里采用了交叉熵和梯度下降。
model
= Batch_Net
(28 * 28, 300, 100, 10)
if torch
.cuda
.is_available
():
model
= model
.cuda
()
criterion
= nn
.CrossEntropyLoss
()
optimizer
= optim
.SGD
(model
.parameters
(), lr
=learning_rate
)
训练模型
epoch
= 0
for data
in train_loader
:
img
, label
= data
img
= img
.view
(img
.size
(0), -1)
if torch
.cuda
.is_available
():
img
= img
.cuda
()
label
= label
.cuda
()
else:
img
= Variable
(img
)
label
= Variable
(label
)
out
= model
(img
)
loss
= criterion
(out
, label
)
print_loss
= loss
.data
.item
()
optimizer
.zero_grad
()
loss
.backward
()
optimizer
.step
()
if epoch
%100 == 0:
print('epoch: {}, loss: {:.4}'.format(epoch
, loss
.data
.item
()))
epoch
+=1
epoch: 0, loss: 0.2853
epoch: 100, loss: 0.2219
epoch: 200, loss: 0.2972
epoch: 300, loss: 0.04177
epoch: 400, loss: 0.2452
epoch: 500, loss: 0.2274
epoch: 600, loss: 0.1519
epoch: 700, loss: 0.07398
epoch: 800, loss: 0.271
epoch: 900, loss: 0.07532
模型评估
model
.eval()
eval_loss
= 0
eval_acc
= 0
for data
in test_loader
:
img
, label
= data
img
= img
.view
(img
.size
(0), -1)
if torch
.cuda
.is_available
():
img
= img
.cuda
()
label
= label
.cuda
()
out
= model
(img
)
loss
= criterion
(out
, label
)
eval_loss
+= loss
.data
.item
()*label
.size
(0)
_
, pred
= torch
.max(out
, 1)
num_correct
= (pred
== label
).sum()
eval_acc
+= num_correct
.item
()
print('Test Loss: {:.6f}, Acc: {:.6f}'.format(
eval_loss
/ (len(test_dataset
)),
eval_acc
/ (len(test_dataset
))
))
Test Loss: 0.140840, Acc: 0.956800
参考资料
新手必备 | 史上最全的PyTorch学习资源汇总
快速上手笔记,PyTorch模型训练实用教程(附代码)
PyTorch学习笔记
《深度学习框架PyTorch:入门与实践》的对应代码
PyTorch 中文文档
深度学习