如何创建一个 Tensor

注解

  • 在 MegEngine 中创建 Tensor 与 NumPy 创建数组 的途径类似;

  • 由于 ndarray 是 Python 数据科学社区中较为通用支持的格式 (例如 SciPy、Pandas、OpenCV 等库都对 ndarray 提供了良好的支持), 如果存在着 NumPy 已经实现但 MegEngine 尚未支持的创建途径,可以先创建 NumPy ndarray, 再将其转换成 MegEngine Tensor. 也是下面提到的最后一种方法。

创建 Tensor 的常见途径如下:

警告

任何通过已有数据创建 Tensor 的方式都是通过拷贝创建的,和原始数据不会共享内存。

将 Python 序列转换为 Tensor

可以使用 Python 序列(例如列表和元组)定义 MegEngine Tensor.

列表 list 和元组 tuple 分别使用 [...](...) 定义,可以用来定义 Tensor 如何创建:

  • 由数字组成的列表将创建 1 维 Tensor;

  • 由列表组成的列表将创建 2 维 Tensor;

  • 同理,更进一步的列表嵌套将创建更加高维的 Tensor.

>>> a1D = megengine.Tensor([1, 2, 3, 4])
>>> a2D = megengine.Tensor([[1, 2], [3, 4]])
>>> a3D = megengine.Tensor([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])

警告

  • 这种写法其实调用了 Tensor 类的构造函数,传入了 data 参数;

  • megengine.tensormegengine.Tensor 的别名,二者本质上没有任何区别。

参见

将 Tensor 转化为 Python 内置数据类型可以使用 itemtolist .

默认的数据类型

参见

当你使用 megengine.Tensor 来定义新的 Tensor 时,需要考虑到其中每个元素的 数据类型

默认行为是以 32 位有符号整数 int32 或浮点数 float32 来创建 Tensor.

>>> megengine.Tensor([1, 2, 3, 4]).dtype
numpy.int32
>>> megengine.Tensor([1., 2., 3., 4.]).dtype
numpy.float32

如果你希望得到的 Tensor 是某种数据类型,则需要指定在创建 Tensor 时显式指定 dtype.

创建时指定数据类型

数据类型是可以被显式指定的,但显式指定 dtype 有可能产生非预期的溢出,例如:

>>> a = megengine.Tensor([127, 128, 129], dtype="int8")
>>> a
Tensor([ 127 -128 -127], dtype=int8, device=xpux:0)

一个 8 位有符号整数表示从 -128 到 127 的整数。将 int8 Tensor 赋值给此范围之外的整数会导致溢出。

如果使用不匹配的数据类型执行计算,可能会得到非预期的结果,例如:

>>> a = megengine.Tensor([2, 3, 4], dtype="uint8")
>>> b = megengine.Tensor([5, 6, 7], dtype="uint8")
>>> a - b
Tensor([253 253 253], dtype=uint8, device=xpux:0)

你可能希望得到的结果是 [-3, -3, -3], 但在 uint8 数据类型下,这些值将表示为 253.

不同数据类型之间的计算

注意上面两个 Tensor 即 ab 有着相同的 dtype: uint8, 因此得到的 Tensor 的数据类型也会相同。 如果你在两个不同 dtype 的 Tensor 之间进行计算,MegEngine 将进行类型提升来满足计算要求:

>>> a - b.astype("int8")
Tensor([-3 -3 -3], dtype=int16, device=xpux:0)

注意到数据类型为 uint8a 与数据类型为 int8b 进行计算, 最终得到了一个数据类型为 int16 的 Tensor.

使用内置函数创建 Tensor

注解

  • MegEngine 的 functional 子包内置了多个创建 Tensor 的函数(位于 创建功能 );

  • 使用这些函数创建的 Tensor 默认数据类型为 float32.

根据它们所创建的 Tensor 的维数,这些函数大致上可以分为三类:

创建 1 维 Tensor

创建 1 维 Tensor 的函数如 arangelinspace 通常需要至少两个输入,即 startstop.

arange 将创建具有规律递增值的 Tensor, 下面显示了一些用法:

>>> megengine.functional.arange(10)
Tensor([0. 1. 2. 3. 4. 5. 6. 7. 8. 9.], device=xpux:0)
>>> megengine.functional.arange(2, 10, dtype="float")
Tensor([2. 3. 4. 5. 6. 7. 8. 9.], device=xpux:0)
>>> megengine.functional.arange(2, 3, 0.1)
Tensor([2.  2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9], device=xpux:0)

使用该函数得到的 Tensor 中的值不包括终点 stop, 即范围为 [start, stop).

linspace 将创建具有指定数量元素的 Tensor, 并在指定的开始值和结束值之间等距间隔。例如:

>>> megengine.functional.linspace(1., 4., 6)
Tensor([1.  1.6 2.2 2.8 3.4 4. ], device=xpux:0)

使用这个函数的好处是可以保证 Tensor 中元素的数量、值的起点和终点。

注解

在 NumPy 中使用 arange 的最佳实践是使用整型的 start, stopstep 值。 这是由于机器表示浮点数时存在着舍入误差,向 arange 传入非整数值时有可能得到非预期结果:

>>> np.arange(7.8, 8.4, 0.05)
array([7.8 , 7.85, 7.9 , 7.95, 8.  , 8.05, 8.1 , 8.15, 8.2 , 8.25, 8.3 ,
    8.35, 8.4 ])

在 NumPy 中由于浮点误差的累积,最终的结果中将会看到 8.4 这个值。

而在 MegEngine 中,arange 内部调用了 linspace 进行实现,此时得到的结果与 NumPy 不同:

>>> megengine.functional.arange(7.8, 8.4, 0.05)
Tensor([7.8  7.85 7.9  7.95 8.   8.05 8.1  8.15 8.2  8.25 8.3  8.35], device=xpux:0)

创建 2 维 Tensor

创建 2 维 Tensor 的函数通常以表示为二维数组的特殊矩阵的属性来定义。

例如 eye 定义了一个 2 维单位矩阵,行索引和列索引相等的元素为 1, 其余为 0, 如下所示:

>>> megengine.functional.eye(3)
Tensor([[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]], device=xpux:0)
>>> megengine.functional.eye(3, 5)
Tensor([[1. 0. 0. 0. 0.]
 [0. 1. 0. 0. 0.]
 [0. 0. 1. 0. 0.]], device=xpux:0)

创建 n 维 Tensor

此类函数如 ones, zeros 通常可以根据给定的形状创建 Tensor.

>>> megengine.functional.zeros((2, 3))
Tensor([[0. 0. 0.]
 [0. 0. 0.]], device=xpux:0)
>>> megengine.functional.zeros((2, 3, 2))
Tensor([[[0. 0.]
  [0. 0.]
  [0. 0.]]
 [[0. 0.]
  [0. 0.]
  [0. 0.]]], device=xpux:0)

参见

  • 本质上它们都是通过调用 full 来实现创建满足给定形状和值的 Tensor;

  • 使用 zeros_like, ones_like, full_like 根据输入 Tensor 形状进行创建。

使用 random 子包随机生成

例如使用 normal 可以从服从正态分布的随机变量中采样:

>>> a = megengine.random.normal(100, 1, (5,))
Tensor([ 99.8308 101.949  100.2816 101.8977  99.9773], device=xpux:0)

使用 uniform 可以从服从均匀分布的随机变量中采样:

>>> megengine.random.uniform(10, 20, (5,))
Tensor([12.557  17.8996 10.0152 18.2324 11.2644], device=xpux:0)

参见

基于现有的 Tensor 进行操作

注解

使用 copy 函数可以拷贝一个 Tensor.

参见

更多具体内容请参考 如何对 Tensor 进行操作 页面。

将 NumPy ndarray 转化为 MegEngine Tensor

我们也能够通过 Tensor, 将 ndarray 作为输入数据传入,得到对应的 Tensor.

>>> a = np.array([1, 2, 3])
>>> a.dtype
dtype('int64')
>>> b = megengine.Tensor(a)
>>> Tensor([1 2 3], dtype=int32, device=xpux:0)
Tensor([1 2 3], dtype=int32, device=xpux:0)

通过 Tensor 的 numpy 方法,我们可以得到 Tensor 转为 ndarray 后的结果:

>>> b.numpy()
array([1, 2, 3], dtype=int32)

参见

相关注意事项如数据类型等,与 将 Python 序列转换为 Tensor 一致。