Bootstrap

pytorch的学习与总结(第二次组会)

一、pytorch的基础学习

1.1 dataset与dataloader

在这里插入图片描述

1.2 可视化工具(tensorboard)、数据转换工具(transforms)

在这里插入图片描述

1.3 卷积、池化、线性层、激活函数

在这里插入图片描述

1.4 损失函数、反向传播、优化器

在这里插入图片描述

1.5 模型的保存、加载、修改

在这里插入图片描述

二、 pytorch分类项目实现

2.1 网络模型

在这里插入图片描述

2.2 具体代码

  1. model与train
# Seven
import torch
import torchvision         # 导入数据集
from torch.utils.tensorboard import SummaryWriter    # 用于日志



# 准备数据集
from torch import nn
from torch.utils.data import DataLoader

# 通过GPU训练还是通过CPU训练
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# 导入训练数据集合
train_data = torchvision.datasets.CIFAR10(root="../data", train=True, transform=torchvision.transforms.ToTensor(), download=True)
# 导入测试数据集
test_data = torchvision.datasets.CIFAR10(root="../data", train=False, transform=torchvision.transforms.ToTensor(), download=True)


# 查看训练集合和测试集合长度
train_data_size = len(train_data)
test_data_size = len(test_data)
# 输出查看
print("训练数据集合的长度为:{}".format(train_data_size))
print("测试数据集合的长度为:{}".format(test_data_size))


# 利用DataLoader 来加载数据集
train_dataloader = DataLoader(dataset=train_data, batch_size=64)
test_dataloader = DataLoader(dataset=test_data, batch_size=64)

# 创建网络模型
class Seven(nn.Module):
    def __init__(self):
        # 初始化
        super(Seven, self).__init__()

        # 设置网络模型
        self.model = nn.Sequential(
            nn.Conv2d(3,32,5,1,2), # 卷积层
            nn.MaxPool2d(2),       # 池化层
            nn.Conv2d(32,32,5,1,2),  # 卷积层
            nn.MaxPool2d(2),       # 池化层
            nn.Conv2d(32,64,5,1,2),  # 卷积层
            nn.MaxPool2d(2),        # 池化层
            nn.Flatten(),    # 展开
            nn.Linear(64*4*4, 64),  # 线性层
            nn.Linear(64, 10)   # 线性层输出
        )


    def forward(self, x):
        x = self.model(x)
        return x

seven = Seven()

#gpu
seven.to(device)

# 损失函数(交叉熵损失)
loss_fn = nn.CrossEntropyLoss()

# 如果是在gpu上跑
loss_fn.to(device)

# 优化器,设置学习率
learning_rate = 1e-2
optimizer = torch.optim.SGD(seven.parameters(), lr=learning_rate)

# 设置网络模型中的一些参数
total_train_step = 0   # 记录训练的次数
total_test_step = 0    # 记录测试的次数
epochs = 10   # 数据扫描次数

# 添加tensorboard  (用于记录log)
writer = SummaryWriter("./logs_train")

for epoch in range(epochs):
    print("第{}轮测试开始".format(epoch+1))

    # 训练步骤开始
    seven.train()   # 标注模型为训练状态,网络模型中例如dropout类似的层会生效
    for data in train_dataloader:
        # 因为我们封装为dataloader,会设置一个批次
        # 这里就会迭代的时候以一个批次大小,将图片与标签返回
        imgs, targets = data

        # gpu
        imgs = imgs.to(device)
        targets = targets.to(device)

        # 把数据丢进模型
        outputs = seven(imgs)

        # 调用损失函数, 看预测值与目标值之间的差距
        loss = loss_fn(outputs, targets)

        # 优化器梯度清零,因为pytorch不会主动给梯度清零
        optimizer.zero_grad()
        # 调用反向传播(其实就是对损失函数求导)
        loss.backward()
        # 进行参数更新
        optimizer.step()

        # 训练个数+1
        total_train_step += 1
        if total_train_step % 100 == 0:
            # loss.item(): 拿到具体的损失值
            print("训练次数:{},loss:{}".format(total_train_step, loss.item()))
            # 每100次记录一次损失
            writer.add_scalar("train_loss", loss.item(), total_train_step)

    # 测试步骤开始
    seven.eval()  # 模型开始测试模式,网络模型中的dropout类似在寻楼层有效的层失效
    total_test_loss = 0  # 记录测试的损失值
    total_accuracy = 0   # 记录预测正确的次数
    with torch.no_grad(): # 下面的内容不进行求梯度与反向传播,
        for data in test_dataloader:
            imgs, targets = data
            # gpu
            imgs = imgs.to(device)
            targets = targets.to(device)


            outputs = seven(imgs)
            loss = loss_fn(outputs, targets)
            # 记录损失值
            total_test_loss = total_test_loss + loss.item()
            # argmax(1) 横向取出预测最大值的下标,因为是分类预测,所以预测的最大概率,就是预测的标签
            # 这里会出现[False,True]这类类型,通过sum()记录这一批量预测值与标签相等的总数
            accuracy = (outputs.argmax(1) == targets).sum()
            # 记录预测成功的总数
            total_accuracy = total_accuracy + accuracy

    print("整体数据集的Loss:{}".format(total_test_loss))
    print("整体测试集上的正确率:{}".format(total_accuracy/test_data_size))
    # 记录一次扫描的损失
    writer.add_scalar("test_loss", total_test_loss, total_test_step)
    # 记录一次扫描的准确率
    writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step)

    total_test_step +=1


    # 每次都保存一次模型
    torch.save(seven, "seven_{}.pth".format(epoch))
    print("第{}次模型保存".format(epoch))


writer.close()
  1. test
import torch
import torchvision
from PIL import Image
from torch import nn

# 设置要预测图片的路径
image_path = "./imgs/feiji.jpg"
# 打开图片
image = Image.open(image_path)
print(image)

# 换大小并转换格式为tensor类型
transform = torchvision.transforms.Compose([torchvision.transforms.Resize((32,32)),
                                            torchvision.transforms.ToTensor()])

image = transform(image)
print(image.shape)


# 搭建神经网络
class Seven(nn.Module):
    def __init__(self):
        # 初始化
        super(Seven, self).__init__()

        # 设置网络模型
        self.model = nn.Sequential(
            nn.Conv2d(3,32,5,1,2), # 卷积层
            nn.MaxPool2d(2),       # 池化层
            nn.Conv2d(32,32,5,1,2),  # 卷积层
            nn.MaxPool2d(2),       # 池化层
            nn.Conv2d(32,64,5,1,2),  # 卷积层
            nn.MaxPool2d(2),        # 池化层
            nn.Flatten(),    # 展开
            nn.Linear(64*4*4, 64),  # 线性层
            nn.Linear(64, 10)   # 线性层输出
        )


    def forward(self, x):
        x = self.model(x)
        return x


# 读取训练的模型
# 当训练时以gpu训练时,但是测试用cpu时需要声明一下读取的模型
model = torch.load("seven_9.pth", map_location=torch.device('cpu'))

print(model)
image = torch.reshape(image, (1,3,32,32))

# 测试模型
model.eval()
with torch.no_grad(): # 声明不计算梯度
    output = model(image)

print(output)
# 选择横向最大的概率的下标
print(output.argmax(1))

;