今天完成的是一个自带的MNIST数据集的分类问题,即手写数字的识别分类。
data_train = datasets.MNIST(root="./data/",
transform = transform,
train= True,
download= False)
data_test = datasets.MNIST(root="./data/",
transform = transform,
train=False)
这段代码实现的就是加载我们所需要的数据集,但是可能会遇到一个下载过慢的问题,这里我给大家提供一个链接,供下载使用(如果你不嫌慢 的话记得把download改为True)。
百度网盘
提取码:rkqo
这里的transform就是在导入数据的时候需要对数据进行的变换操作,我将在下面有所定义,一个加载训练集一个加载测试集。
上面提到的transform,这里来详细解释一下。torch.transform提供了很多类对载入的数据进行变换。首先,我们知道我们获取的是图片数据,而pytorch需要处理的数据类型是tensor,所以这是转换的原因。transform中有很多方法可以解决获取的图片大小不一致的问题,可以对图片进行缩放等操作。对数据的转换方法代码如下:
transform = transforms.Compose([transforms.ToTensor(), #类型转换变换 对载入的图片进行类型转换,将之前的PIL图片转换成Tensor数据类型变量,这样才能够进行计算
transforms.Lambda(lambda x: x.repeat(1,1,1)),# repeat()沿着指定的维度重复tensor
])#数据标准化变换 标准差变化法这里的方式
这里说明一下几个常见的transforms的方法:
(1)transforms.ToTensor:这个是用来对载入图片进行类型转换,将之前的构成PIL图片的数据转换成Tensor数据类型的变量,让Pytorch能够对其进行计算。
(2)transforms.ToPILImage:与上面一个相反,将Tensor变量的数据转换成PIL图片数据,方便图片的显示等。
(3)transforms.Resize:对载入的图片进行放大缩小操作。
数据已经全部得到了,现在该实现对数据的预览以及装载。
1.数据装载
首先解释下什么是装载,简而言之,我们之前是完成的对图片的载入操作,有了这些图片,我们就把他打包好然后直接扔到我们模型中去训练,这里的打包说的就是数据装载,数据装载的代码如下:
data_loader_train = torch.utils.data.DataLoader(dataset=data_train,#对数据进行装载 也就是打包好送去模型来进行训练立
batch_size = 64, #每个包的大小
shuffle = True) #是否在装载过程中打乱图片的顺序
data_loader_test = torch.utils.data.DataLoader(dataset=data_test,
batch_size = 64,
shuffle = True)
对数据的装载使用的是DataLoader类,详细的说明都在代码注释中,自己康。
2.数据预览
装载好了以后,我们就可以进行数据预览了,代码如下:
images, labels = next(iter(data_loader_train)) #通过next和iter获取图片以及图片的标签
img = torchvision.utils.make_grid(images) #狗造成网格模式
img = img.numpy().transpose(1,2,0)
std = [0.5,0.5,0.5]
mean = [0.5,0.5,0.5]
img = img*std + mean
print([labels[i] for i in range(64)])
plt.imshow(img)
plt.show() #没有这句图片不会显示
预览:
数据我门都处理完毕,我们可以构建模型了。
随便构造一个卷积网络,代码如下:
class Model(torch.nn.Module):
def __init__(self):
super(Model,self).__init__()
self.conv1 = torch.nn.Sequential(
torch.nn.Conv2d(1,64,kernel_size=3,stride=1,padding=1), #输入的通道数,输出通道数,卷积核大小,卷积核步长,padding纸大小
torch.nn.ReLU(),
torch.nn.Conv2d(64,128,kernel_size=3,stride=1,padding=1),
torch.nn.ReLU(),
torch.nn.MaxPool2d(stride=2,kernel_size=2))
self.dense=torch.nn.Sequential(
torch.nn.Linear(14*14*128,1024),
torch.nn.ReLU(),
torch.nn.Dropout(p=0.5), #用来防止卷积神经网络在训练中过于拟合,默认0.5
torch.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
这里就不多解释了,打印一下这个网络,确保输出正确,如下图:
最后就是参数优化和模型训练了,代码如下:
n_epochs = 5
for epoch in range(n_epochs):
running_loss = 0.0 #损失的数值
running_correct = 0 #预测的正确数目
print("Epoch {}/{}".format(epoch,n_epochs))
print("-"*10)
for data in data_loader_train:
X_train,y_train = data
X_train,y_train = Variable(X_train), Variable(y_train)
outputs = model(X_train)
_,pred = torch.max(outputs.data,1) # # 从输出结果中取出需要的预测值, axis = 1 表示去按行取最大值
optimizer.zero_grad() # 将累积的梯度置零
loss = cost(outputs,y_train) #交叉熵函数上面定义了
loss.backward() # 反向传播求导
optimizer.step() # 更新所有参数
running_loss += loss.item() #累计所有的损失值
running_correct += torch.sum(pred == y_train.data) #累计所有的正确次数
testing_correct = 0
for data in data_loader_test:
X_test, y_test = data
X_test, y_test = Variable(X_test), Variable(y_test)
outputs = model(X_test)
_, pred = torch.max(outputs.data, 1)
testing_correct += torch.sum(pred == y_test.data)
print("Loss is :{:.4f}, Train Accuracy is :{:.4f}%, Test Accuracy is :{:.4f}".format(torch.true_divide(running_loss, len(data_train)),100*torch.true_divide(running_correct,len(data_train)),
100*torch.true_divide(testing_correct,len(data_test)))
)
```完整代码如下:
```python
import torch
from torchvision import datasets, transforms
import torchvision.transforms
from torch.autograd import Variable
import numpy as np
import matplotlib.pyplot as plt
transform = transforms.Compose([transforms.ToTensor(), #类型转换变换 对载入的图片进行类型转换,将之前的PIL图片转换成Tensor数据类型变量,这样才能够进行计算
transforms.Lambda(lambda x: x.repeat(1,1,1)),# 变成三个信道 repeat()沿着指定的维度重复tensor
])#数据标准化变换 标准差变化法这里的方式
data_train = datasets.MNIST(root="./data/",
transform = transform,
train= True,
download= False)
data_test = datasets.MNIST(root="./data/",
transform = transform,
train=False)
data_loader_train = torch.utils.data.DataLoader(dataset=data_train,#对数据进行装载 也就是打包好送去模型来进行训练立
batch_size = 64, #每个包的大小
shuffle = True) #是否在装载过程中打乱图片的顺序
data_loader_test = torch.utils.data.DataLoader(dataset=data_test,
batch_size = 64,
shuffle = True)
images, labels = next(iter(data_loader_train)) #通过next和iter获取图片以及图片的标签
# img = torchvision.utils.make_grid(images) #狗造成网格模式
#
# img = img.numpy().transpose(1,2,0)
# std = [0.5,0.5,0.5]
# mean = [0.5,0.5,0.5]
# img = img*std + mean
# print([labels[i] for i in range(64)])
# plt.imshow(img)
# plt.show() #没有这句图片不会显示
#构造卷积wnag'luo'o 这是四种方法其中的一种
class Model(torch.nn.Module):
def __init__(self):
super(Model,self).__init__()
self.conv1 = torch.nn.Sequential(
torch.nn.Conv2d(1,64,kernel_size=3,stride=1,padding=1), #输入的通道数,输出通道数,卷积核大小,卷积核步长,padding纸大小
torch.nn.ReLU(),
torch.nn.Conv2d(64,128,kernel_size=3,stride=1,padding=1),
torch.nn.ReLU(),
torch.nn.MaxPool2d(stride=2,kernel_size=2))
self.dense=torch.nn.Sequential(
torch.nn.Linear(14*14*128,1024),
torch.nn.ReLU(),
torch.nn.Dropout(p=0.5), #用来防止卷积神经网络在训练中过于拟合,默认0.5
torch.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()
cost = torch.nn.CrossEntropyLoss() #用于计算交叉熵,定义时候不需要传入参数,使用的时候需要传入两个参数
optimizer = torch.optim.Adam(model.parameters()) #优化函数使用Adam自适应优化算法 默认值1e-4
print(model)
#最后进行模型训练以及参数优化
n_epochs = 5
for epoch in range(n_epochs):
running_loss = 0.0 #损失的数值
running_correct = 0 #预测的正确数目
print("Epoch {}/{}".format(epoch,n_epochs))
print("-"*10)
for data in data_loader_train:
X_train,y_train = data
X_train,y_train = Variable(X_train), Variable(y_train)
outputs = model(X_train)
_,pred = torch.max(outputs.data,1) # # 从输出结果中取出需要的预测值, axis = 1 表示去按行取最大值
optimizer.zero_grad() # 将累积的梯度置零
loss = cost(outputs,y_train) #交叉熵函数上面定义了
loss.backward() # 反向传播求导
optimizer.step() # 更新所有参数
running_loss += loss.item() #累计所有的损失值
running_correct += torch.sum(pred == y_train.data) #累计所有的正确次数
testing_correct = 0
for data in data_loader_test:
X_test, y_test = data
X_test, y_test = Variable(X_test), Variable(y_test)
outputs = model(X_test)
_, pred = torch.max(outputs.data, 1)
testing_correct += torch.sum(pred == y_test.data)
print("Loss is :{:.4f}, Train Accuracy is :{:.4f}%, Test Accuracy is :{:.4f}".format(torch.true_divide(running_loss, len(data_train)),100*torch.true_divide(running_correct,len(data_train)),
100*torch.true_divide(testing_correct,len(data_test)))
)
初学者,写的比较粗糙,难免有错误,尽情谅解。