torchvision包含一些常用的数据集、模型、转换函数等等。当前版本0.5.0包括图片分类、语义切分、目标识别、实例分割、关键点检测、视频分类等工具,它将mask-rcnn功能也都包含在内了。mask-rcnn的Pytorch版本最高支持torchvision 0.2.*,0.3.0之后mask-rcnn就包含到tensorvision之中了。
torchvision是独立于pytorch的关于图像操作的一些方便工具库。torchvision库简介(翻译) - 看看完了 - 博客园 (cnblogs.com)
torchvision主要包括一下几个包:
- vision.datasets : 几个常用视觉数据集,可以下载和加载,这里主要的高级用法就是可以看源码如何自己写自己的Dataset的子类
- vision.models : 流行的模型,例如 AlexNet, VGG, ResNet 和 Densenet 以及 与训练好的参数。
- vision.transforms : 常用的图像操作,例如:随机切割,旋转,数据类型转换,图像到tensor ,numpy 数组到tensor , tensor 到 图像等。
- vision.utils : 用于把形似 (3 x H x W) 的张量保存到硬盘中,给一个mini-batch的图像可以产生一个图像格网。
# ================================================================== #
# Input pipeline for custom dataset #
# ================================================================== #
# You should build your custom dataset as below.
class CustomDataset(torch.utils.data.Dataset):
def __init__(self):
# TODO
# 1. Initialize file paths or a list of file names.
pass
def __getitem__(self, index):
# TODO
# 1. Read one data from file (e.g. using numpy.fromfile, PIL.Image.open).
# 2. Preprocess the data (e.g. torchvision.Transform).
# 3. Return a data pair (e.g. image and label).
pass
def __len__(self):
# You should change 0 to the total size of your dataset.
return 0
# You can then use the prebuilt data loader.
custom_dataset = CustomDataset()
train_loader = torch.utils.data.DataLoader(dataset=custom_dataset,
batch_size=64,
shuffle=True)
(5条消息) PyTorch深度学习初步——如何读取你自己的数据集_白羊是小白-CSDN博客_pytorch读取自己的数据集
import time
import torch
import torchvision
from matplotlib import pyplot as plt
from torch.utils import data
from torchvision import transforms
def get_dataloader_worders():
return 0
#MNIST数据集是图像分类中广泛使用的数据集之一,但是作为基准数据集过于简单,这里使用Fashion-MNIST数据集
#使用框架的内置API将数据集读取到内存中
def load_data_fashion_mnist(batch_size, resize=None):
"""
:param batch_size: 批量大小
:param resize: 图片尺寸变换
:return: 批量数据
"""
"""下载Fashion-MNIST数据集,然后将其加载到内存中"""
# 通过ToTensor实例将图像数据集从PIL类型转换成32位浮点数格式
trans = [transforms.ToTensor()]
if resize:
trans.insert(0, transforms.Resize(resize))
trans = transforms.Compose(trans)
mnist_train = torchvision.datasets.FashionMNIST(root="./data", train=True, transform=trans, download=True)
mnist_test = torchvision.datasets.FashionMNIST(root="./data", train=False, transform=trans, download=True)
return (data.DataLoader(mnist_train, batch_size, shuffle=True, num_workers=get_dataloader_worders()),
data.DataLoader(mnist_test, batch_size, shuffle=True, num_workers=get_dataloader_worders()))
train_generator, test_generator = load_data_fashion_mnist(128)
print(type(train_generator))
#定义两个可视化函数
def get_fashion_mnist_labels(labels):
"""返回Fashion-MNIST数据集的文本标签"""
text_labels = [
't-shirts', 'trouser', 'pullover', 'dress', 'coat', 'sandal', 'shirt',
'sneaker', 'bag', 'ankle boot'
]
return [text_labels[int(i)] for i in labels]
def show_images(imgs, num_rows, num_cols, title=None, scale=2.5):
"""Plot a lsit of imgs"""
figsize = (num_cols * scale, num_rows * scale)
_, axes = plt.subplots(num_rows, num_cols, figsize=figsize)
axes = axes.flatten()
for i, (ax, img) in enumerate(zip(axes, imgs)):
if torch.is_tensor(img):
# 图片张量
ax.imshow(img.numpy())
else:
#PIL图片
ax.imshow(img)
ax.set_title(title[i])
plt.show()
#取出小批量的数据,显示对应的图片和标签
# x, y = next(iter(data.DataLoader(mnist_train, batch_size=18)))
#show_images(x.reshape(18, 28, 28), 2, 9, title=get_fashion_mnist_labels(y))
#读取小批量数据
batch_size = 100
#train_iter = data.DataLoader(mnist_train, batch_size, shuffle=True, num_workers=get_dataloader_worders())
start = time.time()
for x, y in train_generator:
continue
print('%.2f sec' % float(time.time() - start))
import torch
#根据编号取出预测值的方法
#创建一个数据y_hat 其中包含2个样本在三个类别上的预测概率,使用y作为y_hat中改了的索引
y = torch.tensor([0, 2]) #两个真实的标号
print(y)
y_hat = torch.tensor([[0.1, 0.3, 0.6], [0.3, 0.2, 0.5]])
#解释:对于 y_hat[0. y[0]], y_hat[1, y[1]]
print(y_hat[[0, 1], y])
enumerate函数:将一个可遍历的变量转换成 "下标+数值" 形式
Python enumerate() 函数 | 菜鸟教程 (runoob.com)
#图片展示
def show_images(imgs, num_rows, num_cols, title=None, scale=2.5):
"""Plot a lsit of imgs"""
figsize = (num_cols * scale, num_rows * scale)
_, axes = plt.subplots(num_rows, num_cols, figsize=figsize)
axes = axes.flatten() #将ax由n*m的Axes组展平成1*nm的Axes组,也就是说所有的编号就从 0.... nm-1,为了在for循环中索引方便
for i, (ax, img) in enumerate(zip(axes, imgs)):
if torch.is_tensor(img):
# 图片张量
ax.imshow(img.numpy())
else:
#PIL图片
ax.imshow(img)
ax.set_title(title[i])
plt.show()
# 小批量随机梯度优化模型的损失函数
def SGD(params, lr, batch_size): # SGD
"""SGD"""
with torch.no_grad(): # 更新的时候不参与梯度计算
for param in params:
param -= lr * param.grad / batch_size
param.grad.zero_()
def updater(batch_size):
"""小批量随机梯度下降"""
return SGD([w, b], lr, batch_size)
【损失函数】交叉熵损失函数简介 - 知乎 (zhihu.com)
#定义softmax操作 softmax(X) = exp(xi) / sum exp(xi...)
def softmax(x):
x_exp = torch.exp(x)
partition = x_exp.sum(1, keepdim=True)
return x_exp / partition #这里应用了广播机制
#实现交叉熵损失函数
def cross_entropy(y_hat, y):
return -torch.log(y_hat[range(len(y_hat)), y])
#实现softmax回归模型
def net(x):
return softmax(torch.matmul(x.reshape((-1, w.shape[0])), w) + b) #-1就表示根据后面的列数自动推出来行数
class Accumulator:
"""在n个变量上累加"""
def __init__(self, n):
self.data = [0.0] * n #将列表中记录数扩展为n个
def add(self, *args):
#zip(self.data, args):将self.data和args中对应位置的元素打包
self.data = [a + float(b) for a, b in zip(self.data, args)] #实现传进来的列表中元素分别按照编号累加的原列表(self.data)中
def reset(self):
self.data = [0.0] * len(self.data)
def __getitem__(self, idx):
return self.data[idx]
#将预测的类别和真实的y元素进行比较
def accuracy(y_hat, y):
"""计算预测正确的数量"""
if len(y_hat.shape) > 1 and y_hat.shape[1] > 1:
y_hat = y_hat.argmax(axis=1) #取出预测值最大的对应的下标
cmp = y_hat.type(y.dtype) == y #转换成和y同类型的,并比较y_hat和y中值得一致情况,其实就是生成二值向量
return float(cmp.type(y.dtype).sum())
#评估任意模型的准确率
def evaluate_accuracy(net, data_iter):
"""计算在指定数据集上模型的精度"""
if isinstance(net, torch.nn.Module):
net.eval() #将模型设置为评估模式
metric = Accumulator(2) #正确预测数、预测总数 Accumulator累加器
for x, y in data_iter:
metric.add(accuracy(net(x), y), y.numel()) #两个数,一个是预测正确的数,另一个是样本总数
return metric[0] / metric[1] #平均准确率
#训练模型
#训练一轮
def train_epoch(net, train_iter, loss, updater):
if isinstance(net, torch.nn.Module):
net.train()
metric = Accumulator(3)
for x,y in train_iter:
y_hat = net(x)
l = loss(y_hat, y)
if isinstance(updater, torch.optim.Optimizer):
updater.zero_grad()
l.backward()
updater.step() #参数自更新
metric.add(
float(l) * len(y), accuracy(y_hat, y),
y.size().numel()
)
else: #没用框架的话直接计算
l.sum().backward()
updater(x.shape[0])
metric.add(float(l.sum()), accuracy(y_hat, y), y.numel()) #所有的loss的总数、分类正确的样本数,总数
return metric[0] / metric[2], metric[1] / metric[2]
def train_all(net, train_iter, test_iter, loss, num_epochs, updater):
for epoch in range(num_epochs):
train_metrics = train_epoch(net, train_iter, loss, updater)
test_acc = evaluate_accuracy(net, test_iter)
print(f'epoch: {epoch+1}, loss: {train_metrics[0]}, train acc: {train_metrics[1]:.3f}, test acc: {test_acc:.3f}')
#对图像进行预测
def predict(net, test_iter, n = 6):
"""预测标签"""
for x, y in test_iter:
break
trues = get_fashion_mnist_labels(y)
preds = get_fashion_mnist_labels(net(x).argmax(axis=1))
titles = [true + '\n' + pred for true, pred in zip(trues, preds)]
show_images(x[0:n].reshape((n, 28, 28)), 1, n, title=titles[0:n])
import torch
from matplotlib import pyplot as plt
from torch import nn
from torch.utils import data
import torchvision
from torchvision import transforms
def get_dataloader_worders():
return 0
#MNIST数据集是图像分类中广泛使用的数据集之一,但是作为基准数据集过于简单,这里使用Fashion-MNIST数据集
#使用框架的内置API将数据集读取到内存中
def load_data_fashion_mnist(batch_size, resize=None):
"""
:param batch_size: 批量大小
:param resize: 图片尺寸变换
:return: 批量数据
"""
"""下载Fashion-MNIST数据集,然后将其加载到内存中"""
# 通过ToTensor实例将图像数据集从PIL类型转换成32位浮点数格式
trans = [transforms.ToTensor()]
if resize:
trans.insert(0, transforms.Resize(resize))
trans = transforms.Compose(trans)
mnist_train = torchvision.datasets.FashionMNIST(root="./data", train=True, transform=trans, download=True)
mnist_test = torchvision.datasets.FashionMNIST(root="./data", train=False, transform=trans, download=True)
return (data.DataLoader(mnist_train, batch_size, shuffle=True, num_workers=get_dataloader_worders()),
data.DataLoader(mnist_test, batch_size, shuffle=True, num_workers=get_dataloader_worders()))
batch_size = 256
train_iter, test_iter = load_data_fashion_mnist(batch_size)
#Softmax 回归的输出层是一个全连接层
#PyTorch不会隐式地调整输入的形状。因此定义展开层(flatten),在线性层之前调整网络输入的形状
net = nn.Sequential(
nn.Flatten(),
nn.Linear(784, 10)
)
def init_weights(m):
if type(m) == nn.Linear:
nn.init.normal_(m.weight, std=0.01)
net.apply(init_weights)
#在交叉熵损失函数中传递未归一化的预测,并同时计算softmax及其对数
loss = nn.CrossEntropyLoss()
#使用学习率为0.1的小批量随机梯度下降作为优化算法
trainer = torch.optim.SGD(net.parameters(), lr=0.1)