diff --git a/docs/guides/01_paddle2.0_introduction/basic_concept/tensor_introduction_cn.md b/docs/guides/01_paddle2.0_introduction/basic_concept/tensor_introduction_cn.md index 84517dee3ba..571c9d4b676 100644 --- a/docs/guides/01_paddle2.0_introduction/basic_concept/tensor_introduction_cn.md +++ b/docs/guides/01_paddle2.0_introduction/basic_concept/tensor_introduction_cn.md @@ -1,23 +1,76 @@ # Tensor介绍 -## 概述:Tensor 的概念 +## 一、Tensor 的概念介绍 -飞桨(PaddlePaddle,以下简称Paddle)和其他深度学习框架一样,使用**Tensor**来表示数据,在神经网络中传递的数据均为**Tensor**。 +飞桨使用张量([Tensor](../../../api/paddle/Tensor_cn.html)) 来表示神经网络中传递的数据,Tensor 可以理解为多维数组,类似于 [Numpy 数组(ndarray)](https://numpy.org/doc/stable/user/quickstart.html#the-basics) 的概念。与 Numpy 数组相比,Tensor 除了支持运行在 CPU 上,还支持运行在 GPU 及各种 AI 芯片上,以实现计算加速;此外,飞桨基于 Tensor,实现了深度学习所必须的反向传播功能和多种多样的组网算子,从而可更快捷地实现深度学习组网与训练等功能。两者具体异同点可参见下文 [Tensor 与 Numpy 数组相互转换](#newtensor6)。 -**Tensor**可以将其理解为多维数组,其可以具有任意多的维度,不同**Tensor**可以有不同的**数据类型** (dtype) 和**形状** (shape)。 +在飞桨框架中,神经网络的输入、输出数据,以及网络中的参数均采用 Tensor 数据结构,示例如下: +```python +def train(model): + model.train() + epochs = 2 + optim = paddle.optimizer.Adam(learning_rate=0.001, parameters=model.parameters()) + # 模型训练的两层循环 + for epoch in range(epochs): + for batch_id, data in enumerate(train_loader()): + x_data = data[0] + y_data = data[1] + print("x_data: ", x_data[0][0][0][0]) # 打印神经网络的输入:批数据中的第一个数据的第一个元素 + predicts = model(x_data) + print("predicts: ", predicts[0]) # 打印神经网络的输出:批数据中的第一个数据的第一个元素 + print("weight: ", model.linear1.weight[0][0]) # 打印神经网络的权重:linear1层的weight中的第一个元素 + loss = F.cross_entropy(predicts, y_data) + acc = paddle.metric.accuracy(predicts, y_data) + loss.backward() + optim.step() + optim.clear_grad() + break + break +model = LeNet() +train(model) +``` + +```text +x_data: Tensor(shape=[1], dtype=float32, place=Place(gpu:0), stop_gradient=True, + [-1.]) +predicts: Tensor(shape=[1], dtype=float32, place=Place(gpu:0), stop_gradient=False, + [-0.72636688]) +weight: Tensor(shape=[1], dtype=float32, place=Place(gpu:0), stop_gradient=False, + [0.02227839]) +``` +以上示例代码来源 [使用LeNet在MNIST数据集实现图像分类](../../../practices/cv/image_classification) 任务 5.1 小节(篇幅原因仅截取部分),分别打印了神经网络的输入、输出数据和网络中的参数,可以看到均采用了 Tensor 数据结构。 + +## 二、Tensor 的创建 + +飞桨可基于给定数据手动创建 Tensor,并提供了多种方式,如: + +[2.1 指定数据创建](#newtensor1) + +[2.2 指定形状创建](#newtensor2) -同一**Tensor**的中所有元素的数据类型均相同。如果你对 [Numpy](https://numpy.org/doc/stable/user/quickstart.html#the-basics) 熟悉,**Tensor**是类似于 **Numpy 数组(array)** 的概念。 +[2.3 指定区间创建](#newtensor3) -## 一、Tensor的创建 +另外在常见深度学习任务中,数据样本可能是图片(image)、文本(text)、语音(audio)等多种类型,在送入神经网络训练或推理前均需要创建为 Tensor。飞桨提供了将这类数据手动创建为 Tensor 的方法,如: -Paddle提供了多种方式创建**Tensor**,如:指定数据列表创建、指定形状创建、指定区间创建等。 +[2.4 指定图像、文本数据创建](#newtensor4) -### 1.1 指定数据创建 -通过给定Python列表数据,可以创建任意维度(也称为轴)的Tensor,举例如下: +由于这些操作在整个深度学习任务流程中比较常见且固定,飞桨在一些 API 中封装了 Tensor 自动创建的操作,从而无须手动转 Tensor。 + +[2.5 自动创建 Tensor 的功能介绍](#newtensor5) + +如果你熟悉 Numpy,已经使用 Numpy 数组创建好数据,飞桨可以很方便地将 Numpy 数组转为 Tensor,具体介绍如: + +[六、Tensor 与 Numpy 数组相互转换](#newtensor6) + + +### 2.1 指定数据创建 + +与 Numpy 创建数组方式类似,通过给定 Python 序列(如列表 list、元组 tuple),可使用 [paddle.to_tensor](../../../api/paddle/to_tensor_cn.html) 创建任意维度的 Tensor。示例如下: + +(1)创建类似向量(vector)的 1 维 Tensor: ```python -# 创建类似向量(vector)的一维 Tensor -import paddle # 后面的示例代码默认已导入paddle模块 +import paddle # 后面的示例代码默认已导入 paddle 模块 ndim_1_Tensor = paddle.to_tensor([2.0, 3.0, 4.0]) print(ndim_1_Tensor) ``` @@ -27,19 +80,18 @@ Tensor(shape=[3], dtype=float32, place=Place(gpu:0), stop_gradient=True, [2., 3., 4.]) ``` -特殊地,如果仅输入单个标量(scalar)数据(例如float/int/bool类型的单个元素),则会创建形状为[1]的**Tensor** +特殊地,如果仅输入单个标量(scalar)数据(例如 float/int/bool 类型的单个元素),则会创建形状为 [1] 的 Tensor,即 0 维 Tensor: ```python paddle.to_tensor(2) paddle.to_tensor([2]) ``` -上述两种创建方式完全一致,形状均为[1],输出如下: ```text +# 上述两种创建方式完全一致,形状均为 [1],输出如下: Tensor(shape=[1], dtype=int64, place=Place(gpu:0), stop_gradient=True, [2]) ``` - +(2)创建类似矩阵(matrix)的 2 维 Tensor: ```python -# 创建类似矩阵(matrix)的二维 Tensor ndim_2_Tensor = paddle.to_tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]) print(ndim_2_Tensor) @@ -49,9 +101,8 @@ Tensor(shape=[2, 3], dtype=float32, place=Place(gpu:0), stop_gradient=True, [[1., 2., 3.], [4., 5., 6.]]) ``` - +(3)创建 3 维 Tensor: ```python -# 创建多维 Tensor ndim_3_Tensor = paddle.to_tensor([[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]], [[11, 12, 13, 14, 15], @@ -66,12 +117,14 @@ Tensor(shape=[2, 2, 5], dtype=int64, place=Place(gpu:0), stop_gradient=True, [[11, 12, 13, 14, 15], [16, 17, 18, 19, 20]]]) ``` -上述不同维度的**Tensor**可以可视化的表示为: +上述不同维度的 Tensor 可视化的表示如下图所示: + -
+

图1 不同维度的Tensor可视化表示
-> **Tensor**必须形如矩形,也就是,在任何一个维度上,元素的数量必须**相等**,如果为以下情况将会抛出异常: +需要注意的是,Tensor 必须形如矩形,即在任何一个维度上,元素的数量必须相等,否则会抛出异常,示例如下: + ``` ndim_2_Tensor = paddle.to_tensor([[1.0, 2.0], [4.0, 5.0, 6.0]]) @@ -82,14 +135,18 @@ ValueError: Faild to convert input data to a regular ndarray : - Usually this means the input data contains nested lists with different lengths. ``` +> **说明:** +> +> * 飞桨也支持将 Tensor 转换为 Python 序列数据,可通过 [paddle.tolist](../../../api/paddle/tolist_cn.html) 实现,飞桨实际的转换处理过程是 **Python 序列 <-> Numpy 数组 <-> Tensor**。 +> * 基于给定数据创建 Tensor 时,飞桨是通过拷贝方式创建,与原始数据不共享内存。 -### 1.2 指定形状创建 +### 2.2 指定形状创建 -如果要创建一个指定形状的**Tensor**,可以使用以下API: +如果要创建一个指定形状的 Tensor,可以使用 [paddle.zeros](../../../api/paddle/zeros_cn.html)、[paddle.ones](../../../api/paddle/ones_cn.html)、[paddle.full](../../../api/paddle/full_cn.html) 实现。 ```python -paddle.zeros([m, n]) # 创建数据全为0,形状为[m, n]的Tensor -paddle.ones([m, n]) # 创建数据全为1,形状为[m, n]的Tensor -paddle.full([m, n], 10) # 创建数据全为10,形状为[m, n]的Tensor +paddle.zeros([m, n]) # 创建数据全为 0,形状为 [m, n] 的 Tensor +paddle.ones([m, n]) # 创建数据全为 1,形状为 [m, n] 的 Tensor +paddle.full([m, n], 10) # 创建数据全为 10,形状为 [m, n] 的 Tensor ``` 例如,`paddle.ones([2,3])`输出如下: ```text @@ -98,36 +155,122 @@ Tensor(shape=[2, 3], dtype=float32, place=Place(gpu:0), stop_gradient=True, [1., 1., 1.]]) ``` -### 1.3 指定区间创建 -如果要在指定区间内创建**Tensor**,可以使用以下API: +### 2.3 指定区间创建 + +如果要在指定区间内创建 Tensor,可以使用[paddle.arrange](../../../api/paddle/arrange_cn.html)、 [paddle.linspace](../../../api/paddle/linspace_cn.html) 实现。 ```python paddle.arange(start, end, step) # 创建以步长step均匀分隔区间[start, end)的Tensor paddle.linspace(start, end, num) # 创建以元素个数num均匀分隔区间[start, end)的Tensor ``` -例如,`paddle.arange(start=1, end=5, step=1)`输出如下: +示例如下: + +```python +paddle.arange(start=1, end=5, step=1) +``` ```text Tensor(shape=[4], dtype=int64, place=Place(gpu:0), stop_gradient=True, [1, 2, 3, 4]) ``` +> **说明:** +> +> 除了以上指定数据、形状、区间创建 Tensor 的方法,飞桨还支持如下类似的创建方式,如: +> * **创建一个空 Tensor**,即根据 shape 和 dtype 创建尚未初始化元素值的 Tensor,可通过 [paddle.empty](../../../api/paddle/empty_cn.html) 实现。 +> * **创建一个与其他 Tensor 具有相同 shape 与 dtype 的 Tensor**,可通过 [paddle.ones_like](../../../api/paddle/ones_like_cn.html) 、 [paddle.zeros_like](../../../api/paddle/zeros_like_cn.html) 、 [paddle.full_like](../../../api/paddle/full_like_cn.html) 、[paddle.empty_like](../../../api/paddle/empty_like_cn.html) 实现。 +> * **拷贝并创建一个与其他 Tensor 完全相同的 Tensor**,可通过 [paddle.clone](../../../api/paddle/clone_cn.html) 实现。 +> * **创建一个满足特定分布的Tensor**,如 [paddle.rand](../../../api/paddle/rand_cn.html), [paddle.randn](../../../api/paddle/randn_cn.html) , [paddle.randint](../../../api/paddle/randint_cn.html) 等。 +> * **通过设置随机种子创建 Tensor**,可每次生成相同元素值的随机数 Tensor,可通过 [paddle.seed](../../../api/paddle/seed_cn.html) 和 [paddle.rand](../../../api/paddle/rand_cn.html) 组合实现。 + + + +### 2.4 指定图像、文本数据创建 + +在常见深度学习任务中,数据样本可能是图片(image)、文本(text)、语音(audio)等多种类型,在送入神经网络训练或推理前,这些数据和对应的标签均需要创建为 Tensor。以下是图像场景和 NLP 场景中手动转换 Tensor 方法的介绍。 + +* 对于图像场景,可使用 [paddle.vision.transforms.ToTensor](../../../api/paddle/vision/transforms/ToTensor_cn.html) 直接将 PIL.Image 格式的数据转为 Tensor,使用 [paddle.to_tensor](../../../api/paddle/to_tensor_cn.html) 将图像的标签(Label,通常是Python 或 Numpy 格式的数据)转为 Tensor。 +* 对于文本场景,需将文本数据解码为数字后,再通过 [paddle.to_tensor](../../../api/paddle/to_tensor_cn.html) 转为 Tensor。不同文本任务标签形式不一样,有的任务标签也是文本,有的则是数字,均需最终通过 paddle.to_tensor 转为 Tensor。 + +下面以图像场景为例介绍,以下示例代码中将随机生成的图片转换为 Tensor。 + +```python +import numpy as np +from PIL import Image +import paddle.vision.transforms as T +import paddle.vision.transforms.functional as F + +fake_img = Image.fromarray((np.random.rand(224, 224, 3) * 255.).astype(np.uint8)) # 创建随机图片 +transform = T.ToTensor() +tensor = transform(fake_img) # 使用ToTensor()将图片转换为Tensor +print(tensor) +``` + +```text +Tensor(shape=[3, 224, 224], dtype=float32, place=Place(gpu:0), stop_gradient=True, + [[[0.78039223, 0.72941178, 0.34117648, ..., 0.76470596, 0.57647061, 0.94901967], + ..., + [0.49803925, 0.72941178, 0.80392164, ..., 0.08627451, 0.97647065, 0.43137258]]]) +``` +> **说明:** +> +>实际编码时,由于飞桨数据加载的 [paddle.io.DataLoader](../../../api/paddle/io/DataLoader_cn.html) API 能够将原始 [paddle.io.Dataset](../../../api/paddle/io/Dataset_cn.html) 定义的数据自动转换为 Tensor,所以可以不做手动转换。具体如下节介绍。 + +### 2.5 自动创建 Tensor 的功能介绍 + +除了手动创建 Tensor 外,实际在飞桨框架中有一些 API 封装了 Tensor 创建的操作,从而无需用户手动创建 Tensor。例如 [paddle.io.DataLoader](../../../api/paddle/io/DataLoader_cn.html) 能够基于原始 Dataset,返回读取 Dataset 数据的迭代器,迭代器返回的数据中的每个元素都是一个 Tensor。另外在一些高层API,如 [paddle.Model.fit](../../../api/paddle/Model_cn.html) 、[paddle.Model.predict](../../../api/paddle/Model_cn.html) ,如果传入的数据不是 Tensor,会自动转为 Tensor 再进行模型训练或推理。 +> **说明:** +> +> paddle.Model.fit、paddle.Model.predict 等高层 API 支持传入 Dataset 或 DataLoader,如果传入的是 Dataset,那么会用 DataLoader 封装转为 Tensor 数据;如果传入的是 DataLoader,则直接从 DataLoader 迭代读取 Tensor 数据送入模型训练或推理。因此即使没有写将数据转为 Tensor 的代码,也能正常执行,提升了编程效率和容错性。 + +以下示例代码中,分别打印了原始数据集的数据,和送入 DataLoader 后返回的数据,可以看到数据结构由 Python list 转为了 Tensor。 +```python +import paddle + +from paddle.vision.transforms import Compose, Normalize + +transform = Compose([Normalize(mean=[127.5], + std=[127.5], + data_format='CHW')]) + +test_dataset = paddle.vision.datasets.MNIST(mode='test', transform=transform) +print(test_dataset[0][1]) # 打印原始数据集的第一个数据的label +loader = paddle.io.DataLoader(test_dataset) +for data in enumerate(loader): + x, label = data[1] + print(label) # 打印由DataLoader返回的迭代器中的第一个数据的label + break +``` +```text +[7] # 原始数据中label为Python list +Tensor(shape=[1, 1], dtype=int64, place=Place(gpu_pinned), stop_gradient=True, + [[7]]) # 由DataLoader转换后,label为Tensor +``` -## 二、Tensor的属性 +## 三、Tensor 的属性 -### 2.1 Tensor的形状 +在前文中,可以看到打印 Tensor 时有 shape、dtype、place 等信息,这些都是 Tensor 的重要属性,想要了解如何操作 Tensor 需要对其属性有一定了解,接下来分别展开介绍 Tensor 的属性相关概念。 +```text +Tensor(shape=[3], dtype=float32, place=Place(gpu:0), stop_gradient=True, + [2., 3., 4.]) +``` -查看一个**Tensor**的形状可以通过 **Tensor.shape**,形状是 **Tensor** 的一个重要属性,以下为相关概念: +### 3.1 Tensor的形状(shape) -1. shape:描述了Tensor每个维度上元素的数量 -2. ndim: Tensor的维度数量,例如向量的维度为1,矩阵的维度为2,Tensor可以有任意数量的维度 -3. axis或者dimension:指Tensor某个特定的维度 -4. size:指Tensor中全部元素的个数 +**(1)形状的介绍** -创建1个四维 **Tensor**,并通过图形来直观表达以上几个概念之间的关系; +形状是 Tensor 的一个重要的基础属性,可以通过 [Tensor.shape](../../../api/paddle/Tensor_cn.html#shape) 查看一个 Tensor 的形状,以下为相关概念: + + * shape:描述了 Tensor 每个维度上元素的数量。 + * ndim: Tensor 的维度数量,例如向量的维度为 1,矩阵的维度为2,Tensor 可以有任意数量的维度。 + * axis 或者 dimension:Tensor 的轴,即某个特定的维度。 + * size:Tensor 中全部元素的个数。 + +创建 1 个四维 Tensor ,并通过图形来直观表达以上几个概念之间的关系: ```python ndim_4_Tensor = paddle.ones([2, 3, 4, 5]) ``` -
+ +

图2 Tensor的shape、axis、dimension、ndim之间的关系
```python @@ -144,66 +287,97 @@ Shape of Tensor: [2, 3, 4, 5] Elements number along axis 0 of Tensor: 2 Elements number along the last axis of Tensor: 5 ``` +**(2)重置 Tensor 形状(Reshape) 的方法** + +重新设置 Tensor 的 shape 在深度学习任务中比较常见,如一些计算类 API 会对输入数据有特定的形状要求,这时可通过 [paddle.reshape](../../../api/paddle/reshape_cn.html) 接口来改变 Tensor 的 shape,但并不改变 Tensor 的 size 和其中的元素数据。 -重新设置**Tensor**的shape在实际编程中具有重要意义,Paddle提供了reshape接口来改变Tensor的shape: + +以下示例代码中,创建 1 个 `shape=[3]` 的一维 Tensor,使用 reshape 功能将该 Tensor 重置为 `shape=[1, 3]` 的二维 Tensor。这种做法经常用在把一维的标签(label)数据扩展为二维,由于飞桨框架中神经网络通常需要传入一个 batch 的数据进行计算,因此可将数据增加一个 batch 维,方便后面的数据计算。 ```python -ndim_3_Tensor = paddle.to_tensor([[[1, 2, 3, 4, 5], - [6, 7, 8, 9, 10]], - [[11, 12, 13, 14, 15], - [16, 17, 18, 19, 20]], - [[21, 22, 23, 24, 25], - [26, 27, 28, 29, 30]]]) -print("the shape of ndim_3_Tensor:", ndim_3_Tensor.shape) +ndim_1_Tensor = paddle.to_tensor([1, 2, 3]) +print("the shape of ndim_1_Tensor:", ndim_1_Tensor.shape) -reshape_Tensor = paddle.reshape(ndim_3_Tensor, [2, 5, 3]) +reshape_Tensor = paddle.reshape(ndim_1_Tensor, [1, 3]) print("After reshape:", reshape_Tensor.shape) ``` ```text -the shape of ndim_3_Tensor: [3, 2, 5] -After reshape: [2, 5, 3] +the shape of ndim_1_Tensor: [3] +After reshape: [1, 3] ``` -在指定新的shape时存在一些技巧: +在指定新的 shape 时存在一些技巧: + * `-1` 表示这个维度的值是从 Tensor 的元素总数和剩余维度自动推断出来的。因此,有且只有一个维度可以被设置为 -1。 + * `0` 表示该维度的元素数量与原值相同,因此 shape 中 0 的索引值必须小于 Tensor 的维度(索引值从 0 开始计,如第 1 维的索引值是 0,第二维的索引值是 1)。 -**1.** -1 表示这个维度的值是从Tensor的元素总数和剩余维度推断出来的。因此,有且只有一个维度可以被设置为-1。 - -**2.** 0 表示实际的维数是从Tensor的对应维数中复制出来的,因此shape中0的索引值不能超过Tensor的维度。 - -有一些例子可以很好解释这些技巧: +通过几个例子来详细了解: ```text -origin:[3, 2, 5] reshape:[3, 10] actual: [3, 10] -origin:[3, 2, 5] reshape:[-1] actual: [30] -origin:[3, 2, 5] reshape:[0, 5, -1] actual: [3, 5, 2] +origin:[3, 2, 5] reshape:[3, 10] actual: [3, 10] # 直接指定目标 shape +origin:[3, 2, 5] reshape:[-1] actual: [30] # 转换为1维,维度根据元素总数推断出来是3*2*5=30 +origin:[3, 2, 5] reshape:[-1, 5] actual: [6, 5] # 转换为2维,固定一个维度5,另一个维度根据元素总数推断出来是30÷5=6 +origin:[3, 2, 5] reshape:[0, -1] actual: [3, 6] # reshape:[0, -1]中0的索引值为0,按照规则,转换后第0维的元素数量与原始Tensor第0维的元素数量相同,为3;第1维的元素数量根据元素总值计算得出为30÷3=10。 +origin:[3, 2] reshape:[3, 1, 0] error: # reshape:[3, 1, 0]中0的索引值为2,但原Tensor只有2维,无法找到与第3维对应的元素数量,因此出错。 ``` -可以发现,reshape为[-1]时,会将Tensor按其在计算机上的内存分布展平为一维。 +从上面的例子可以看到,通过 reshape:[-1] ,可以很方便地将 Tensor 按其在计算机上的内存分布展平为一维。 ```python print("Tensor flattened to Vector:", paddle.reshape(ndim_3_Tensor, [-1]).numpy()) ``` ```text Tensor flattened to Vector: [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30] ``` -### 2.2 Tensor的数据类型 +> **说明:** +> +> 除了 paddle.reshape 可重置 Tensor 的形状,还可通过如下方法改变 shape: +> * [paddle.squeeze](../../../api/paddle/squeeze_cn.html),可实现 Tensor 的降维操作,即把 Tensor 中尺寸为 1 的维度删除。 +> * [paddle.unsqueeze](../../../api/paddle/unsqueeze_cn.html),可实现 Tensor 的升维操作,即向 Tensor 中某个位置插入尺寸为 1 的维度。 +> * [paddle.flatten](../../../api/paddle/flatten_cn.html),将 Tensor 的数据在指定的连续维度上展平。 +> * [transpose](../../../api/paddle/transpose_cn.html),对 Tensor 的数据进行重排。 -**Tensor**的数据类型,可以通过 Tensor.dtype 来查看,dtype支持:'bool', 'float16', 'float32', 'float64', 'uint8', 'int8', 'int16', 'int32', 'int64'。 +**(3)原位(Inplace)操作和非原位操作的区别** -* 通过Python元素创建的Tensor,可以通过dtype来进行指定,如果未指定: +飞桨框架的 API 有原位(Inplace)操作和非原位操作之分,原位操作即在原 Tensor 上保存操作结果,输出 Tensor 将与输入Tensor 共享数据,并且没有 Tensor 数据拷贝的过程。非原位操作则不会修改原 Tensor,而是返回一个新的 Tensor。通过 API 名称区分两者,如 [paddle.reshape](../../../api/paddle/reshape_cn.html) 是非原位操作,[paddle.reshape_](../../../api/paddle/reshape__cn.html) 是原位操作。 - * 对于python整型数据,则会创建int64型Tensor - * 对于python浮点型数据,默认会创建float32型Tensor,并且可以通过set_default_type来调整浮点型数据的默认类型。 +下面以 reshape 为例说明,通过对比Tensor的 name (每个 Tensor 创建时都会有一个独一无二的 name),判断是否为同一个Tensor。 +```python +origin_tensor = paddle.to_tensor([1, 2, 3]) +new_tensor = paddle.reshape(origin_tensor, [1, 3]) # 非原位操作 +same_tensor = paddle.reshape_(origin_tensor, [1, 3]) # 原位操作 +print("origin_tensor name: ", origin_tensor.name) +print("new_tensor name: ", new_tensor.name) +print("same_tensor name: ", same_tensor.name) +``` +```text +origin_tensor name: generated_tensor_0 +new_tensor name: auto_0_ # 非原位操作后产生的Tensor与原始Tensor的名称不同 +same_tensor name: generated_tensor_0 # 原位操作后产生的Tensor与原始Tensor的名称相同 +``` + +### 3.2 Tensor的数据类型(dtype) +**(1)指定数据类型的介绍** + +Tensor 的数据类型 dtype 可以通过 [Tensor.dtype](../../../api/paddle/Tensor_cn.html#dtype) 查看,支持类型包括:`bool`、`float16`、`float32`、`float64`、`uint8`、`int8`、`int16`、`int32`、`int64`、`complex64`、`complex128`。 -* 通过Numpy数组创建的Tensor,则与其原来的数据类型保持相同。 +同一 Tensor 中所有元素的数据类型均相同,通常通过如下方式指定: +* 通过给定 Python 序列创建的 Tensor,可直接使用 dtype 参数指定。如果未指定: + + * 对于 Python 整型数据,默认会创建 `int64` 型 Tensor; + * 对于 Python 浮点型数据,默认会创建 `float32` 型 Tensor,并且可以通过 [paddle.set_default_dtype](../../../api/paddle/set_default_dtype_cn.html) 来调整浮点型数据的默认类型。 ```python +# 创建Tensor时指定dtype +ndim_1_tensor = paddle.to_tensor([2.0, 3.0, 4.0], dtype='float64') +print("Tensor dtype of ndim_1_tensor:", ndim_1_tensor.dtype) +# 创建Tensor时不指定dtype,自动选择对应的默认类型 print("Tensor dtype from Python integers:", paddle.to_tensor(1).dtype) print("Tensor dtype from Python floating point:", paddle.to_tensor(1.0).dtype) ``` ```text +Tensor dtype of ndim_1_tensor: paddle.float64 Tensor dtype from Python integers: paddle.int64 Tensor dtype from Python floating point: paddle.float32 ``` - -**Tensor**不仅支持 floats、ints 类型数据,也支持复数类型数据。如果输入为复数,则**Tensor**的dtype为 ``complex64`` 或 ``complex128`` ,其每个元素均为1个复数: +* 通过 Numpy 数组或其他 Tensor 创建的 Tensor,则与其原来的数据类型保持相同。 +* Tensor 不仅支持 float、int 类型数据,也支持 complex 复数类型数据。如果输入为复数,则 Tensor 的 dtype 为 ``complex64`` 或 ``complex128`` ,其每个元素均为 1 个复数。如果未指定,默认数据类型是``complex64``: ```python ndim_2_Tensor = paddle.to_tensor([[(1+1j), (2+2j)], @@ -216,8 +390,9 @@ Tensor(shape=[2, 2], dtype=complex64, place=Place(gpu:0), stop_gradient=True, [[(1+1j), (2+2j)], [(3+3j), (4+4j)]]) ``` +**(2)修改数据类型的方法** -Paddle提供了**cast**接口来改变dtype: +飞桨框架提供了[paddle.cast](../../../api/paddle/cast_cn.html) 接口来改变 Tensor 的 dtype: ```python float32_Tensor = paddle.to_tensor(1.0) @@ -231,12 +406,14 @@ print("Tensor after cast to int64:", int64_Tensor.dtype) Tensor after cast to float64: paddle.float64 Tensor after cast to int64: paddle.int64 ``` +### 3.3 Tensor的设备位置(place) +初始化 Tensor 时可以通过 [Tensor.place](../../../api/paddle/Tensor_cn.html#place) 来指定其分配的设备位置,可支持的设备位置有:CPU、GPU、固定内存、XPU(Baidu Kunlun)、NPU(Huawei)、MLU(寒武纪)、IPU(Graphcore)等。其中固定内存也称为不可分页内存或锁页内存,其与 GPU 之间具有更高的读写效率,并且支持异步传输,这对网络整体性能会有进一步提升,但其缺点是分配空间过多时可能会降低主机系统的性能,因为其减少了用于存储虚拟内存数据的可分页内存。 +> **说明:** +> +> * 当未指定 place 时,Tensor 默认设备位置和安装的飞桨框架版本一致。如安装了 GPU 版本的飞桨,则设备位置默认为 GPU,即 Tensor 的`place` 默认为 [paddle.CUDAPlace](../../../api/paddle/CUDAPlace_cn.html)。 +> * 使用 [paddle.device.set_device](../../../api/paddle/device/set_device_cn.html) 可设置全局默认的设备位置。Tensor.place 的指定值优先级高于全局默认值。 -### 2.3 Tensor的设备位置 - -初始化**Tensor**时可以通过**place**来指定其分配的设备位置,可支持的设备位置有三种:CPU/GPU/固定内存,其中固定内存也称为不可分页内存或锁页内存,其与GPU之间具有更高的读写效率,并且支持异步传输,这对网络整体性能会有进一步提升,但其缺点是分配空间过多时可能会降低主机系统的性能,因为其减少了用于存储虚拟内存数据的可分页内存。当未指定place时,Tensor默认设备位置和安装的Paddle版本一致,如安装了GPU版本的Paddle,则设备位置默认为GPU。 - -以下示例分别创建了CPU、GPU和固定内存上的Tensor,并通过 `Tensor.place` 查看Tensor所在的设备位置: +以下示例分别创建了CPU、GPU和固定内存上的 Tensor,并通过 `Tensor.place` 查看 Tensor 所在的设备位置: * **创建CPU上的Tensor** ```python @@ -268,9 +445,9 @@ print(pin_memory_Tensor.place) Place(gpu_pinned) ``` -### 2.4 Tensor的名称 +### 3.4 Tensor的名称(name) -Tensor的名称是其唯一的标识符,为python字符串类型,查看一个Tensor的名称可以通过Tensor.name属性。默认地,在每个Tensor创建时,Paddle会自定义一个独一无二的名称。 +Tensor 的名称是其唯一的标识符,为 Python 字符串类型,查看一个 Tensor 的名称可以通过 Tensor.name 属性。默认地,在每个Tensor 创建时,会自定义一个独一无二的名称。 ```python print("Tensor name:", paddle.to_tensor(1).name) @@ -278,21 +455,34 @@ print("Tensor name:", paddle.to_tensor(1).name) ```text Tensor name: generated_tensor_0 ``` +### 3.5 Tensor 的 stop_gradient 属性 +stop_gradient 表示是否停止计算梯度,默认值为 True,表示停止计算梯度,梯度不再回传。在设计网络时,如不需要对某些参数进行训练更新,可以将参数的stop_gradient设置为True。可参考以下代码直接设置 stop_gradient 的值。 + +```python +eg = paddle.to_tensor(1) +print("Tensor stop_gradient:", eg.stop_gradient) +eg.stop_gradient = False +print("Tensor stop_gradient:", eg.stop_gradient) +``` +```text +Tensor stop_gradient: True +Tensor stop_gradient: False +``` -## 三、Tensor的操作 +## 四、Tensor的操作 -### 3.1 索引和切片 -您可以通过索引或切片方便地访问或修改 Tensor。Paddle 使用标准的 Python 索引规则与 Numpy 索引规则,与 [Indexing a list or a string in Python](https://docs.python.org/3/tutorial/introduction.html#strings)类似。具有以下特点: +### 4.1 索引和切片 +通过索引或切片方式可访问或修改 Tensor。飞桨框架使用标准的 Python 索引规则与 Numpy 索引规则,与 [Indexing a list or a string in Python](https://docs.python.org/3/tutorial/introduction.html#strings) 类似。具有以下特点: -1. 基于 0-n 的下标进行索引,如果下标为负数,则从尾部开始计算 -2. 通过冒号 ``:`` 分隔切片参数 ``start:stop:step`` 来进行切片操作,其中 start、stop、step 均可缺省 +1. 基于 0-n 的下标进行索引,如果下标为负数,则从尾部开始计算。 +2. 通过冒号 ``:`` 分隔切片参数,``start:stop:step`` 来进行切片操作,其中 start、stop、step 均可缺省。 -#### 访问 Tensor -* 针对一维 **Tensor**,则仅有单个轴上的索引或切片: +#### 4.1.1 访问 Tensor +* 针对一维 Tensor,仅有单个维度上的索引或切片: ```python ndim_1_Tensor = paddle.to_tensor([0, 1, 2, 3, 4, 5, 6, 7, 8]) -print("Origin Tensor:", ndim_1_Tensor.numpy()) -print("First element:", ndim_1_Tensor[0].numpy()) +print("Origin Tensor:", ndim_1_Tensor.numpy()) # 原始1维Tensor +print("First element:", ndim_1_Tensor[0].numpy()) # 取Tensor第一个元素的值? print("Last element:", ndim_1_Tensor[-1].numpy()) print("All element:", ndim_1_Tensor[:].numpy()) print("Before 3:", ndim_1_Tensor[:3].numpy()) @@ -313,6 +503,7 @@ Interval of 3: [0 3 6] Reverse: [8 7 6 5 4 3 2 1 0] ``` + * 针对二维及以上的 **Tensor**,则会有多个维度上的索引或切片: ```python ndim_2_Tensor = paddle.to_tensor([[0, 1, 2, 3], @@ -340,7 +531,7 @@ All element: [[ 0 1 2 3] First row and second column: [1] ``` -索引或切片的第一个值对应第 0 维,第二个值对应第 1 维,以此类推,如果某个维度上未指定索引,则默认为 ``:`` 。例如: +索引或切片的第一个值对应第 0 维,第二个值对应第 1 维,依次类推,如果某个维度上未指定索引,则默认为 ``:`` 。例如: ```python ndim_2_Tensor[1] ndim_2_Tensor[1, :] @@ -352,13 +543,12 @@ Tensor(shape=[4], dtype=int64, place=Place(gpu:0), stop_gradient=True, [4, 5, 6, 7]) ``` -#### 修改 Tensor +#### 4.1.2 修改 Tensor +与访问 Tensor 类似,修改 Tensor 可以在单个或多个维度上通过索引或切片操作。同时,支持将多种类型的数据赋值给该 Tensor,当前支持的数据类型有:`int`,`float`,`numpy.ndarray`,`omplex`,`Tensor`。 > **注意:** > -> 请慎重通过索引或切片修改 Tensor,该操作会**原地**修改该 Tensor 的数值,且原值不会被保存。如果被修改的 Tensor 参与梯度计算,将仅会使用修改后的数值,这可能会给梯度计算引入风险。Paddle 之后将会对具有风险的操作进行检测和报错。 - -与访问 Tensor 类似,修改 Tensor 可以在单个或多个轴上通过索引或切片操作。同时,支持将多种类型的数据赋值给该 Tensor,当前支持的数据类型有:`int`, `float`, `numpy.ndarray`, `Tensor`。 +> 请慎重通过索引或切片修改 Tensor,该操作会**原地**修改该 Tensor 的数值,且原值不会被保存。如果被修改的 Tensor 参与梯度计算,仅会使用修改后的数值,这可能会给梯度计算引入风险。飞桨框架会自动检测不当的原位(inplace)使用并报错。 ```python import numpy as np @@ -376,7 +566,7 @@ x[1] = paddle.ones([3]) # x : [[1., 2., 3.], [1., 1., 1.]] --- -同时,Paddle 还提供了丰富的 Tensor 操作的 API,包括数学运算、逻辑运算、线性代数等100余种 API,这些 API 调用有两种方法: +同时,飞桨还提供了丰富的 Tensor 操作的 API,包括数学运算、逻辑运算、线性代数等100余种 API,这些 API 调用有两种方法: ```python x = paddle.to_tensor([[1.1, 2.2], [3.3, 4.4]], dtype="float64") y = paddle.to_tensor([[5.5, 6.6], [7.7, 8.8]], dtype="float64") @@ -395,9 +585,9 @@ Tensor(shape=[2, 2], dtype=float64, place=Place(gpu:0), stop_gradient=True, [11. , 13.20000000]]) ``` -可以看出,使用 **Tensor 类成员函数** 和 **Paddle API** 具有相同的效果,由于 **类成员函数** 操作更为方便,以下均从 **Tensor 类成员函数** 的角度,对常用 **Tensor** 操作进行介绍。 +可以看出,使用 **Tensor 类成员函数** 和 **Paddle API** 具有相同的效果,由于 **类成员函数** 操作更为方便,以下均从 **Tensor 类成员函数** 的角度,对常用 Tensor 操作进行介绍。 -### 3.2 数学运算 +### 4.2 数学运算 ```python x.abs() #逐元素取绝对值 x.ceil() #逐元素向上取整 @@ -422,7 +612,7 @@ x.prod() #指定维度上元素累乘,默认为全部维 x.sum() #指定维度上元素的和,默认为全部维度 ``` -Paddle对python数学运算相关的魔法函数进行了重写,例如: +飞桨框架对 Python 数学运算相关的魔法函数进行了重写,例如: ```text x + y -> x.add(y) #逐元素相加 x - y -> x.subtract(y) #逐元素相减 @@ -432,7 +622,7 @@ x % y -> x.mod(y) #逐元素相除并取余 x ** y -> x.pow(y) #逐元素幂运算 ``` -### 3.3 逻辑运算 +### 4.3 逻辑运算 ```python x.isfinite() #判断Tensor中元素是否是有限的数字,即不包括inf与nan x.equal_all(y) #判断两个Tensor的全部元素是否相等,并返回形状为[1]的布尔类Tensor @@ -445,7 +635,7 @@ x.greater_equal(y) #判断Tensor x的元素是否大于或等于Tenso x.allclose(y) #判断Tensor x的全部元素是否与Tensor y的全部元素接近,并返回形状为[1]的布尔类Tensor ``` -同样地,Paddle对python逻辑比较相关的魔法函数进行了重写,以下操作与上述结果相同。 +同样地,飞桨框架对 Python 逻辑比较相关的魔法函数进行了重写,以下操作与上述结果相同。 ```text x == y -> x.equal(y) #判断两个Tensor的每个元素是否相等 x != y -> x.not_equal(y) #判断两个Tensor的每个元素是否不相等 @@ -455,7 +645,7 @@ x > y -> x.greater_than(y) #判断Tensor x的元素是否大于Tensor y的对 x >= y -> x.greater_equal(y) #判断Tensor x的元素是否大于或等于Tensor y的对应元素 ``` -以下操作仅针对bool型Tensor: +以下操作仅针对 bool 型Tensor: ```python x.logical_and(y) #对两个布尔类型Tensor逐元素进行逻辑与操作 x.logical_or(y) #对两个布尔类型Tensor逐元素进行逻辑或操作 @@ -463,7 +653,7 @@ x.logical_xor(y) #对两个布尔类型Tensor逐元素进行逻辑 x.logical_not(y) #对两个布尔类型Tensor逐元素进行逻辑非操作 ``` -### 3.4 线性代数 +### 4.4 线性代数 ```python x.t() #矩阵转置 x.transpose([1, 0]) #交换第 0 维与第 1 维的顺序 @@ -474,54 +664,34 @@ x.matmul(y) #矩阵乘法 > **注意** > -> Paddle中API有原位(inplace)操作和非原位操作之分。原位操作即在原**Tensor**上保存操作结果,非原位(inplace)操作则不会修改原**Tensor**,而是返回一个新的**Tensor**来表示运算结果。在Paddle2.1后,部分API有对应的原位操作版本,在API后加上 `_` 表示,如`x.add(y)`是非原位操作,`x.add_(y)`为原位操作。 +> 以上计算 API 也有原位(inplace)操作和非原位操作之分,如`x.add(y)`是非原位操作,`x.add_(y)`为原位操作。 -更多Tensor操作相关的API,请参考 [class paddle.Tensor](../../../api/paddle/Tensor_cn.html) -## 四、Tensor 与 numpy数组 相互转换 -### 4.1 Tensor转换为numpy数组 -通过 Tensor.numpy() 方法,将 **Tensor** 转化为 **Numpy数组**: -```python -tensor_to_convert = paddle.to_tensor([1.,2.]) -tensor_to_convert.numpy() -``` -```text -array([1., 2.], dtype=float32) -``` -### 4.2 numpy数组转换为Tensor -通过paddle.to_tensor() 方法,将 **Numpy数组** 转化为 **Tensor**: -```python -tensor_temp = paddle.to_tensor(np.array([1.0, 2.0])) -print(tensor_temp) -``` -```text -Tensor(shape=[2], dtype=float64, place=Place(gpu:0), stop_gradient=True, - [1., 2.]) -``` -创建的 **Tensor** 与原 **Numpy array** 具有相同的形状与数据类型。 +## 五、Tensor 的广播机制 -## 五、Tensor 的广播操作 -Paddle和其他框架一样,提供的一些API支持广播(broadcasting)机制,允许在一些运算时使用不同形状的Tensor。 -通常来讲,如果有一个形状较小和一个形状较大的Tensor,会希望多次使用较小的Tensor来对较大的Tensor执行一些操作,看起来像是较小形状的Tensor的形状首先被扩展到和较大形状的Tensor一致,然后做运算。值得注意的是,这期间并没有对较小形状Tensor的数据拷贝操作。 +在深度学习任务中,有时需要使用较小形状的 Tensor 与较大形状的 Tensor 执行计算,广播机制就是将较小形状的 Tensor 扩展到与较大形状的 Tensor 一样的形状,便于匹配计算,同时又没有对较小形状 Tensor 进行数据拷贝操作,从而提升算法实现的运算效率。 +飞桨框架提供的一些API支持广播(broadcasting)机制,允许在一些运算时使用不同形状的 Tensor。 +飞桨 Tensor 的广播机制主要遵循如下规则(参考 [Numpy 广播机制](https://numpy.org/doc/stable/user/basics.broadcasting.html#module-numpy.doc.broadcasting)): -Paddle的广播机制主要遵循如下规则(参考 [Numpy 广播机制](https://numpy.org/doc/stable/user/basics.broadcasting.html#module-numpy.doc.broadcasting)): +* 每个 Tensor 至少为一维 Tensor +* 从最后一个维度向前开始比较两个 Tensor 的形状,需要满足如下条件才能进行广播:两个 Tensor 的维度大小相等;或者其中一个 Tensor 的维度等于 1;或者其中一个 Tensor 的维度不存在。 -1. 每个Tensor至少为一维Tensor -2. 从后往前比较Tensor的形状,当前维度的大小要么相等,要么其中一个等于一,要么其中一个不存在 - -例如: +举例如下: ```python +# 可以广播的例子1 x = paddle.ones((2, 3, 4)) y = paddle.ones((2, 3, 4)) # 两个Tensor 形状一致,可以广播 z = x + y print(z.shape) # [2, 3, 4] - +``` +```python +# 可以广播的例子2 x = paddle.ones((2, 3, 1, 5)) y = paddle.ones((3, 4, 1)) -# 从后向前依次比较: +# 从最后一个维度向前依次比较: # 第一次:y的维度大小是1 # 第二次:x的维度大小是1 # 第三次:x和y的维度大小相等 @@ -530,31 +700,64 @@ y = paddle.ones((3, 4, 1)) z = x + y print(z.shape) # [2, 3, 4, 5] - -# 相反 +``` +```python +# 不可广播的例子 x = paddle.ones((2, 3, 4)) y = paddle.ones((2, 3, 6)) -# 此时x和y是不可广播的,因为第一次比较 4不等于6 +# 此时x和y是不可广播的,因为第一次比较:4不等于6 # z = x + y # ValueError: (InvalidArgument) Broadcast dimension mismatch. ``` -现在你知道什么情况下两个Tensor是可以广播的,两个Tensor进行广播语义后的结果Tensor的形状计算规则如下: +在了解两个 Tensor 在什么情况下可以广播的规则后,两个Tensor进行广播语义后的结果Tensor的形状计算规则如下: -1. 如果两个Tensor的形状的长度不一致,那么需要在较小形状长度的矩阵向前添加1,直到两个Tensor的形状长度相等。 -2. 保证两个Tensor形状相等之后,每个维度上的结果维度就是当前维度上较大的那个。 +* 如果两个Tensor的形状的长度不一致,会在较小长度的形状矩阵前部添加1,直到两个Tensor的形状长度相等。 +* 保证两个Tensor形状相等之后,每个维度上的结果维度就是当前维度上的较大值。 -例如: +举例如下: ```python x = paddle.ones((2, 1, 4)) -y = paddle.ones((3, 1)) +y = paddle.ones((3, 1)) # y的形状长度为2,小于x的形状长度3,因此会在y的形状前部添加1,结果就是y的形状变为[1, 3, 1] z = x + y print(z.shape) -# z的形状: [2,3,4] +# z的形状: [2,3,4],z的每一维度上的尺寸,将取x和y对应维度上尺寸的较大值,如第0维x的尺寸为2,y的尺寸为1,则z的第0维尺寸为2 +``` -x = paddle.ones((2, 1, 4)) -y = paddle.ones((3, 2)) -# z = x + y -# ValueError: (InvalidArgument) Broadcast dimension mismatch. + +
+
图3 Tensor 广播示例
+ +## 六、Tensor 与 Numpy 数组相互转换 + +如果你已熟悉 Numpy,通过以下要点,可以方便地理解和迁移到 Tensor 的使用上: +* Tensor 的很多基础操作 API 和 Numpy 在功能、用法上基本保持一致。如前文中介绍的指定数据、形状、区间创建 Tensor,Tensor 的形状、数据类型属性,Tensor 的各种操作,以及 Tensor 的广播,可以很方便地在 Numpy 中找到相似操作。 +* 但是,Tensor 也有一些独有的属性和操作,而 Numpy 中没有对应概念或功能,这是为了更好地支持深度学习任务。如前文中介绍的通过图像、文本等原始数据手动或自动创建 Tensor 的功能,能够更便捷地处理数据,Tensor 的设备位置属性,可以很方便地将 Tensor 迁移到 GPU 或各种 AI 加速硬件上,Tensor 的 stop_gradient 属性,也是 Tensor 独有的,以便更好地支持深度学习任务。 + +如果已有 Numpy 数组,可使用 [paddle.to_tensor](../../../api/paddle/to_tensor_cn.html) 创建任意维度的 Tensor,创建的 Tensor 与原 Numpy 数组具有相同的形状与数据类型。 +```python +tensor_temp = paddle.to_tensor(np.array([1.0, 2.0])) +print(tensor_temp) ``` +```text +Tensor(shape=[2], dtype=float64, place=Place(gpu:0), stop_gradient=True, + [1., 2.]) +``` +> **注意:** +> +> * 基于 Numpy 数组创建 Tensor 时,飞桨是通过拷贝方式创建,与原始数据不共享内存。 + + +相对应地,飞桨也支持将 Tensor 转换为 Numpy 数组,可通过 [Tensor.numpy](../../../api/paddle/Tensor_cn.html#numpy) 方法实现。 +```python +tensor_to_convert = paddle.to_tensor([1.,2.]) +tensor_to_convert.numpy() +``` +```text +array([1., 2.], dtype=float32) +``` + +## 七、总结 + +Tensor 作为飞桨框架中重要的数据结构,具有丰富的 API 用以对 Tensor 进行创建、访问、修改、计算等一系列操作,从而满足深度学习任务的需要。更多 Tensor 相关的介绍,请参考 [paddle.Tensor](../../../api/paddle/Tensor_cn.html) API 文档。 diff --git a/docs/guides/09_hardware_support/hardware_info_cn.md b/docs/guides/09_hardware_support/hardware_info_cn.md index 9d2663a9bd7..369e504d1ab 100644 --- a/docs/guides/09_hardware_support/hardware_info_cn.md +++ b/docs/guides/09_hardware_support/hardware_info_cn.md @@ -10,7 +10,7 @@ | 服务端GPU | | NVIDIA | 常见GPU型号如V100、T4等| [安装](https://www.paddlepaddle.org.cn/install/quick?docurl=/documentation/docs/zh/2.0/install/pip/linux-pip.html) | [源码编译](https://www.paddlepaddle.org.cn/install/quick?docurl=/documentation/docs/zh/2.0/install/compile/linux-compile.html) | ✔️ | | | AI加速芯片 | 达芬奇 | 华为 | 昇腾910 | 即将提供 | | | | | AI加速芯片 | | 海光 | 海光DCU | [安装](https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/guides/rocm_docs/paddle_install_cn.html) | [源码编译](https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/guides/rocm_docs/paddle_install_cn.html) | ✔️ | [支持模型](https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/guides/rocm_docs/paddle_rocm_cn.html) | -| AI加速芯片 | XPU | 百度 | 昆仑K100、K200等 | [安装](https://www.paddlepaddle.org.cn/documentation/docs/zh/guides/xpu_docs/paddle_install_cn.html#wheel) | [源码编译](https://www.paddlepaddle.org.cn/documentation/docs/zh/guides/xpu_docs/paddle_install_cn.html#id2) | | [支持模型](https://www.paddlepaddle.org.cn/documentation/docs/zh/guides/xpu_docs/paddle_2.0_xpu_cn.html) | +| AI加速芯片 | XPU | 百度 | 昆仑K200、R200等 | [安装](https://www.paddlepaddle.org.cn/documentation/docs/zh/guides/xpu_docs/paddle_install_cn.html#wheel) | [源码编译](https://www.paddlepaddle.org.cn/documentation/docs/zh/guides/xpu_docs/paddle_install_cn.html#id2) | | [支持模型](https://www.paddlepaddle.org.cn/documentation/docs/zh/guides/xpu_docs/paddle_2.0_xpu_cn.html) | | AI加速芯片 | IPU | Graphcore | GC200 | | [源码编译](/documentation/docs/guides/09_hardware_support/ipu_docs/index_cn.html) | | | ## Paddle Inference @@ -21,12 +21,12 @@ | 服务端GPU | | NVIDIA | 常见GPU型号如V100、T4等 | [预编译库](https://paddleinference.paddlepaddle.org.cn/user_guides/download_lib.html) | [源码编译](https://paddleinference.paddlepaddle.org.cn/user_guides/source_compile.html) | ✔️ | | | 移动端GPU | | NVIDIA | Jetson系列 | [预编译库](https://paddleinference.paddlepaddle.org.cn/user_guides/download_lib.html) | [源码编译](https://paddleinference.paddlepaddle.org.cn/user_guides/source_compile.html) | ✔️ | | | AI加速芯片 | 达芬奇 | 华为 | 昇腾910 | 即将提供 | | | | -| AI加速芯片 | | 海光 | 海光DCU | [预编译库](https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/guides/rocm_docs/paddle_install_cn.html) | [源码编译](https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/guides/rocm_docs/paddle_install_cn.html) | ✔️ | [支持模型](https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/guides/rocm_docs/paddle_rocm_cn.html) | -| AI加速芯片 | XPU | 百度 | 昆仑K100、K200等 | [预编译库](https://www.paddlepaddle.org.cn/documentation/docs/zh/guides/xpu_docs/paddle_install_cn.html#wheel) | [源码编译](https://www.paddlepaddle.org.cn/documentation/docs/zh/guides/xpu_docs/paddle_install_cn.html#id2) | | [支持模型](https://www.paddlepaddle.org.cn/documentation/docs/zh/guides/xpu_docs/paddle_2.0_xpu_cn.html) | -| 服务端CPU | ARM | 飞腾 | FT-2000+/64 | |[源码编译](https://www.paddlepaddle.org.cn/install/quick?docurl=/documentation/docs/zh/2.0/install/compile/arm-compile.html#anchor-1) | | [支持模型](https://www.paddlepaddle.org.cn/install/quick?docurl=/documentation/docs/zh/2.0/install/compile/arm-compile.html#anchor-6) | +| AI加速芯片 | | 海光 | 海光DCU | [预编译库](https://www.paddlepaddle.org.cn/documentation/docs/zh/guides/09_hardware_support/rocm_docs/paddle_install_cn.html) | [源码编译](https://www.paddlepaddle.org.cn/documentation/docs/zh/guides/09_hardware_support/rocm_docs/paddle_install_cn.html) | ✔️ | [支持模型](https://www.paddlepaddle.org.cn/documentation/docs/zh/guides/09_hardware_support/rocm_docs/paddle_rocm_cn.html) | +| AI加速芯片 | XPU | 百度 | 昆仑K200、R200等 | [预编译库](https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/guides/09_hardware_support/xpu_docs/inference_install_example_cn.html#wheel) | [源码编译](https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/guides/09_hardware_support/xpu_docs/paddle_install_cn.html#id2) | | [支持模型](https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/guides/09_hardware_support/xpu_docs/paddle_2.0_xpu_cn.html#xunlianzhichi) | +| 服务端CPU | ARM | 飞腾 | FT-2000+/64、S2500 | |[源码编译](https://www.paddlepaddle.org.cn/documentation/docs/zh/install/compile/arm-compile.html#anchor-1) | | [支持模型](https://www.paddlepaddle.org.cn/install/quick?docurl=/documentation/docs/zh/2.0/install/compile/arm-compile.html#anchor-6) | | 服务端CPU | ARM | 华为 | 鲲鹏 920 2426SK | |[源码编译](https://www.paddlepaddle.org.cn/install/quick?docurl=/documentation/docs/zh/2.0/install/compile/arm-compile.html#anchor-1) | | [支持模型](https://www.paddlepaddle.org.cn/install/quick?docurl=/documentation/docs/zh/2.0/install/compile/arm-compile.html#anchor-6) | -| 服务端CPU | MIPS | 龙芯 | 龙芯3A4000 | |[源码编译](https://www.paddlepaddle.org.cn/install/quick?docurl=/documentation/docs/zh/2.0/install/compile/mips-compile.html#anchor-1) | | [支持模型](https://www.paddlepaddle.org.cn/install/quick?docurl=/documentation/docs/zh/2.0/install/compile/mips-compile.html#anchor-6) | -| 服务端CPU | x86 | 兆芯 | 全系列CPU | |[源码编译](https://www.paddlepaddle.org.cn/install/quick?docurl=/documentation/docs/zh/2.0/install/compile/zhaoxin-compile.html#anchor-1) | | [支持模型](https://www.paddlepaddle.org.cn/install/quick?docurl=/documentation/docs/zh/2.0/install/compile/zhaoxin-compile.html#anchor-6) | +| 服务端CPU | MIPS | 龙芯 | 龙芯3A4000、3A5000、3C5000L | |[源码编译](https://www.paddlepaddle.org.cn/install/quick?docurl=/documentation/docs/zh/2.0/install/compile/mips-compile.html#anchor-1) | | [支持模型](https://www.paddlepaddle.org.cn/install/quick?docurl=/documentation/docs/zh/2.0/install/compile/mips-compile.html#anchor-6) | +| 服务端CPU | x86 | 兆芯 | 全系列CPU | |[源码编译](https://www.paddlepaddle.org.cn/documentation/docs/zh/install/compile/zhaoxin-compile.html#anchor-1) | | [支持模型](https://www.paddlepaddle.org.cn/install/quick?docurl=/documentation/docs/zh/2.0/install/compile/zhaoxin-compile.html#anchor-6) | ## Paddle Lite @@ -40,7 +40,7 @@ | AI加速芯片 | | RockChip | RK1808 | | [源码编译](https://paddlelite.paddlepaddle.org.cn/demo_guides/rockchip_npu.html#id5) | | [支持模型](https://paddlelite.paddlepaddle.org.cn/demo_guides/rockchip_npu.html#id1) | | AI加速芯片 | | MTK | NeuroPilot APU | | [源码编译](https://paddlelite.paddlepaddle.org.cn/demo_guides/mediatek_apu.html#id1) | | [支持模型](https://paddlelite.paddlepaddle.org.cn/demo_guides/mediatek_apu.html#id1) | | AI加速芯片 | | Imagination | PowerVR 2NX | | [源码编译](https://paddlelite.paddlepaddle.org.cn/demo_guides/huawei_kirin_npu.html#id5) | | [支持模型](https://paddlelite.paddlepaddle.org.cn/demo_guides/huawei_kirin_npu.html#id1) | -| AI加速芯片 | | 百度 | 昆仑K100、K200等 | | [源码编译](https://paddlelite.paddlepaddle.org.cn/demo_guides/baidu_xpu.html#id4) | | [支持模型](https://paddlelite.paddlepaddle.org.cn/demo_guides/baidu_xpu.html#id1) | +| AI加速芯片 | | 百度 | 昆仑K200、R200等 | | [源码编译](https://paddlelite.paddlepaddle.org.cn/demo_guides/baidu_xpu.html#id4) | | [支持模型](https://paddlelite.paddlepaddle.org.cn/demo_guides/baidu_xpu.html#id1) | | AI加速芯片 | | 寒武纪 | 思元270 | | 即将提供 | | | | AI加速芯片 | | 比特大陆 | 算丰BM16系列芯片 | | [源码编译](https://paddlelite.paddlepaddle.org.cn/demo_guides/bitmain.html#id5) | | [支持模型](https://paddlelite.paddlepaddle.org.cn/demo_guides/bitmain.html#id1) | | FPGA | | 百度 | 百度Edgeboard开发板 | | [源码编译](https://paddlelite.paddlepaddle.org.cn/demo_guides/baidu_xpu.html#id4) | | [支持模型](https://ai.baidu.com/ai-doc/HWCE/Qkda68drw) | diff --git a/docs/guides/09_hardware_support/index_cn.rst b/docs/guides/09_hardware_support/index_cn.rst index 12c1f6a1dc1..cd5dff525c4 100644 --- a/docs/guides/09_hardware_support/index_cn.rst +++ b/docs/guides/09_hardware_support/index_cn.rst @@ -19,4 +19,4 @@ xpu_docs/index_cn.rst rocm_docs/index_cn.rst npu_docs/index_cn.rst - ipu_docs/index_cn.rst + ipu_docs/index_cn.rst \ No newline at end of file diff --git a/docs/guides/09_hardware_support/xpu_docs/index_cn.rst b/docs/guides/09_hardware_support/xpu_docs/index_cn.rst index 360e63d5929..7711af86684 100644 --- a/docs/guides/09_hardware_support/xpu_docs/index_cn.rst +++ b/docs/guides/09_hardware_support/xpu_docs/index_cn.rst @@ -1,21 +1,32 @@ .. _cn_xpu_information: #################### -昆仑XPU芯片运行飞桨 +昆仑芯片运行飞桨 #################### -百度昆仑AI计算处理器(Baidu KUNLUN AI Computing Processor)是百度集十年AI产业技术实践于2019年推出的全功能AI芯片。基于自主研发的先进XPU架构,为云端和边缘端的人工智能业务而设计。 百度昆仑与飞桨及其他国产软硬件强强组合,打造一个全面领先的国产化AI技术生态,部署和应用于诸多 “人工智能+“的行业领域,包括智能云和高性能计算,智慧制造、智慧城市和安防等。更多昆仑XPU芯片详情及技术指标请 `点击这里 `_ 。 +百度昆仑AI计算处理器(Baidu KUNLUN AI Computing Processor)是百度集十年AI产业技术实践于2019年推出的全功能AI芯片。基于自主研发的先进XPU架构,为云端和边缘端的人工智能业务而设计。 百度昆仑与飞桨及其他国产软硬件强强组合,打造一个全面领先的国产化AI技术生态,部署和应用于诸多 “人工智能+“的行业领域,包括智能云和高性能计算,智慧制造、智慧城市和安防等。更多昆仑XPU芯片详情及技术指标请 `点击这里 `_ 。 参考以下内容可快速了解和体验昆仑XPU芯片上运行飞桨: -- `飞桨对昆仑XPU芯片的支持 <./paddle_2.0_xpu_cn.html>`_ : 飞桨支持昆仑XPU芯片运行 -- `飞桨框架昆仑xpu版安装说明 <./paddle_install_cn.html>`_ : 飞桨框架昆仑xpu版安装说明 -- `飞桨框架昆仑XPU版训练示例 <./train_example_cn.html>`_ : 飞桨框架昆仑XPU版训练示例 -- `飞桨预测库昆仑XPU版安装及使用 <./inference_install_example_cn.html>`_ : 飞桨预测库昆仑XPU版安装及使用示例 +昆仑芯2代芯片: + + - `飞桨对昆仑2代芯片的支持 <./paddle_2.0_xpu_cn.html>`_ : 飞桨支持昆仑2代芯片(R200、R300)运行 + - `飞桨框架昆仑2代芯片安装说明 <./paddle_install_cn.html>`_ : 飞桨框架昆仑2代芯片(R200、R300)安装说明 + - `飞桨框架昆仑2代芯片训练示例 <./train_example_cn.html>`_ : 飞桨框架昆仑2代芯片(R200、R300)训练示例 + +昆仑芯1代芯片: + + - `飞桨对昆仑1代芯片的支持 <./paddle_2.0_xpu_cn.html>`_ : 飞桨支持昆仑1代芯片(K100、K200)运行 + - `飞桨框架昆仑1代芯片安装说明 <./paddle_install_cn.html>`_ : 飞桨框架昆仑1代芯片(K100、K200)安装说明 + - `飞桨框架昆仑1代芯片训练示例 <./train_example_cn.html>`_ : 飞桨框架昆仑1代芯片(K100、K200)训练示例 + - `飞桨预测库昆仑1代芯片安装及使用 <./inference_install_example_cn.html>`_ : 飞桨预测库昆仑1代芯片(K100、K200)版安装及使用示例 .. toctree:: :hidden: + paddle_2.0_xpu2_cn.md + paddle_install_xpu2_cn.md + train_example_xpu2_cn.md paddle_2.0_xpu_cn.md paddle_install_cn.md train_example_cn.md - inference_install_example_cn.md \ No newline at end of file + inference_install_example_cn.md diff --git a/docs/guides/09_hardware_support/xpu_docs/paddle_2.0_xpu2_cn.md b/docs/guides/09_hardware_support/xpu_docs/paddle_2.0_xpu2_cn.md new file mode 100644 index 00000000000..140ca61ffd1 --- /dev/null +++ b/docs/guides/09_hardware_support/xpu_docs/paddle_2.0_xpu2_cn.md @@ -0,0 +1,36 @@ +# 飞桨对昆仑2代芯片的支持 + +飞桨自2.3rc版本起支持在昆仑2代芯片上(R200,R300)运行,经验证的模型训练的支持情况如下: + +## 训练支持 + +可进行单机单卡/单机多卡训练的模型,如下所示: + +| 模型 | 领域 | 编程范式 | 可用的CPU类型 | 单机单卡支持 | 单机多卡支持 | +| ------------------ | -------- |------------- | ----------------------- | -------------- | -------------- | +| ResNet50 | 图像分类 | 动态图 | X86(Intel) | 支持 |- | +| MobileNet_v3 | 图像分类 | 动态图 | X86(Intel) | 支持 |- | +| UNet | 图像分割 | 动态图 | X86(Intel) | 支持 |- | +| Yolov3-DarkNet53 | 目标检测 | 动态图 | X86(Intel) | 支持 |- | +| SSD-ResNet34 | 目标检测 | 动态图 | X86(Intel) | 支持 |支持 | +| OCR-DB | 文字检测 | 动态图 | X86(Intel) | 支持 |- | +| Bert-Base | NLP | 静态图 | X86(Intel) | 支持 |支持 | +| Transformer | NLP | 静态图 | X86(Intel) | 支持 |支持 | +| GPT-2 | NLP | 动态图 | X86(Intel) | 支持 |- | +| DeepFM | 推荐 | 动态图 | X86(Intel) | 支持 |- | +| Wide&Deep | 推荐 | 动态图 | X86(Intel) | 支持 |- | + + + +模型放置在飞桨模型套件中,作为github.com/PaddlePaddle下的独立repo存在,git clone下载即可获取所需的模型文件: + +| 领域 | 套件名称 | 分支/版本 | +| -------- | --------------- | ----------- | +| 图像分类 | [PaddleClas](https://github.com/PaddlePaddle/PaddleClas) | [develop](https://github.com/PaddlePaddle/PaddleClas/tree/develop) | +| 目标检测 | [PaddleDetection](https://github.com/PaddlePaddle/PaddleDetection) | [develop](https://github.com/PaddlePaddle/PaddleDetection/tree/develop) | +| 图像分割 | [PaddleSeg](https://github.com/PaddlePaddle/PaddleSeg) | [develop](https://github.com/PaddlePaddle/PaddleSeg/tree/develop) | +| NLP | [PaddleNLP](https://github.com/PaddlePaddle/PaddleNLP) | [develop](https://github.com/PaddlePaddle/PaddleNLP/tree/develop) | +| OCR | [PaddleOCR](https://github.com/PaddlePaddle/PaddleOCR) | [dygraph](https://github.com/PaddlePaddle/PaddleOCR/tree/dygraph) | +| 推荐 | [PaddleREC](https://github.com/PaddlePaddle/PaddleRec) | [master](https://github.com/PaddlePaddle/PaddleRec/tree/master) | + +* 注:支持基于Kermel Primitive算子的昆仑2代芯片支持,[点击这里](https://www.paddlepaddle.org.cn/documentation/docs/zh/guides/07_new_op/kernel_primitive_api/index_cn.html)。 diff --git a/docs/guides/09_hardware_support/xpu_docs/paddle_install_xpu2_cn.md b/docs/guides/09_hardware_support/xpu_docs/paddle_install_xpu2_cn.md new file mode 100644 index 00000000000..afb522d9cf1 --- /dev/null +++ b/docs/guides/09_hardware_support/xpu_docs/paddle_install_xpu2_cn.md @@ -0,0 +1,175 @@ +# 飞桨框架昆仑2代芯片安装说明 + +在昆仑2代芯片上,飞桨框架支持基于python的训练和原生预测,当前最新版本为2.3rc,提供两种安装方式: + +**1. 预编译的支持昆仑2代芯片的wheel包** + +目前此wheel包只支持一种环境: + +英特尔CPU+昆仑2代芯片+Linux操作系统 + +**2. 源码编译安装** + +其他环境请选择源码编译安装。 + +## 安装方式一:通过Wheel包安装 + +### 下载安装包 + +**环境1:英特尔CPU+昆仑2代芯片+Linux操作系统** + +Linux发行版建议选择CentOS 7系统 + +Python3.7 + +``` +wget https://paddle-inference-lib.bj.bcebos.com/2.3.0-rc0/python/Linux/XPU2/x86-64_gcc8.2_py36_avx_mkl/paddlepaddle_xpu-2.3.0rc0-cp37-cp37m-linux_x86_64.whl +``` + +``` +python3.7 -m pip install -U paddlepaddle_xpu-2.3.0rc0-cp37-cp37m-linux_x86_64.whl +``` + + +### 验证安装 + +安装完成后您可以使用 python 或 python3 进入python解释器,输入 + +``` +import paddle +``` + +再输入 + +``` +paddle.utils.run_check() +``` + +如果出现PaddlePaddle is installed successfully!,说明您已成功安装。 + +* 注:支持基于Kermel Primitive算子的昆仑2代芯片编译whl包,[点击这里查看](https://www.kunlunxin.com.cn)。 + +## 安装方式二:从源码编译支持昆仑XPU的包 + +### 环境准备 + +**英特尔CPU+昆仑2代芯片+CentOS系统** + +- **处理器:Intel(R) Xeon(R) Gold 6148 CPU @2.40GHz** +- **操作系统:CentOS 7.8.2003(建议使用CentOS 7)** +- **Python版本: 3.7 (64 bit)** +- **pip或pip3版本:9.0.1+ (64 bit)** +- **cmake版本:3.15+** +- **gcc/g++版本:8.2+** + + +### 源码编译安装步骤: + + +(1)Paddle依赖cmake进行编译构建,需要cmake版本>=3.15,如果操作系统提供的源包括了合适版本的cmake,直接安装即可,否则需要 + +``` +wget https://github.com/Kitware/CMake/releases/download/v3.16.8/cmake-3.16.8.tar.gz +tar -xzf cmake-3.16.8.tar.gz && cd cmake-3.16.8 +./bootstrap && make && sudo make install +``` + +(2)Paddle内部使用patchelf来修改动态库的rpath,如果操作系统提供的源包括了patchelf,直接安装即可,否则需要源码安装,请参考 + +``` +./bootstrap.sh +./configure +make +make check +sudo make install +``` + +(3)根据[requirments.txt](https://github.com/PaddlePaddle/Paddle/blob/develop/python/requirements.txt)安装Python依赖库 + +(4)将Paddle的源代码克隆到当下目录下的Paddle文件夹中,并进入Paddle目录 + +``` +git clone https://github.com/PaddlePaddle/Paddle.git +cd Paddle +``` + +使用较稳定的版本编译,建议切换到release2.3分支下: + +``` +git checkout release/2.3 +``` + +(5)进行Wheel包的编译,请创建并进入一个叫build的目录下 + +``` +mkdir build && cd build +``` + +具体编译选项含义可参见[编译选项表](https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/install/Tables.html#Compile) + +**英特尔CPU+昆仑2代芯+CentOS系统** + +链接过程中打开文件数较多,可能超过系统默认限制导致编译出错,设置进程允许打开的最大文件数: + +``` +ulimit -n 4096 +``` + +执行cmake,完成编译 + +Python3.7 + +``` +cmake .. -DPY_VERSION=3.7 \ + -DCMAKE_BUILD_TYPE=Release \ + -DWITH_GPU=OFF \ + -DWITH_XPU=ON \ + -DON_INFER=ON \ + -DWITH_PYTHON=ON \ + -DWITH_AVX=ON \ + -DWITH_MKL=ON \ + -DWITH_MKLDNN=ON \ + -DWITH_XPU_BKCL=ON \ + -DWITH_DISTRIBUTE=ON \ + -DWITH_NCCL=OFF + +make -j$(nproc) +``` + +(6)编译成功后进入Paddle/build/python/dist目录下找到生成的.whl包 。 + +(7)将生成的.whl包copy至带有昆仑XPU的目标机器上,并在目标机器上根据[requirments.txt](https://github.com/PaddlePaddle/Paddle/blob/develop/python/requirements.txt)安装Python依赖库。(如果编译机器同时为带有昆仑XPU的目标机器,略过此步) + +(8)在带有昆仑XPU的目标机器安装编译好的.whl包:pip install -U(whl包的名字)或pip3 install -U(whl包的名字)。恭喜,至此您已完成昆仑XPU机器上PaddlePaddle的编译安装。 + +**验证安装** + +安装完成后您可以使用 python 或 python3 进入python解释器,输入 + +``` +import paddle +``` + +再输入 + +``` +paddle.utils.run_check() +``` + +如果出现PaddlePaddle is installed successfully!,说明您已成功安装。 + +### 如何卸载 + +使用以下命令卸载PaddlePaddle: + +``` +pip uninstall paddlepaddle +``` + +或 + +``` +pip3 uninstall paddlepaddle +``` + +* 注:支持基于Kermel Primitive算子的昆仑2代芯片源码编译,[点击这里查看](https://www.kunlunxin.com.cn)。 diff --git a/docs/guides/09_hardware_support/xpu_docs/train_example_xpu2_cn.md b/docs/guides/09_hardware_support/xpu_docs/train_example_xpu2_cn.md new file mode 100644 index 00000000000..158450d9f3e --- /dev/null +++ b/docs/guides/09_hardware_support/xpu_docs/train_example_xpu2_cn.md @@ -0,0 +1,67 @@ +# 飞桨框架昆仑2代芯片训练示例 + +使用XPU训练与CPU/GPU相同,只需要简单配置XPU,就可以执行在昆仑设备上。 + +#### ResNet50下载并运行示例: + +1、 安装依赖: +``` +git clone https://github.com/PaddlePaddle/PaddleClas.git -b develop +cd PaddleClas +python -m pip install -r requirements.txt +``` + +2、下载数据集: +基于CIFAR100数据集的ResNet50训练任务 +``` +cd dataset +rm -rf ILSVRC2012 +wget -nc https://paddle-imagenet-models-name.bj.bcebos.com/data/whole_chain/whole_chain_CIFAR100.tar +tar xf whole_chain_CIFAR100.tar +ln -s whole_chain_CIFAR100 ILSVRC2012 +cd ILSVRC2012 +mv train.txt train_list.txt +mv test.txt val_list.txt +``` + +3、配置XPU进行训练的命令非常简单: +``` +cd ../.. +#FLAGS指定单卡或多卡训练,此示例运行1个卡 +export FLAGS_selected_xpus=2 +export XPUSIM_DEVICE_MODEL=KUNLUN2 +#启动训练 +python tools/train.py \ +-c ppcls/configs/ImageNet/ResNet/ResNet50.yaml \ +-o Global.device=xpu +``` + +#### YOLOv3-DarkNet53下载并运行示例: + +1、安装依赖: +``` +git clone https://github.com/PaddlePaddle/PaddleDetection.git -b develop +cd PaddleDetection/ +pip install -U pip Cython +pip install -r requirements.txt +``` + +2、下载数据集 +``` +cd dataset/voc/ +python download_voc.py +python create_list.py +cd ../.. +``` + +3、配置XPU进行训练的命令非常简单: +``` +#FLAGS指定单卡或多卡训练,此示例运行1个卡 +export FLAGS_selected_xpus=2 +export XPUSIM_DEVICE_MODEL=KUNLUN2 +#启动训练 +python -u tools/train.py \ +-c configs/yolov3/yolov3_darknet53_270e_voc.yml \ +-o use_gpu=false use_xpu=true LearningRate.base_lr=0.000125 \ +--eval +```