赞
踩
通过设计一个卷积神经网络模型,实现对MNIST数据集中的手写数字图片进行识别。
- #1 导入必要的模块
- import numpy as np
- import matplotlib.pyplot as plt
- import torch
- from torchvision import transforms,datasets
- from torch.utils.data import DataLoader
- import torchvision
对数据进行预处理操作,即通过Compose方法把多种预处理操作组合在一起
- #2 定义数据预处理操作【通过Compose方法把多种预处理操作组合在一起】
- pipline=transforms.Compose([transforms.ToTensor(),transforms.Normalize([0.5],[0.5])])
torchvision是pytorch的一个图形库,它是服务于PyTorch深度学习框架的,主要用来构建计算机视觉模型。torchvision.transforms主要是用于常见的一些图形变换。其中的torchvision.transforms.Compose()类主要作用是串联多个图片变换的操作。这个类的构造如下:
- class torchvision.transforms.Compose(transforms):
- # Composes several transforms together.
- # Parameters: transforms (list of Transform objects) – list of transforms to compose.
可以看出Compose里面的参数实际上就是个列表,而这个列表里面的元素就是你想要执行的transform操作。
下载MNIST数据集
- #3 下载数据集
- train_dataset=datasets.MNIST('./data',train=True,transform=pipline,download=True)
- test_dataset=datasets.MNIST('./data',train=False,transform=pipline,download=True)
分批加载数据集
- #分批加载数据集
- train_loader=DataLoader(train_dataset,batch_size=16,shuffle=True)
- test_loader=DataLoader(test_dataset,batch_size=16,shuffle=False)
shuffle=True用于打乱数据集,每次都会以不同的顺序返回。
shuffle的实际效果为,假设有数据a,b,c,d,batch_size=2后打乱,具体是下面的第二种情况:
1.先按顺序取batch,对batch内打乱,即先取a,b,a,b进行打乱;
2.先打乱,再取batch。
部分数据可视化
第一种数据可视化方法
- examples=enumerate(train_loader) #enumerate迭代器
- _,(example_data,example_target)=next(examples)
- #利用enumerate()中的next()属性取值,用不到索引值,用_接一下值
- for i in range(9):
- plt.subplot(3,3,i+1)
- plt.axis('off')
- plt.imshow(torch.squeeze(example_data[i]),cmap='gray')
- plt.title(example_target[i].numpy())
enumerate()是python中的内置函数之一,属于迭代器函数。用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。
例如:
- >>> seasons = ['Spring', 'Summer', 'Fall', 'Winter']
- >>> list(enumerate(seasons))
- [(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
next()函数用于取出可迭代对象的元素,一般与iter()函数联合使用。next函数可以调用生成器的对象以参数形式传入到next(params),返回迭代器到下一个项目。用法:next(iterobject, defalt)
1.iterobject:可迭代的对象
2.default:可选
当第二个参数不写入的时候,如果可迭代的元素全部取出来后,会返回Stoplteration的异常;当第二个参数写入的时候,可迭代对象完之后,会一直返回第二个参数写的数值。
第2种数据可视化方法
- def imshow(img):
- img=img/2+0.5 #反归一化
- np_img=img.numpy()
- plt.axis('off')
- plt.imshow(np.transpose(np_img,(1,2,0)))
- plt.show()
-
- dataiter=iter(train_loader)
- images,labels=next(dataiter)
- imshow(torchvision.utils.make_grid(images))
归一话的时候是先减去平均值0.5 ,然后再除以标准偏差0.5;那么反归一化就是先乘以0.5,再加0.5。
构建网络模型
- import torch.nn as nn
- class CNN(nn.Module):
- def __init__(self):
- super(CNN,self).__init__()
- self.layer01=nn.Sequential( #模块化
- nn.Conv2d(in_channels=1,out_channels=6,kernel_size=(3,3),padding=1), #卷积层
- nn.BatchNorm2d(6), #批正则化
- nn.ReLU(),
- nn.MaxPool2d(kernel_size=2,stride=2) #最大池化
-
- ) #16*14*14
-
- self.layer02=nn.Sequential(
- nn.Conv2d(6,16,3), #32*12*12
- nn.BatchNorm2d(16),
- nn.ReLU(),
- nn.MaxPool2d(2,2) #32*6*6
- )
- self.fc=nn.Sequential(
- nn.Linear(16*6*6,10),
-
- )
- def forward(self,x): #前向传播
- x=self.layer01(x)
- x=self.layer02(x)
- x=x.view(x.size(0),-1) ##四维(b,c,h,w)->二维
- x=self.fc(x)
- return x
实例化操作
- net=CNN()
- net
- for m in net.modules():
- if isinstance(m,nn.Conv2d):
- nn.init.normal_(m.weight)
- nn.init.xavier_normal_(m.weight)
- nn.init.constant_(m.bias,0)
- elif isinstance(m,nn.Linear):
- nn.init.normal_(m.weight)
定义损失函数和优化器
- loss_fun=nn.CrossEntropyLoss() #交叉熵损失
- optimizer=torch.optim.Adam(net.parameters(),lr=0.01) #优化器
-
- tot_loss=0.0
- tot_all=0.0
- tot_correct=0.0
- loss_per_epoch=[]
- avg_acc_per_epoch=[]
通过上述代码初始化了一个优化器,该优化器使用的是Adam优化算法,optim包里面还包含了其他优化算法。初始化时我们将我们定义的神经网络中的参数传入优化器中,并传入我们定义的学习率。
打印每轮后的损失和时间
- import time
- start=time.time()
- for epoch in range(10):
- for iteration,(X_bat,y_bat) in enumerate(train_loader): #枚举器,索引值也可取出
- y_pred=net(X_bat) #得到预测标签
- loss=loss_fun(y_pred,y_bat) #计算损失
- optimizer.zero_grad() #梯度清零
- loss.backward() #反向传播
- optimizer.step() #梯度更新
- #argmax()取最大值对应的索引,利用data属性取出数值,再转化为numpy类型
- predict_y = torch.argmax(y_pred, 1).data.numpy()
- tot_correct += sum(predict_y == y_bat.data.numpy())
- tot_all += len(predict_y)
- tot_loss += loss.item() * len(predict_y)
- # 打印一轮中的平均精度和损失函数值
- avg_acc = tot_correct / tot_all * 100.0
- loss_epoch = tot_loss / tot_all
- print('[Epoch %d] avg_loss: %.4f, avg_acc: %.4f %%' % \
- (epoch+1, loss_epoch , avg_acc))
- loss_per_epoch.append(loss_epoch)
- avg_acc_per_epoch.append(avg_acc)
-
- tot_loss=0.0
- tot_correct=0.0
- tot_all=0.0
-
- end=time.time()
- print('traning time:',end-start)
损失和训练精度可视化
- tot_test=0.0
- tot_test_correct=0.0
- pred_test_list=[]
- true_test_list=[]
- for image,target in test_loader:
- y_out_test=net(image)
- y_pred_test=torch.argmax(y_out_test,1).data.numpy()
- tot_test+=len(y_pred_test)
- tot_test_correct+=sum(y_pred_test==target.data.numpy())
- pred_test_list+=list(y_pred_test)
- true_test_list+=list(target.data.numpy())
- test_acc=tot_test_correct/tot_test*100.0
- print('TestAccuracy:%4f%%'%(test_acc))
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。