手写数字识别
torchvision包功能是实现数据的处理、导入和预览等,通过包来获取手写数字的训练集和测试集。
import torch from torchvision import datasets,transforms from torch.autograd import Variable from torchvision.datasets import MNIST data_train=datasets.MNIST(root='./data/',transform=transforms,train=True,download=True) data_test=datasets.MNIST(root='./data/',transform=transform,train=False)
root存放指定数据集下载之后的存放路径,transform是对数据进行转换操作,train用于指定数据集下载完成后需要载入哪部分数据,如果设置为True,则为该数据集的训练集部分,为False则为测试集部分。
当获取到的图像和我们预期的不一致时,我们可以使用transfrom进行归一化和大小缩放等操作。transform很大一部分可以用于实现数据增强(Data Argumentation)。若我们的数据集有限,可以同宫对有限的图片数据集进行各种变换,生成新的训练集,可以做的是水平或垂直翻转和缩小或放大数据。
transform=transforms.Compose([ transforms.ToTensor(), transforms.Normalize(mean=[0.5,0.5,0.5],std=[0.5,0.5,0.5]) #将数据进行标准化转换 ])
其中标准化变换计算公式:
t图片下载完成后,将数据打包载入,通过Batchsize值来确定每个包的大小,shuffle为是否打乱数据
train_loader=DataLoader(dataset=data_train,batch_size=64,shuffle=True) test_loader=DataLoader(dataset=data_test,batch_size=64,shuffle=True)
使用iter和next获取一个批次的图片数据和相对应的标签
torchvision.utils.make_grid功能:
将该批次的图片构成网格模式
每个批次的装载数据都是4维的,维度的构成 从前往后分别为batch_size、channel、height和weight,分别对应一个批 次中的数据个数、每张图片的色彩通道数、
每张图片的高度和宽度。在 通过torchvision.utils.make_grid之后,图片的维度变成了 (channel,height,weight),这个批次的图片全部被整合到了一起
所以 在这个维度中对应的值也和之前不一样了,但是色彩通道数保持不变。
images,labels=next(iter(train_loader)) img=torchvision.utils.make_grid(images) img=img.numpy().transpose(1,2,0) mean=[0.5,0.5,0.5] std=[0.5,0.5,0.5] img=img*std+mean print([labels[i] for i in range(64)]) plt.imshow(img)
将图片进行numpy和transpose转换,从而用matplotlib绘制出图像
接下来搭建简单的卷积神经网络
class Model(nn.Module): def __init__(self): super(Model, self).__init__() self.conv1=nn.Sequential( nn.Conv2d(1,64,kernel_size=3,stride=1,padding=1), nn.ReLU(), nn.Conv2d(64,128,kernel_size=3,stride=1,padding=1), nn.ReLU(), nn.MaxPool2d(stride=2,kernel_size=2) ) self.dense=nn.Sequential( nn.Linear(14*14*128,1024), nn.ReLU(), nn.Dropout(p=0.5), nn.Linear(1024,10) ) def forward(self,x): x=self.conv1(x) x=x.view(-1,14*14*128) x=self.dense(x) return x
开始对模型进行训练和参数优化
model=Model().to(device) cost=nn.CrossEntropyLoss() optimizer=optim.Adam(model.parameters()) n_epochs=5 for epoch in range(n_epochs): running_loss=0 running_correct=0 print("Epoch{}/{}".format(epoch,n_epochs)) print("*"*10) for data in train_loader: images,labels=data images,labels=Variable(images),Variable(labels) images, labels =images.to(device),labels.to(device) y_pred=model(images) _,pred=torch.max(y_pred.data,1) optimizer.zero_grad() loss=cost(y_pred,labels) loss.backward() optimizer.step() running_loss+=loss.item() running_correct+=torch.sum(pred==labels.data) testing_correct=0 for data in test_loader: images,labels=data images, labels = Variable(images), Variable(labels) images, labels = images.to(device), labels.to(device) y_pred=model(images) _, pred = torch.max(y_pred.data, 1) testing_correct+=torch.sum(pred==labels.data) print("Train Loss:{:4f},Train Accuracy:{:.4f}%,Test Accuracy:{:.4f}".format(running_loss/len(data_train),100*running_correct/len(data_train),100*testing_correct/len(data_test)))
运行结果:
可以看到结果表现很不错,训练集和测试集最高都达到了99%的准确率,如果使用更加强大的卷积神经网络,会取得比这更好的结果。