python(5) softmax回归实例

ToTensor作用
  • 将输入转化为Tensor
  • 将图片的变量顺序变为(channal,height,width),规范图片格式
  • 将像素取值范围规范到(0,1),归一化

DataLoader作用

  1. 乱序 shuffle
  2. 将数据采样为小批次 batch_size
  3. num_workers 实现多图片同时读取
  4. 设置批次处理函数 collate_fn

加载数据集并显示图片

import torch
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

#torchvison加载内置数据集
import torchvision
from torchvision.transforms import ToTensor #transforms里是一些处理图片的方法

#数据集都在torchvision的datasets里
#设定缓存地址和下载的是train还是test数据,不填就全下载
#download=True时代码会自动检测相应目录下是否有文件
train_dataset = torchvision.datasets.MNIST('data',train=True,download=True,transform=ToTensor())
test_dataset  = torchvision.datasets.MNIST('data',train =False,download=True,transform=ToTensor())

#DataLoader类来进行对dataset封装:
#1.乱序 shuffle
#2.将数据采样为小批次 batch_size
#3.num_workers 实现多图片同时读取
#4.设置批次处理函数 collate_fn
train_dataloader = torch.utils.data.DataLoader(train_dataset,batch_size = 64,shuffle = True)
test_dataloader  = torch.utils.data.DataLoader(test_dataset,batch_size = 64)

#查看数据,iter是生成器,next返回一个批次的数据,包括image和labels
imgs,labels = next(iter(train_dataloader))
#64是批次有多少图片,1是通道,黑白,然后是高宽
print(imgs.shape)
#figsize,规定图片规格,这里是10张横的图片
plt.figure(figsize=(10,1))
#切片前十张
#for表示i<10,取前十张,img表示取的是imgs里的图片
for i,img in enumerate(imgs[:10]):
        npimg = img.numpy()#imgshitensor,要转换为numpy
        npimg = np.squeeze(npimg) #因为绘图时不能有1维,所以去掉
        plt.subplot(1,10,i+1)
        plt.imshow(npimg)
        plt.axis('off')
plt.show()
print(labels[:10]) #显示图片与编号一致

MNIST多分类模型创建

神经网络学习笔记(一):全连接层的作用是什么?_Dr Xplorer的博客-CSDN博客_神经网络全连接层作用

nn.Linear层是全连接层

NumPy学习笔记(四)—— argmax()函数_ac不知深的博客-CSDN博客_argmax

import torch
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from torch import nn

#torchvison加载内置数据集
import torchvision
from torchvision.transforms import ToTensor #transforms里是一些处理图片的方法

#数据集都在torchvision的datasets里
#设定缓存地址和下载的是train还是test数据,不填就全下载
#download=True时代码会自动检测相应目录下是否有文件
train_dataset = torchvision.datasets.MNIST('data',train=True,download=True,transform=ToTensor())
test_dataset  = torchvision.datasets.MNIST('data',train =False,download=True,transform=ToTensor())

#DataLoader类来进行对dataset封装:
#1.乱序 shuffle
#2.将数据采样为小批次 batch_size
#3.num_workers 实现多图片同时读取
#4.设置批次处理函数 collate_fn
train_dataloader = torch.utils.data.DataLoader(train_dataset,batch_size = 64,shuffle = True)
test_dataloader  = torch.utils.data.DataLoader(test_dataset,batch_size = 64)

#查看数据,iter是生成器,next返回一个批次的数据,包括image和labels
imgs,labels = next(iter(train_dataloader))
#64是批次有多少图片,1是通道,黑白,然后是高宽。(1,28,28)
print(imgs.shape)
#figsize,规定图片规格,这里是10张横的图片
# plt.figure(figsize=(10,1))
# #切片前十张
# #for表示i<10,取前十张,img表示取的是imgs里的图片
# for i,img in enumerate(imgs[:10]):
#         npimg = img.numpy()#imgshitensor,要转换为numpy
#         npimg = np.squeeze(npimg) #因为绘图时不能有1维,所以去掉
#         plt.subplot(1,10,i+1)
#         plt.imshow(npimg)
#         plt.axis('off')
#plt.show()
#print(labels[:10]) #显示图片与编号一致

#创建多层感知器模型
# 全连接层,对全部输入加权求和,要求输入数据为一维
#nn.Linear() #输入都是(batch,features),features必须是一维

class model(nn.Module):
        def __init__(self):
                super(model, self).__init__()
                self.linear_1 = nn.Linear(28*28,120) #linear输入为一维,所以将所有像素展开为一维,即通道*高*宽,1*28*28
                self.linear_2 = nn.Linear(120, 84)
                self.linear_3 = nn.Linear(84, 10) #因为要输出十个,从0到9
        def forward(self,input):
#因为输入的是图片,有通道,高宽,所以先对输入进行展平
                x = input.view(-1,1*28*28) #-1是batch维,随batch变化,后面则是后三维相乘
#此时x已展开,可以连接linear层了
                x = torch.relu(self.linear_1(x))
                x = torch.relu(self.linear_2(x))
                logits = self.linear_3(x) #softmax分类在损失函数中计算,所以不用激活
                return logits #logits一般被称为未激活的输出。因为分类问题的损失函数需要的输入是未激活的

#初始化模型,使模型在当前可用设备上使用.标准写法
device = 'cuda' if torch.cuda.is_available() else 'cpu'
model = model().to(device)
#损失函数
loss_fn = torch.nn.CrossEntropyLoss()
#优化
opt = torch.optim.SGD(model.parameters(),lr=0.001)

#编写通用训练函数代码
def train(dataloader,model,loss_fn,optimizer):
        size = len(dataloader.dataset)    #获得当前数据的总样本数
        num_batches = len(dataloader)    #批次数:如全部数据为100,batch=16,则7次可全部训练一遍,7就是批次数

        train_loss,correct = 0,0  #train_loss所有批次的损失和,correct为累加的预测正确的样本数

        for x,y in dataloader: #注意:x,y都是一个批次的值
                x,y = x.to(device),y.to(device)
                pred = model(x)
                loss = loss_fn(pred,y)
                optimizer.zero_grad()
                loss.backward()
                optimizer.step()
                with torch.no_grad():#argmax(axis),这里axis=1,即按行看,返回最大元素的位置
                        correct += (pred.argmax(1) == y).type(torch.float).sum().item()#计算预测对了多少个样本。地0维是batch,所以用1
                        train_loss += loss.item()

        #计算正确率和每个样本的平均损失值
        correct /=size
        train_loss /=num_batches
        return correct,train_loss

#编写通用测试函数代码
def ttest(test_dataloader,model,loss_fn): #注意名字不要取成test,不然会自动运行pytest
        size = len(test_dataloader.dataset)    #获得当前数据的总样本数
        num_batches = len(test_dataloader)   #批次数

        test_loss,correct = 0,0  #train_loss所有批次的损失和,correct为累加的预测正确的样本数
        with torch.no_grad(): #测试流程不需要跟踪梯度
                for x,y in test_dataloader: #注意:x,y都是一个批次的值
                        x,y = x.to(device),y.to(device)
                        pred = model(x)
                        loss = loss_fn(pred,y)
                        correct += (pred.argmax(1) == y).type(torch.float).sum().item()
                        test_loss += loss.item()
                correct /=size
                test_loss /=num_batches
                return correct,test_loss

# #每一个epoch代表将全部数据集训练一遍
# epoches = 50
# #创建4个空列表,记录每个epoch的平均损失和正确率
# train_loss = []
# train_correct = []
# test_loss = []
# test_correct = []
#
# for epoch in range(epoches):
#         epoch_correct,epoch_loss = train(train_dataloader,model,loss_fn,opt)
#         epoch_test_correct,epoch_test_loss = ttest(test_dataloader, model, loss_fn)
#         #记录训练情况
#         test_loss.append(epoch_test_loss)
#         train_loss.append(epoch_loss)
#         test_correct.append(epoch_test_correct)
#         train_correct.append(epoch_correct)
#
#         #打印模板,用的字符串格式化.注意双引号是中文双引号
#         template = ("epoch:{:2d},train_loss:{:.5f},train_correct:{:.1f},test_loss:{:.5f},test_correct:{:.1f}")
#         #注意这里输出的是当前循环的loss和correct,不是存入列表的train_loss
#         print(template.format(epoch,epoch_loss,epoch_correct*100,epoch_test_loss,epoch_test_correct*100))
# print('Done')


#可创建一个通用的fit训练函数

def fit(epoches,train_dataloader,test_dataloader,model,loss_fn,opt):
        train_loss = []
        train_correct = []
        test_loss = []
        test_correct = []

        for epoch in range(epoches):
                epoch_correct, epoch_loss = train(train_dataloader, model, loss_fn, opt)
                epoch_test_correct, epoch_test_loss = ttest(test_dataloader, model, loss_fn)
                # 记录训练情况
                test_loss.append(epoch_test_loss)
                train_loss.append(epoch_loss)
                test_correct.append(epoch_test_correct)
                train_correct.append(epoch_correct)

                # 打印模板,用的字符串格式化.注意双引号是中文双引号
                template = ("epoch:{:2d},train_loss:{:.5f},train_correct:{:.1f},test_loss:{:.5f},test_correct:{:.1f}")
                # 注意这里输出的是当前循环的loss和correct,不是存入列表的train_loss
                print(template.format(epoch, epoch_loss, epoch_correct * 100, epoch_test_loss,
                                      epoch_test_correct * 100))
        print('Done')
        return train_loss,train_correct,test_loss,test_correct

#直接调用fit函数
train_loss,train_correct,test_loss,test_correct = fit(100,train_dataloader,test_dataloader,model,loss_fn,opt)

#也可绘图
plt.plot(range(100),train_loss,label='train_loss')
plt.plot(range(100),test_loss,label='test_loss')
plt.legend()
plt.show()

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值