学习pytorch-计算机视觉-02

今天完成的是一个自带的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)))
            )

初学者,写的比较粗糙,难免有错误,尽情谅解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值