pytorch学习第三课-全连接网络2-MNIST分类

完成了简单的全连接网络之后,我们是用pytorch进行MNIST手写数字的分类问题,这次的网络相对复杂一下,输入输出和hidden layer都更多,表达能力更强

首先是下载MINIST的数据集:

import torch
import torch.nn as nn
from torchvision import datasets, transforms
import torch.nn.functional as F
import matplotlib.pyplot as plt
import numpy as np
from torch.autograd import Variable
import os

transform=transforms.Compose([transforms.ToTensor(),
							 transforms.Normalize((0.5,),(0.5,))])


#下载训练集和验证集
training_datasets=datasets.MNIST(root='./data',train=True,download=True,transform=transform)
validation_datasets=datasets.MNIST(root='./data',train=False,download=True,transform=transform)

training_loader=datsets.MNIST(datasets=training_datasets,batch_size=100,shuffle=True)
validation_loader=datsets.MNIST(datasets=validation_datasets,batch_size=100,shuffle=False)

这里注意,一定是transforms.Normalize((0.5,),(0.5,)),不是transforms.Normalize((0.5),(0.5)),一个逗号之差,数据类型会不是 tuple,然后就会报错 “IndexError: too many indices for tensor of dimension 0”

然后我们可以看一下training_loader里面的图片都长什么样子:

def im_convert(tensor):
	image=tensor.clone().detach().numpy()
	image=image.transpose(1,2,0) # 从 N*W*H,转成W*H*N
	image=image*np.array(0.5,)+np.array(0.5) #这步是transform Normalize的反向过程
	image=image.clip(0,1)
	image=image.squeeze()
	return image

dataiter=iter(training_loader)
images,labels=dataiter.next() 
fig=plt.figure(figsize=(25,4))

# 展示20幅图
for idx in range(20):
	ax=fig.add_subplot(2,10,idx+1)
	plt.imshow(im_convert(images[idx]))
	ax.set_title(labels[idx].item())

在这里插入图片描述

然后是神经网络的结构,全连接网络,有两个隐藏层

class Classifier(nn.Module):
	def __init__(self,input_size,h1,h2,output_Size):
		super().__init__()
		self.linear1=nn.Linear(input_size,h1)
		self.linear2=nn.Linear(h1,h2)
		self.linear3=nn.Linear(h2,output_size)
	def forward(self,x):
		pred1=F.relu(self.linear1(x))
		pred2=F.relu(self.linear1(pred1))
		pred=self.linear1(pred2) 
		#最后一层这里的不用softmax的原因是,后面我们会用 CrossEntropyLoss,里面就包括了softmax log 等操作,直接return 线性层的输出就够了
		return pred


use_gpu=torch.cuda.is_avaliable() #检查gpu是否可用

model=Classifier(28*28,125,65,10)
criterion=nn.CrossEntropyLoss()
optimizer=torch.optim.Adam(model.parameters(),lr=0.01)

if use_gpu:
	#将数据放在cuda上,才能用GPU运算
    model=model.cuda()
    criterion=criterion.cuda()
 
epoch=12
losses=[]

val_losses=[]
val_acces=[]

for i in range(epoch):
	running_loss=0
	dataiter=iter(training_loader)
	for j in range(len(dataiter)):

	#for steps,(inputs,labels) in enumerate(training_loader): 也是一样的,都是从training_loader里取training data
		inputs,labels=dataiter.next()
		inputs=inputs.view(inputs.shape[0],-1)
		#将输入变成 batchsize*input_size的样子
		
		if use_gpu:
			inputs=inputs.cuda()
			labels=labels.cuda()
		y_pred=model.forward(inputs)
		
		loss=criterion(y_pred,labels)
		optimizer.zero_grad()
		loss.backward()
		optimizer.step()
		running_loss+=loss.item()
	#每一个epoch都记录一下 loss
	running_loss=running_loss/inputs.shape[0]
	losses.append(running_loss/len(dataiter))
	
	val_running_loss=0.0
	val_running_acc=0.0
	
	val_dataiter=iter(validation_loader)
	
	for j in range(len(val_dataiter)):
		inputs,labels=val_dataiter.next()
		inputs=inputs.view(inputs.shape[0],-1)
		#将输入变成 batchsize*input_size的样子
		
		if use_gpu:
			inputs=inputs.cuda()
			labels=labels.cuda()
		y_pred=model.forward(inputs)
		loss=criterion(y_pred,labels)
		#validation 不需要进行反向传播,但是可以进行准确度的计算
		_,preds=torch.max(y_pred,1)
		val_running_acc+=torch.sum(preds=labels.data)
		val_running_loss+=loss.item()
	
	val_running_acc=val_running_acc/inputs.shape[0]
	val_running_loss=val_running_loss/inputs.shape[0]
	
	val_losses.append(val_running_loss/len(val_dataiter))	
	val_acces.append(val_running_acc/len(val_dataiter))

	plt.close()
    plt.plot(losses,label='training_loss')
    plt.plot(val_losses,label='validation_loss')
    plt.legend()
	
	#保存每一个epoch 的model
	dir='./deep_nn_checkpoint'
    PATH=os.path.join(dir,'model'+str(i)+'.pth')
    torch.save(model.state_dict(), PATH)

在这里插入图片描述
分割结束后,我们可以进行测试:
首先,我们可以选择中间的训练结果,也不是最后一个,因为训练的时候,我们将每一个epoch的model都存了下来,所以可以直接加载

dir='./deep_nn_checkpoint'
PATH=os.path.join(dir,'model'+str(5)+'.pth')
model.load_state_dict(torch.load(PATH))
model.eval()

然后我们找到一张数字图像,然后进行识别:
在这里插入图片描述
一张白底黑色的图片,所以对于这个图片,需要将其转化为我们训练时的格式:

from PIL import Image
img=Image.open('deep_nn_test_image.jpg')
img=PIL.ImageOps.invert(img) #将图片反色,变成黑底白字
img=Image.Convert('1') #转成单通道图片

transform=transforms.Compose([transforms.Resize([28,28]),
							  transforms.ToTensor(),
							  transforms.Normalize((0.5,),(0.5,))])
img=transform(img)

inputs= img.view(img.shape[0],-1)

pred=model.forward(inputs)
_,preds=torch.max(pred,1)
print(preds)

输出结果为 5,识别正确

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个使用PyTorch编写的全连接神经网络MNIST识别示例: ```python import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms # 定义超参数 batch_size = 64 learning_rate = 0.01 num_epochs = 10 # 载入MNIST数据集 transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))]) train_dataset = datasets.MNIST(root='./data/', train=True, transform=transform, download=True) test_dataset = datasets.MNIST(root='./data/', train=False, transform=transform, download=True) 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=batch_size, shuffle=False) # 定义全连接神经网络模型 class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.fc1 = nn.Linear(28*28, 512) self.fc2 = nn.Linear(512, 256) self.fc3 = nn.Linear(256, 10) self.relu = nn.ReLU() self.dropout = nn.Dropout(p=0.5) def forward(self, x): x = x.view(-1, 28*28) x = self.relu(self.fc1(x)) x = self.dropout(x) x = self.relu(self.fc2(x)) x = self.dropout(x) x = self.fc3(x) return x model = Net() # 定义优化器和损失函数 criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(model.parameters(), lr=learning_rate) # 训练模型 for epoch in range(num_epochs): for i, (images, labels) in enumerate(train_loader): # 前向传播、计算损失、反向传播、更新权重 outputs = model(images) loss = criterion(outputs, labels) optimizer.zero_grad() loss.backward() optimizer.step() # 打印训练日志 if (i+1) % 100 == 0: print("Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}".format(epoch+1, num_epochs, i+1, len(train_loader), loss.item())) # 测试模型 model.eval() with torch.no_grad(): correct = 0 total = 0 for images, labels in test_loader: outputs = model(images) _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() print('Test Accuracy of the model on the 10000 test images: {} %'.format(100 * correct / total)) ``` 该模型定义了一个具有3个全连接的神经网络模型,其中第一具有512个神经元,第二具有256个神经元,第三输出10个类别的概率分布。模型使用ReLU激活函数和Dropout正则化。在训练过程中,使用了交叉熵损失函数和随机梯度下降优化器。最终,在测试集上计算了模型的准确度。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值