前言:
会用到的工具包pytorch(导入方式为import torch
,import torchvision
)、numpy、matplotlib.pyplot,os,PIL
参考资料:《深度学习之pytorch实战计算机视觉》
正如numpy的nadrry与pandas的dataframe一样,pytorch也有自己的类型叫做tensor,我们认识一样tensor类型如何转化
torch.FloatTensor():
np.array()
类似,当你在括号中输入一个列表他就能帮你转化成浮点型的Tensor类型torch.IntTensor():
这个也跟numpy中的np.random
类似,下面来演示几个常用的
torch.rand()
torch.randn()
torch.range()
torch.zeros()
加减乘除,数乘,点乘等方法
torch.add()
,参数可输入两个tensor,也可输入一个tensor一个常量torch.abs()
torch.clamp()
三个参数:第一个数据集,第二个下界,第三个上界torch.div()
参数可输入两个tensor,也可输入一个tensor一个常量torch.mul()
两个tensor,对应位置相乘,一个常量乘tensor每一个元素的位置torch.pow()
可两个tensor,也可一个tensor一个常量torch.mm()
注意维度torch.mv()
注意维度Variable(数据集,requires_grad = False)
requires_grad
:为False时,自动梯度计算的过程中不会保留梯度值,Ture时则会保留梯度值a.data
,当对象只有一个数据时使用a.item()
a.grad.data
a.grad.data.zero_()
需要引入torch.nn.Module
类来完成
torch.nn.Module
这个类class Model(torch.nn.Moduele):
)super
函数来引入父类的初始化方法。(super(Model,self).__init__()
)self.名称 = torch.nn.Sequential(模型内容)
来定义模型torch.nn.Sequential
表示的是一个容器,比如卷积中的卷积层,池化层,激活层都可以放置在里面,我们还可以设置另一个新的torch.nn.Sequential
来存放全连接层
torch.nn.Linear()
:线性激活,接收参数有三个:输入的特征数,输出的特征数,是否使用偏置(b)torch.nn.ReLU()
:ReLU激活函数torch.nn.Conv2d()
:卷积层:接收参数第一第二分别是输入的通道数,输出的通道数,kernel_size:卷积核(过滤器)大小,stride:步长,padding:填充值torch.nn.MaxPool2d()
:最大池化层,kernel_size:池化窗口大小,stride:步长,padding:填充值torch.nn.Dropout()
:随机失活,p每个节点随机丢失的概率,在卷积神经网络中一般用在全连接层的部分中torch.nn.RNN()
:input_size:输入数据特征数,hidden_size:隐藏层的输出特征数,num_layers:循环层对叠数,默认1,bias:是否使用偏置默认True,batch_first:布尔值,False(序列长度,批次数量,输入或输出特征) True:(批次数量,序列长度,输入或输出特征)torch.nn.Upsample(scale_factor=2,mode="nearest")
model.parameters()
获得模型中的各个参数如果想要吧模型放入GPU里面计算,在定义好model后加个.cuda()
,再对Variable对象后面加个.cuda()
torch.nn.MSELoss()
:均方误差函数计算损失值,prew_y,ytorch.nn.L1Loss()
:平均绝对误差torch.nn.CrossEntropyLoss()
:交叉熵主要类型有:SGD,AdaGrad,RMSProp,Adam
使用流程:
# 定义优化参数方法
optimzer = torch.optim.Adam(model.parameter())
# 定义损失函数方法
loss_f = torch.nn.CrossEntropyLoss()
# 在更新参数前使用,将梯度清零
optimzer.zero_grad()
# 计算损失值
loss = loss_f(prev_y,y)
# 计算梯度
loss.backward()
# 更新参数
optimizer.step()
torchvision是专门用来解决CV(Computer Vision)问题的一个工具包
一般我们使用
from torchvision import trainsforms,datasets
来导入
trainsforms.Compose()
转化容器,参数是用列表括起来的转化方式transforms.Resize()
:按照我们的需求对图片进行缩放,一般输入一个(h,w)的参数,h高度,w宽度transforms.Scale()
:和Resize一样transforms.CenterCrop()
:以图片中心为原点按照输入参数的进行裁剪,输入元组宽高transforms.RandomCrop()
:对图片,按照输入参数的尺寸进行随机裁剪transforms.RandomVerticalFlip()
,对载入图片按照随机概率进行垂直翻转,输入的参数随机概率,默认值为0.5transforms.ToTensor()
,对载入的图片数据进行类型转换,将之前的构造PIL图片转换成Tensor数据类型ransforms.Normalize(mean=[0.5],std=[0.5])
,对数据进行标准化,参数可以修改transforms.ToPILImage()
用于将tensor变量的数据转化成PIL图片transform = transforms.Compose([转化内容])
来定义转化方式data_train = datasets.数据名(root="目录",trannsform=转化方式,train=True(是否为训练集),download=True(从网上下载))
data_test = datasets.数据名(root="目录",transform=转化方式,train=Flase)
需要的工具:torch.utils.data.DataLoader()
参数: datasets是数据集,batch_size是批量的大小,shuffle是是否进行随机打乱
data_loader_train = torch.utils.data.DataLoader(dataset=data_train,batch_size=64,shuffle=True)
数据装载有两种用途,一种用于展示,一种用于训练预测:
用于展示:
images,labels = next(iter(data_loader_train))
将其提取出来img = torchvision.utils.make_grid(images)
img = img.numpy().transpose(1,2,0)
来实现转换plt输出格式,对用GPU训练后的数据,需要在numpy前面加上.cpu()plt.imshow(img)
了,如果没有出现图片就加一个plt.show()
用于训练、预测
enumerate()
函数,他用于返回可迭代对象中的索引和数据,第一个参数输入可迭代对象,第二个参数输入索引起始位置for batch,data in enumerate(dataloader,1):
遍历这个可迭代对象X,y=data
y_pred = model(X)
_,pred = torch.max(y_pred.data,1)
来提取
在计算机视觉领域中,要训练一个好的模型是很耗费时间和精力的,于是我们产生了迁移学习,在别人训练过的模型基础上我们进行再训练,从而使得这个模型倾向于解决我们的问题。
要引用别人的模型,我们需要使用到torchvision中的models
model = models.vgg16(pretrained=True)
for parma in model.parameters():
parme.requires_grad = False
print(model)
查看他们输出部分的模型叫什么名字model.名字 = torch.nn.Sequential()
进行修改 model.fc = torch.nn.Sequential(
修改内容(其他的可以不改变,但是在最后输出的一句Linear中我们需要把输出维度改成我们希望的)
)
optimizer = torch.optim.Adam(model.fc.parameters())
需要的python包os
os.path.dirname()
用于返回目录的目录名os.path.exists()
用于测试输入参数指定的文件是否存在os.path.isdir()
用于测试输入参数是否是目录名os.path.isfile()
用于测试输入参数是否为一个文件os.path.samefile()
用于测试两个输入的路径参数是否指向同一个文件os.path.split()
用于对输入参数中的目录名进行分割,返回一个元组,元组由目录名和文件名组成os.path.join()
将输入参数中的两个名字拼接成一个完整的文件路径分为两种,提取单个数据和提取数据集,需要PIL中的Image
提取单个数据:
img = Image.open("路径")
img =tranform(img)
img = img.unsqueeze(0)
在0维度前增加一个维度,0的数值可以修改提取数据集
# 转换类型
data_transform = {x:transforms.Compose([transforms.Resize([224,224]),transforms.ToTensor(),transforms.Normalize(mean=[0.5],std=[0.5])]) for x in ["train","valid"]}
# 打开文件并转换
image_datasets = {x:datasets.ImageFolder(root = os.path.join(data_dir,x),transform=data_transform[x]) for x in ["train","valid"]}
# 装载数据
dataloader = {x:torch.utils.data.DataLoader(dataset = image_datasets[x],batch_size=16,shuffle=True) for x in ["train","valid"]}
保存整个模型:torch.save(model,Path)
保存模型参数:torch.save(net.state_dict(),Path)
加载整个模型:model = torch.load(Path)
加载参数:model = model.load_state_dict(torch.load(Path))