目录

数据集

从零实现

简单实现


数据集

导入所需库

torchvision计算机视觉所用torch的库

%matplotlib inline
import torch
import torchvision
from torch.utils import data
from torchvision import transforms
from d2l import torch as d2l
# 用SVG清晰度高
d2l.use_svg_display()

使用ToTensor()实例将图像数据从PIL类型转化成32位浮点数格式 并除以255使得所有像素的数值位于0到1之间

trans=transforms.ToTensor()
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)
len(mnist_train),len(mnist_test)
def get_fashion_mnist_labels(labels):  #@save"""返回Fashion-MNIST数据集的文本标签"""text_labels = ['t-shirt', '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, titles=None, scale=1.5):  #@save"""绘制图像列表"""figsize = (num_cols * scale, num_rows * scale)_, axes = d2l.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.axes.get_xaxis().set_visible(False)ax.axes.get_yaxis().set_visible(False)if titles:ax.set_title(titles[i])return axes
X,y=next(iter(data.DataLoader(mnist_train,batch_size=18)))
show_images(X.reshape(18,28,28),2,9,titles=get_fashion_mnist_labels(y))

加载数据集

batch_size = 256def get_dataloader_workers():  #@save"""使用4个进程来读取数据"""return 4train_iter = data.DataLoader(mnist_train, batch_size, shuffle=True,num_workers=get_dataloader_workers())

判断读入数据所需时间

timer = d2l.Timer()
for X, y in train_iter:continue
f'{timer.stop():.2f} sec'

封装所有读取方法

def load_data_fashion_mnist(batch_size, resize=None):  #@save"""下载Fashion-MNIST数据集,然后将其加载到内存中"""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_workers()),data.DataLoader(mnist_test, batch_size, shuffle=False,num_workers=get_dataloader_workers()))
train_iter, test_iter = load_data_fashion_mnist(32, resize=64)
for X, y in train_iter:print(X.shape, X.dtype, y.shape, y.dtype)break

从零实现

导入库并加载数据集

%matplotlib inline
import torch
import torchvision
from torch.utils import data
from torchvision import transforms
from d2l import torch as d2l
# 用SVG清晰度高
d2l.use_svg_display()
from IPython import display
def get_dataloader_workers():  #@save"""使用4个进程来读取数据"""return 4
def load_data_fashion_mnist(batch_size, resize=None):  #@save"""下载Fashion-MNIST数据集,然后将其加载到内存中"""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_workers()),data.DataLoader(mnist_test, batch_size, shuffle=False,num_workers=get_dataloader_workers()))
train_iter, test_iter = load_data_fashion_mnist(256)
for X, y in train_iter:print(X.shape, X.dtype, y.shape, y.dtype)break

因为我们的数据集有10个类别,所以网络输出维度为10。 因此,权重将构成一个的784x10的矩阵, 偏置将构成一个1x10的行向量。 与线性回归一样,我们将使用正态分布初始化我们的权重W,偏置初始化为0。

num_inputs = 784
num_outputs = 10W = torch.normal(0, 0.01, size=(num_inputs, num_outputs), requires_grad=True)
b = torch.zeros(num_outputs, requires_grad=True)

Softmax

对每个项求幂(使用exp);

对每一行求和(小批量中每个样本是一行),得到每个样本的规范化常数;

将每一行除以其规范化常数,确保结果的和为1。

def softmax(X):X_exp = torch.exp(X)partition = X_exp.sum(1, keepdim=True)return X_exp / partition  # 这里应用了广播机制

定义softmax操作后,我们可以实现softmax回归模型。 下面的代码定义了输入如何通过网络映射到输出。 注意,将数据传递到模型之前,我们使用reshape函数将每张原始图像展平为向量。

def net(X):return softmax(torch.matmul(X.reshape((-1, W.shape[0])), W) + b)

回顾一下,交叉熵采用真实标签的预测概率的负对数似然。 这里我们不使用Python的for循环迭代预测(这往往是低效的), 而是通过一个运算符选择所有元素。 下面,我们创建一个数据样本y_hat,其中包含2个样本在3个类别的预测概率, 以及它们对应的标签y。 有了y,我们知道在第一个样本中,第一类是正确的预测; 而在第二个样本中,第三类是正确的预测。 然后使用y作为y_hat中概率的索引, 我们选择第一个样本中第一个类的概率和第二个样本中第三个类的概率。

高级索引的一种方式

y = torch.tensor([0, 2])
y_hat = torch.tensor([[0.1, 0.3, 0.6], [0.3, 0.2, 0.5]])
y_hat[[0, 1], y]

返回对应预测的概率,交叉熵

def cross_entropy(y_hat, y):return - torch.log(y_hat[range(len(y_hat)), y])cross_entropy(y_hat, y)

首先,如果y_hat是矩阵,那么假定第二个维度存储每个类的预测分数。 我们使用argmax获得每行中最大元素的索引来获得预测类别。 然后我们将预测类别与真实y元素进行比较。 由于等式运算符“==”对数据类型很敏感, 因此我们将y_hat的数据类型转换为与y的数据类型一致。 结果是一个包含0(错)和1(对)的张量。 最后,我们求和会得到正确预测的数量。

def accuracy(y_hat, y):  #@save"""计算预测正确的数量"""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) == yreturn float(cmp.type(y.dtype).sum())

可以看到,第一个样本的预测类别是2(该行的最大元素为0.6,索引为2),这与实际标签0不一致。 第二个样本的预测类别是2(该行的最大元素为0.5,索引为2),这与实际标签2一致。 因此,这两个样本的分类精度率为0.5。

accuracy(y_hat, y) / len(y)

同样,对于任意数据迭代器data_iter可访问的数据集, 我们可以评估在任意模型net的精度。

def evaluate_accuracy(net, data_iter):  #@save"""计算在指定数据集上模型的精度"""if isinstance(net, torch.nn.Module):net.eval()  # 将模型设置为评估模式metric = Accumulator(2)  # 正确预测数、预测总数with torch.no_grad():for X, y in data_iter:metric.add(accuracy(net(X), y), y.numel())return metric[0] / metric[1]

这里定义一个实用程序类Accumulator,用于对多个变量进行累加。 在上面的evaluate_accuracy函数中, 我们在Accumulator实例中创建了2个变量, 分别用于存储正确预测的数量和预测的总数量。 当我们遍历数据集时,两者都将随着时间的推移而累加。

class Accumulator:  #@save"""在n个变量上累加"""def __init__(self, n):self.data = [0.0] * ndef add(self, *args):self.data = [a + float(b) for a, b in zip(self.data, args)]def reset(self):self.data = [0.0] * len(self.data)def __getitem__(self, idx):return self.data[idx]
evaluate_accuracy(net, test_iter)

这里所输出的概率在10%左右,因为我们进行的是10分类任务,

在这里,我们重构训练过程的实现以使其可重复使用。 首先,我们定义一个函数来训练一个迭代周期。 请注意,updater是更新模型参数的常用函数,它接受批量大小作为参数。 它可以是d2l.sgd函数,也可以是框架的内置优化函数。

def train_epoch_ch3(net, train_iter, loss, updater):  #@save"""训练模型一个迭代周期(定义见第3章)"""# 将模型设置为训练模式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):# 使用PyTorch内置的优化器和损失函数updater.zero_grad()l.mean().backward()updater.step()else:# 使用定制的优化器和损失函数l.sum().backward()updater(X.shape[0])metric.add(float(l.sum()), accuracy(y_hat, y), y.numel())# 返回训练损失和训练精度return metric[0] / metric[2], metric[1] / metric[2]

在展示训练函数的实现之前,我们定义一个在动画中绘制数据的实用程序类Animator

class Animator:  #@save"""在动画中绘制数据"""def __init__(self, xlabel=None, ylabel=None, legend=None, xlim=None,ylim=None, xscale='linear', yscale='linear',fmts=('-', 'm--', 'g-.', 'r:'), nrows=1, ncols=1,figsize=(3.5, 2.5)):# 增量地绘制多条线if legend is None:legend = []d2l.use_svg_display()self.fig, self.axes = d2l.plt.subplots(nrows, ncols, figsize=figsize)if nrows * ncols == 1:self.axes = [self.axes, ]# 使用lambda函数捕获参数self.config_axes = lambda: d2l.set_axes(self.axes[0], xlabel, ylabel, xlim, ylim, xscale, yscale, legend)self.X, self.Y, self.fmts = None, None, fmtsdef add(self, x, y):# 向图表中添加多个数据点if not hasattr(y, "__len__"):y = [y]n = len(y)if not hasattr(x, "__len__"):x = [x] * nif not self.X:self.X = [[] for _ in range(n)]if not self.Y:self.Y = [[] for _ in range(n)]for i, (a, b) in enumerate(zip(x, y)):if a is not None and b is not None:self.X[i].append(a)self.Y[i].append(b)self.axes[0].cla()for x, y, fmt in zip(self.X, self.Y, self.fmts):self.axes[0].plot(x, y, fmt)self.config_axes()display.display(self.fig)display.clear_output(wait=True)

接下来我们实现一个训练函数, 它会在train_iter访问到的训练数据集上训练一个模型net。 该训练函数将会运行多个迭代周期(由num_epochs指定)。 在每个迭代周期结束时,利用test_iter访问到的测试数据集对模型进行评估。 我们将利用Animator类来可视化训练进度。

def train_ch3(net, train_iter, test_iter, loss, num_epochs, updater):  #@save"""训练模型(定义见第3章)"""animator = Animator(xlabel='epoch', xlim=[1, num_epochs], ylim=[0.3, 0.9],legend=['train loss', 'train acc', 'test acc'])for epoch in range(num_epochs):train_metrics = train_epoch_ch3(net, train_iter, loss, updater)test_acc = evaluate_accuracy(net, test_iter)animator.add(epoch + 1, train_metrics + (test_acc,))train_loss, train_acc = train_metricsassert train_loss < 0.5, train_lossassert train_acc <= 1 and train_acc > 0.7, train_accassert test_acc <= 1 and test_acc > 0.7, test_acc

作为一个从零开始的实现,我们使用 3.2节中定义的 小批量随机梯度下降来优化模型的损失函数,设置学习率为0.1。

lr = 0.1def updater(batch_size):return d2l.sgd([W, b], lr, batch_size)

模型训练

num_epochs = 10
train_ch3(net, train_iter, test_iter, cross_entropy, num_epochs, updater)

现在训练已经完成,我们的模型已经准备好对图像进行分类预测。 给定一系列图像,我们将比较它们的实际标签(文本输出的第一行)和模型预测(文本输出的第二行)。

def predict_ch3(net, test_iter, n=6):  #@save"""预测标签(定义见第3章)"""for X, y in test_iter:breaktrues = d2l.get_fashion_mnist_labels(y)preds = d2l.get_fashion_mnist_labels(net(X).argmax(axis=1))titles = [true +'\n' + pred for true, pred in zip(trues, preds)]d2l.show_images(X[0:n].reshape((n, 28, 28)), 1, n, titles=titles[0:n])predict_ch3(net, test_iter)

简单实现

导入数据集

%matplotlib inline
import torch
import torchvision
from torch.utils import data
from torch import nn
from torchvision import transforms
from d2l import torch as d2l
# 用SVG清晰度高
d2l.use_svg_display()
from IPython import display
def get_dataloader_workers():  #@save"""使用4个进程来读取数据"""return 4
def load_data_fashion_mnist(batch_size, resize=None):  #@save"""下载Fashion-MNIST数据集,然后将其加载到内存中"""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_workers()),data.DataLoader(mnist_test, batch_size, shuffle=False,num_workers=get_dataloader_workers()))
train_iter, test_iter = load_data_fashion_mnist(256)

softmax回归的输出层是一个全连接层。 因此,为了实现我们的模型, 我们只需在Sequential中添加一个带有10个输出的全连接层。 同样,在这里Sequential并不是必要的, 但它是实现深度模型的基础。 我们仍然以均值0和标准差0.01随机初始化权重。

# 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()

定义优化算法

trainer = torch.optim.SGD(net.parameters(), lr=0.1)

模型训练

num_epochs = 10
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, trainer)

Pytorch SoftMax回归相关推荐

  1. 小白也能看懂的pytorch——softmax回归

    前言:本篇文章的服务对象是没有武力值也想和pytorch沾沾边的小白朋友们,主要的内容是对于经典代码的逐行解读,解读内容以注释的形式展示. 本篇文章的代码来源为(李沐 动手学深度学习pytorch版) ...

  2. 【深度学习】基于Pytorch的softmax回归问题辨析和应用(一)

    [深度学习]基于Pytorch的softmax回归问题辨析和应用(一) 文章目录 1 概述 2 网络结构 3 softmax运算 4 仿射变换 5 对数似然 6 图像分类数据集 7 数据预处理 8 总 ...

  3. 【深度学习】基于Pytorch的softmax回归问题辨析和应用(二)

    [深度学习]基于Pytorch的softmax回归问题辨析和应用(二) 文章目录1 softmax回归的实现1.1 初始化模型参数1.2 Softmax的实现1.3 优化器1.4 训练 2 多分类问题 ...

  4. [pytorch、学习] - 3.7 softmax回归的简洁实现

    参考 3.7. softmax回归的简洁实现 使用pytorch实现softmax import torch from torch import nn from torch.nn import ini ...

  5. pytorch学习笔记(九):softmax回归的简洁实现

    文章目录 1. 获取和读取数据 2. 定义和初始化模型 3. softmax和交叉熵损失函数 4. 定义优化算法 5. 训练模型 6. 总代码 7.小结 使用Pytorch实现一个softmax回归模 ...

  6. pytorch学习笔记(八):softmax回归的从零开始实现

    文章目录 1. 获取和读取数据 2. 初始化模型参数 3. 实现softmax运算 4. 定义模型 5. 定义损失函数 6. 计算分类准确率 7. 训练模型 8. 预测 9. 总代码 小结 这一节我们 ...

  7. 【深度学习】基于MindSpore和pytorch的Softmax回归及前馈神经网络

    1 实验内容简介 1.1 实验目的 (1)熟练掌握tensor相关各种操作: (2)掌握广义线性回归模型(logistic模型.sofmax模型).前馈神经网络模型的原理: (3)熟练掌握基于mind ...

  8. Pytorch总结三之 softmax回归用于分类问题

    Pytorch总结三之 softmax回归用于分类问题 上篇博文Pytorch总结二之线性回归算法原理与实现介绍的线性回归模型适⽤于输出为连续值的情景. 在另⼀类情景中,模型输出可以是⼀个像图像类别这 ...

  9. 【深度学习】:《PyTorch入门到项目实战》第五天:从0到1实现Softmax回归(含源码)

    [深度学习]:<PyTorch入门到项目实战>第五天:从0到1实现Softmax回归 ✨本文收录于[深度学习]:<PyTorch入门到项目实战>专栏,此专栏主要记录如何使用Py ...

最新文章

  1. bert速度提升fastbert
  2. C++brent method布伦特方法找extrema极值的算法(附完整源码)
  3. 整合Struts2、Spring、Hibernate构建J2EE应用
  4. 网上看的几点人生建议
  5. onhashchange
  6. 大学计算机基础python第二次作业_第二次python作业-titanic数据练习
  7. SQL中自增(AUTO_INCREMENT)字段介绍
  8. Civil3D二次开发常见问题总结
  9. SLAM_SLAM中一般是如何求解相机的运动的?
  10. colab 数据集_Google Colab上的YOLOv4:轻松训练您的自定义数据集(交通标志)
  11. Linux三剑客之awk精讲
  12. linux压缩到最小命令,Linux 压缩打包命令详细教程
  13. c语言round函数作用,if条件函数怎样和round一起用?!,C++中round函数怎么用
  14. debian怎么安装oracle数据库,Debian上安装Oracle客户端
  15. LeetCode(力扣)_接雨水
  16. linux下4g拨号上网问题,解决 Ubuntu 18.04 下无法建立 4G 拨号的问题
  17. 逍遥模拟器的安装和使用
  18. FleaPHP 开发指南 - 6. 访问数据库
  19. 基于STM32C8T6的智能蓝牙小车(毕业设计)
  20. js --- 转数值类型

热门文章

  1. 系统调用(Linux)
  2. 安装r 源代码 linux,在RStudio中从源代码安装R软件包时遇到问题-Ubuntu 16.04
  3. vue3.0抢先看(附尤雨溪vue分享ppt)
  4. unity 2d角色移动卡住的原因
  5. LTE----013 UE开机后的第一件事: PLMN选择
  6. TabIndex 属性 Tabindex=-1 与Tabindex=0、任意数字
  7. apicloud 预览图片_APICloud(三):预览图片
  8. 视觉slam14讲学习(一)之se3上的定位表示:轨迹显示与轨迹误差
  9. 基本数据类型引用数据类型
  10. Kafka(生产者)