文章目录
1.数据载入之Dataset和DataLoader
1.1Dataset类
dataset类
所谓数据集,无非就是一组{x:y}的集合吗,你只需要在这个类里说明“有一组{x:y}的集合”就可以了。
对于图像分类任务,图像+分类
对于目标检测任务,图像+bbox、分类
对于超分辨率任务,低分辨率图像+超分辨率图像
对于文本分类任务,文本+分类
建立一个Dataset的子类MyDataSet,必须要重写__len__()和__getitem__()
1.__len__函数:使得类对象拥有 "len(object)"功能,返回dataset的size。
2.__getitem__函数:使得类对象拥有"object[index]"功能,可以用索引i去获得第i+1个样本
分两步:首先将数据包装为Dataset类,然后传入DataLoader
# 首先将数据包装为Dataset类
class MyDataSet(Dataset):
def __init__(self):
self.sample_list = ...
def __getitem__(self, index):
x= ...
y= ...
return x, y
def __len__(self):
return len(self.sample_list)
# 然后传入DataLoader
DataLoader(MyDataSet, batch_size=1, shuffle=False, sampler=None,
batch_sampler=None, num_workers=0, collate_fn=None,
pin_memory=False, drop_last=False, timeout=0,
worker_init_fn=None)
1.2ImageFolder类
from torchvision import transforms
from torchvision.datasets import ImageFolder
from torch.utils.data import DataLoader
data_path = r'./images'
# 将图像RGB三个通道的像素值分别减去0.5再除以0.5,从而将所有像素值
# 固定到[-1.0, 1.0]范围内
data_transforms = transforms.Compose([
#裁剪为256*256
transforms.Resize((256,256)),
#随机垂直翻转
transforms.RandomVerticalFlip(),
#将0-255范围的像素转为0-1.0范围的tensor
transforms.ToTensor(),
transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])
])
train_dataset = ImageFolder(data_path,transform=data_transforms)
print('训练集大小:',len(train_dataset)) # 训练集大小(图像数量) out: 1067
print('训练集第一张图像张量以及对应的标签,二维元组:',train_dataset[0]) # 训练集第一张图像张量以及对应的标签,二维元组
print('训练集第一张图像的张量:',train_dataset[0][0]) # 训练集第一张图像的张量
print('训练集第一张图像的标签:',train_dataset[0][0]) # 训练集第一张图像的标签
train_folder = DataLoader(train_dataset,batch_size=4,shuffle=True)
print(len(train_folder))
epochs = 2
for epoch in range(epochs):
for i,(inputs,labels) in enumerate(train_folder):
print(epoch,' ',i,'inputs:',inputs.data.size(),'labels:',labels.data.size())
参考:pytorch ImageFolder和Dataloader加载自制图像数据集
参考:Pytorch(五)入门:DataLoader 和 Dataset
2.模型保存与载入
方法一:保存网络的参数
#导入模块
import torch
##创建网络,当然还需要损失函数梯度等省略
net=Net()
#保存:可以是pth文件或者pt文件
torch.save(net.state_dict(),'state_dict_model.pth')
#我们想要在另外的一个python文件中读取我们之前已经保存好的模型,我们需要先创建一个和之前模型一样的空模型来接收。
from old_py import Net
#载入保存的模型参数
model=Net()
model.load_state_dict(torch.load(PATH))
#显示model.state_dict()中包含了那些内容
print("Model's state_dict:")
for param_tensor in model.state_dict():
print(param_tensor, "\t", model.state_dict()[param_tensor].size())
#不启用 BatchNormalization 和 Dropout
model.eval()
方法二:保存整个网络
import torch
net=Net()
# Save
torch.save(net, "entire_model.pt")
# Load
model = torch.load("entire_model.pt")
model.eval()
基于两种方法的区别,方法一:保存模型的参数,而不保存模型的框架,在读取模型参数前要先定义一个模型(模型必须与原模型相同的构造),也就是上面的先实例化网络模型,再导入参数。方法二:保存模型的结构与参数,读取时,直接加载模型。一般用的都是第一种。
3.指定GPU
1.终端指定
CUDA_VISIBLE_DEVICES=0 python xxx.py
2.代码中指定
import os
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
3.程序中指定
# 指定GPU0
device = torch.device('cuda:0')
# 把数据移到cuda上
train_data = train_data.to(device)
label_data = label_data.to(device)
model.to(device)
# 训练完成后,输出数据移动到cpu上,返回的是tensor
predict_data = predict_data.cpu()
# 还可以转换成numpy类型
# predict_data = predict_data.cpu().numpy()
4.配上If操作
if torch.cuda.is_available():
train_data = train_data.to(device)
label_data = label_data.to(device)
model.to(device)
4.torchvision.models
torchvision.models
torchvision.models 中为我们提供了已经训练好的模型,让我们可以加载之后,直接使用。
torchvision.models模块的 子模块中包含以下模型结构。
AlexNet
VGG
ResNet
SqueezeNet
DenseNet
我们可以直接使用如下代码来快速创建一个权重随机初始化的模型
import torchvision.models as models
resnet18 = models.resnet18()
alexnet = models.alexnet()
squeezenet = models.squeezenet1_0()
densenet = models.densenet_161()
也可以通过使用 pretrained=True 来加载一个别人预训练好的模型
import torchvision.models as models
resnet18 = models.resnet18(pretrained=True)
alexnet = models.alexnet(pretrained=True)
import torchvision.models as models
# 加载一个 resnet18 模型
resnet18 = models.resnet18()
print(resnet18)
import torchvision.models as models
resnet18 = models.resnet18(pretrained=True) # 加载一个已经预训练好的模型, 需要下载一段时间...
5.tochvision.transforms
transforms提供了一般图像操作的类
transforms.Normalize(mean,std)
如果需要同时使用几个transforms,就用transforms.Compose()
# 我们这里还是对MNIST进行处理,初始的MNIST是 28 * 28,我们把它处理成 96 * 96 的torch.Tensor的格式
from torchvision import transforms as transforms
import torchvision
from torch.utils.data import DataLoader
# 图像预处理步骤
transform = transforms.Compose([
transforms.Resize(96), # 缩放到 96 * 96 大小
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) # 归一化
])
DOWNLOAD = True
BATCH_SIZE = 32
train_dataset = torchvision.datasets.MNIST(root='./data/', train=True, transform=transform, download=DOWNLOAD)
train_loader = DataLoader(dataset=train_dataset,
batch_size=BATCH_SIZE,
shuffle=True)
print(len(train_dataset))
print(len(train_loader))