Skip to content

Tensor张量

Tensors

  • Tensor(张量)是什么
  • Tensor(张量)的应用
  • Tensor(张量)的优势
  • Numpy
  • 初始化Tensor(张量)
  • Tensor(张量)的属性
  • Tensor(张量)的运算
  • 与NumPy的关系

Tensor是什么

  • 在深度学习里,Tensor(张量)实际上就是一个多维数组。而张量的目的是能够创造更高维度的矩阵、向量
  • Tensor 是深度学习框架中极为基础的概念,也是 PyTorch、TensorFlow 中最重要的知识点之一,它是一种数据的存储和处理结构。

Tensor是什么

  • 我们将不同维度的数组定义为不同阶的张量:
  • 将标量(只有大小没有方向的数)定义为0阶张量

Tensor是什么

  • 将一维数组定义为一阶张量,构成“一条直线”

Tensor是什么

  • 将多个一维数组的拼接,即矩阵定义为二阶张量,构成“一张平面”

Tensor是什么

  • 将多个矩阵的叠加,定义为三阶张量,设想“三张平面”构成一个“立方体”

Tensor是什么

  • 下面我们类比一阶张量,将三阶张量排列为一个数组,数组的元素是三阶张量,如果我们将三阶张量记为:

  • 那么多个元素组成的数组就定义为四阶张量

Tensor是什么

  • 同样,将四阶张量拼接,组成三阶张量的矩阵,称为五阶张量
  • 对上面的定义进行循环重复,我们就可以定义更高阶的张量了

Tensor的应用

  • 一阶张量是一个一维数组,即一组数,可以将一组数表示为一个矢量。
  • 二阶张量是一个矩阵,因此可以将张量作为矢量和矩阵概念的推广。

Tensor的应用

  • 三阶张量,对于 RGB 图片,可以理解为由三张分别表示 R,G,B 分量的图片堆叠而成。
  • 对于每个分量图片,我们都可以看成一个矩阵,那么一张 RGB 图片就可以用三阶的张量进行表示。

Tensor的应用

  • 四阶张量,对于多张 RGB 图片,我们可以用四阶张量进行表示,可以看作是三阶张量(单张RGB图像)的数组(多张 RGB 图片,即视频)。
  • 五阶张量,视频是由多张图片组成的,因此每个视频可以用一个四阶张量表示,显然,多个视频可以用五阶张量表示。

Tensor的优势

张量是一种特殊的数据结构,非常类似于数组和矩阵。在PyTorch中,我们使用张量来编码模型的输入和输出,以及模型的参数
张量类似于NumPy的ndarrays,只是张量可以运行在GPU或其他硬件加速器上。事实上,张量和NumPy数组通常可以共享相同的底层内存,从而消除了复制数据的需要。张量也为自动微分进行了优化

Numpy

Numpy——应用广泛

  • 主流深度学习框架 PyTorch 与 TensorFlow 中最基本的计算单元 Tensor,都与 NumPy 数组有着类似的计算逻辑。
  • NumPy 还被广泛用在 Pandas,SciPy 等其他数据科学与科学计算的 Python 模块中。

Numpy——定义

  • Numpy是一个开源的Python数据科学计算库,支持对N维数组和矩阵的操作,用于快速处理任意维度的数组。
  • Numpy主要使用ndarray来处理N维数组,numpy中的大部分属性和方法都是为ndarray服务的。所以,掌握了ndarray的用法,基本就掌握了numpy的用法。

Numpy

  • ndarray(N-dimensional array)是一个N维数组类型的对象。
    • Python 中的列表可以动态地改变,而 NumPy 数组是不可以的,它在创建时就有固定大小了。
    • ndarray在存储的数据类型上做限制,换取了运算效率的提升和数据处理的便捷。
    • ndarray在存储的数据类型上做限制,换取了运算效率的提升和数据处理的便捷。
      import numpy as np
      
      array_a = np.array([[1, 2, 3], [4, 5, 6]])
      print(array_a)
      print('ndarray的  维度: ', array_a.ndim)
      print('ndarray的形状: ', array_a.shape)
      print('ndarray的元素数量: ', array_a.size)
      print('ndarray中的数据类型: ', array_a.dtype)
      print(type(array_a))
      

初始化张量

初始化张量——张量的类型

  • Tensor 支持的数据类型有很多种,这里列举较为常用的几种格式
  • torch.float32、torch.float64、torch.uint8、 torch.int64

初始化张量——张量的创建

import torch
import numpy as np

# Directly from data  直接来自数据列表
data = [[1, 2],[3, 4]]
x_data = torch.tensor(data)

# From a NumPy array  来自NumPy数组
np_array = np.array(data)
x_np = torch.from_numpy(np_array)

# From another tensor:  来自另一个张量
x_ones = torch.ones_like(x_data) # retains the properties of x_data
print(f"Ones Tensor: \n {x_ones} \n")

x_rand = torch.rand_like(x_data, dtype=torch.float) # overrides the datatype of x_data
print(f"Random Tensor: \n {x_rand} \n")

初始化张量——张量的创建

  • torch.rand 用于生成数据类型为浮点型且维度指定的随机的Tensor,随机生成的浮点数据在 0~1 区间均匀分布。
  • torch.ones 用于建全一矩阵的Tensor。
  • torch.zeros 用于建全零矩阵的Tensor。

初始化张量——张量的创建

# With random or constant values:  来自随机或连续值
shape = (2,3,)
rand_tensor = torch.rand(shape)
ones_tensor = torch.ones(shape)
zeros_tensor = torch.zeros(shape)

print(f"Random Tensor: \n {rand_tensor} \n")
print(f"Ones Tensor: \n {ones_tensor} \n")
print(f"Zeros Tensor: \n {zeros_tensor}")

张量的属性

  • 张量属性描述了它们的形状、数据类型和存储它们的设备。

张量的属性

tensor = torch.rand(3,4)

print(f"Shape of tensor: {tensor.shape}")
print(f"Datatype of tensor: {tensor.dtype}")
print(f"Device tensor is stored on: {tensor.device}")

张量的运算

超过100种张量运算,包括算术、线性代数、矩阵操作(转置、索引、切片)、采样等等,在这里都有全面的描述。 这些操作都可以在GPU上运行(通常比在CPU上运行速度更快)。如果您使用的是Colab,请转到运行时>更改运行时类型> GPU来分配GPU。

张量的运算

默认情况下,张量是在CPU上创建的。我们需要使用.to方法(在检查GPU可用性之后)。请记住,从时间和内存的角度来看,跨设备复制大型张量是非常昂贵的!

张量的运算

# We move our tensor to the GPU if available
# 如果GPU可用,我们将张量移至GPU上计算
if torch.cuda.is_available():
    tensor = tensor.to("cuda")

# Standard numpy-like indexing and slicing:
# 标准的类似数字的索引和切片:
tensor = torch.ones(4, 4)
print(f"First row: {tensor[0]}")
print(f"First column: {tensor[:, 0]}")
print(f"Last column: {tensor[..., -1]}")
tensor[:,1] = 0
print(tensor)

# Joining tensors 连接张量
t1 = torch.cat([tensor, tensor, tensor], dim=1)
print(t1)

# Arithmetic operations 算数运算

# This computes the matrix multiplication between two tensors. y1, y2, y3 will have the same value
y1 = tensor @ tensor.T
y2 = tensor.matmul(tensor.T)

y3 = torch.rand_like(tensor)
torch.matmul(tensor, tensor.T, out=y3)

# This computes the element-wise product. z1, z2, z3 will have the same value
z1 = tensor * tensor
z2 = tensor.mul(tensor)

z3 = torch.rand_like(tensor)
torch.mul(tensor, tensor, out=z3)

# Single-element tensors 单元素张量
agg = tensor.sum()
agg_item = agg.item()
print(agg_item, type(agg_item))

# In-place operations
print(f"{tensor} \n")
tensor.add_(5)
print(tensor)

与NumPy的关系

CPU和NumPy数组上的张量可以共享它们的底层内存位置,改变一个就会改变另一个。

与NumPy的关系

# Tensor to NumPy array
t = torch.ones(5)
print(f"t: {t}")
n = t.numpy()
print(f"n: {n}")

# A change in the tensor reflects in the NumPy array.
t.add_(1)
print(f"t: {t}")
print(f"n: {n}")

# NumPy array to Tensor

n = np.ones(5)
t = torch.from_numpy(n)

np.add(n, 1, out=n)
print(f"t: {t}")
print(f"n: {n}")