介绍
像多层感知机网络,为了熟悉网络的搭建,训练流程,我们可以选择使用numpy 去编写,自己编写网络模型,自己实现随机梯度下降算法等。
但是今天的主题不是为了扎实基础,而是如何更快的上手。
为了快速、高效搭建神经网络,有很多的深度模型框架可以使用,例如Pytorch、Caffe、TensorFlow等等。
各有各的好处,每个人可以根据自己的习惯选择喜欢的框架进行开发。
就留给同学们课下去了解了
#引入
import torch
import torchvision
import torch.nn as nn # 网络模型
import torch.nn.functional as F #方法 损失函数,激活函数
pytorch 的语法跟 numpy很像,如果你熟练numpy 的话,应该可以很轻松的上手pytorch的。
a = torch.zeros((5,2))
b = torch.ones((1,8))
e = torch.eye(8)
print(e)
这些是基础,感兴趣的可以课下去深入实践。
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
正文
今天讲的是在MNIST 数据集上训练一个多层感知器
我们在实现代码的时候需要做的工作大体为
- 准备数据
- 编写深度网络模型
- 训练网络
- 测试网络
参数管理
准备好了
准备数据
可以使用别人已经处理好的数据,也可以使用原始数据自己处理
为了方便,我在这里就直接使用pytorch已经处理好的数据,
dir_path = "./data"
if not os.path.isdir(dir_path):
os.mkdir(dir_path)
# MNIST 数据集
train_dataset = torchvision.datasets.MNIST(root=dir_path,
train= True,
transform= torchvision.transforms.ToTensor(),
download=True)
test_dataset = torchvision.datasets.MNIST(root=dir_path,
train=False,
transform=torchvision.transforms.ToTensor(),
download=True)
我们可以来看看数据的样子
def show_picture(data_numpy,label_numpy,index=0):
plt.imshow(data_numpy[index].reshape((28,28)),cmap='gray')
plt.title(label_numpy[index])
plt.show()
print(data_numpy.shape)
show_index = 7
data_numpy = train_dataset.data.numpy()
label_numpy = train_dataset.train_labels.numpy()
show_picture(data_numpy,label_numpy,show_index)
# Data Loader
train_loader = torch.utils.data.DataLoader(dataset= train_dataset,
batch_size=batch_size,
shuffle= True)
test_loader = torch.utils.data.DataLoader(dataset=test_dataset,
batch_size=args.batch_size,
shuffle=False)
创建模型类
继承 nn.Module 类
实现的init方法和 forward 方法。
class MNIST_NET_MODEL(nn.Module):
def __init__(self,input_dim,hidden_dim1,hidden_dim2,hidden_dim3,hidden_dim4,ouput_dim):
super(MNIST_NET_MODEL,self).__init__()
self.fc1 = nn.Linear(input_dim,hidden_dim1)
self.fc2 = nn.Linear(hidden_dim1,hidden_dim2)
self.fc3 = nn.Linear(hidden_dim2,hidden_dim3)
self.fc4 = nn.Linear(hidden_dim3,hidden_dim4)
self.fc5 = nn.Linear(hidden_dim4,ouput_dim)
def train(self,input):
h1 = torch.relu(self.fc1(input))
h2 = torch.relu(self.fc2(h1))
h3 = torch.relu(self.fc3(h2))
h4 = torch.relu(self.fc4(h3))
output = torch.log_softmax(h4, dim=1)
return output
def forward(self,X):
output = self.train(X)
return output
训练
这里实现了很多的常用优化方法,感兴趣的可以课下尝试不同优化方法的区别,
这里
model = MNIST_NET_MODEL(input_dim,hidden_dim1,hidden_dim2,hidden_dim3,hidden_dim4,output_dim).to(device=device)
optimizer = torch.optim.Adam(model.parameters(),lr=args.learning_rate)
for epoch in range(args.epochs):
pre_loss = 0
sum_loss = 0
for (i,(data,target)) in enumerate(train_loader):
data, target= data.to(device).view(-1,input_dim), target.to(device)
output = model(data)
loss = F.nll_loss(output,target) # 损失函数
optimizer.zero_grad() # 清空梯度
loss.backward() # 计算梯度
optimizer.step() # 更新
if (i + 1) % 10 == 0:
print("Epoch[{}/{}],Step[{}/{}],loss:{:.4f}"
.format(epoch + 1, args.epochs, i + 1, len(train_loader), loss.item()))
sum_loss += loss.item()
if epoch > args.early_stopping and sum_loss - pre_loss < args.threshold_value:
torch.save(model.state_dict(),'MNOST_MODEL_PARAME.pth')
break
pre_loss = sum_loss
sum_loss = 0
else:
torch.save(model.state_dict(), 'MNOST_MODEL_PARAME.pth')
torch.save(model,'MNIST_MODEL.pth')
测试网络
hit, total = 0, 0
for i, (data,target) in enumerate(test_loader):
with torch.no_grad():
data = data.to(device).view(data.shape[0],-1)
target = target.to(device)
output = model(data)
print(output.topk(k=1,dim=1)[1])
hit += (output.topk(k=1,dim=1)[1] == target.view(-1,1)).sum().item()
total += data.shape[0]
acc = hit / total
print('Test accuracy: %.3f\t' % (acc))