[pytorch学习笔记] 使用pytorch 搭建自己的网络

目录

数据预处理

加载训练集和测试集

查看迭代器中的图片

使用GPU训练

搭建自己的网络

定义损失函数

定义优化方法 SGD 随机梯度下降 

开始训练

可视化训练误差和测试误差    

模型的保存

测试

参考


 完整源码:

https://github.com/yanganlan0310/build-a-simple-CNN-based-pytorch.git

数据预处理

使用torchvision中的transforms模块对数据进行预处理:

# 使用Composes将transforms组合在一起,tranforms子类进行数据预处理和数据增强 
data_transforms = {
    'train':transforms.Compose([transforms.ToTensor(),  # 图像转换成pytorch中的张量
                                transforms.RandomHorizontalFlip(p=0.5),  # 图像依概率随机翻转
                                transforms.RandomGrayscale(p=0.2),   # 图像依概率随机灰度化
                                transforms.RandomAffine(5),  # 图像中心保持不变的随机仿射变换
                                transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5)), # 归一化
                                ]),
    'val':transforms.Compose([transforms.ToTensor(),  # 图像转换成pytorch中的张量
                                transforms.RandomHorizontalFlip(p=0.5),  # 图像依概率随机翻转
                                transforms.RandomGrayscale(p=0.2),   # 图像依概率随机灰度化
                                transforms.RandomAffine(5),  # 图像中心保持不变的随机仿射变换
                                transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5)), # 归一化
                                ])
}

官方文档: transforms

Transforming and augmenting images — Torchvision 0.12 documentation (pytorch.org)

 我们使用FashionMnist 数据集进行训练和分类,它是由 Zalando(一家德国的时尚科技公司)旗下的研究部门提供。其涵盖了来自 10 种类别的共 7 万个不同商品的正面图片。Fashion-MNIST数据集包含了10个类别的图像,分别是:t-shirt(T恤),trouser(牛仔裤),pullover(套衫),dress(裙子),coat(外套),sandal(凉鞋),shirt(衬衫),sneaker(运动鞋),bag(包),ankle boot(短靴)。 FashionMNIST 的大小、格式和训练集/测试集划分与原始的 MNIST 完全一致。60000/10000 的训练测试数据划分,28x28 的灰度图片。

加载训练集和测试集

# 加载训练集
training_data = datasets.FashionMNIST(
    root='data',
    train=True,
    download=True,  # 若本地没有数据集,下载
    transform=data_transforms
) 
# 构建训练集数据载入器 并提供给定数据集的可迭代对象。
training_loader = torch.utils.data.DataLoader(training_data,batch_size=16,shuffle=True)
# 加载测试集
test_data = datasets.FashionMNIST(
    root='data',
    train=False,
    download=True,
    transform=data_transforms
)
# 构建测试集数据载入器 
test_loader = torch.utils.data.DataLoader(test_data,batch_size=16,shuffle=False)

查看迭代器中的图片

# 查看一下图片
img,label = next(iter(training_loader))
# img 中有4张图片
# print("img:",img)
# print(f"img.size:{img.size()}")
# print("label:",label)
# print(f"lebel.size:",label.size())

使用GPU训练

# 如果有GPU 使用GPU训练,否则CPU
device = torch.device('cuda' if torch.cuda.is_available() else "CPU")
# print(f"using: {device}")

搭建自己的网络

class myModule2(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = nn.Linear(784, 256)
        self.fc2 = nn.Linear(256, 128)
        self.fc3 = nn.Linear(128, 64)
        self.fc4 = nn.Linear(64, 10)
        
    def forward(self, x):
        """
        在forward方法中进行数据操作
        parameter:
        x: 输入的数据
        """
        x = x.view(x.shape[0], -1)    # make sure input tensor is flattened
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = F.relu(self.fc3(x))
        x = F.log_softmax(self.fc4(x), dim=1)
        
        return x

定义损失函数

因为是多分类问题,所以我们用交叉熵损失函数:

# 定义损失函数

criterion = nn.CrossEntropyLoss()   # 多分类,使用交叉熵损失函数

定义优化方法 SGD 随机梯度下降 

# 定义优化方法 SGD 随机梯度下降
optimizer = optim.SGD(my_model.parameters(),lr=0.005,momentum=0.1)

开始训练

# 训练神经网络
epochs = 20
# 训练误差和测试误差存储在这里,最后进行可视化
training_losses = []
test_losses = []
for epoch in range(epochs):
    total_loss = 0.0
    # 遍历训练集中所有数据
    for images,labels in training_loader:
        images,labels = images.to(device),labels.to(device)
        optimizer.zero_grad()   # 将优化器中的所有求导结果设置位0
        output = my_model(images)   # 神经网络的输出
        loss = criterion(output,labels) # 损失函数
        loss.backward() # 后向传播
        optimizer.step()    # 更新参数
        total_loss += loss.item()   # 损失函数求和
    else:
        # 测试数据集
        test_loss = 0
        accuracy = 0
        # 测试的时候不需要自动求导和反向传播
        with torch.no_grad():
            # 关闭Dorpout
            my_model.eval() # 预测结果前必须要做的步骤,其作用为将模型转为evaluation模式
            # 遍历测试集
            for images,labels in test_loader:
                # 对传入的图片进行正向推断
                # 将数据也送入GPU
                images,labels = images.to(device),labels.to(device)
                output = my_model(images)
                test_loss += criterion(output,labels)
                ps = torch.exp(output)
                top_p,top_class = ps.topk(1,dim=1)
                equals = top_class == labels.view(*top_class.shape)
                accuracy += torch.mean(equals.type(torch.FloatTensor))
        # 恢复Dropout
        my_model.train()
        # 将训练误差和测试误差存储在列表中
        training_losses.append(total_loss/len(training_loader))
        test_losses.append(test_loss/len(test_loader))
        
        print("训练集训练次数:{}/{}:".format((epoch+1),epochs),
              "训练误差:{:.3f}".format(total_loss/len(training_loader)),
              "测试误差:{:.3f}".format(test_loss/len(test_loader)),
              "模型分类准确率:{:.3f}".format(accuracy/len(test_loader)))

可视化训练误差和测试误差    

使用 matplotlib.pyplot 可视化训练误差和测试误差

# 可视化训练误差和测试误差      
# 将训练误差和测试误差数据从GPU转回CPU 并且将tensor->numpy (因为numpy 是cup only 的数据类型)
training_losses = np.array(torch.tensor(training_losses,device='cpu'))
test_losses = np.array(torch.tensor(test_losses,device='cpu'))
# 可视化
plt.plot(training_losses,label="training_losses")
plt.plot(test_losses,label="test_losses")
plt.legend()
plt.show()

[pytorch学习笔记] 使用pytorch 搭建自己的网络_第1张图片

  

[pytorch学习笔记] 使用pytorch 搭建自己的网络_第2张图片

模型的保存

# 模型保存
torch.save(my_model.state_dict(),'FashionMnist_weight.pth')

测试

class myModule2(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = nn.Linear(784, 256)
        self.fc2 = nn.Linear(256, 128)
        self.fc3 = nn.Linear(128, 64)
        self.fc4 = nn.Linear(64, 10)
        
    def forward(self, x):
        # make sure input tensor is flattened
        x = x.view(x.shape[0], -1)
        
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = F.relu(self.fc3(x))
        x = F.log_softmax(self.fc4(x), dim=1)
        
        return x

# 加载测试集
test_data = datasets.FashionMNIST(
    root='data',
    train=False,
    download=True,
    transform=transforms.ToTensor()
)
# 构建测试集数据载入器 
test_loader = torch.utils.data.DataLoader(test_data,batch_size=16,shuffle=False)

model = myModule2() # 实例化一个神经网络模型,需要和权重文件的网络模型一样
model.load_state_dict(torch.load("FashionMnist_weight.pth"))    # 加载预训练模型
model.eval()    # 预测结果前必须要做的步骤,其作用为将模型转为evaluation模式
# test_loader = torch.tensor(test_loader(),device='cpu')
images,labels = iter(test_loader).next()
img = images[0]
img = img.reshape((28,28)).numpy()
# plt.imshow(img)

# 图片个数转化为tensor
img = torch.from_numpy(img)
img = img.view(1,784)   # 矩阵压扁
# 测试
with torch.no_grad():
    output = model.forward(img)
ps = torch.exp(output)
# 返回矩阵每一行最大值和下标,元组类型
top_p, top_class = ps.topk(1, dim=1)
labellist = ['T恤','裤子','套衫','裙子','外套','凉鞋','汗衫','运动鞋','包包','靴子']
prediction = labellist[top_class]
probability = float(top_p)
print(f'神经网络猜测图片里是 {prediction},概率为{probability*100}%')

参考

(18条消息) 【PyTorch】从头搭建并训练一个神经网络模型(图像分类、CNN)_sin(豪)的博客-CSDN博客_搭建神经网络模型

你可能感兴趣的:(pytorch,pytorch)