Pytorch框架
- Pytorch官方文档:https://pytorch.org/docs/stable/index.html
(一)MyDataset制作
制作自己的MyDataSet以供dataloader使用,必须继承Dataset重写 init,getitem 函数。
import numpy as np
from tensorboardX.utils import make_grid
from torch.utils.data import Dataset, DataLoader
from PIL import Image
import os
from torchvision import transforms
from torch.utils.tensorboard import SummaryWriter
writer = SummaryWriter("logs")
class MyDataset(Dataset):
def __init__(self, root_dir, image_dir, label_dir, transform):
self.root_dir = root_dir #根目录名
self.image_dir = image_dir #照片存储文件夹名
self.label_dir = label_dir #标签存储文件夹名
self.label_path = os.path.join(self.root_dir, self.label_dir)#标签存储路径
self.image_path = os.path.join(self.root_dir, self.image_dir)#照片存储路径
self.image_list = os.listdir(self.image_path)#列出该路径下的所有文件(照片)
self.label_list = os.listdir(self.label_path)#列出该路径下的所有文件(标签)
self.transform = transform #照片格式转换器
# 因为label 和 Image文件名相同,进行一样的排序,可以保证取出的数据和label是一一对应的
self.image_list.sort()
self.label_list.sort()
def __getitem__(self, idx):
img_name = self.image_list[idx] #获取指定位置文件(照片)名
label_name = self.label_list[idx] #获取指定位置文件(标签)名
img_item_path = os.path.join(self.root_dir, self.image_dir, img_name)#照片路径
label_item_path = os.path.join(self.root_dir, self.label_dir, label_name)#标签路径
img = Image.open(img_item_path).convert("RGB")#转化为三通道
with open(label_item_path, 'r') as f:
label = f.readline() #读取标签文件标签
# img = np.array(img)
img = self.transform(img) #将照片转化成想要的格式一般是tensor类型
sample = {'img': img, 'label': label}
return sample #返回需要的样本
def __len__(self):
assert len(self.image_list) == len(self.label_list) #照片数应当与标签数相同
return len(self.image_list) #返回样本数
#测试MyDataset数据集
if __name__ == '__main__':
for epoch in range(10):
#构造照片格式转化器
transform = transforms.Compose([transforms.Resize((32,32)), transforms.ToTensor()])
root_dir = "dataset/train"
image_dir_name = "ants_image"
label_dir_name = "ants_label"
#构建数据集
train_dataset = MyDataset(root_dir, image_dir_name, label_dir_name, transform)
# transforms = transforms.Compose([transforms.Resize(256, 256)])
#dataloader建立线程与样本时间的关系,shuffle:洗牌,num_workers:线程
dataloader = DataLoader(train_dataset, batch_size=8, shuffle=True,num_workers=2)
for index , sample in enumerate(dataloader): #返回一个元组 (0, sample[0])...
print(type(sample))
print(index, sample['img'].shape)
writer.add_image("train", make_grid(np.array(sample['img'])), index)
writer.close()
(二)DataLoader使用
import torchvision
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
from tensorboardX.utils import make_grid
import numpy as np
# 准备的测试数据集
test_data = torchvision.datasets.CIFAR10("./dataset/CIFAR10", train=False, transform=torchvision.transforms.ToTensor())
test_loader = DataLoader(dataset=test_data, batch_size=24, shuffle=True, num_workers=2, drop_last=False)
writer = SummaryWriter("dataloader")
if __name__ == '__main__':
print(test_data[0]['img'].shape)#更改数据集__getitem__返回字典
for index, sample in enumerate(test_loader): # 返回一个元组 (0, sample[0])...
print(type(sample))
print(index, sample['img'].shape)
writer.add_image("train", make_grid(np.array(sample['img'])), index)
# step=0
# for sample in test_loader: #更改数据集__getitem__返回字典
# print(type(sample["img"]))
# writer.add_image("train", make_grid(np.array(sample['img'])), step)
# step=step+1
writer.close()
(三)Tensorboard使用
from torch.utils.tensorboard import SummaryWriter
writer = SummaryWriter("logs")#日志存储文件夹
# title名,图像(torch.Tensor, numpy.array),下标,图像格式(高、宽、通道Channel)
writer.add_image("train", array_or_tensor_img, 1, dataformats='HWC')
for i in range(100):
writer.add_scalar("y=2x", 3*i, i)
writer.close()
(四)Transform使用
照片格式转化,Resize默认三个通道同时变换。
transform = transforms.Compose([transforms.Resize((32,32)), transforms.ToTensor()])
(五)Model搭建
import torch
from torch import nn
# 搭建神经网络
class VGG16(nn.Module):
def __init__(self):
super(VGG16, self).__init__()
self.model = nn.Sequential(
# 3inchaneel->32outchaneel:5x5kernelUnion[int, Tuple[int, int]],
# stride: Union[int, Tuple[int, int]] = 1, padding: Union[str, int, Tuple[int, int]] = 0,
# dilation: Union[int, Tuple[int, int]] = 1
nn.Conv2d(3, 32, 5, 1, 2),
nn.MaxPool2d(2), # help查看使用方法
nn.Conv2d(32, 32, 5, 1, 2),
nn.MaxPool2d(2),
nn.Conv2d(32, 64, 5, 1, 2),
nn.MaxPool2d(2),
nn.Flatten(), #摊平
nn.Linear(64*4*4, 64),
nn.Linear(64, 10)
)
def forward(self, x):
x = self.model(x)
return x
if __name__ == '__main__':
VGG16 = VGG16()
input = torch.ones((64, 3, 32, 32))
output = VGG16(input)
print(output.shape)
(六)Loss&Optimizer使用
import torch
from torch.nn import L1Loss
from torch import nn
from torch.nn import Sequential, Conv2d, MaxPool2d, Flatten, Linear
inputs = torch.tensor([1, 2, 3], dtype=torch.float32)
targets = torch.tensor([1, 2, 5], dtype=torch.float32)
inputs = torch.reshape(inputs, (1, 1, 1, 3))#1 batch_size,1chaneel,1array,3elemen
targets = torch.reshape(targets, (1, 1, 1, 3))#1 batch_size,1chaneel,1array,3elemen
loss = L1Loss(reduction='sum')
result = loss(inputs, targets)
loss_mse = nn.MSELoss()
result_mse = loss_mse(inputs, targets)
# print(result)
# print(result_mse)
x = torch.tensor([0.1, 0.2, 0.3]) # torch.Size([3])
# print(x.shape)
y = torch.tensor([1])# target.shape:torch.Size([1, 3]) (N)
x = torch.reshape(x, (1,3))# input.shape:torch.Size([1]) (N,C)
# print(x.shape)
# print(y.shape)
loss_cross = nn.CrossEntropyLoss()
result_cross = loss_cross(x, y)
print(result_cross)
from torch.optim.lr_scheduler import StepLR
loss = nn.CrossEntropyLoss()
VGG16 = VGG16()
optim = torch.optim.SGD(VGG16.parameters(), lr=0.01)#模型参数,学习率
scheduler = StepLR(optim, step_size=5, gamma=0.1)#等间隔衰减学习率 StepLR, 将学习率调整为 lr*gamma
for epoch in range(20):
running_loss = 0.0
for data in dataloader: #Dataset return targets,imgs
imgs, targets = data
outputs = VGG16(imgs)
result_loss = loss(outputs, targets)
optim.zero_grad()
result_loss.backward()
scheduler.step()
running_loss = running_loss + result_loss
print(running_loss)
(七)Save&Load模型
保存模型:torch.save(model ,“model.pth”)&torch.save(model.state_dict() , “model.pth”)
加载模型:不管哪一种形式加载模型,都要先加载模型原型。
from model_save import *
import torchvision
vgg16 = torchvision.models.vgg16(pretrained=False)
# 保存方式1,模型结构+模型参数
torch.save(vgg16, "vgg16_method1.pth")
# 保存方式2,模型参数(官方推荐)
torch.save(vgg16.state_dict(), "vgg16_method2.pth")
#方式1,加载模型
model = torchvision.models.vgg16(pretrained=False)
model = torch.load("vgg16_method1.pth")
# 方式2,加载模型
vgg16 = torchvision.models.vgg16(pretrained=False)
vgg16.load_state_dict(torch.load("vgg16_method2.pth"))
(八)CPU&GPU训练
指定训练设备主要在三个地方指定,1、数据加载,2、模型加载,3损失函数
import torch
import torchvision
from torch.utils.tensorboard import SummaryWriter
from torch import nn
from torch.utils.data import DataLoader
# 准备数据集
train_data = torchvision.datasets.CIFAR10(root="../data", train=True, transform=torchvision.transforms.ToTensor(),download=True)
test_data = torchvision.datasets.CIFAR10(root="../data", train=False, transform=torchvision.transforms.ToTensor(),download=True)
# length 长度
train_data_size = len(train_data)
test_data_size = len(test_data)
# 如果train_data_size=10, 训练数据集的长度为:10
print("训练数据集的长度为:{}".format(train_data_size))
print("测试数据集的长度为:{}".format(test_data_size))
# 利用 DataLoader 来加载数据集
train_dataloader = DataLoader(train_data, batch_size=64)
test_dataloader = DataLoader(test_data, batch_size=64)
# 创建网络模型
class VGG16(nn.Module):
def __init__(self):
super(VGG16, self).__init__()
self.model = nn.Sequential(
nn.Conv2d(3, 32, 5, 1, 2),
nn.MaxPool2d(2),
nn.Conv2d(32, 32, 5, 1, 2),
nn.MaxPool2d(2),
nn.Conv2d(32, 64, 5, 1, 2),
nn.MaxPool2d(2),
nn.Flatten(),
nn.Linear(64*4*4, 64),
nn.Linear(64, 10)
)
def forward(self, x):
x = self.model(x)
return x
VGG16 = VGG16()
if torch.cuda.is_available():
VGG16 = VGG16.cuda()#<-------------------------------模型加载cuda
# 损失函数
loss_fn = nn.CrossEntropyLoss()
if torch.cuda.is_available():
loss_fn = loss_fn.cuda()#<-------------------------------损失函数加载cuda
# 优化器
# learning_rate = 0.01
# 1e-2=1 x (10)^(-2) = 1 /100 = 0.01
learning_rate = 1e-2
optimizer = torch.optim.SGD(VGG16.parameters(), lr=learning_rate)
# 设置训练网络的一些参数
# 记录训练的次数
total_train_step = 0
# 记录测试的次数
total_test_step = 0
# 训练的轮数
epoch = 10
# 添加tensorboard
writer = SummaryWriter("../logs_train")
for i in range(epoch):
print("-------第 {} 轮训练开始-------".format(i+1))
# 训练步骤开始
VGG16.train()
for data in train_dataloader:
targets,imgs = data
if torch.cuda.is_available():
imgs = imgs.cuda()#<-------------------------------数据加载cuda
targets = targets.cuda()#<-------------------------------数据加载cuda
outputs = VGG16(imgs)
loss = loss_fn(outputs, targets)
# 优化器优化模型
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_train_step = total_train_step + 1
if total_train_step % 100 == 0:
print("训练次数:{}, Loss: {}".format(total_train_step, loss.item()))
writer.add_scalar("train_loss", loss.item(), total_train_step)
# 测试步骤开始
VGG16.eval()
total_test_loss = 0
total_accuracy = 0
with torch.no_grad():
for data in test_dataloader:
imgs, targets = data
if torch.cuda.is_available():
imgs = imgs.cuda()#<-------------------------------数据加载cuda
targets = targets.cuda()#<-------------------------------数据加载cuda
outputs = VGG16(imgs)
loss = loss_fn(outputs, targets)
total_test_loss = total_test_loss + loss.item()
accuracy = (outputs.argmax(1) == targets).sum()
total_accuracy = total_accuracy + accuracy
print("整体测试集上的Loss: {}".format(total_test_loss))
print("整体测试集上的正确率: {}".format(total_accuracy/test_data_size))
writer.add_scalar("test_loss", total_test_loss, total_test_step)
writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step)
total_test_step = total_test_step + 1
torch.save(VGG16.state_dict(), "VGG16_{}.pth".format(i))
print("模型已保存")
writer.close()
import torch
import torchvision
from torch.utils.tensorboard import SummaryWriter
from torch import nn
from torch.utils.data import DataLoader
# if torch.cuda.is_available():#<-------------------------------指定cuda
# device = torch.device("cuda")
# else :
# device = torch.device("cpu")
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
# 准备数据集
train_data = torchvision.datasets.CIFAR10(root="dataset/CIFAR10", train=True, transform=torchvision.transforms.ToTensor(),
download=False)
test_data = torchvision.datasets.CIFAR10(root="dataset/CIFAR10", train=False, transform=torchvision.transforms.ToTensor(),
download=False)
# length 长度
train_data_size = len(train_data)
test_data_size = len(test_data)
# 如果train_data_size=10, 训练数据集的长度为:10
print("训练数据集的长度为:{}".format(train_data_size))
print("测试数据集的长度为:{}".format(test_data_size))
# 利用 DataLoader 来加载数据集
train_dataloader = DataLoader(train_data, batch_size=64)
test_dataloader = DataLoader(test_data, batch_size=64)
# 创建网络模型
class VGG(nn.Module):
def __init__(self):
super(VGG, self).__init__()
self.model = nn.Sequential(
nn.Conv2d(3, 32, 5, 1, 2),
nn.MaxPool2d(2),
nn.Conv2d(32, 32, 5, 1, 2),
nn.MaxPool2d(2),
nn.Conv2d(32, 64, 5, 1, 2),
nn.MaxPool2d(2),
nn.Flatten(),
nn.Linear(64*4*4, 64),
nn.Linear(64, 10)
)
def forward(self, x):
x = self.model(x)
return x
VGG = VGG()
VGG.to(device)#<-------------------------------模型加载cuda
# 损失函数
loss_fn = nn.CrossEntropyLoss()
loss_fn.to(device)#<-------------------------------损失函数加载cuda
# 优化器
# learning_rate = 0.01
# 1e-2=1 x (10)^(-2) = 1 /100 = 0.01
learning_rate = 1e-2
optimizer = torch.optim.SGD(VGG.parameters(), lr=learning_rate)
# 设置训练网络的一些参数
# 记录训练的次数
total_train_step = 0
# 记录测试的次数
total_test_step = 0
# 训练的轮数
epoch = 10
# 添加tensorboard
writer = SummaryWriter("logs")
for i in range(epoch):
print("-------第 {} 轮训练开始-------".format(i+1))
# 训练步骤开始
VGG.train()
for data in train_dataloader:
# targets,imgs= data
targets,imgs = data[0].to(device), data[1].to(device)
# imgs.to(device)#<-------------------------------数据加载cuda
# targets.to(device)#<-------------------------------数据加载cuda
outputs = VGG(imgs)
loss = loss_fn(outputs, targets)
# 优化器优化模型
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_train_step = total_train_step + 1
if total_train_step % 100 == 0:
print("训练次数:{}, Loss: {}".format(total_train_step, loss.item()))
writer.add_scalar("train_loss", loss.item(), total_train_step)
torch.save(VGG.state_dict(), "VGG_{}.pth".format(i+1))
print("第{}轮模型已保存".format(i+1))
print("-------第 {} 轮测试开始-------".format(i + 1))
# 测试步骤开始
VGG.eval()
total_test_loss = 0
total_accuracy = 0
with torch.no_grad():
for data in test_dataloader:
targets,imgs = data
imgs.to(device)#<-------------------------------数据加载cuda
targets.to(device)#<-------------------------------数据加载cuda
outputs = VGG(imgs)
loss = loss_fn(outputs, targets)
total_test_loss = total_test_loss + loss.item()
accuracy = (outputs.argmax(1) == targets).sum()
total_accuracy = total_accuracy + accuracy
print("整体测试集上的Loss: {}".format(total_test_loss))
print("整体测试集上的正确率: {}".format(total_accuracy/test_data_size))
writer.add_scalar("test_loss", total_test_loss, total_test_step)
writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step)
total_test_step = total_test_step + 1
writer.close()
(九)开源项目分析
Readme文件、args声明函数
def parse_args():
parser = argparse.ArgumentParser(description='escrebtion help..')
parser.add_argument('--root_dir', default="../rootdir",help='the path for source data')
parser.add_argument('--window_size', default='70_70',help='The size of kernel, format: h_w')
parser.add_argument('--output_folder',default="../outputdir", help='descrebtion help.....')
parser.add_argument('--mode', default="train", help='descrebtion help...........')
args = parser.parse_args()
return args
(十)快捷键使用
常用快捷键
-
Ctrl + Space 基本的代码完成(类、方法、属性)
-
Ctrl + Alt + Space 快速导入任意类
-
Ctrl + Shift + Enter 语句完成
-
Ctrl + P 参数信息(在方法中调用参数)
-
Ctrl + Q 快速查看文档 ,使用help()拥有更加详细的信息
-
F1 Web帮助文档主页
-
Shift + F1 选中对象的Web帮助文档
-
Ctrl + 悬浮/单击鼠标左键 简介/进入代码定义
-
Ctrl + Z 撤销上次操作
-
Ctrl + Shift + Z 重做,恢复上次的撤销
-
Ctrl + F1 显示错误描述或警告信息
-
Alt + Insert 自动生成代码
-
Ctrl + O 重新方法
-
Ctrl + Alt + T 选中
-
Ctrl + / 行注释/取消注释,在python中多行注释用三个单引号’’‘多行代码’’'或者三个双引号""“多行代码”""
-
Ctrl + Shift + / 块注释
-
Ctrl + W 选中增加的代码块
-
Ctrl + Shift + W 回到之前状态
-
Ctrl + Shift + ]/[ 选定代码块结束、开始
-
Alt + Enter 快速修正
-
Ctrl + Alt + L 代码格式化
-
Ctrl + Alt + O 优化导入
-
Ctrl + Alt + I 自动缩进
-
Tab / Shift + Tab 缩进、不缩进当前行
-
Ctrl+X/Shift+Delete 剪切当前行或选定的代码块到剪贴板
-
Ctrl+C/Ctrl+Insert 复制当前行或选定的代码块到剪贴板
-
Ctrl+V/Shift+Insert 从剪贴板粘贴
-
Ctrl + Shift + V 从最近的缓冲区粘贴
-
Ctrl + D 复制选定的区域或行
-
Ctrl + Y 删除选定的行
-
Ctrl + Shift + J 添加智能线
-
Ctrl + Enter 智能线切割
-
Shift + Enter 另起一行
-
Ctrl + Shift + U 在选定的区域或代码块间切换
-
Ctrl + Delete 删除到字符结束
-
Ctrl + Backspace 删除到字符开始
-
Ctrl + Numpad+/- 展开/折叠代码块(当前位置:函数、注释等)
-
Ctrl + Shift + Numpad+/- 展开/折叠所有代码块
-
Ctrl + F4 关闭运行的选项卡
-
2、查找/替换(Search/Replace)
-
F3 下一个
-
Shift + F3 前一个
-
Ctrl + R 替换
-
Ctrl + Shift + R 全局替换
-
Ctrl + Shift + F 全局查找(可以在整个项目中查找某个字符串什么的,如查找某个函数名)
-
连续敲击两次Shift键 查找函数
-
3、运行(Running)
-
Alt + Shift + F10 运行模式配置
-
Alt + Shift + F9 调试模式配置
-
Shift + F10 运行
-
Shift + F9 调试
-
Ctrl + Shift + F10 运行编辑器配置
-
Ctrl + Alt + R 运行manage.py任务
-
4、调试(Debugging)
-
F8 跳过
-
F7 进入
-
Shift + F8 退出
-
Alt + F9 运行游标
-
Alt + F8 验证表达式
-
Ctrl + Alt + F8 快速验证表达式
-
F9 恢复程序
-
Ctrl + F8 断点开关
-
Ctrl + Shift + F8 查看断点
-
5、导航(Navigation)
-
Ctrl + N 跳转到类
-
Ctrl + Shift + N 跳转到符号
-
Alt + Right/Left 跳转到下一个、前一个编辑的选项卡(代码文件)
-
Alt + Up/Down跳转到上一个、下一个方法
-
F12 回到先前的工具窗口
-
Esc 从工具窗口回到编辑窗口
-
Shift + Esc 隐藏运行的、最近运行的窗口
-
Ctrl + Shift + F4 关闭主动运行的选项卡
-
Ctrl + G 查看当前行号、字符号
-
Ctrl + E 在当前文件弹出最近使用的文件列表
-
Ctrl+Alt+Left/Right 后退、前进
-
Ctrl+Shift+Backspace 导航到最近编辑区域(差不多就是返回上次编辑的位置)
-
Alt + F1 查找当前文件或标识
-
Ctrl+B / Ctrl+Click 跳转到声明
-
Ctrl + Alt + B 跳转到实现
-
Ctrl + Shift + I 查看快速定义
-
Ctrl + Shift + B 跳转到类型声明
-
Ctrl + U 跳转到父方法、父类
-
Alt + Up/Down 跳转到上一个、下一个方法
-
Ctrl + ]/[ 跳转到代码块结束、开始
-
Ctrl + F12 弹出文件结构
-
Ctrl + H 类型层次结构
-
Ctrl + Shift + H 方法层次结构
-
Ctrl + Alt + H 调用层次结构
-
F2 / Shift + F2 下一条、前一条高亮的错误
-
F4 / Ctrl + Enter 编辑资源、查看资源
-
Alt + Home显示导航条F11 书签开关
-
Ctrl + Shift + F11 书签助记开关
-
Ctrl + #[0-9] 跳转到标识的书签
-
Shift + F11 显示书签
-
6、搜索相关(Usage Search)
-
Alt + F7/Ctrl + F7 文件中查询用法
-
Ctrl + Shift + F7 文件中用法高亮显示
-
Ctrl + Alt + F7 显示用法
-
7、重构(Refactoring)
-
Alt + Delete 安全删除
-
Shift + F6 重命名文件
-
Ctrl + F6 更改签名
-
Ctrl + Alt + N 内联
-
Ctrl + Alt + M 提取方法
-
Ctrl + Alt + V 提取属性
-
Ctrl + Alt + F 提取字段
-
Ctrl + Alt + C 提取常量
-
Ctrl + Alt + P 提取参数
-
8、控制VCS/Local History
-
Ctrl + K 提交项目
-
Ctrl + T 更新项目
-
Alt + Shift + C 查看最近的变化
-
Alt + BackQuote(’) VCS快速弹出
-
9、模版(Live Templates)
-
Ctrl + Alt + J 当前行使用模版
-
Ctrl + J 插入模版
-
10、基本(General)
-
Alt + #[0-9] 打开相应的工具窗口
-
Ctrl + Alt + Y 同步
-
Ctrl + Shift + F12 最大化编辑开关
-
Alt + Shift + F 添加到最喜欢
-
Alt + Shift + I 根据配置检查当前文件
-
Ctrl + BackQuote(’) 快速切换当前计划
-
Ctrl + Alt + S 打开设置页
-
Ctrl + Shift + A 查找编辑器里所有的动作
-
Ctrl + Tab 在窗口间进行切换
help (torch.reshape)
Example:
>>> a = torch.arange(4.)
>>> torch.reshape(a, (2, 2))
tensor([[ 0., 1.],
[ 2., 3.]])
>>> b = torch.tensor([[0, 1], [2, 3]])
>>> torch.reshape(b, (-1,))#~=nn.Flatten()
tensor([ 0, 1, 2, 3])
>>> b.getitem()
[ 0, 1, 2, 3]