神经网络之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或GPUt.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…如有问题恳请大佬指出