200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > (pytorch-深度学习系列)pytorch实现对Fashion-MNIST数据集进行图像分类

(pytorch-深度学习系列)pytorch实现对Fashion-MNIST数据集进行图像分类

时间:2021-09-27 04:30:11

相关推荐

(pytorch-深度学习系列)pytorch实现对Fashion-MNIST数据集进行图像分类

pytorch实现对Fashion-MNIST数据集进行图像分类

导入所需模块:

import torchimport torchvisionimport torchvision.transforms as transformsimport matplotlib.pyplot as pltimport timeimport sys

对数据集的操作(读取数据集):

由于像素值为0到255的整数,所以刚好是uint8所能表示的范围,包括transforms.ToTensor()在内的一些关于图片的函数就默认输入的是uint8型,若不是,可能不会报错但可能得不到想要的结果。所以,如果用像素值(0-255整数)表示图片数据,那么一律将其类型设置成uint8,避免不必要的bug

通过torchvision的torchvision.datasets来下载这个数据集。第一次调用时数据集目录不存在,会自动从网上获取数据。

mnist_train = torchvision.datasets.FashionMNIST(root='~/Datasets/FashionMNIST', train=True, download=True, transform=transforms.ToTensor())mnist_test = torchvision.datasets.FashionMNIST(root='~/Datasets/FashionMNIST', train=False, download=True, transform=transforms.ToTensor())

获取标签:

def get_fashion_mnist_labels(labels):text_labels = ['t-shirt', 'trouser', 'pullover', 'dress', 'coat','sandal', 'shirt', 'sneaker', 'bag', 'ankle boot']return [text_labels[int(i)] for i in labels]

定义画图函数:

def use_svg_display():# 用矢量图显示display.set_matplotlib_formats('svg')def set_figsize(figsize=(3.5, 2.5)):use_svg_display()# 设置图的尺寸plt.rcParams['figure.figsize'] = figsizedef show_fashion_mnist(images, labels):use_svg_display()# 这里的_表示我们忽略(不使用)的变量_, figs = plt.subplots(1, len(images), figsize=(12, 12))for f, img, lbl in zip(figs, images, labels):f.imshow(img.view((28, 28)).numpy())f.set_title(lbl)f.axes.get_xaxis().set_visible(False)f.axes.get_yaxis().set_visible(False)plt.show()

展示数据集中的前10个样本:

X, y = [], []for i in range(10):X.append(mnist_train[i][0])y.append(mnist_train[i][1])show_fashion_mnist(X, get_fashion_mnist_labels(y))

PyTorch的DataLoader允许使用多进程来加速数据读取

通过参数num_workers来设置4个进程读取数据:

batch_size = 256if sys.platform.startswith('win'):num_workers = 0 # 0表示不用额外的进程来加速读取数据else:num_workers = 4train_iter = torch.utils.data.DataLoader(mnist_train, batch_size=batch_size, shuffle=True, num_workers=num_workers)test_iter = torch.utils.data.DataLoader(mnist_test, batch_size=batch_size, shuffle=False, num_workers=num_workers)

初始化模型参数:

num_inputs = 784 # 784个样本num_outputs = 10 # 分为10类W = torch.tensor(np.random.normal(0, 0.01, (num_inputs, num_outputs)), dtype=torch.float)b = torch.zeros(num_outputs, dtype=torch.float)# 模型参数梯度回调W.requires_grad_(requires_grad=True)b.requires_grad_(requires_grad=True)

定义softmax运算:

softmax运算会先通过exp函数对每个元素做指数运算,再对exp矩阵同行元素求和,最后令矩阵每行各元素与该行元素之和相除。这样一来,最终得到的矩阵每行元素和为1且非负。因此,该矩阵每行都是合法的概率分布。softmax运算的输出矩阵中的任意一行元素代表了一个样本在各个输出类别上的预测概率。

def softmax(X):#对于随机输入,每个元素变成了非负数,且每一行和为1X_exp = X.exp()partition = X_exp.sum(dim=1, keepdim=True) # 按行求和return X_exp / partition # 这里应用了广播机制,会自动对partition进行扩展到与X_exp尺度相同

定义模型:

def net(X): # 定义模型return softmax(torch.mm(X.view((-1, num_inputs)), W) + b)def cross_entropy(y_hat, y): # 交叉熵损失函数return - torch.log(y_hat.gather(1, y.view(-1, 1)))def accuracy(y_hat, y): # 定义准确率计算return (y_hat.argmax(dim=1) == y).float().mean().item()

这里讲一下为什么使用softmax可以将输出定在(0-9)这样的离散类别中

因为,模型中使用到的线性规划层:输出=输入*w+b

其中w是一个(输入,输出)维度的张量,b是一个(输出)维度的向量

根据矩阵运算,输入*w+b的结果就是一个向量,该向量列数为输出(也就是类别数),而softmax做的,就是将该向量的元素进行归一化处理,使得其变为概率向量,这样,该模型的输出就可以代表样本为某一类别的概率,其和为1.

训练模型:

num_epochs, lr = 5, 0.1def sgd(params, lr, batch_size): # 随机梯度下降算法for param in params:param.data -= lr * param.grad / batch_size # 注意这里更改param时用的param.datadef evaluate_accuracy(data_iter, net):acc_sum, n = 0.0, 0for X, y in data_iter:acc_sum += (net(X).argmax(dim=1) == y).float().sum().item()n += y.shape[0]return acc_sum / ndef train_ch3(net, train_iter, test_iter, loss, num_epochs, batch_size,params=None, lr=None, optimizer=None):for epoch in range(num_epochs):train_l_sum, train_acc_sum, n = 0.0, 0.0, 0for X, y in train_iter:y_hat = net(X)l = loss(y_hat, y).sum()# 梯度清零if optimizer is not None:optimizer.zero_grad() # 这里我们没有用到优化器,所以直接对参数进行梯度清零elif params is not None and params[0].grad is not None:for param in params:param.grad.data.zero_()l.backward()if optimizer is None:sgd(params, lr, batch_size)else:optimizer.step() # 简洁实现将用到优化器这里train_l_sum += l.item()train_acc_sum += (y_hat.argmax(dim=1) == y).sum().item()n += y.shape[0] test_acc = evaluate_accuracy(test_iter, net)print('epoch %d, loss %.4f, train acc %.3f, test acc %.3f'% (epoch + 1, train_l_sum / n, train_acc_sum / n, test_acc))train_ch3(net, train_iter, test_iter, cross_entropy, num_epochs, batch_size, [W, b], lr)

注意,这里的每一个train_iter是以batch_size个样本为实例的,所以每一个train_iter包含多个(tensor, type)组合。

训练完毕进行预测:

X, y = iter(test_iter).next()true_labels = get_fashion_mnist_labels(y.numpy())pred_labels = get_fashion_mnist_labels(net(X).argmax(dim=1).numpy())titles = [true + '\n' + pred for true, pred in zip(true_labels, pred_labels)]show_fashion_mnist(X[0:9], titles[0:9])

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。