Pytorch-张量基础操作

张量

张量是一个多维数组,它是标量、向量和矩阵概念的推广。在深度学习中,张量被广泛用于表示数据和模型参数。

具体来说,张量的“张”可以理解为“维度”,张量的阶或维数称为秩。例如,零阶张量是一个标量,一阶张量是一个向量,二阶张量是一个矩阵,三阶及以上的张量则可以看作是高维数组。

在不同的上下文中,张量的意义可能会有所不同:

  1. 数据表示:在深度学习中,张量通常用于表示数据。例如,一幅RGB图像可以表示为一个三维张量,其中两个空间维度(高度和宽度)和一个颜色维度(红、绿和蓝)。
  2. 模型参数:神经网络的权重和偏置通常也以张量形式存储。
  3. 数学运算:在多线性代数中,张量用于描述涉及多个向量或矩阵的操作。
  4. 物理和工程:在物理学和工程学中,张量用于描述具有多个方向性质的现象,如应力和应变。
  5. 计算机科学:在计算机图形学中,张量用于表示变换矩阵和其他与几何相关的概念。

接下来我们看看张量的基础操作

张量类型转换

在深度学习框架中,如TensorFlow或PyTorch,张量类型转换是一个常见的操作。这通常涉及到将一个张量的数据类型转换为另一个数据类型,以便满足特定的计算需求或优化内存使用。

TensorFlow

在TensorFlow中,你可以使用tf.cast函数来转换张量的类型。tf.cast函数接受两个参数:要转换的张量和目标数据类型。

import tensorflow as tf

# 创建一个张量
tensor = tf.constant([1.0, 2.0, 3.0], dtype=tf.float32)

# 将张量的类型从 float32 转换为 int32
int32_tensor = tf.cast(tensor, dtype=tf.int32)

print("Original Tensor:", tensor)
print("Casted Tensor:", int32_tensor)

PyTorch

在PyTorch中,张量类型转换可以通过调用to方法并指定目标类型来完成。

import torch

# 创建一个张量
tensor = torch.tensor([1.0, 2.0, 3.0], dtype=torch.float32)

# 将张量的类型从 float32 转换为 int32
int32_tensor = tensor.to(dtype=torch.int32)

print("Original Tensor:", tensor)
print("Casted Tensor:", int32_tensor)

我们创建了一个浮点类型的张量,并将其转换为整数类型。请注意,类型转换可能会导致数据丢失,例如,将浮点数转换为整数会截断小数部分。因此,在进行类型转换时,需要确保这种转换是你想要的。 

张量转换为 numpy 数组

Tensor.numpy 函数可以将张量转换为 ndarray 数组,但是共享内存,可以使用 copy 函数避免共享。

import torch
import numpy as np

# 创建一个张量
tensor = torch.tensor([[1, 2], [3, 4]])

# 将张量转换为numpy数组
numpy_array = tensor.numpy()

print("Numpy array:", numpy_array)

numpy 转换为张量 

  1. 使用 from_numpy 可以将 ndarray 数组转换为 Tensor,默认共享内存,使用 copy 函数避免共享。
  2. 使用 torch.tensor 可以将 ndarray 数组转换为 Tensor,默认不共享内存。
import tensorflow as tf
import numpy as np

# 创建一个numpy数组
numpy_array = np.array([[1, 2], [3, 4]])

# 将numpy数组转换为张量
tensor = tf.convert_to_tensor(numpy_array)

print("Tensor:", tensor)
import torch
import numpy as np

# 创建一个numpy数组
numpy_array = np.array([[1, 2], [3, 4]])

# 将numpy数组转换为张量
tensor = torch.from_numpy(numpy_array)

print("Tensor:", tensor)

标量张量和数字的转换

对于只有一个元素的张量,使用 item 方法将该值从张量中提取出来。 

def test03():

    # 当张量只包含一个元素时, 可以通过 item 函数提取出该值
    data = torch.tensor([30,])
    print(data.item())

    data = torch.tensor(30)
    print(data.item())


if __name__ == '__main__':
    test03()

# 30
# 30

张量拼接操作

张量的拼接操作在神经网络搭建过程中是非常常用的方法,残差网络、注意力机制中都使用到了张量拼接。为了有效地进行张量操作,了解和熟悉这些基本操作是非常必要的,它们在实际的深度学习模型构建和数据处理中扮演着重要角色。

在进行张量拼接时,需要特别注意以下几点:

  • 确保所有张量在非拼接轴上的尺寸是相同的。
  • 当使用 torch.stack() 时,被堆叠的张量必须具有相同的形状。
  • 拼接操作不会修改原始张量,而是返回一个新的张量。

torch.cat 函数可以将两个张量根据指定的维度拼接起来

import torch


def func():

    data1 = torch.randint(0, 10, [3, 5, 4])
    data2 = torch.randint(0, 10, [3, 5, 4])

    print(data1)
    print(data2)
    print('-' * 50)

    # 按0维度拼接
    new_data = torch.cat([data1, data2], dim=0)
    print(new_data.shape)
    print('-' * 50)

    # 按1维度拼接
    new_data = torch.cat([data1, data2], dim=1)
    print(new_data.shape)

    # 按2维度拼接
    new_data = torch.cat([data1, data2], dim=2)
    print(new_data)


if __name__ == '__main__':
    func()

torch.stack 函数可以将两个张量根据指定的维度叠加起来

torch.stack() 函数用于在新的维度上堆叠张量。它接受一个张量列表作为输入,并返回一个新的张量,其中每个输入张量都沿着新添加的维度进行堆叠。 

import torch

# 创建两个张量
tensor1 = torch.tensor([1, 2, 3])
tensor2 = torch.tensor([4, 5, 6])

# 使用 torch.stack() 函数将两个张量堆叠在一起
stacked_tensor = torch.stack((tensor1, tensor2))

print(stacked_tensor)

tensor([[1, 2, 3],

[4, 5, 6]])

张量索引操作 

我们在操作张量时,经常需要去进行获取或者修改操作,掌握张量的花式索引操作是必须的一项能力。在深度学习框架中,张量索引操作通常用于访问和修改张量中的数据。以下是一些基本的张量索引操作:

  1. 基础索引:可以通过指定张量的维度和对应的索引值来获取张量中的特定元素。例如,对于一个二维张量 tensor,可以使用 tensor[i, j] 来获取第 i 行第 j 列的元素。
  2. 切片索引:可以用来选择张量的子张量。通过指定起始和终止索引以及步长,可以获取张量中的一部分。例如,t1[2:8] 将会返回从索引2到7的张量元素,形成一个新张量。如果指定步长为2,如 t1[2:8:2],则会隔一个元素取一个,返回索引为2、4、6的元素形成的新张量。
  3. 高级索引:包括布尔索引和掩码索引等。布尔索引允许根据一个布尔张量来选择数据,而掩码索引则使用一个具有相同形状的张量作为掩码来选择数据。
  4. 多维索引:对于多维张量,可以通过指定多个维度的索引来访问数据,例如 tensor[i, j, k] 将访问三维张量中第 i 层、第 j 行、第 k 列的元素。
  5. 负数步长:在Python的传统列表中,步长可以为负数,表示倒序排列。但在张量中,步长必须大于0,否则会报错。这意味着不能使用负数步长来逆序索引张量元素。
  6. 内存共享:与 numpy.ndarray 类似,张量的索引操作通常会返回与原张量共享内存的结果。这意味着如果你修改了返回的张量,原始张量也会受到影响。

在进行张量索引操作时,需要确保索引不超出张量的形状范围,否则会引发错误。此外,由于张量通常用于存储和处理大量数据,因此高效的索引操作对于性能至关重要。 

import torch

data = torch.randint(0, 10, [4, 5])
print(data)
print('-' * 50)

tensor([[0, 7, 6, 5, 9],

[6, 8, 3, 1, 0],

[6, 3, 8, 7, 3],

[4, 9, 5, 3, 1]])

print(data[0])
print(data[:, 0])

# tensor([0, 7, 6, 5, 9])
# tensor([0, 6, 6, 4])

列表索引

def test():

    
    print(data[[0, 1], [1, 2]])
    
    print(data[[[0], [1]], [1, 2]])
if __name__ == '__main__':
    test()

# tensor([7, 3])

# tensor([[7, 6],
        [8, 3]])
  • 范围索引:类似于Python的列表切片,张量也支持范围索引。这意味着你可以使用start:end:step的形式来获取张量的子集。例如,t[1:3]将返回张量t的第2到第3个元素。需要注意的是,步长step必须是正数,因为张量不支持负数步长。
  • 布尔索引:布尔索引是使用一个与目标张量形状相同的布尔张量来选择元素。在布尔张量中,True值对应的位置元素会被选中并组成一个新的张量。例如,如果有一个张量t和一个相同形状的布尔张量b,那么t[b]将返回t中所有对应b中为True的元素。
import torch

# 创建一个张量
t = torch.tensor([1, 2, 3, 4, 5])

# 范围索引
print(t[1:3])  # 输出 [2, 3]

# 布尔索引
b = torch.tensor([True, False, True, False, True])
print(t[b])  # 输出 [1, 3, 5]

在上述代码中,我们首先创建了一个张量t,然后使用范围索引获取了第2到第3个元素。接着,我们创建了一个与t形状相同的布尔张量b,并使用布尔索引选择了所有对应b中为True的元素。最后,我们将结果打印出来。

️这些就是张量的基础操作,下一节我们看看张量的其他性质~

Pytorch-张量基础操作_第1张图片

你可能感兴趣的:(实战Pytorch,python,人工智能,tensorflow)