神经网络之Pytorch学习笔记

神经网络之Pytorch学习笔记



前言

入门神经网络的选择有很多,pytorch的简洁灵活成为了现在的主流选择,但也不排除以后会有更好的框架。


一、张量(tensor)

1 创建张量

1.1 数据转换

  先得到数据data副本再对副本进行转变

  • torch.Tensor()转换后的数据类型与全局缺省值相同
  • torch.tensor()转换后的数据类型与data原类型相同#使用较多#

  与原数据data共享内存

  • torch.as_tensor()转换后的数据类型与data原类型相同#使用较多#
  • torch.from_numpy()转换后的数据类型与data原类型相同
data = np.array([1,2,3])
torch.Tensor(data)#copy
torch.tensor(data)#copy
torch.as_tensor(data)#share
torch.from_numpy(data)#share
print('\n',t1,t1.dtype,'\n',t2,'\n',t3,'\n',t4)
torch.get_default_dtype()#获取全局缺省值类型
 tensor([1., 2., 3.]) torch.float32 
 tensor([1, 2, 3], dtype=torch.int32) 
 tensor([1, 2, 3], dtype=torch.int32) 
 tensor([1, 2, 3], dtype=torch.int32)
 torch.float32

改变了data的元素时:

data[0] = 0
data[1] = 0
data[2] = 0
print('\n',t1,t1.dtype,'\n',t2,'\n',t3,'\n',t4)
 tensor([1., 2., 3.]) torch.float32 
 tensor([1, 2, 3], dtype=torch.int32) 
 tensor([0, 0, 0], dtype=torch.int32) 
 tensor([0, 0, 0], dtype=torch.int32)

1.2 直接创建

  • torch.eye(2) 单位矩阵
  • torch.zero(2,2) 0矩阵
  • torch.one(2,2) 1矩阵
  • torch.rand(2,2) 随机矩阵

1.3 查看张量状态

  • t.dtype 查看数据类型
  • t.device 查看张量在CPU或GPU
  • t.layout 查看张量数据如何在内存中分布:stried或sparse_coo分别对应顺序储存、离散储存

2.重塑操作

2.1 查看张量形状与元素个数

  • t.size() 查看形状
  • t.shape() 查看形状
  • t.prod() 查看张量数据如何在内存中分布:stried或sparse_coo分别对应顺序
  • t.numel() 查看张量数据如何在内存中分布:stried或sparse_coo分别对应顺序

2.2 重塑、压缩、解压、拼接、叠加

  • t.reshape(1,12) 重塑:将原先的张量重塑为
  • t.squeeze() 压缩:将输入张量形状中的1 去除并返回。 如果输入是形如(A×1×B×1×C×1×D),那么输出形状就为: (A×B×C×D),当给定dim时,那么挤压操作只在给定维度上。例如,输入形状为: (A×1×B),t.squeeze(dim=0) 将会保持张量不变,只有用 t.squeeze(dim=1),形状会变成 (A×B)。
  • t.unsqueeze(dim=0) 解压:返回一个新的张量,对输入的既定位置(dim=0)插入维度 1
  • torch.cat((t1,t2,t3),dim = 0) 拼接:在指定维度(dim=0)下拼接。
t1 = torch.tensor([[2,2,2],[2,2,2]])
t2 = torch.tensor([[2,2,2],[2,2,2]])
print(torch.cat((t1,t2),dim=0))
print(torch.cat((t1,t2),dim=1))
tensor([[2, 2, 2],
        [2, 2, 2],
        [2, 2, 2],
        [2, 2, 2]])
tensor([[2, 2, 2, 2, 2, 2],
        [2, 2, 2, 2, 2, 2]])
  • torch.stack((t1,t2,t3),dim=0) 叠加:要求输入张量的大小完全相同,得到的张量的维度会比输入的张量的大小多1
t1 = torch.tensor([
	[2,2,2],
	[2,2,2]])
t2 = torch.tensor([2,2,2])
print(torch.stack((t1,t2),dim=0))
print(torch.stack((t1,t2),dim=1))
tensor([[2, 2, 2],
        [2, 2, 2]])
tensor([[2, 2],
        [2, 2],
        [2, 2]])

3.元素操作

3.1 运算、广播

  在张量的运算中:对于t0+t1这样的两个张量形状不相同的运算,首先是将t1通过torch.tensor(np.broadcast_to(2,t0.shape))转化为:tensor([[2, 2, 2], [2, 2, 2]])再对其中的元素一一对应相加。
  形如这样,复制一个数据的某个维度,来将较低的秩的张量以匹配更高阶的张量,称为广播

t0 = torch.tensor([
	[2,2,2]
	,[2,2,2]
	])
t1 = torch.tensor([1,1,1])
t2 = t0+2
t3 = t0+t1
print(t2,'\n',t3)
tensor([[4, 4, 4],
        [4, 4, 4]])
        
tensor([[3, 3, 3],
        [3, 3, 3]])

3.2 缩减、其他

  • t.sum(dim = 0) 将得到指定维度的累加值
t = torch.tensor([
   [2,1,1],
   [2,1,1],
   [2,1,1]
])
t.sum(dim=0)
t.sum(dim=1)
tensor([6, 3, 3])
tensor([4, 4, 4])
  • torch.argmax(t,dim = 0)将得到0维度上的最大值的索引
t = torch.tensor([
    [2,1,1],
    [2,1,1],
    [2,1,1]
])
print(torch.argmax(t,dim=0))
print(torch.argmax(t,dim=1))
tensor([2, 2, 2])
tensor([0, 0, 0])

二、准备数据

1.FashionMINST数据集

  在学习神经网络的过程中,一个容易导入的有效数据是是难能可贵的,其中最为经典就是MINST以及FashionMINST,不同于MNIST手写数据集,Fashion-MNIST数据集包含了10个类别的图像,分别是:t-shirt(T恤),trouser(牛仔裤),pullover(套衫),dress(裙子),coat(外套),sandal(凉鞋),shirt(衬衫),sneaker(运动鞋),bag(包),ankle boot(短靴)。
在这里插入图片描述

Fashion-MNIST载入数据函数:

  • torchvision.datasets.FashionMNIST(root, train=True, transform=None, target_transform=None, download=False)

函数参数说明:

  • root (string) – 数据集的根目录。训练集与测试集具体地址为:Fashion-MNIST/processed/training.pt and Fashion-MNIST/processed/test.pt exist.

  • train (bool, optional)– 如果为真, 从training.pt创建训练集, 否则从test.pt创建测试集.

  • download (bool, optional) – 如果为真, 从互联网下载数据,并存入数据集根目录下.如果数据已存在,则不会重新下载。

  • transform (callable, optional) – 接受PIL图像并返回转换后版本的函数/转换。例如:transforms.RandomCrop

  • target_transform (callable, optional) – 接受目标并对其进行转换的函数/转换。

数据加载器函数:

  • 这里我们主要使用它的分组功能,即把数据分成若干个大小为多少的小批次,故只使用两个参数:torch.utils.data.DataLoader(train_set,batch_size=100)其余设定查阅官方文档

参数说明:

  • dataset (Dataset) – 要加载数据的数据集。
  • batch_size – 每个批次要加载多少个样本(默认值:1)
import torch
import torchvision
import torchvision.transforms as transforms

train_set = torchvision.datasets.FashionMNIST(
        root='./data/FashionMNIST'#数据保存路径
        ,train=True#训练集为True,测试集为False
        ,download=True#若在数据保存路径中没有找到,是否下载
        ,transform=transforms.Compose([
                transforms.ToTensor()
        ])#接受PIL图像并返回已转换版本
)
train_loader = torch.utils.data.DataLoader(
        train_set,batch_size=100
        )

  这组数据有图像和标签两列变量,使用train_set.train_labels.bincount()查看每个标签下的图像是否平衡:

train_set.train_labels.bincount()
tensor([6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000])

  灰度图像数据可视化,可以利用matplotlib库中的plt.imshow()函数来将图像打印出来

import numpy as np
import matplotlib.pyplot as plt
torch.set_printoptions(linewidth=120)

sample = next(iter(train_set))
image,label = sample

plt.imshow(image.squeeze(),cmap='gray')

在这里插入图片描述


三、建立模型

1.CNN网络参数设定以及搭建

  首先创建一个nn.Module的基础类,将网络的层如self.conv1定义为类属性,定义流动函数forward(),其中流动函数的写法要根据实际网络的情况,如卷积层需要激活函数torch.relu()激活后,再经过最大池化层torch.max_pool2d(),在卷积层传入线性层时,要注意张量大小,因为在最后一层的卷积层经过池化层后,数据大小变为了12*4*4个。
  其中,各个参数的意义为:

  • kernel_size:卷滤波器大小,若输入 5 5 5 则默认为 5 × 5 5\times 5 5×5 大小的方形。
    • out_channels:卷积层输出的特征图(feature_map)个数数
    • stride:卷积层的卷积滤波器移动步长,默认值为1
    • out_features:线性层输出的特征(feature)个数
    • 偏差:是否启用线性层的偏差,默认值为Ture
class Network(nn.Module):
    def __init__(self):
        super().__init__()#doble“_”
        self.conv1 = nn.Conv2d(in_channels=1,out_channels=6,kernel_size=5)
        self.conv2 = nn.Conv2d(in_channels=6,out_channels=12,kernel_size=5)#卷积层
        
        self.fc1 = nn.Linear(in_features=12*4*4,out_features=120)#线性层
        self.fc2 = nn.Linear(in_features=120,out_features=60)
        self.out = nn.Linear(in_features=60,out_features=10)
        

    def forward(self,t):
        # (1) input layer
        #t = t
        # (2) hidden conv layer
        t = torch.relu(self.conv1(t))
        t = torch.max_pool2d(t, kernel_size=2, stride=2)
        # (3) hidden conv layer
        t = torch.relu(self.conv2(t))
        t = torch.max_pool2d(t, kernel_size=2, stride=2)
        # (4)(5) hidden linear layer
        t = torch.relu(self.fc1(t.reshape(-1, 12 * 4 * 4)))
        t = torch.relu(self.fc2(t))

        # (6) output layer
        t = self.out(t)
        #t = torch.softmax(t, dim=1)
        return t

四、训练模型

1.CNN网络反向传播训练

  首先初始化网络类network = Network(),优化器参数设定torch.optim.Adam(parameters(), lr),lr为学习率,下面这个例子使用了五个epoch(周期)训练,每个batch(批次)大小为100,一个批次学习完毕后,利用 entroy(preds, labels)计算平均损失值,再利用梯度反向传播loss.backward生成反向传播梯度图,从而用optimizer.step()把生成的梯度图去更新该网络的权重和偏置。
  其中images为四维变量,其大小为:torch.Size([100, 1, 28, 28]),分别代表:样本序号、色彩通道、长、宽。(故在pytorch框架下,CNN网络是默认四维的数据,可以直接成批次学习)

def get_num_correct(preds,labels):
    return preds.argmax(dim=1).eq(labels).sum().item()
    
network = Network()#初始化网络
entroy=nn.CrossEntropyLoss()

train_loader = torch.utils.data.DataLoader(
	train_set, 
	batch_size=100
)#将训练集加载为若干个小批次,大小为100个样本

optimizer = torch.optim.Adam(network.parameters(), lr=0.01)#优化器设定,学习率为0.01

for epoch in range(5):#进行五个训练周期(epoch)
    total_loss = 0#总损失值初始化
    total_correct = 0#总正确预测次数

    for batch in train_loader:#遍历所有批次
        images,labels = batch#从batch中获得
        
        preds = network(images) # Pass Batch
        loss = entroy(preds, labels) # 计算损失值
        optimizer.zero_grad()#梯度图归0

        loss.backward() # 计算梯度图
        optimizer.step() # 更新权重等

        total_correct = total_correct + get_num_correct(preds,labels)
        total_loss = total_loss + loss.item()
        
    print('epoch:',epoch,'total_loss:', total_loss,'total_correct:',total_correct)

epoch: 0 total_loss: 330.01528219878674 total_correct: 47602
epoch: 1 total_loss: 231.22278858721256 total_correct: 51514
epoch: 2 total_loss: 215.0638506859541 total_correct: 52037
epoch: 3 total_loss: 206.70368824899197 total_correct: 52399
epoch: 4 total_loss: 198.21306644380093 total_correct: 52563
print('correct rate:',(total_correct / len(train_set))*100,'%')
correct rate: 87.605 %

五、分析结果

1.TensorBorad

还在学习中。

总结

持续更新ing…如有问题恳请大佬指出

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刺兹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值