热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

快速入门torch.nn(一)

本文翻译自:https:pytorch.orgtutorialsbeginnernn_tutorial.html这是第一部分:如何用纯Python构造一个神经网络。Pytorch提

本文翻译自:https://pytorch.org/tutorials/beginner/nn_tutorial.html 这是第一部分:如何用纯Python构造一个神经网络。

Pytorch提供了几个设计得非常棒的模块和类,比如 torch.nn,torch.optim,Dataset 以及 DataLoader,来帮助你设计和训练神经网络。为了充分利用他们来解决你的问题,你需要明白他们具体是做什么的。为了帮助大家理解这些内容,我们首先基于MNIST数据集,不用以上提到的模块和类来训练一个基础的神经网络,只用到基本的PyTorch tensor 函数。然后我们会逐渐地使用来自torch.nn,torch.optim,Dataset 以及 DataLoader的功能。展示每个模块具体的功能,他的运作过程。这样来使得代码逐渐简洁和灵活。

MNIST数据集

我们使用经典的MNIST数据集。这个数据集由手写数字0~9的黑白照片组成。

我们使用pathlib包来解决文件路径问题(这是python3的一个标准包),我们使用requests函数来下载数据。我们只导入我们需要用到的模块,所以你可以清晰地看到每一步具体用了什么。

from pathlib import Path
import requests
DATA_PATH = Path("data")
PATH = DATA_PATH / "mnist"
PATH.mkdir(parents=True, exist_ok=True)
URL = "http://deeplearning.net/data/mnist/"
FILENAME = "mnist.pkl.gz"
if not (PATH / FILENAME).exists():
content = requests.get(URL + FILENAME).content
(PATH / FILENAME).open("wb").write(content)

数据现在是numpy array格式,用pickle存储起来了。这是Python特有的串行数据格式。

import pickle
import gzip
with gzip.open((PATH / FILENAME).as_posix(), "rb") as f:
((x_train, y_train), (x_valid, y_valid), _) = pickle.load(f, encoding="latin-1")

每一张照片都是 28*28大小的一个数组,但是被存成了一个长度为784(28*28)的一行。现在给大家展示其中一张图片,首先我们要把它重新组织成28*28的一个二维形状。

from matplotlib import pyplot
import numpy as np
pyplot.imshow(x_train[0].reshape((28, 28)), cmap="gray")
print(x_train.shape)

输出:

《快速入门torch.nn(一)》
《快速入门torch.nn(一)》

(50000, 784)

Pytorch使用 torch.tensor,而不是 numpy arrays。所以我们首先需要转换我们的数据。

import torch
x_train, y_train, x_valid, y_valid = map(
torch.tensor, (x_train, y_train, x_valid, y_valid)
)
n, c = x_train.shape
print(x_train, y_train)
print(x_train.shape)
print(y_train.min(), y_train.max())

输出:

tensor([[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
...,
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.]]) tensor([5, 0, 4, ..., 8, 4, 8])
torch.Size([50000, 784])
tensor(0) tensor(9)

利用scratch(不是 torch.nn)构建神经网络

让我们首先只用PyTorch tensor的基本操作来构造我们的神经网络。首先假设你已经有一定的神经网络知识基础。如果没有,可以在 course.fast.ai 里面学习。(译者:或者可以通过《神经网络设计》这本书学习,这本书深入浅出,从基本的神经元讲起,很适合初学者)

PyTorch提供了一些创建随机或者零张量(tensor)的方法。我们可以利用他们去构建线性模型(linear model)所用到的权值(weights)和偏移(bias)。这些都是常规的张量,除了一个方面,他们需要一个梯度(gradient)。这样会使得PyTorch会记录所有对这个张量所进行的操作,所以这样可以自动计算关于这些权值和偏移的梯度。(关于pytorch gradient这个问题具体可以看https://www.jianshu.com/p/cbce2dd60120 我也会马上写一篇关于介绍这个的文章)

对于权值张量,我们在初始化它的时候设置 requires_grad

import math
weights = torch.randn(784, 10) / math.sqrt(784)
weights.requires_grad_()
bias = torch.zeros(10, requires_grad=True)

多亏了PyTorch自动计算梯度的这个功能,所以我们可以用任何标准的PyTorch函数。所以让我们来构建一个包含矩阵乘法和张量加法的简单线性模型。我们还需要一个激活函数(activation function)。所以我们写一个 log_softmax 函数。记住:虽然PyTorch提供了大量写好的损失函数(loss function)和激活函数(activation function)。但是你也可以用简单基本的Python语言实现。

def log_softmax(x):
return x - x.exp().sum(-1).log().unsqueeze(-1)
def model(xb):
return log_softmax(xb @ weights + bias)

以上代码中“@”表示点积(dot production)操作,我们将会使他作用于每一批量(batch)的数据(这个例子是64张图片的数据)。这是一次向前过程(forward pass)。注意我们这样的预测并不会比随机判断好多少,因为我们的权值刚开始是随机产生的。

bs = 64 # batch size
xb = x_train[0:bs] # a mini-batch from x
preds = model(xb) # predictions
preds[0], preds.shape
print(preds[0], preds.shape)

输出:

tensor([-1.5058, -2.1150, -2.4652, -2.4982, -2.4030, -3.0075, -2.2017, -2.8193,
-2.6561, -2.2075], grad_fn=) torch.Size([64, 10])

正如你所看到的一样,张量 preds 不仅包含了他的数值,也包含一个梯度函数。我们等下会用到它来做反向传播。

然我们来实现一个 negative log_likehood 函数作为他的损失函数。仍然用的是Python 标准函数,没有用PyTorch集成的函数。

def nll(input, target):
return -input[range(target.shape[0]), target].mean()
loss_func = nll

让我们来检测一下我们模型的损失值,这样我们在下一个回合就可以比较损失值的变化了。

yb = y_train[0:bs]
print(loss_func(preds, yb))

输出:

tensor(2.2584, grad_fn=)

让我们再来实现一个函数计算我们模型预测出来的结果的正确性。在每次预测中,输出向量最大值得下标索引如果和目标值(标签)相同,则认为预测结果是对的。

def accuracy(out, yb):
preds = torch.argmax(out, dim=1)
return (preds == yb).float().mean()

让我们来检测我们模型的正确率,这样我们就可以看到随着损失函数的提升,正确率也随之提升。

print(accuracy(preds, yb))

输出:

tensor(0.1094)

现在我们可以运行整个训练过程。在每次迭代中,我们将会:

  • 选择一个最小批量的数据(代码中表示为 bs,即每次进入神经网络的数据单元)
  • 用模型去得到预测结果
  • 计算损失函数值
  • loss.backward()更新模型的梯度,在这里是权值(weights)和偏移(bias)。

现在我们用梯度去更新权值和偏移。我们在更新时设置 torch.no_grad() ,因为我们不想把这个操作也记录到梯度中。

然后我们把梯度清零。这样我们就可以进行下一个循环过程。不然的话梯度会记录所有的操作。

from IPython.core.debugger import set_trace
lr = 0.5 # learning rate
epochs = 2 # how many epochs to train for
for epoch in range(epochs):
for i in range((n - 1) // bs + 1):
# set_trace()
start_i = i * bs
end_i = start_i + bs
xb = x_train[start_i:end_i]
yb = y_train[start_i:end_i]
pred = model(xb)
loss = loss_func(pred, yb)
loss.backward()
with torch.no_grad():
weights -= weights.grad * lr
bias -= bias.grad * lr
weights.grad.zero_()
bias.grad.zero_()

这就是我们用纯Python构建的神经网络。(这个例子中,这是一个逻辑回归,就两层,没有隐含层)。

让我们来检测这个模型的损失值和正确率。我们期望的是损失值能够降下来,正确率能够上升。

print(loss_func(model(xb), yb), accuracy(model(xb), yb))

输出:

tensor(0.0849, grad_fn=) tensor(1.)

正确率是1.


推荐阅读
  • 【论文】ICLR 2020 九篇满分论文!!!
    点击上方,选择星标或置顶,每天给你送干货!阅读大概需要11分钟跟随小博主,每天进步一丢丢来自:深度学习技术前沿 ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • 本文由编程笔记#小编为大家整理,主要介绍了logistic回归(线性和非线性)相关的知识,包括线性logistic回归的代码和数据集的分布情况。希望对你有一定的参考价值。 ... [详细]
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • 阿里Treebased Deep Match(TDM) 学习笔记及技术发展回顾
    本文介绍了阿里Treebased Deep Match(TDM)的学习笔记,同时回顾了工业界技术发展的几代演进。从基于统计的启发式规则方法到基于内积模型的向量检索方法,再到引入复杂深度学习模型的下一代匹配技术。文章详细解释了基于统计的启发式规则方法和基于内积模型的向量检索方法的原理和应用,并介绍了TDM的背景和优势。最后,文章提到了向量距离和基于向量聚类的索引结构对于加速匹配效率的作用。本文对于理解TDM的学习过程和了解匹配技术的发展具有重要意义。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • Html5-Canvas实现简易的抽奖转盘效果
    本文介绍了如何使用Html5和Canvas标签来实现简易的抽奖转盘效果,同时使用了jQueryRotate.js旋转插件。文章中给出了主要的html和css代码,并展示了实现的基本效果。 ... [详细]
author-avatar
嘤_嘤_嘤
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有