提交 8b959a85 编写于 作者: 片刻小哥哥's avatar 片刻小哥哥

删除 1.2 版本 (过渡版本)

上级 867312ef
# <center>PyTorch 1.2 中文文档 & 教程</center>
![](../../docs/img/logo.svg)
<center>PyTorch 是一个针对深度学习, 并且使用 GPU 和 CPU 来优化的 tensor library (张量库)</center>
<br/>
<table>
<tr align="center">
<td colspan="3"><a title="Pytorch 1.2 中文版本" href="https://pytorch.apachecn.org/docs/1.2/" target="_blank"><font size="5">正在校验: 1.2 中文版本</font></a></td>
</tr>
<tr align="center">
<td><a title="Pytorch 1.0 中文版本" href="https://pytorch.apachecn.org/docs/1.0/" target="_blank"><font size="5">1.0 中文版本</font></a></td>
<td><a title="Pytorch 最新 英文教程" href="https://pytorch.org/tutorials/" target="_blank"><font size="5">最新 英文教程</font></a></td>
<td><a title="Pytorch 最新 英文文档" href="https://pytorch.org/docs/master/" target="_blank"><font size="5">最新 英文文档</font></a></td>
</tr>
<tr align="center">
<td><a title="Pytorch 0.4 中文版本" href="https://pytorch.apachecn.org/docs/0.4/" target="_blank"><font size="5">0.4 中文版本</font></a></td>
<td><a title="Pytorch 0.3 中文版本" href="https://pytorch.apachecn.org/docs/0.3/" target="_blank"><font size="5">0.3 中文版本</font></a></td>
<td><a title="Pytorch 0.2 中文版本" href="https://pytorch.apachecn.org/docs/0.2/" target="_blank"><font size="5">0.2 中文版本</font></a></td>
</tr>
</table>
<br/>
> 欢迎任何人参与和完善:一个人可以走的很快,但是一群人却可以走的更远。
+ [在线阅读](http://pytorch.apachecn.org)
+ [ApacheCN 学习资源](http://www.apachecn.org/)
+ [PyTorch 中文翻译组 | ApacheCN 713436582](http://shang.qq.com/wpa/qunwpa?idkey=349eb1bbaeeff1cf20408899cbe75669132ef145ff5ee6599f78a77dd144c367)
## 目录结构
* [Introduction](README.md)
* 中文教程
* 入门
* [PyTorch 深度学习: 60 分钟极速入门](beginner/deep_learning_60min_blitz.md)
* [什么是PyTorch?](beginner/blitz/tensor_tutorial.md)
* [Autograd:自动求导](beginner/blitz/autograd_tutorial.md)
* [神经网络](beginner/blitz/neural_networks_tutorial.md)
* [训练分类器](beginner/blitz/cifar10_tutorial.md)
* [可选: 数据并行处理](beginner/blitz/data_parallel_tutorial.md)
* [数据加载和处理教程](beginner/data_loading_tutorial.html)
* [用例子学习 PyTorch](beginner/pytorch_with_examples.html)
* [迁移学习教程](beginner/transfer_learning_tutorial.html)
* [利用 TorchScript 部署 Seq2Seq 模型](beginner/deploy_seq2seq_hybrid_frontend_tutorial.html)
* [使用 TensorBoard 可视化模型,数据和训练](intermediate/tensorboard_tutorial.html)
* [保存和加载模型](beginner/saving_loading_models.html)
* [torch.nn 到底是什么?](beginner/nn_tutorial.html)
* 图片
* [TorchVision 对象检测微调教程](intermediate/torchvision_tutorial.html)
* [微调Torchvision模型](beginner/finetuning_torchvision_models_tutorial.html)
* [空间变压器网络教程](intermediate/spatial_transformer_tutorial.html)
* [使用PyTorch进行神经网络传递](advanced/neural_style_tutorial.html)
* [对抗性示例生成](beginner/fgsm_tutorial.html)
* [DCGAN教程](beginner/dcgan_faces_tutorial.html)
* 音频
* [torchaudio教程](beginner/audio_preprocessing_tutorial.html)
* 文本
* [NLP From Scratch: 使用char-RNN对姓氏进行分类](intermediate/char_rnn_classification_tutorial.html)
* [NLP From Scratch: 生成名称与字符级RNN](intermediate/char_rnn_generation_tutorial.html)
* [NLP From Scratch: 基于注意力机制的 seq2seq 神经网络翻译](intermediate/seq2seq_translation_tutorial.html)
* [文本分类与TorchText ](beginner/text_sentiment_ngrams_tutorial.html)
* [语言翻译与TorchText ](beginner/torchtext_translation_tutorial.html)
* [序列到序列与nn.Transformer和TorchText建模](beginner/transformer_tutorial.html)
* 强化学习
* [强化学习(DQN)教程](intermediate/reinforcement_q_learning.html)
* 在生产部署PyTorch模型
* [部署PyTorch在Python经由REST API从Flask](intermediate/flask_rest_api_tutorial.html)
* [介绍TorchScript](beginner/Intro_to_TorchScript_tutorial.html)
* [在C ++中加载TorchScript模型 ](advanced/cpp_export.html)
* [(可选)将模型从PyTorch导出到ONNX并使用ONNX Runtime运行 ](advanced/super_resolution_with_onnxruntime.html)
* 并行和分布式训练
* [模型并行化最佳实践](intermediate/model_parallel_tutorial.html)
* [入门分布式数据并行](intermediate/ddp_tutorial.html)
* [PyTorch编写分布式应用](intermediate/dist_tuto.html)
* [(高级)PyTorch 1.0分布式训练与Amazon AWS](beginner/aws_distributed_training_tutorial.html)
* 扩展PyTorch
* [使用自定义 C++ 扩展算TorchScript ](advanced/torch_script_custom_ops.html)
* [用 numpy 和 scipy 创建扩展](advanced/numpy_extensions_tutorial.html)
* [自定义 C++ 和CUDA扩展](advanced/cpp_extension.html)
* PyTorch在其他语言
* [使用PyTorch C++ 前端](advanced/cpp_frontend.html)
* 中文文档
* 注解
* [自动求导机制](notes/autograd.html)
* [广播语义](notes/broadcasting.html)
* [CPU线程和TorchScript推理](notes/cpu_threading_torchscript_inference.html)
* [CUDA语义](notes/cuda.html)
* [扩展PyTorch](notes/extending.html)
* [常见问题](notes/faq.html)
* [对于大规模部署的特点](notes/large_scale_deployments.html)
* [并行处理最佳实践](notes/multiprocessing.html)
* [重复性](notes/randomness.html)
* [序列化语义](notes/serialization.html)
* [Windows 常见问题](notes/windows.html)
* 社区
* [PyTorch贡献说明书](community/contribution_guide.html)
* [PyTorch治理](community/governance.html)
* [PyTorch治理感兴趣的人](community/persons_of_interest.html)
* 封装参考文献
* [torch](torch.html)
* [torch.Tensor](tensors.html)
* [Tensor Attributes](tensor_attributes.html)
* [Type Info](type_info.html)
* [torch.sparse](sparse.html)
* [torch.cuda](cuda.html)
* [torch.Storage](storage.html)
* [torch.nn](nn.html)
* [torch.nn.functional](nn.functional.html)
* [torch.nn.init](nn.init.html)
* [torch.optim](optim.html)
* [torch.autograd](autograd.html)
* [torch.distributed](distributed.html)
* [torch.distributions](distributions.html)
* [torch.hub](hub.html)
* [torch.jit](jit.html)
* [torch.multiprocessing](multiprocessing.html)
* [torch.random](random.html)
* [torch.utils.bottleneck](bottleneck.html)
* [torch.utils.checkpoint](checkpoint.html)
* [torch.utils.cpp_extension](cpp_extension.html)
* [torch.utils.data](data.html)
* [torch.utils.dlpack](dlpack.html)
* [torch.utils.model_zoo](model_zoo.html)
* [torch.utils.tensorboard](tensorboard.html)
* [torch.onnx](onnx.html)
* [torch.\_\_ config\_\_](__config__.html)
* torchvision Reference
* [torchvision](torchvision/index.html)
* torchaudio Reference
* [torchaudio](https://pytorch.org/audio)
* torchtext Reference
* [torchtext](https://pytorch.org/text)
# Summary
* [Introduction](README.md)
* 中文教程
* 入门
* [PyTorch 深度学习: 60 分钟极速入门](beginner/deep_learning_60min_blitz.md)
* [什么是PyTorch?](beginner/blitz/tensor_tutorial.md)
* [Autograd:自动求导](beginner/blitz/autograd_tutorial.md)
* [神经网络](beginner/blitz/neural_networks_tutorial.md)
* [训练分类器](beginner/blitz/cifar10_tutorial.md)
* [可选: 数据并行处理](beginner/blitz/data_parallel_tutorial.md)
* [数据加载和处理教程](beginner/data_loading_tutorial.md)
* [用例子学习 PyTorch](beginner/pytorch_with_examples.md)
* [迁移学习教程](beginner/transfer_learning_tutorial.md)
* [利用 TorchScript 部署 Seq2Seq 模型](beginner/deploy_seq2seq_hybrid_frontend_tutorial.md)
* [使用 TensorBoard 可视化模型,数据和训练](intermediate/tensorboard_tutorial.md)
* [保存和加载模型](beginner/saving_loading_models.md)
* [torch.nn 到底是什么?](beginner/nn_tutorial.md)
* 图片
* [TorchVision 对象检测微调教程](intermediate/torchvision_tutorial.md)
* [微调Torchvision模型](beginner/finetuning_torchvision_models_tutorial.md)
* [空间变压器网络教程](intermediate/spatial_transformer_tutorial.md)
* [使用PyTorch进行神经网络传递](advanced/neural_style_tutorial.md)
* [对抗性示例生成](beginner/fgsm_tutorial.md)
* [DCGAN教程](beginner/dcgan_faces_tutorial.md)
* 音频
* [torchaudio教程](beginner/audio_preprocessing_tutorial.md)
* 文本
* [NLP From Scratch: 使用char-RNN对姓氏进行分类](intermediate/char_rnn_classification_tutorial.md)
* [NLP From Scratch: 生成名称与字符级RNN](intermediate/char_rnn_generation_tutorial.md)
* [NLP From Scratch: 基于注意力机制的 seq2seq 神经网络翻译](intermediate/seq2seq_translation_tutorial.md)
* [文本分类与TorchText](beginner/text_sentiment_ngrams_tutorial.md)
* [语言翻译与TorchText](beginner/torchtext_translation_tutorial.md)
* [序列到序列与nn.Transformer和TorchText建模](beginner/transformer_tutorial.md)
* 强化学习
* [强化学习(DQN)教程](intermediate/reinforcement_q_learning.md)
* 在生产部署PyTorch模型
* [部署PyTorch在Python经由REST API从Flask](intermediate/flask_rest_api_tutorial.md)
* [介绍TorchScript](beginner/Intro_to_TorchScript_tutorial.md)
* [在C ++中加载TorchScript模型 ](advanced/cpp_export.md)
* [(可选)将模型从PyTorch导出到ONNX并使用ONNX Runtime运行 ](advanced/super_resolution_with_onnxruntime.md)
* 并行和分布式训练
* [模型并行化最佳实践](intermediate/model_parallel_tutorial.md)
* [入门分布式数据并行](intermediate/ddp_tutorial.md)
* [PyTorch编写分布式应用](intermediate/dist_tuto.md)
* [(高级)PyTorch 1.0分布式训练与Amazon AWS](beginner/aws_distributed_training_tutorial.md)
* 扩展PyTorch
* [使用自定义 C++ 扩展算TorchScript ](advanced/torch_script_custom_ops.md)
* [用 numpy 和 scipy 创建扩展](advanced/numpy_extensions_tutorial.md)
* [自定义 C++ 和CUDA扩展](advanced/cpp_extension.md)
* PyTorch在其他语言
* [使用PyTorch C++ 前端](advanced/cpp_frontend.md)
* 中文文档
* 注解
* [自动求导机制](notes/autograd.md)
* [广播语义](notes/broadcasting.md)
* [CPU线程和TorchScript推理](notes/cpu_threading_torchscript_inference.md)
* [CUDA语义](notes/cuda.md)
* [扩展PyTorch](notes/extending.md)
* [常见问题](notes/faq.md)
* [对于大规模部署的特点](notes/large_scale_deployments.md)
* [并行处理最佳实践](notes/multiprocessing.md)
* [重复性](notes/randomness.md)
* [序列化语义](notes/serialization.md)
* [Windows 常见问题](notes/windows.md)
* 社区
* [PyTorch贡献说明书](community/contribution_guide.md)
* [PyTorch治理](community/governance.md)
* [PyTorch治理感兴趣的人](community/persons_of_interest.md)
* 封装参考文献
* [torch](torch.md)
* [torch.Tensor](tensors.md)
* [Tensor Attributes](tensor_attributes.md)
* [Type Info](type_info.md)
* [torch.sparse](sparse.md)
* [torch.cuda](cuda.md)
* [torch.Storage](storage.md)
* [torch.nn](nn.md)
* [torch.nn.functional](nn.functional.md)
* [torch.nn.init](nn.init.md)
* [torch.optim](optim.md)
* [torch.autograd](autograd.md)
* [torch.distributed](distributed.md)
* [torch.distributions](distributions.md)
* [torch.hub](hub.md)
* [torch.jit](jit.md)
* [torch.multiprocessing](multiprocessing.md)
* [torch.random](random.md)
* [torch.utils.bottleneck](bottleneck.md)
* [torch.utils.checkpoint](checkpoint.md)
* [torch.utils.cpp_extension](cpp_extension.md)
* [torch.utils.data](data.md)
* [torch.utils.dlpack](dlpack.md)
* [torch.utils.model_zoo](model_zoo.md)
* [torch.utils.tensorboard](tensorboard.md)
* [torch.onnx](onnx.md)
* [torch.__ config__](__config__.md)
* torchvision 参考文献
* [torchvision](torchvision/index.md)
* torchaudio Reference
* [torchaudio](https://pytorch.org/audio)
* torchtext Reference
* [torchtext](https://pytorch.org/text)
# 在C++ 中加载 TorchScript 模型
> 译者:[talengu](https://github.com/talengu)
本教程已更新为可与PyTorch 1.2一起使用
顾名思义,PyTorch的主要接口是Python编程语言。尽管Python是许多需要动态性和易于迭代的场景的合适且首选的语言,但是在同样许多情况下,Python的这些属性恰恰是不利的。后者通常适用的一种环境是生产 -低延迟和严格部署要求的土地。对于生产场景,即使只将C ++绑定到Java,Rust或Go之类的另一种语言中,它通常也是首选语言。以下段落将概述PyTorch提供的从现有Python模型到可以加载和执行的序列化表示形式的路径 完全来自C ++,不依赖Python。
## 步骤1:将PyTorch模型转换为Torch脚本
PyTorch模型从Python到C ++的旅程由[Torch Script](https://pytorch.org/docs/master/jit.html)启用,[Torch Script](https://pytorch.org/docs/master/jit.html)是PyTorch模型的表示形式,可以由Torch Script编译器理解,编译和序列化。如果您是从使用vanilla “eager” API编写的现有PyTorch模型开始的,则必须首先将模型转换为Torch脚本。在最常见的情况下(如下所述),这只需要很少的努力。如果您已经有了Torch脚本模块,则可以跳到本教程的下一部分。
有两种将PyTorch模型转换为Torch脚本的方法。第一种称为跟踪,一种机制,通过使用示例输入对模型的结构进行一次评估,并记录这些输入在模型中的流动,从而捕获模型的结构。这适用于有限使用控制流的模型。第二种方法是在模型中添加显式批注,以告知Torch Script编译器可以根据Torch Script语言施加的约束直接解析和编译模型代码。
> 小贴士
您可以在官方[Torch Script](https://pytorch.org/docs/master/jit.html)中找到有关这两种方法的完整文档,以及使用方法的进一步指导。
## 通过跟踪转换为 Torch Script
要将PyTorch模型通过跟踪转换为Torch Script,必须将模型的实例以及示例输入传递给`torch.jit.trace` 函数。这将产生一个`torch.jit.ScriptModule`对象,该对象的模型评估轨迹将嵌入在模块的`forward`方法中:
```py
import torch
import torchvision
# An instance of your model.
model = torchvision.models.resnet18()
# An example input you would normally provide to your model's forward() method.
example = torch.rand(1, 3, 224, 224)
# Use torch.jit.trace to generate a torch.jit.ScriptModule via tracing.
traced_script_module = torch.jit.trace(model, example)
```
ScriptModule现在可以与常规PyTorch模块相同地评估被跟踪的对象:
```py
In[1]: output = traced_script_module(torch.ones(1, 3, 224, 224))
In[2]: output[0, :5]
Out[2]: tensor([-0.2698, -0.0381, 0.4023, -0.3010, -0.0448], grad_fn=<SliceBackward>)
```
### 通过Annotation将Model转换为Torch Script
在某些情况下,例如,如果模型使用特定形式的控制流,如果想要直接在Torch Script中编写模型并相应地标注(annotate)模型。例如,假设有以下普通的 Pytorch模型:
```py
import torch
class MyModule(torch.nn.Module):
def __init__(self, N, M):
super(MyModule, self).__init__()
self.weight = torch.nn.Parameter(torch.rand(N, M))
def forward(self, input):
if input.sum() > 0:
output = self.weight.mv(input)
else:
output = self.weight + input
return output
```
因为`forward`此模块的方法使用取决于输入的控制流,所以它不适合跟踪。相反,我们可以将其转换为`ScriptModule`。为了将模块转换为`ScriptModule`,需要按以下方式编译模块`torch.jit.script`
```py
class MyModule(torch.nn.Module):
def __init__(self, N, M):
super(MyModule, self).__init__()
self.weight = torch.nn.Parameter(torch.rand(N, M))
def forward(self, input):
if input.sum() > 0:
output = self.weight.mv(input)
else:
output = self.weight + input
return output
my_module = MyModule(10,20)
sm = torch.jit.script(my_module)
```
如果您需要排除某些方法,`nn.Module` 因为它们使用的是`TorchScript`不支持的Python功能,则可以使用以下方法注释这些方法`@torch.jit.ignore`
`my_module``ScriptModule`已经准备好进行序列化的实例 。
## 步骤2:将脚本模块序列化为文件
一旦有了对`ScriptModule` PyTorch模型的跟踪或注释,就可以将其序列化为文件了。稍后,您将能够使用C++从此文件加载模块并执行它,而无需依赖Python。假设我们要序列化`ResNet18`先前在跟踪示例中显示的模型。要执行此序列化,只需 在模块上调用 [save](https://pytorch.org/docs/master/jit.html#torch.jit.ScriptModule.save) 并传递一个文件名即可:
```py
traced_script_module.save("traced_resnet_model.pt")
```
这将`traced_resnet_model.pt`在您的工作目录中生成一个文件。如果您还想序列化`my_module`,请回调`my_module.save("my_module_model.pt")`我们现在已经正式离开Python领域,并准备跨入C ++领域。
## 步骤3:在C++中加载脚本模块
要在C ++中加载序列化的PyTorch模型,您的应用程序必须依赖于 `PyTorch C++ API`(也称为LibTorch)。LibTorch发行版包含共享库,头文件和CMake构建配置文件的集合。虽然CMake不是依赖LibTorch的要求,但它是推荐的方法,并且将来会得到很好的支持。对于本教程,我们将使用CMake和LibTorch构建一个最小的C ++应用程序,该应用程序简单地加载并执行序列化的PyTorch模型。
### 最小的C ++应用程序
让我们从讨论加载模块的代码开始。以下将已经做:
```py
#include <torch/script.h> // One-stop header.
#include <iostream>
#include <memory>
int main(int argc, const char* argv[]) {
if (argc != 2) {
std::cerr << "usage: example-app <path-to-exported-script-module>\n";
return -1;
}
torch::jit::script::Module module;
try {
// Deserialize the ScriptModule from a file using torch::jit::load().
module = torch::jit::load(argv[1]);
}
catch (const c10::Error& e) {
std::cerr << "error loading the model\n";
return -1;
}
std::cout << "ok\n";
}
```
`<torch/script.h>`首标包括由运行示例所必需的库LibTorch所有相关包括。我们的应用程序接受序列化的PyTorch的文件路径`ScriptModule`作为其唯一的命令行参数,然后使用该`torch::jit::load()`函数继续反序列化该模块,该函数将该文件路径作为输入。作为回报,我们收到一个`torch::jit::script::Module`对象。我们将稍后讨论如何执行它。
### 取决于LibTorch和构建应用程序
假设我们将上述代码存储到名为的文件中`example-app.cpp`。最小`CMakeLists.txt`的构建看起来可能很简单:
```py
cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
project(custom_ops)
find_package(Torch REQUIRED)
add_executable(example-app example-app.cpp)
target_link_libraries(example-app "${TORCH_LIBRARIES}")
set_property(TARGET example-app PROPERTY CXX_STANDARD 11)
```
建立示例应用程序的最后一件事是LibTorch发行版。您可以随时从PyTorch网站的下载页面上获取最新的稳定版本。如果[下载](https://pytorch.org/)并解压缩最新的归档文件,则应收到具有以下目录结构的文件夹:
```py
libtorch/
bin/
include/
lib/
share/
```
* `lib/` 文件夹包含您必须链接的共享库,
* `include/` 文件夹包含程序需要包含的头文件,
* `share/` 文件夹包含必要的CMake配置,以启用`find_package(Torch)`上面的简单命令。
> 小贴士
在Windows上,调试和发行版本不兼容ABI。如果您打算以调试模式构建项目,请尝试使用LibTorch的调试版本。
最后一步是构建应用程序。为此,假定示例目录的布局如下:
```py
example-app/
CMakeLists.txt
example-app.cpp
```
现在,我们可以运行以下命令从`example-app/`文件夹中构建应用程序 :
```py
mkdir build
cd build
cmake -DCMAKE_PREFIX_PATH=/path/to/libtorch ..
make
```
这里`/path/to/libtorch`应该是解压的LibTorch分布的完整路径。如果一切顺利,它将看起来像这样:
```py
root@4b5a67132e81:/example-app# mkdir build
root@4b5a67132e81:/example-app# cd build
root@4b5a67132e81:/example-app/build# cmake -DCMAKE_PREFIX_PATH=/path/to/libtorch ..
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - not found
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
-- Configuring done
-- Generating done
-- Build files have been written to: /example-app/build
root@4b5a67132e81:/example-app/build# make
Scanning dependencies of target example-app
[ 50%] Building CXX object CMakeFiles/example-app.dir/example-app.cpp.o
[100%] Linking CXX executable example-app
[100%] Built target example-app
```
如果将生成的跟踪`ResNet18`模型的路径提供给`traced_resnet_model.pt`生成的`example-app`二进制文件,我们应该得到友好的“确定”。请注意,如果尝试与`my_module_model.pt`您一起运行此示例,则会收到一条错误消息,提示您输入的形状不兼容。`my_module_model.pt`期望使用1D而不是4D。
```py
root@4b5a67132e81:/example-app/build# ./example-app <path_to_model>/traced_resnet_model.pt
ok
```
## 步骤4:在C ++中执行脚本模块
成功加载了`ResNet18``C++`编写的序列化代码后,现在离执行它仅几行代码了!让我们将这些行添加到`C++`应用程序的`main()`函数中:
```py
// Create a vector of inputs.
std::vector<torch::jit::IValue> inputs;
inputs.push_back(torch::ones({1, 3, 224, 224}));
// Execute the model and turn its output into a tensor.
at::Tensor output = module.forward(inputs).toTensor();
std::cout << output.slice(/*dim=*/1, /*start=*/0, /*end=*/5) << '\n';
```
前两行设置了我们模型的输入。我们创建一个向量 `torch::jit::IValue`(类型擦除的值类型`script::Module`方法接受并返回),并添加单个输入。要创建输入张量,我们使用 `torch::ones()`,等效`torch.ones`于C++ API。然后,我们运行`script::Module``forward`方法,并将创建的输入向量传递给它。作为回报,我们得到一个新的`IValue`,通过调用将其转换为张量`toTensor()`
> 小贴士
要大致了解诸如`torch::ones` PyTorch C ++ API之类的功能,请参阅 <https://pytorch.org/cppdocs> 上的文档。PyTorch C ++ API提供了与Python API几乎相同的功能奇偶校验,使您可以像在Python中一样进一步操纵和处理张量。
在最后一行中,我们打印输出的前五个条目。由于在本教程前面的部分中,我们向Python中的模型提供了相同的输入,因此理想情况下,我们应该看到相同的输出。让我们通过重新编译应用程序并使用相同的序列化模型运行它来进行尝试:
```py
Scanning dependencies of target example-app
[ 50%] Building CXX object CMakeFiles/example-app.dir/example-app.cpp.o
[100%] Linking CXX executable example-app
[100%] Built target example-app
root@4b5a67132e81:/example-app/build# ./example-app traced_resnet_model.pt
-0.2698 -0.0381 0.4023 -0.3010 -0.0448
[ Variable[CPUFloatType]{1,5} ]
```
作为参考,之前Python代码的输出是:
```py
tensor([-0.2698, -0.0381, 0.4023, -0.3010, -0.0448], grad_fn=<SliceBackward>)
```
看起来很不错!
> 小贴士
要将模型移至GPU内存,可以编写`model.to(at::kCUDA)`;。通过调用来确保模型的输入也位于CUDA内存中`tensor.to(at::kCUDA)`,这将在CUDA内存中返回新的张量。
## 步骤5:获取帮助并探索API
希望本教程使您对PyTorch模型从Python到C++的路径有一个大致的了解。使用本教程中描述的概念,您应该能够从原始的“eager”的PyTorch模型,`ScriptModule`用Python 编译,在磁盘上序列化的文件,以及(关闭循环)到`script::Module` C++ 的可执行文件。
当然,有许多我们没有介绍的概念。例如,您可能会发现自己想要扩展`ScriptModule`使用C++或CUDA中实现的自定义运算符,并希望`ScriptModule`在纯C++生产环境中加载的内部执行此自定义运算符 。好消息是:这是可能的,并且得到了很好的支持!现在,您可以浏览[此文件夹](https://github.com/pytorch/pytorch/tree/master/test/custom_operator)中的示例,我们将很快提供一个教程。目前,以下链接通常可能会有所帮助:
* Torch Script 参考: [https://pytorch.org/docs/master/jit.html](https://pytorch.org/docs/master/jit.html)
* PyTorch C++ API 文档: [https://pytorch.org/cppdocs/](https://pytorch.org/cppdocs/)
* PyTorch Python API 文档: [https://pytorch.org/docs/](https://pytorch.org/docs/)
与往常一样,如果您遇到任何问题或疑问,可以使用我们的 [论坛](https://discuss.pytorch.org/)[GitHub](https://github.com/pytorch/pytorch/issues)问题进行联系。
此差异已折叠。
此差异已折叠。
# 使用PyTorch进行神经网络传递
> **作者**:[Alexis Jacq](https://alexis-jacq.github.io)
>
> **编辑**:[Winston Herring](https://github.com/winston6)
>
> 译者:[片刻](https://github.com/jiangzhonglian)
>
> 校验:[片刻](https://github.com/jiangzhonglian)
## 简介
本教程介绍了如何实现 由Leon A. Gatys,Alexander S. Ecker和Matthias Bethge开发的[神经风格算法](https://arxiv.org/abs/1508.06576)。神经风格或神经传递,使您可以拍摄图像并以新的艺术风格对其进行再现。该算法获取三个图像,即输入图像,内容图像和样式图像,然后更改输入以使其类似于内容图像的内容和样式图像的艺术风格。
![https://pytorch.org/tutorials/_images/neuralstyle.png](https://pytorch.org/tutorials/_images/neuralstyle.png)
## 基本原理
原理很简单:我们定义了两个距离,一个用于内容 $$(D_S)$$ 和一种样式 $$(D_S)$$。 $$(D_C)$$ 测量两个图像之间的内容有多不同,而 $$(D_S)$$ 测量两个图像之间样式的差异。然后,我们获取第三个图像输入,并将其转换为最小化与内容图像的内容距离和与样式图像的样式距离。现在我们可以导入必要的包并开始神经传递。
## 导入软件包并选择设备
以下是实现神经传递所需的软件包列表。
* `torch``torch.nn``numpy`(与PyTorch神经网络包赛前必读)
* `torch.optim` (有效的梯度下降)
* `PIL``PIL.Image``matplotlib.pyplot`(加载和显示图像)
* `torchvision.transforms` (将PIL图像转换为张量)
* `torchvision.models` (训练或加载预训练模型)
* `copy` (以深层复制模型;系统包)
from __future__ import print_function
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from PIL import Image
import matplotlib.pyplot as plt
import torchvision.transforms as transforms
import torchvision.models as models
import copy
接下来,我们需要选择要在哪个设备上运行网络并导入内容和样式图像。 在大图像上运行神经传递算法需要更长的时间,并且在GPU上运行时会更快。 我们可以使用`torch.cuda.is_available()`来检测是否有GPU。 接下来,我们设置`torch.device`以在整个教程中使用。 `.to(device)`方法也用于将张量或模块移动到所需的设备。
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
## 加载图像
现在,我们将导入样式和内容图像。原始的PIL图像的值在0到255之间,但是当转换为Torch张量时,其值将转换为0到1之间。图像也需要调整大小以具有相同的尺寸。需要注意的一个重要细节是,使用从0到1的张量值对Torch库中的神经网络进行训练。如果尝试为网络提供0到255张量图像,则激活的特征图将无法感知预期的内容和风格。但是,来自Caffe库的预训练网络使用0到255张量图像进行训练。
> Note
> 通过以下链接下载到运行教程所需的图像:[picasso.jpg](https://pytorch.org/tutorials/_static/img/neural-style/picasso.jpg)和[dancing.jpg](https://pytorch.org/tutorials/_static/img/neural-style/dancing.jpg)。下载这两个图像并将它们添加到images当前工作目录中具有名称的目录中。
# desired size of the output image
imsize = 512 if torch.cuda.is_available() else 128 # use small size if no gpu
loader = transforms.Compose([
transforms.Resize(imsize), # scale imported image
transforms.ToTensor()]) # transform it into a torch tensor
def image_loader(image_name):
image = Image.open(image_name)
# fake batch dimension required to fit network's input dimensions
image = loader(image).unsqueeze(0)
return image.to(device, torch.float)
style_img = image_loader("./data/images/neural-style/picasso.jpg")
content_img = image_loader("./data/images/neural-style/dancing.jpg")
assert style_img.size() == content_img.size(), \
"we need to import style and content images of the same size"
现在,让我们创建一个通过将图像的副本转换为PIL格式并使用来显示图像的功能`plt.imshow`。我们将尝试显示内容和样式图像,以确保正确导入它们。
unloader = transforms.ToPILImage() # reconvert into PIL image
plt.ion()
def imshow(tensor, title=None):
image = tensor.cpu().clone() # we clone the tensor to not do changes on it
image = image.squeeze(0) # remove the fake batch dimension
image = unloader(image)
plt.imshow(image)
if title is not None:
plt.title(title)
plt.pause(0.001) # pause a bit so that plots are updated
plt.figure()
imshow(style_img, title='Style Image')
plt.figure()
imshow(content_img, title='Content Image')
![https://pytorch.org/tutorials/_images/sphx_glr_neural_style_tutorial_001.png](https://pytorch.org/tutorials/_images/sphx_glr_neural_style_tutorial_001.png)
![https://pytorch.org/tutorials/_images/sphx_glr_neural_style_tutorial_002.png](https://pytorch.org/tutorials/_images/sphx_glr_neural_style_tutorial_002.png)
## 损失函数
### 内容损失
内容损失是代表单个图层内容距离的加权版本的函数。该功能获取特征图$$F_{XL}$$ 一层$$L$$在网络中处理输入$$X$$并返回加权内容距离$$w_{CL}.D_C^L(X,C)$$图像之间$$X$$和内容图片$$C$$。内容图像的特征图($$F_{CL}$$函数必须知道)才能计算内容距离。我们将此函数作为带有构造函数的torch模块来实现$$F_{CL}$$作为输入。距离$$\|F_{XL} - F_{CL}\|^2$$是两组要素图之间的均方误差,可以使用进行计算`nn.MSELoss`
我们将直接在用于计算内容距离的卷积层之后添加此内容丢失模块。这样,每次向网络提供输入图像时,都会在所需层上计算内容损失,并且由于自动渐变,将计算所有梯度。现在,为了使内容丢失层透明,我们必须定义一种`forward`方法来计算内容丢失,然后返回该层的输入。计算出的损耗将保存为模块的参数。
class ContentLoss(nn.Module):
def __init__(self, target,):
super(ContentLoss, self).__init__()
# we 'detach' the target content from the tree used
# to dynamically compute the gradient: this is a stated value,
# not a variable. Otherwise the forward method of the criterion
# will throw an error.
self.target = target.detach()
def forward(self, input):
self.loss = F.mse_loss(input, self.target)
return input
> Note
> **重要细节**:尽管此模块名为`ContentLoss`,但它不是真正的PyTorch损失函数。如果要将内容损失定义为PyTorch损失函数,则必须创建一个PyTorch autograd函数以在`backward`方法中手动重新计算/实现梯度。
### 风格损失
风格损失模块类似地实现对内容的损失模块。它将作为其计算该层的风格损失的网络中的透明层。为了计算的样式的损失,我们需要计算克矩阵$$G_{XL}$$。甲克矩阵是通过它的转置矩阵的给定矩阵相乘的结果。在本申请中给出的矩阵是特征的重整的版本映射$$F_{XL}$$层$$L$$。$$F_{XL}$$重塑形成$$\hat{F}_{XL}$$,$$K$$ X $$N$$矩阵,其中 $$K$$ 是特征图中的层$$L$$和数$$N$$是任何量化特征地图 $$F_{XL}^k$$ 的长度。例如,的第一行 $$\hat{F}_{XL}$$ 对应于第一量化特征地图 $$F_{XL}^1$$。
最后,克矩阵必须由在矩阵元素的总数量除以每个元素进行归一化。这种归一化是为了抵消这一事实$$\hat{F}_{XL}$$具有大$$N$$维产量较大的革兰氏矩阵值的矩阵。这些较大的值将导致第一层(池层之前),以具有梯度下降期间产生更大的影响。风格特征往往是在网络的更深层所以这归一化步骤是至关重​​要的。
def gram_matrix(input):
a, b, c, d = input.size() # a=batch size(=1)
# b=number of feature maps
# (c,d)=dimensions of a f. map (N=c*d)
features = input.view(a * b, c * d) # resise F_XL into \hat F_XL
G = torch.mm(features, features.t()) # compute the gram product
# we 'normalize' the values of the gram matrix
# by dividing by the number of element in each feature maps.
return G.div(a * b * c * d)
现在,样式丢失模块看起来几乎与内容丢失模块完全一样。样式距离也可以使用$$G_{XL}$$ 和 $$G_{SL}$$。
class StyleLoss(nn.Module):
def __init__(self, target_feature):
super(StyleLoss, self).__init__()
self.target = gram_matrix(target_feature).detach()
def forward(self, input):
G = gram_matrix(input)
self.loss = F.mse_loss(G, self.target)
return input
## 导入模型
现在我们需要导入一个预训练的神经网络。我们将使用19层VGG网络,就像本文中使用的那样。
PyTorch的VGG实现是一个模块,分为两个子 `Sequential`模块:(`features`包含卷积和池化层)和`classifier`(包含完全连接的层)。我们将使用该`features`模块,因为我们需要各个卷积层的输出来测量内容和样式损失。某些层在训练期间的行为与评估不同,因此我们必须使用将网络设置为评估模式`.eval()`
cnn = models.vgg19(pretrained=True).features.to(device).eval()
另外,在图像上训练VGG网络,每个通道的均值通过 mean=[0.485,0.456,0.406]和 std=[0.229,0.224,0.225]归一化。在将其发送到网络之前,我们将使用它们对图像进行规范化。
cnn_normalization_mean = torch.tensor([0.485, 0.456, 0.406]).to(device)
cnn_normalization_std = torch.tensor([0.229, 0.224, 0.225]).to(device)
# create a module to normalize input image so we can easily put it in a
# nn.Sequential
class Normalization(nn.Module):
def __init__(self, mean, std):
super(Normalization, self).__init__()
# .view the mean and std to make them [C x 1 x 1] so that they can
# directly work with image Tensor of shape [B x C x H x W].
# B is batch size. C is number of channels. H is height and W is width.
self.mean = torch.tensor(mean).view(-1, 1, 1)
self.std = torch.tensor(std).view(-1, 1, 1)
def forward(self, img):
# normalize img
return (img - self.mean) / self.std
`Sequential`模块包含子模块的有序列表。 例如,`vgg19.features`包含以正确的深度顺序对齐的序列(Conv2d,ReLU,MaxPool2d,Conv2d,ReLU…)。 我们需要在检测到的卷积层之后立即添加内容丢失层和样式丢失层。 为此,我们必须创建一个新`Sequential`模块,该模块具有正确插入的内容丢失和样式丢失模块。
# desired depth layers to compute style/content losses :
content_layers_default = ['conv_4']
style_layers_default = ['conv_1', 'conv_2', 'conv_3', 'conv_4', 'conv_5']
def get_style_model_and_losses(cnn, normalization_mean, normalization_std,
style_img, content_img,
content_layers=content_layers_default,
style_layers=style_layers_default):
cnn = copy.deepcopy(cnn)
# normalization module
normalization = Normalization(normalization_mean, normalization_std).to(device)
# just in order to have an iterable access to or list of content/syle
# losses
content_losses = []
style_losses = []
# assuming that cnn is a nn.Sequential, so we make a new nn.Sequential
# to put in modules that are supposed to be activated sequentially
model = nn.Sequential(normalization)
i = 0 # increment every time we see a conv
for layer in cnn.children():
if isinstance(layer, nn.Conv2d):
i += 1
name = 'conv_{}'.format(i)
elif isinstance(layer, nn.ReLU):
name = 'relu_{}'.format(i)
# The in-place version doesn't play very nicely with the ContentLoss
# and StyleLoss we insert below. So we replace with out-of-place
# ones here.
layer = nn.ReLU(inplace=False)
elif isinstance(layer, nn.MaxPool2d):
name = 'pool_{}'.format(i)
elif isinstance(layer, nn.BatchNorm2d):
name = 'bn_{}'.format(i)
else:
raise RuntimeError('Unrecognized layer: {}'.format(layer.__class__.__name__))
model.add_module(name, layer)
if name in content_layers:
# add content loss:
target = model(content_img).detach()
content_loss = ContentLoss(target)
model.add_module("content_loss_{}".format(i), content_loss)
content_losses.append(content_loss)
if name in style_layers:
# add style loss:
target_feature = model(style_img).detach()
style_loss = StyleLoss(target_feature)
model.add_module("style_loss_{}".format(i), style_loss)
style_losses.append(style_loss)
# now we trim off the layers after the last content and style losses
for i in range(len(model) - 1, -1, -1):
if isinstance(model[i], ContentLoss) or isinstance(model[i], StyleLoss):
break
model = model[:(i + 1)]
return model, style_losses, content_losses
接下来,我们选择输入图像。您可以使用内容图像或白噪声的副本。
input_img = content_img.clone()
# if you want to use white noise instead uncomment the below line:
# input_img = torch.randn(content_img.data.size(), device=device)
# add the original input image to the figure:
plt.figure()
imshow(input_img, title='Input Image')
![https://pytorch.org/tutorials/_images/sphx_glr_neural_style_tutorial_003.png](https://pytorch.org/tutorials/_images/sphx_glr_neural_style_tutorial_003.png)
## 梯度下降
正如该算法的作者Leon Gatys在[此处](https://discuss.pytorch.org/t/pytorch-tutorial-for-neural-transfert-of-artistic-style/336/20?u=alexis-jacq)建议的那样,我们将使用L-BFGS算法来运行我们的梯度下降。与训练网络不同,我们希望训练输入图像以最大程度地减少内容/样式损失。我们将创建一个PyTorch L-BFGS优化器`optim.LBFGS`,并将图像作为张量传递给它进行优化。
def get_input_optimizer(input_img):
# this line to show that input is a parameter that requires a gradient
optimizer = optim.LBFGS([input_img.requires_grad_()])
return optimizer
最后,我们必须定义一个执行神经传递的函数。对于网络的每次迭代,它都会被提供更新的输入并计算新的损耗。我们将运行`backward`每个损失模块的方法来动态计算其梯度。优化器需要“关闭”功能,该功能可以重新评估模数并返回损耗。
我们还有最后一个约束要解决。网络可能会尝试使用超出图像的0到1张量范围的值来优化输入。我们可以通过在每次网络运行时将输入值校正为0到1之间来解决此问题。
def run_style_transfer(cnn, normalization_mean, normalization_std,
content_img, style_img, input_img, num_steps=300,
style_weight=1000000, content_weight=1):
"""Run the style transfer."""
print('Building the style transfer model..')
model, style_losses, content_losses = get_style_model_and_losses(cnn,
normalization_mean, normalization_std, style_img, content_img)
optimizer = get_input_optimizer(input_img)
print('Optimizing..')
run = [0]
while run[0] <= num_steps:
def closure():
# correct the values of updated input image
input_img.data.clamp_(0, 1)
optimizer.zero_grad()
model(input_img)
style_score = 0
content_score = 0
for sl in style_losses:
style_score += sl.loss
for cl in content_losses:
content_score += cl.loss
style_score *= style_weight
content_score *= content_weight
loss = style_score + content_score
loss.backward()
run[0] += 1
if run[0] % 50 == 0:
print("run {}:".format(run))
print('Style Loss : {:4f} Content Loss: {:4f}'.format(
style_score.item(), content_score.item()))
print()
return style_score + content_score
optimizer.step(closure)
# a last correction...
input_img.data.clamp_(0, 1)
return input_img
最后,我们可以运行算法。
output = run_style_transfer(cnn, cnn_normalization_mean, cnn_normalization_std,
content_img, style_img, input_img)
plt.figure()
imshow(output, title='Output Image')
# sphinx_gallery_thumbnail_number = 4
plt.ioff()
plt.show()
![https://pytorch.org/tutorials/_images/sphx_glr_neural_style_tutorial_004.png](https://pytorch.org/tutorials/_images/sphx_glr_neural_style_tutorial_004.png)
Out:
Building the style transfer model..
Optimizing..
run [50]:
Style Loss : 4.169304 Content Loss: 4.235329
run [100]:
Style Loss : 1.145476 Content Loss: 3.039176
run [150]:
Style Loss : 0.716769 Content Loss: 2.663749
run [200]:
Style Loss : 0.476047 Content Loss: 2.500893
run [250]:
Style Loss : 0.347092 Content Loss: 2.410895
run [300]:
Style Loss : 0.263698 Content Loss: 2.358449
**脚本的总运行时间:** (1分钟9.573秒)
[`Download Python source code:
neural_style_tutorial.py`](../_downloads/7d103bc16c40d35006cd24e65cf978d0/neural_style_tutorial.py)
[`Download Jupyter notebook:
neural_style_tutorial.ipynb`](../_downloads/f16c4cab7b50f6dea0beb900dee4bf0e/neural_style_tutorial.ipynb)
# 用 numpy 和 scipy 创建扩展
> **作者** :[Adam Paszke](https://github.com/apaszke)
>
>**修订者**: [Adam Dziedzic](https://github.com/adam-dziedzic)
>
> 译者:[Foxerlee](https://github.com/FoxerLee)、[cangyunye](https://github.com/cangyunye)
>
> 校验:[Foxerlee](https://github.com/FoxerLee)、[FontTian](https://github.com/fonttian)
在本教程中,我们需要完成两个任务:
1. 创建一个无参数神经网络层。
- 这里需要调用 **numpy** 包作为实现的一部分。
2. 创建一个权重自主优化的神经网络层。
- 这里需要调用 **Scipy** 包作为实现的一部分。
```python
import torch
from torch.autograd import Function
```
## 无参数神经网络层示例
该层并没有做任何有用的或数学上正确的事情。
它只是被恰当的命名为 BadFFTFunction
**本层的实现方式**
```python
from numpy.fft import rfft2, irfft2
class BadFFTFunction(Function):
def forward(self, input):
numpy_input = input.detach().numpy()
result = abs(rfft2(numpy_input))
return input.new(result)
def backward(self, grad_output):
numpy_go = grad_output.numpy()
result = irfft2(numpy_go)
return grad_output.new(result)
# 由于本层没有任何参数,我们可以简单的声明为一个函数,
# 而不是当做 nn.Module 类
def incorrect_fft(input):
return BadFFTFunction()(input)
```
**创建无参数神经网络层的示例方法:**
```python
input = torch.randn(8, 8, requires_grad=True)
result = incorrect_fft(input)
print(result)
result.backward(torch.randn(result.size()))
print(input)
```
输出:
```python
tensor([[ 0.4073, 11.6080, 7.4098, 18.1538, 3.4384],
[ 4.9980, 3.5935, 6.9132, 3.8621, 6.1521],
[ 5.2876, 6.2480, 9.3535, 5.1881, 9.5353],
[ 4.5351, 2.3523, 6.9937, 4.2700, 2.6574],
[ 0.7658, 7.8288, 3.9512, 5.2703, 15.0991],
[ 4.5351, 4.9517, 7.7959, 17.9770, 2.6574],
[ 5.2876, 11.0435, 4.1705, 0.9899, 9.5353],
[ 4.9980, 11.1055, 5.8031, 3.1775, 6.1521]],
grad_fn=<BadFFTFunctionBackward>)
tensor([[-1.4503, -0.6550, 0.0648, 0.2886, 1.9357, -1.2299, -1.7474, 0.6866],
[-0.2466, -1.0292, 0.3109, -0.4289, -0.3620, 1.1854, -1.3372, -0.2717],
[ 0.0828, 0.9115, 0.7877, -0.5776, 1.6676, -0.5576, -0.2321, -0.3273],
[ 0.1632, 0.3835, 0.5422, -0.9144, 0.2871, 0.1441, -1.8333, 1.4951],
[-0.2183, -0.5220, 0.9151, 0.0540, -1.0642, 0.4409, 0.7906, -1.2262],
[ 0.4039, 0.3374, 1.0567, -0.8190, 0.7870, -0.6152, -0.2887, 1.3878],
[ 1.6407, 0.0220, 1.4984, -1.9722, 0.3797, -0.0180, -0.7096, -0.2454],
[ 0.7194, 2.3345, -0.0780, -0.2043, -0.4576, -0.9087, -2.4926, 0.9283]],
requires_grad=True)
```
## 参数化示例
在深度学习的文献中,这一层被误解的称作卷积 `convolution`,尽管该层的实际操作是交叉-关联性 `cross-correlation` (唯一的区别是滤波器 `filter` 是为了卷积而翻转,而不是为了交叉关联)。
本层的可自优化权重的实现,依赖于交叉-关联 `cross-correlation` 一个表示权重的滤波器。
后向传播函数 `backward` 计算的是输入数据的梯度以及滤波器的梯度。
```python
from numpy import flip
import numpy as np
from scipy.signal import convolve2d, correlate2d
from torch.nn.modules.module import Module
from torch.nn.parameter import Parameter
class ScipyConv2dFunction(Function):
@staticmethod
def forward(ctx, input, filter, bias):
# detach so we can cast to NumPy
input, filter, bias = input.detach(), filter.detach(), bias.detach()
result = correlate2d(input.numpy(), filter.numpy(), mode='valid')
result += bias.numpy()
ctx.save_for_backward(input, filter, bias)
return torch.as_tensor(result, dtype=input.dtype)
@staticmethod
def backward(ctx, grad_output):
grad_output = grad_output.detach()
input, filter, bias = ctx.saved_tensors
grad_output = grad_output.numpy()
grad_bias = np.sum(grad_output, keepdims=True)
grad_input = convolve2d(grad_output, filter.numpy(), mode='full')
# the previous line can be expressed equivalently as:
# grad_input = correlate2d(grad_output, flip(flip(filter.numpy(), axis=0), axis=1), mode='full')
grad_filter = correlate2d(input.numpy(), grad_output, mode='valid')
return torch.from_numpy(grad_input), torch.from_numpy(grad_filter).to(torch.float), torch.from_numpy(grad_bias).to(torch.float)
class ScipyConv2d(Module):
def __init__(self, filter_width, filter_height):
super(ScipyConv2d, self).__init__()
self.filter = Parameter(torch.randn(filter_width, filter_height))
self.bias = Parameter(torch.randn(1, 1))
def forward(self, input):
return ScipyConv2dFunction.apply(input, self.filter, self.bias)
```
**示例:**
```python
module = ScipyConv2d(3, 3)
print("Filter and bias: ", list(module.parameters()))
input = torch.randn(10, 10, requires_grad=True)
output = module(input)
print("Output from the convolution: ", output)
output.backward(torch.randn(8, 8))
print("Gradient for the input map: ", input.grad)
```
输出:
```python
Filter and bias: [Parameter containing:
tensor([[ 0.6693, -0.2222, 0.4118],
[-0.3676, -0.9931, 0.2691],
[-0.1429, 1.8659, -0.7335]], requires_grad=True), Parameter containing:
tensor([[-1.3466]], requires_grad=True)]
Output from the convolution: tensor([[ 0.5250, -4.8840, -0.5804, -0.4413, -0.2209, -5.1590, -2.2587, -3.5415],
[ 0.1437, -3.4806, 2.8613, -2.5486, -0.6023, 0.8587, 0.6923, -3.9129],
[-6.2535, 2.7522, -2.5025, 0.0493, -3.2200, 1.2887, -2.4957, 1.6669],
[ 1.6953, -0.9312, -4.6079, -0.9992, -1.4760, 0.2594, -3.8285, -2.9756],
[ 1.2716, -5.1037, -0.2461, -1.1965, -1.6461, -0.6712, -3.1600, -0.9869],
[-2.0643, -1.1037, 1.0145, -0.4984, 1.6899, -1.2842, -3.5010, 0.8348],
[-2.6977, 0.7242, -5.2932, -2.1470, -4.0301, -2.8247, -1.4165, 0.0572],
[-1.1560, 0.8500, -3.5242, 0.0686, -1.9708, 0.8417, 2.1091, -4.5537]],
grad_fn=<ScipyConv2dFunctionBackward>)
Gradient for the input map: tensor([[ 0.2475, -1.0357, 0.9908, -1.5128, 0.9041, 0.0582, -0.5316, 1.0466,
-0.4844, 0.2972],
[-1.5626, 1.4143, -0.3199, -0.9362, 1.0149, -1.6612, -0.1623, 1.0273,
-0.8157, 0.4636],
[ 1.1604, 2.5787, -5.6081, 4.6548, -2.7051, 1.4152, 1.0695, -5.0619,
1.9227, -1.4557],
[ 0.8890, -5.4601, 5.3478, 0.3287, -3.0955, 1.7628, 1.3722, 0.9022,
4.6063, -1.7763],
[ 0.4180, -1.4749, 1.9056, -6.5754, 1.1695, -0.3068, -2.7579, -1.2399,
-3.2611, 1.7447],
[-1.5550, 1.0767, 0.5541, 0.5231, 3.7888, -2.4053, 0.4745, 4.5228,
-5.2254, 0.7871],
[ 0.8094, 5.9939, -4.4974, 1.9711, -4.6029, -0.7072, 0.8058, -1.0656,
1.7967, -0.5905],
[-1.1218, -4.8356, -3.5650, 2.0387, 0.6232, 1.4451, 0.9014, -1.1660,
-0.5986, 0.7368],
[ 0.4346, 3.4302, 5.3058, -3.0440, 1.0593, -3.6538, -1.7829, -0.0543,
-0.4385, 0.2770],
[ 0.2144, -2.5117, -2.6153, 1.1894, -0.6176, 1.9013, -0.7186, 0.4952,
0.6256, -0.3308]])
```
**检查梯度:**
```python
from torch.autograd.gradcheck import gradcheck
moduleConv = ScipyConv2d(3, 3)
input = [torch.randn(20, 20, dtype=torch.double, requires_grad=True)]
test = gradcheck(moduleConv, input, eps=1e-6, atol=1e-4)
print("Are the gradients correct: ", test)
```
输出:
```python
Are the gradients correct: True
```
脚本的总运行时间:(0分钟 4.128秒)
# 4.(可选)从导出到PyTorch一个ONNX模型并使用运行它ONNX运行时
在本教程中,我们将介绍如何在PyTorch定义的模型转换成ONNX格式,然后用ONNX运行时运行它。
ONNX运行时是ONNX模型,跨多个平台和硬件(在Windows,Linux和Mac和两个CPU和GPU)有效地推论一个注重性能的发动机。
ONNX运行时已被证明大大增加了多种型号的性能,解释[此处](https://cloudblogs.microsoft.com/opensource/2019/05/22/onnx-
runtime-machine-learning-inferencing-0-4-release)
在本教程中,你需要安装[ ONNX ](https://github.com/onnx/onnx)[
ONNX运行[HTG3。你可以得到的二进制建立ONNX和ONNX运行与`点子 安装 onnx onnxruntime
[HTG13。需要注意的是ONNX运行与Python版本3.5到3.7兼容。`](https://github.com/microsoft/onnxruntime)
`注 `:本教程需要PyTorch主分支可通过以下的说明[这里被安装](https://github.com/pytorch/pytorch#from-
source)
# Some standard imports
import io
import numpy as np
from torch import nn
import torch.utils.model_zoo as model_zoo
import torch.onnx
超分辨率越来越多的图像,视频分辨率的方式,被广泛应用于图像处理和视频编辑。在本教程中,我们将使用一个小的超分辨率模型。
首先,让我们创建一个PyTorch超分辨模型。该模型采用在[中描述的“实时单幅图像和视频超分辨率采用高效的子像素卷积神经网络”的高效子像素卷积层 -
石等](https://arxiv.org/abs/1609.05158)用于提高图像的分辨率由高档的因素。该模型预计的图像作为输入的所述YCbCr的Y成分,并且输出在超分辨率放大的Y分量。
[该模型](https://github.com/pytorch/examples/blob/master/super_resolution/model.py)直接从PyTorch的例子来不加修改:
# Super Resolution model definition in PyTorch
import torch.nn as nn
import torch.nn.init as init
class SuperResolutionNet(nn.Module):
def __init__(self, upscale_factor, inplace=False):
super(SuperResolutionNet, self).__init__()
self.relu = nn.ReLU(inplace=inplace)
self.conv1 = nn.Conv2d(1, 64, (5, 5), (1, 1), (2, 2))
self.conv2 = nn.Conv2d(64, 64, (3, 3), (1, 1), (1, 1))
self.conv3 = nn.Conv2d(64, 32, (3, 3), (1, 1), (1, 1))
self.conv4 = nn.Conv2d(32, upscale_factor ** 2, (3, 3), (1, 1), (1, 1))
self.pixel_shuffle = nn.PixelShuffle(upscale_factor)
self._initialize_weights()
def forward(self, x):
x = self.relu(self.conv1(x))
x = self.relu(self.conv2(x))
x = self.relu(self.conv3(x))
x = self.pixel_shuffle(self.conv4(x))
return x
def _initialize_weights(self):
init.orthogonal_(self.conv1.weight, init.calculate_gain('relu'))
init.orthogonal_(self.conv2.weight, init.calculate_gain('relu'))
init.orthogonal_(self.conv3.weight, init.calculate_gain('relu'))
init.orthogonal_(self.conv4.weight)
# Create the super-resolution model by using the above model definition.
torch_model = SuperResolutionNet(upscale_factor=3)
通常情况下,你现在会训练这个模型;然而,在本教程中,我们反而会下载一些预训练的权重。请注意,这种模式并没有良好的精度全面训练,在这里仅用于演示目的。
它调用`torch_model.eval() ``torch_model.train(假)
`导出模型前,把该模型是非常重要的推论模式。既然喜欢在不同的推断和训练模式辍学或batchnorm运营商的行为,这是必需的。
# Load pretrained model weights
model_url = 'https://s3.amazonaws.com/pytorch/test_data/export/superres_epoch100-44c6958e.pth'
batch_size = 1 # just a random number
# Initialize model with the pretrained weights
map_location = lambda storage, loc: storage
if torch.cuda.is_available():
map_location = None
torch_model.load_state_dict(model_zoo.load_url(model_url, map_location=map_location))
# set the model to inference mode
torch_model.eval()
导出在PyTorch模型通过跟踪或脚本作品。这个教程将作为一个例子使用由跟踪导出的模型。要导出模型,我们称之为`torch.onnx.export()
`功能。这将执行模式,记录的是什么运营商来计算输出跟踪。因为`出口 `运行模型,我们需要提供一个输入张量`*
[HTG11。只要它是正确的类型和尺寸在此的值可以是随机的。注意,输入尺寸将被固定在导出ONNX图形用于将输入的所有维的,除非指定为动态轴。在这个例子中,我们用的batch_size
1的输入导出模型,但然后指定所述第一尺寸为动态在`dynamic_axes`参数`torch.onnx.export ()
`。由此导出的模型将接受尺寸的输入[batch_size时,1,224,224],其中的batch_size可以是可变的。`
要了解PyTorch的出口接口的详细信息,请查看[
torch.onnx文献[HTG1。](https://pytorch.org/docs/master/onnx.html)
# Input to the model
x = torch.randn(batch_size, 1, 224, 224, requires_grad=True)
torch_out = torch_model(x)
# Export the model
torch.onnx.export(torch_model, # model being run
x, # model input (or a tuple for multiple inputs)
"super_resolution.onnx", # where to save the model (can be a file or file-like object)
export_params=True, # store the trained parameter weights inside the model file
opset_version=10, # the ONNX version to export the model to
do_constant_folding=True, # wether to execute constant folding for optimization
input_names = ['input'], # the model's input names
output_names = ['output'], # the model's output names
dynamic_axes={'input' : {0 : 'batch_size'}, # variable lenght axes
'output' : {0 : 'batch_size'}})
我们还计算`torch_out`,该模型,我们将用它来验证ONNX运行中运行时,我们出口的模型计算相同的值后输出。
但在验证模型与ONNX运行时输出之前,我们将检查与ONNX的API的ONNX模型。首先,`
onnx.load(“super_resolution.onnx”)
`将加载保存的模型和将输出一个onnx.ModelProto结构(用于捆绑一个ML一个顶层文件/容器格式模型。详细信息[
onnx.proto文档](https://github.com/onnx/onnx/blob/master/onnx/onnx.proto))。然后,`
onnx.checker.check_model(onnx_model)HTG8]
`将验证模型的结构,并确认该模型有一个有效的模式。所述ONNX图表的有效性是通过检查模型的版本,图的结构,以及作为节点,其输入和输出验证。
import onnx
onnx_model = onnx.load("super_resolution.onnx")
onnx.checker.check_model(onnx_model)
现在,让我们计算使用ONNX运行的Python的API的输出。这一部分通常可以在一个单独的进程或另一台机器上完成,但我们会继续以同样的过程,使我们可以验证ONNX运行和PyTorch被计算为网络相同的值。
为了运行与ONNX运行模式,我们需要与所选择的配置参数(在这里我们使用默认配置)创建模型推断会话。一旦会话创建,我们评估使用的run()API模型。这个调用的输出是含有ONNX运行时计算出的模型的输出列表。
import onnxruntime
ort_session = onnxruntime.InferenceSession("super_resolution.onnx")
def to_numpy(tensor):
return tensor.detach().cpu().numpy() if tensor.requires_grad else tensor.cpu().numpy()
# compute ONNX Runtime output prediction
ort_inputs = {ort_session.get_inputs()[0].name: to_numpy(x)}
ort_outs = ort_session.run(None, ort_inputs)
# compare ONNX Runtime and PyTorch results
np.testing.assert_allclose(to_numpy(torch_out), ort_outs[0], rtol=1e-03, atol=1e-05)
print("Exported model has been tested with ONNXRuntime, and the result looks good!")
我们应该看到,PyTorch和ONNX运行时的输出数值上运行,与之相匹配的给定精度(RTOL = 1E-03和蒂=
1E-05)。作为一个侧面说明,如果他们不匹配,则有在ONNX出口的问题,请与我们联系在这种情况下。
## 运行使用图像上的模型ONNX运行时
到目前为止,我们已经从PyTorch导出的模型,并展示了如何加载和运行ONNX与伪张量作为输入运行它。
在本教程中,我们将使用广泛使用的一个著名的猫形象,它看起来像下面
![cat](img/cat_224x224.jpg)
首先,让我们使用标准的PIL Python库加载图像,预先对其进行处理。请注意,这是预处理的数据处理训练/测试神经网络的标准做法。
我们首先调整图像的大小,以适应模型的输入(224x224)的大小。然后我们图象分成了Y,Cb和Cr分量。这些组件代表灰度图像(Y)和蓝色差(Cb)和红色差(Cr)的色度分量。
Y分量是对人眼更敏感,我们感兴趣的是这部分,我们将改造。提取Y分量后,我们把它转换成这将是我们模型的输入张量。
from PIL import Image
import torchvision.transforms as transforms
img = Image.open("./_static/img/cat.jpg")
resize = transforms.Resize([224, 224])
img = resize(img)
img_ycbcr = img.convert('YCbCr')
img_y, img_cb, img_cr = img_ycbcr.split()
to_tensor = transforms.ToTensor()
img_y = to_tensor(img_y)
img_y.unsqueeze_(0)
现在,作为下一步,让我们代表灰度调整猫形象的张量和运行ONNX运行超高分辨率模型如前所述。
ort_inputs = {ort_session.get_inputs()[0].name: to_numpy(img_y)}
ort_outs = ort_session.run(None, ort_inputs)
img_out_y = ort_outs[0]
在这一点上,该模型的输出是一个张量。现在,我们将处理模型的输出从输出张建设回来的最终输出图像,并保存图像。后处理步骤已经从PyTorch实现超高分辨率模型[此处](https://github.com/pytorch/examples/blob/master/super_resolution/super_resolve.py)采用。
img_out_y = Image.fromarray(np.uint8((img_out_y[0] * 255.0).clip(0, 255)[0]), mode='L')
# get the output image follow post-processing step from PyTorch implementation
final_img = Image.merge(
"YCbCr", [
img_out_y,
img_cb.resize(img_out_y.size, Image.BICUBIC),
img_cr.resize(img_out_y.size, Image.BICUBIC),
]).convert("RGB")
# Save the image, we will compare this with the output image from mobile device
final_img.save("./_static/img/cat_superres_with_ort.jpg")
![output\\_cat](img/cat_superres_with_ort.jpg)
ONNX运行时是一个跨平台的引擎,可以跨多个平台和两个CPU和GPU运行它。
ONNX运行时也可以部署到云中使用Azure的机器学习Services模型推理。更多信息[此处[HTG1。](https://docs.microsoft.com/en-
us/azure/machine-learning/service/concept-onnx)
关于ONNX运行时的性能[此处](https://github.com/microsoft/onnxruntime#high-
performance)更多信息。
有关ONNX运行[此处](https://github.com/microsoft/onnxruntime)更多信息。
**脚本的总运行时间:** (0分钟0.000秒)
[`Download Python source code:
super_resolution_with_onnxruntime.py`](../_downloads/58ce6e85b9b9e9647d302d6b48feccb0/super_resolution_with_onnxruntime.py)
[`Download Jupyter notebook:
super_resolution_with_onnxruntime.ipynb`](../_downloads/8c7f0be1e1c3803fcb4c41bcd9f4226b/super_resolution_with_onnxruntime.ipynb)
[通过斯芬克斯-廊产生廊](https://sphinx-gallery.readthedocs.io)
[Next ![](../_static/images/chevron-right-
orange.svg)](../intermediate/model_parallel_tutorial.html "1. Model Parallel
Best Practices") [![](../_static/images/chevron-right-orange.svg)
Previous](cpp_export.html "3. Loading a TorchScript Model in C++")
* * *
Was this helpful?
Yes
No
Thank you
* * *
©版权所有2017年,PyTorch。
* [HTG0 (可选)将模型从PyTorch导出到ONNX并使用ONNX Runtime运行
* 运行使用ONNX运行时的图像上的模型
![](https://www.facebook.com/tr?id=243028289693773&ev=PageView
&noscript=1)
![](https://www.googleadservices.com/pagead/conversion/795629140/?label=txkmCPmdtosBENSssfsC&guid=ON&script=0)
[](https://www.facebook.com/pytorch) [](https://twitter.com/pytorch)
分析流量和优化经验,我们为这个站点的Cookie。通过点击或导航,您同意我们的cookies的使用。因为这个网站目前维护者,Facebook的Cookie政策的适用。了解更多信息,包括有关可用的控制:[饼干政策[HTG1。](https://www.facebook.com/policies/cookies/)
![](../_static/images/pytorch-x.svg)
[](https://pytorch.org/)
此差异已折叠。
此差异已折叠。
# torchaudio教程
> 译者:[片刻](https://github.com/jiangzhonglian)
>
> 校验:[片刻](https://github.com/jiangzhonglian)
PyTorch是一个开源深度学习平台,提供了从研究原型到具有GPU支持的生产部署的无缝路径。
解决机器学习问题的巨大努力在于数据准备。torchaudio利用PyTorch的GPU支持,并提供许多工具来简化数据加载并使其更具可读性。在本教程中,我们将看到如何从简单的数据集中加载和预处理数据。
对于本教程,请确保`matplotlib`已安装该软件包, 以方便查看。
import torch
import torchaudio
import matplotlib.pyplot as plt
## 打开数据集
torchaudio支持以wav和mp3格式加载声音文件。我们将波形称为原始音频信号。
filename = "https://pytorch.org/tutorials/_static/img/steam-train-whistle-daniel_simon-converted-from-mp3.wav"
waveform, sample_rate = torchaudio.load(filename)
print("Shape of waveform: {}".format(waveform.size()))
print("Sample rate of waveform: {}".format(sample_rate))
plt.figure()
plt.plot(waveform.t().numpy())
![https://pytorch.org/tutorials/_images/sphx_glr_audio_preprocessing_tutorial_001.png](https://pytorch.org/tutorials/_images/sphx_glr_audio_preprocessing_tutorial_001.png)
日期:
Shape of waveform: torch.Size([2, 276858])
Sample rate of waveform: 44100
转换
torchaudio支持越来越多的 [转换](https://pytorch.org/audio/transforms.html)
* **Resample** :将波形重采样为其他采样率。
* **Spectrogram** :根据波形创建频谱图。
* **MelScale** :使用转换矩阵将普通STFT转换为Mel频率STFT。
* **AmplitudeToDB** :这将频谱图从功率/振幅标度转换为分贝标度。
* **MFCC** :从波形创建梅尔频率倒谱系数。
* **MelSpectrogram** :使用PyTorch中的STFT功能从波形创建MEL频谱图。
* **MuLawEncoding** :基于mu-law压扩对波形进行编码。
* **MuLawDecoding** :解码mu-law编码的波形。
由于所有变换都是nn.Modules或jit.ScriptModules,因此它们可以随时用作神经网络的一部分。
首先,我们可以以对数刻度查看频谱图的对数。
specgram = torchaudio.transforms.Spectrogram()(waveform)
print("Shape of spectrogram: {}".format(specgram.size()))
plt.figure()
plt.imshow(specgram.log2()[0,:,:].numpy(), cmap='gray')
![https://pytorch.org/tutorials/_images/sphx_glr_audio_preprocessing_tutorial_002.png](https://pytorch.org/tutorials/_images/sphx_glr_audio_preprocessing_tutorial_002.png)
Out:
Shape of spectrogram: torch.Size([2, 201, 1385])
或者我们可以以对数刻度查看梅尔光谱图。
specgram = torchaudio.transforms.MelSpectrogram()(waveform)
print("Shape of spectrogram: {}".format(specgram.size()))
plt.figure()
p = plt.imshow(specgram.log2()[0,:,:].detach().numpy(), cmap='gray')
![https://pytorch.org/tutorials/_images/sphx_glr_audio_preprocessing_tutorial_003.png](https://pytorch.org/tutorials/_images/sphx_glr_audio_preprocessing_tutorial_003.png)
Out:
Shape of spectrogram: torch.Size([2, 128, 1385])
我们可以一次对一个通道重新采样波形。
new_sample_rate = sample_rate/10
# Since Resample applies to a single channel, we resample first channel here
channel = 0
transformed = torchaudio.transforms.Resample(sample_rate, new_sample_rate)(waveform[channel,:].view(1,-1))
print("Shape of transformed waveform: {}".format(transformed.size()))
plt.figure()
plt.plot(transformed[0,:].numpy())
![https://pytorch.org/tutorials/_images/sphx_glr_audio_preprocessing_tutorial_004.png](https://pytorch.org/tutorials/_images/sphx_glr_audio_preprocessing_tutorial_004.png)
Out:
Shape of transformed waveform: torch.Size([1, 27686])
作为变换的另一个示例,我们可以基于Mu-Law编码对信号进行编码。但是要这样做,我们需要信号在-1和1之间。由于张量只是常规的PyTorch张量,因此我们可以在其上应用标准运算符。
# Let's check if the tensor is in the interval [-1,1]
print("Min of waveform: {}\nMax of waveform: {}\nMean of waveform: {}".format(waveform.min(), waveform.max(), waveform.mean()))
Out:
Min of waveform: -0.572845458984375
Max of waveform: 0.575958251953125
Mean of waveform: 9.293758921558037e-05
由于波形已经在-1和1之间,因此我们不需要对其进行归一化。
def normalize(tensor):
# Subtract the mean, and scale to the interval [-1,1]
tensor_minusmean = tensor - tensor.mean()
return tensor_minusmean/tensor_minusmean.abs().max()
# Let's normalize to the full interval [-1,1]
# waveform = normalize(waveform)
让我们对波形进行编码。
transformed = torchaudio.transforms.MuLawEncoding()(waveform)
print("Shape of transformed waveform: {}".format(transformed.size()))
plt.figure()
plt.plot(transformed[0,:].numpy())
![https://pytorch.org/tutorials/_images/sphx_glr_audio_preprocessing_tutorial_005.png](https://pytorch.org/tutorials/_images/sphx_glr_audio_preprocessing_tutorial_005.png)
Out:
Shape of transformed waveform: torch.Size([2, 276858])
现在解码。
reconstructed = torchaudio.transforms.MuLawDecoding()(transformed)
print("Shape of recovered waveform: {}".format(reconstructed.size()))
plt.figure()
plt.plot(reconstructed[0,:].numpy())
![https://pytorch.org/tutorials/_images/sphx_glr_audio_preprocessing_tutorial_006.png](https://pytorch.org/tutorials/_images/sphx_glr_audio_preprocessing_tutorial_006.png)
Out:
Shape of recovered waveform: torch.Size([2, 276858])
我们最终可以将原始波形与其重构版本进行比较。
# Compute median relative difference
err = ((waveform-reconstructed).abs() / waveform.abs()).median()
print("Median relative difference between original and MuLaw reconstucted signals: {:.2%}".format(err))
Out:
Median relative difference between original and MuLaw reconstucted signals: 1.28%
## 从Kaldi迁移到Torchaudio
用户可能熟悉 语音识别工具包[Kaldi](http://github.com/kaldi-asr/kaldi)。torchaudio在中提供与之的兼容性 `torchaudio.kaldi_io`。实际上,它可以通过以下方式从kaldi scp或ark文件或流中读取:
* read_vec_int_ark
* read_vec_flt_scp
* read_vec_flt_arkfile /流
* read_mat_scp
* read_mat_ark
torchaudio为GPU提供支持 spectrogram 并 fbank受益于Kaldi兼容的转换,请参见[此处](compliance.kaldi.html)以获取更多信息。
n_fft = 400.0
frame_length = n_fft / sample_rate * 1000.0
frame_shift = frame_length / 2.0
params = {
"channel": 0,
"dither": 0.0,
"window_type": "hanning",
"frame_length": frame_length,
"frame_shift": frame_shift,
"remove_dc_offset": False,
"round_to_power_of_two": False,
"sample_frequency": sample_rate,
}
specgram = torchaudio.compliance.kaldi.spectrogram(waveform, **params)
print("Shape of spectrogram: {}".format(specgram.size()))
plt.figure()
plt.imshow(specgram.t().numpy(), cmap='gray')
![https://pytorch.org/tutorials/_images/sphx_glr_audio_preprocessing_tutorial_007.png](https://pytorch.org/tutorials/_images/sphx_glr_audio_preprocessing_tutorial_007.png)
Out:
Shape of spectrogram: torch.Size([1383, 201])
我们还支持根据波形计算滤波器组特征,与Kaldi的实现相匹配。
fbank = torchaudio.compliance.kaldi.fbank(waveform, **params)
print("Shape of fbank: {}".format(fbank.size()))
plt.figure()
plt.imshow(fbank.t().numpy(), cmap='gray')
![https://pytorch.org/tutorials/_images/sphx_glr_audio_preprocessing_tutorial_008.png](https://pytorch.org/tutorials/_images/sphx_glr_audio_preprocessing_tutorial_008.png)
Out:
Shape of fbank: torch.Size([1383, 23])
## 结论
我们使用示例原始音频信号或波形来说明如何使用torchaudio打开音频文件,以及如何预处理和转换此类波形。鉴于torchaudio是基于PyTorch构建的,则这些技术可在利用GPU的同时用作更高级音频应用(例如语音识别)的构建块。
**脚本的总运行时间:** (0分钟2.343秒)
[`Download Python source code:
audio_preprocessing_tutorial.py`](https://pytorch.org/tutorials/_downloads/5ffe15ce830e55b3a9e9c294d04ab41c/audio_preprocessing_tutorial.py)
[`Download Jupyter notebook:
audio_preprocessing_tutorial.ipynb`](https://pytorch.org/tutorials/_downloads/7303ce3181f4dbc9a50bc1ed5bb3218f/audio_preprocessing_tutorial.ipynb)
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
# PyTorch 深度学习: 60 分钟极速入门
> **作者**:[Soumith Chintala](http://soumith.ch)
>
> 译者:[bat67](https://github.com/bat67)、[Foxerlee](https://github.com/FoxerLee)
>
> 校验:[Foxerlee](https://github.com/FoxerLee)
此教程的目标:
* 在高层上理解 PyTorch 的 Tensor 库以及神经网络。
* 训练一个可用于分类图像的简单神经网络。
*本教程假设你对 numpy 有基本的了解*
**注意**
- 确保你安装了 [torch](https://github.com/pytorch/pytorch)[torchvision](https://github.com/pytorch/vision) 包。
![_images/tensor_illustration_flat.png](https://pytorch.org/tutorials/_images/tensor_illustration_flat.png)
[PyTorch 是什么?](blitz/tensor_tutorial.html#sphx-glr-beginner-blitz-tensor-tutorial-py)
![_images/autodiff.png](https://pytorch.org/tutorials/_images/autodiff.png)
[Autograd:自动求导](blitz/autograd_tutorial.html#sphx-glr-beginner-blitz-autograd-tutorial-py)
![_images/mnist1.png](https://pytorch.org/tutorials/_images/mnist1.png)
[神经网络](blitz/neural_networks_tutorial.html#sphx-glr-beginner-blitz-neural-networks-tutorial-py)
![_images/cifar101.png](https://pytorch.org/tutorials/_images/cifar101.png)
[训练分类器](blitz/cifar10_tutorial.html#sphx-glr-beginner-blitz-cifar10-tutorial-py)
![_images/data_parallel.png](https://pytorch.org/tutorials/_images/data_parallel.png)
[可选:数据并行](blitz/data_parallel_tutorial.html#sphx-glr-beginner-blitz-data-parallel-tutorial-py)
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
# torch.utils.bottleneck
> 译者: [belonHan](https://github.com/belonHan)
`torch.utils.bottleneck`是 调试瓶颈`bottleneck`时首先用到的工具.它总结了python分析工具与PyTorch自动梯度分析工具在脚本运行中情况.
在命令行运行如下命令
```py
python -m torch.utils.bottleneck /path/to/source/script.py [args]
```
其中 `[args]``script.py`脚本的参数(任意个数).运行`python -m torch.utils.bottleneck -h`命令获取更多帮助说明.
警告
请确保脚本在分析时能够在有限时间内退出.
警告
当运行CUDA代码时,由于CUDA内核的异步特性, cProfile的输出 和cpu模式的autograd分析工具可能无法显示正确的计时: 报告的CPU时间 是用于启动内核的时间,不包括在GPU上执行的时间。 在常规cpu模式分析器下,同步操作是非常昂贵的。在这种无法准确计时的情况下,可以使用cuda模式的autograd分析工具。
注意
选择查看哪个分析工具的输出结果(CPU模式还是CUDA模式) ,首先应确定脚本是不是CPU密集型`CPU-bound`(“CPU总时间远大于CUDA总时间”)。如果是cpu密集型,选择查看cpu模式的结果。相反,如果大部分时间都运行在GPU上,再查看CUDA分析结果中相应的CUDA操作。
当然,实际情况取决于您的模型,可能会更复杂,不属于上面两种极端情况。除了分析结果之外,可以尝试使用`nvprof`命令查看[`torch.autograd.profiler.emit_nvtx()`](autograd.html#torch.autograd.profiler.emit_nvtx "torch.autograd.profiler.emit_nvtx")的结果.然而需要注意NVTX的开销是非常高的,时间线经常会有严重的偏差。
警告
如果您在分析CUDA代码, `bottleneck`运行的第一个分析工具 (cProfile),它的时间中会包含CUDA的启动(CUDA缓存分配)时间。当然,如果CUDA启动时间远小于代码的中瓶颈,这就被可以忽略。
更多更复杂关于分析工具的使用方法(比如多GPU),请点击[https://docs.python.org/3/library/profile.html](https://docs.python.org/3/library/profile.html) 或者 [`torch.autograd.profiler.profile()`](autograd.html#torch.autograd.profiler.profile "torch.autograd.profiler.profile").
# torch.utils.checkpoint
> 译者: [belonHan](https://github.com/belonHan)
注意
checkpointing的实现方法是在向后传播期间重新运行已被checkpint的前向传播段。 所以会导致像RNG这类(模型)的持久化的状态比实际更超前。默认情况下,checkpoint包含了使用RNG状态的逻辑(例如通过dropout),与non-checkpointed传递相比,checkpointed具有更确定的输出。RNG状态的存储逻辑可能会导致一定的性能损失。如果不需要确定的输出,设置全局标志(global flag) `torch.utils.checkpoint.preserve_rng_state=False` 忽略RNG状态在checkpoint时的存取。
```py
torch.utils.checkpoint.checkpoint(function, *args)
```
checkpoint模型或模型的一部分
checkpoint通过计算换内存空间来工作。与向后传播中存储整个计算图的所有中间激活不同的是,checkpoint不会保存中间激活部分,而是在反向传递中重新计算它们。它被应用于模型的任何部分。
具体来说,在正向传播中,`function`将以`torch.no_grad()`方式运行 ,即不存储中间激活,但保存输入元组和 `function`的参数。在向后传播中,保存的输入变量以及 `function`会被取回,并且`function`在正向传播中被重新计算.现在跟踪中间激活,然后使用这些激活值来计算梯度。
Warning
警告
Checkpointing 在 [`torch.autograd.grad()`](autograd.html#torch.autograd.grad "torch.autograd.grad")中不起作用, 仅作用于 [`torch.autograd.backward()`](autograd.html#torch.autograd.backward "torch.autograd.backward").
警告
如果function在向后执行和前向执行不同,例如,由于某个全局变量,checkpoint版本将会不同,并且无法被检测到。
参数:
* **function** - 描述在模型的正向传递或模型的一部分中运行的内容。它也应该知道如何处理作为元组传递的输入。例如,在LSTM中,如果用户通过 ,应正确使用第一个输入作为第二个输入(activation, hidden)functionactivationhidden
* **args** – 包含输入的元组function
| Returns: | 输出 |
| --- | --- |
```py
torch.utils.checkpoint.checkpoint_sequential(functions, segments, *inputs)
```
用于checkpoint sequential模型的辅助函数
Sequential模型按顺序执行模块/函数。因此,我们可以将这样的模型划分为不同的段(segment),并对每个段进行checkpoint。除最后一段外的所有段都将以`torch.no_grad()`方式运行,即,不存储中间活动。将保存每个checkpoint段的输入,以便在向后传递中重新运行该段。
checkpointing工作方式: [`checkpoint()`](#torch.utils.checkpoint.checkpoint "torch.utils.checkpoint.checkpoint").
警告
Checkpointing无法作用于[`torch.autograd.grad()`](autograd.html#torch.autograd.grad "torch.autograd.grad"), 只作用于[`torch.autograd.backward()`](autograd.html#torch.autograd.backward "torch.autograd.backward").
参数:
* **functions** – 按顺序执行的模型, 一个 [`torch.nn.Sequential`](nn.html#torch.nn.Sequential "torch.nn.Sequential")对象,或者一个由modules或functions组成的list。
* **segments** – 段的数量
* **inputs** – 输入,Tensor组成的元组
| Returns: | 按顺序返回每个`*inputs`的结果
| --- | --- |
例子
```py
>>> model = nn.Sequential(...)
>>> input_var = checkpoint_sequential(model, chunks, input_var)
```
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
# torch.utils.dlpack
`torch.utils.dlpack.from_dlpack`( _dlpack_ ) → Tensor
解码DLPack到张量。
Parameters
**dlpack** - 与dltensor一个PyCapsule对象
张量将与dlpack表示的对象共享存储器。请注意,每个dlpack只能使用一次消耗。
`torch.utils.dlpack.to_dlpack`( _tensor_ ) → PyCapsule
返回表示张量DLPack。
Parameters
**tensor** - 要导出的张量
该dlpack共享内存的张量。请注意,每个dlpack只能使用一次消耗。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册