PyTorch基础2——快速开始

快速开始

接下来会用三个例子,展示用PyTorch训练一个网络的基本代码

训练的基本步骤

  1. 加载数据
  2. 定义网络结构
  3. 定义损失函数,梯度下降算法,让参数可训练
  4. 进行前向传播,获取预测值
  5. 计算损失函数,反向传播,进行梯度下降,将之前的梯度清空
  6. 验证结果的准确率
  7. 保存模型权重
  8. 重复步骤4-7多次,得到满意的结果

1、第一段代码

import torch
from torch import nn
import random

# step1:加载数据
# 随机生成100张图片和标签
# 每张图片是32*32的,并且有三个通道
# 随机生成5个标签(类别)
img_list = []
label_list = []
for i in range(100):
    img = torch.rand(3,32,32)

    label = random.randint(0,4) # 随机生成[0,4]的数,总共有5个
    label_tensor = torch.tensor(label,dtype=torch.int64)

    img_list.append(img)
    label_list.append(label_tensor)

data = torch.stack(img_list,axis=0) # 将一百张照片放在一起,组成一个数据集
labels = torch.stack(label_list,axis=0)

# print(labels.size())
# print(labels[:10].size())
# print(data[10:20].size())

# step2: 定义一个网络
# 定义一个网络
class Model(nn.Module):
    def __init__(self,class_num):
        super(Model, self).__init__()
        self.conv1 = nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3) #卷积
        self.pool = nn.MaxPool2d(kernel_size=2, stride=2) # 池化
        self.conv2 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5) #卷积
        self.dropout = nn.Dropout2d(p=0.1) # dropout
        self.adaptive_pool = nn.AdaptiveMaxPool2d((1, 1)) #全局池化
        self.flatten = nn.Flatten()
        self.linear1 = nn.Linear(64, 32) #线性层
        self.relu = nn.ReLU()
        self.linear2 = nn.Linear(32, class_num) #最终分了多少个类
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        x = self.conv1(x)
        x = self.pool(x)
        x = self.conv2(x)
        x = self.pool(x)
        x = self.dropout(x)
        x = self.adaptive_pool(x)
        x = self.flatten(x)
        x = self.linear1(x)
        x = self.relu(x)
        x = self.linear2(x)
        y = self.sigmoid(x)
        return y

net = Model(class_num=5)
# print(net)

# 3.定义损失函数,梯度下降算法
# 定义损失函数
loss_func = nn.CrossEntropyLoss()
# 定义梯度下降的优化器Adam
optimizer = torch.optim.Adam(params=net.parameters(),lr = 0.01)

# 让参数变成可训练的
for params in net.parameters():
    params.requires_grad = True

# 训练100个epoch
for epoch_num in range(100):

    i = 0
    batch_size = 20

    # 训练数据只有100个
    while i < 100:



        each_data = data[i:i+batch_size] # 获取数据
        each_label = labels[i:i+batch_size] # 获取标签

        # step4: 进行前向传播,获取预测值
        pred = net(each_data) # 预测的结果

        # step5.计算损失函数,反向传播,进行梯度下降,将之前的梯度清空
        loss = loss_func(pred,each_label) # 计算损失值
        print(f"Epoch:{epoch_num} {i}/100, loss:{loss.item()}")

        loss.backward() # 反向传播,求梯度
        optimizer.step() # 进行梯度下降
        # 梯度清零,这一步必须要操作,因为不操作则会保留上一次训练的信息
        optimizer.zero_grad()

        i = i+batch_size

2、第二段代码

加载了MNist数据集,这是一个手写识别的数据集
将训练的权重进行保存

import torch
from torch import nn
from torchvision import datasets, transforms #导入Mnist数据集

BATCH_SIZE = 10


# step1.加载数据
# 预先定义对每张图片进行变换规则
transforms = transforms.Compose([
                  transforms.ToTensor(), #转换为张量结构
                  transforms.Normalize((0.1037,), (0.3081,)) #对数据进行标准化
              ])
# 获取数据集
train_dataset = datasets.MNIST('data', train = True, download = True,transform = transforms )
# 将数据导入迭代器DataLoader之中, shuffle表示是否要将数据打乱
train_loader = torch.utils.data.DataLoader(train_dataset,batch_size = BATCH_SIZE, shuffle = True)



# step2.定义网络结构
# 定义一个网络
class Model(nn.Module):
    def __init__(self,class_num,input_channel=3):
        super(Model, self).__init__()
        self.conv1 = nn.Conv2d(in_channels=input_channel, out_channels=32, kernel_size=3) #卷积
        self.pool = nn.MaxPool2d(kernel_size=2, stride=2) # 池化
        self.conv2 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5) #卷积
        self.dropout = nn.Dropout2d(p=0.1) # dropout
        self.adaptive_pool = nn.AdaptiveMaxPool2d((1, 1)) #全局池化
        self.flatten = nn.Flatten()
        self.linear1 = nn.Linear(64, 32) #线性层
        self.relu = nn.ReLU()
        self.linear2 = nn.Linear(32, class_num) #最终分了多少个类
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        x = self.conv1(x)
        x = self.pool(x)
        x = self.conv2(x)
        x = self.pool(x)
        x = self.dropout(x)
        x = self.adaptive_pool(x)
        x = self.flatten(x)
        x = self.linear1(x)
        x = self.relu(x)
        x = self.linear2(x)
        y = self.sigmoid(x)
        return y
# 只识别10个,且输入通道为1
net = Model(class_num=10,input_channel=1)
# print(net)

# step3.定义损失函数,梯度下降算法
# 定义损失函数
loss_func = nn.CrossEntropyLoss()
# 定义梯度下降的优化器Adam
optimizer = torch.optim.Adam(params=net.parameters(),lr = 0.01)


# 让参数变成可训练的
for params in net.parameters():
    params.requires_grad = True

# 训练100个epoch
for epoch_num in range(100):

    for i,(each_data,each_label) in enumerate(train_loader):

        # 梯度清零,这一步必须要操作,因为不操作则会保留上一次训练的信息
        optimizer.zero_grad()

        # each_data # 获取数据
        # each_label # 获取标签

        # step4.进行前向传播,获取预测值
        pred = net(each_data) # 预测的结果

        # step5.计算损失函数,反向传播,进行梯度下降,将之前的梯度清空
        loss = loss_func(pred,each_label) # 计算损失值
        loss.backward() # 反向传播,求梯度
        optimizer.step() # 进行梯度下降

        if i%20 ==0:
            print(f"Epoch:{epoch_num} {i} , loss:{loss.item()}")

    # step6.验证结果的准确率
    # 训练完成之后进行验证。
    # ....


    # step7.保存模型权重
    # 保存权重,权重文件是一个字典
    params_dict = net.state_dict()
    torch.save(params_dict,"net.pth")

3、第三段代码

添加了验证的代码

# 对mnist数据集进行识别

# 训练模型的基本步骤
# 1.加载数据
# 2.定义网络结构
# 3.定义损失函数,梯度下降算法,让参数可训练
# 4.进行前向传播,获取预测值
# 5.计算损失函数,反向传播,进行梯度下降,将之前的梯度清空
# 6.验证结果的准确率
# 7.保存模型权重
# 8.重复步骤4-7多次,得到满意的结果


import torch
from torch import nn
from torchvision import datasets, transforms  # 导入Mnist数据集

BATCH_SIZE = 20

# step1.加载数据
# 预先定义对每张图片进行变换规则
transforms = transforms.Compose([
    transforms.ToTensor(),  # 转换为张量结构
    transforms.Normalize((0.1037,), (0.3081,))  # 对数据进行标准化
])
# 获取数据集
train_dataset = datasets.MNIST('data', train=True, download=True, transform=transforms)
# 将数据导入迭代器DataLoader之中, shuffle表示是否要将数据打乱
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=BATCH_SIZE, shuffle=True)


# 定义测试数据集
test_dataset = datasets.MNIST('data', train=True, download=True, transform=transforms)
# 将数据导入迭代器DataLoader之中, shuffle表示是否要将数据打乱
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=BATCH_SIZE, shuffle=True)


# step2.定义网络结构
# 定义一个网络
class Model(nn.Module):
    def __init__(self, class_num, input_channel=3):
        super(Model, self).__init__()
        self.conv1 = nn.Conv2d(in_channels=input_channel, out_channels=32, kernel_size=3)  # 卷积
        self.pool = nn.MaxPool2d(kernel_size=2, stride=2)  # 池化
        self.conv2 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5)  # 卷积
        self.dropout = nn.Dropout2d(p=0.1)  # dropout
        self.adaptive_pool = nn.AdaptiveMaxPool2d((1, 1))  # 全局池化
        self.flatten = nn.Flatten()
        self.linear1 = nn.Linear(64, 32)  # 线性层
        self.relu = nn.ReLU()
        self.linear2 = nn.Linear(32, class_num)  # 最终分了多少个类
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        x = self.conv1(x)
        x = self.pool(x)
        x = self.conv2(x)
        x = self.pool(x)
        x = self.dropout(x)
        x = self.adaptive_pool(x)
        x = self.flatten(x)
        x = self.linear1(x)
        x = self.relu(x)
        x = self.linear2(x)
        y = self.sigmoid(x)
        return y


# 只识别10个,且输入通道为1
net = Model(class_num=10, input_channel=1)
# print(net)

# step3.定义损失函数,梯度下降算法
# 定义损失函数
loss_func = nn.CrossEntropyLoss()
# 定义梯度下降的优化器Adam
optimizer = torch.optim.Adam(params=net.parameters(), lr=0.01)


# 让参数变成可训练的
for params in net.parameters():
    params.requires_grad = True

# step6.验证结果的准确率的函数
def val(test_loader, net):
    sum_= 0
    all_count = 0
    for i, (each_data, each_label) in enumerate(test_loader):
    	
    	with torch.no_grad():
        	pred = net(each_data)

        pred_index = torch.argmax(pred, dim=1) #求概率最大值,则为其预测值
        correct_num = torch.sum(pred_index == each_label).item() # 计算总共有多少个预测正确
        num = BATCH_SIZE #总共有多少个数

        print("batchSize准确率",correct_num/num)

        sum_ += correct_num
        all_count += num
    print("总准确率为",sum_/all_count)



# 训练100个epoch
for epoch_num in range(100):

    for i, (each_data, each_label) in enumerate(train_loader):
		
		# 让参数可训练
        for params in net.parameters():
            params.requires_grad = True

        # 梯度清零,这一步必须要操作,因为不操作则会保留上一次训练的信息
        optimizer.zero_grad()

        # each_data # 获取数据
        # each_label # 获取标签
		
        # step4.进行前向传播,获取预测值
        pred = net(each_data)  # 预测的结果


        # step5.计算损失函数,反向传播,进行梯度下降,将之前的梯度清空
        loss = loss_func(pred, each_label)  # 计算损失值
        loss.backward()  # 反向传播,求梯度
        optimizer.step()  # 进行梯度下降

        if i % 20 == 0:
            print(f"Epoch:{epoch_num} {i} , loss:{loss.item()}")

    # step6.验证结果的准确率
    # 训练完成之后进行验证。
    # ....
    val(test_loader, net)


    # step7.保存模型权重
    # 保存权重,权重文件是一个字典
    params_dict = net.state_dict() #获得网络权重
    torch.save(params_dict, "net.pth")


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值