张量转换为 numpy 数组
🔎使用 Tensor.numpy 函数可以将张量转换为 ndarray 数组,但是共享内存,可以使用 copy 函数避免共享。
data_tensor = torch.tensor([2, 3, 4]) data_numpy = data_tensor.numpy() print(type(data_tensor)) print(type(data_numpy)) data_numpy[0] = 100 print(data_tensor) print(data_numpy)
我们可以通过对象拷贝避免共享内存:
data_tensor = torch.tensor([2, 3, 4]) data_numpy = data_tensor.numpy().copy() print(type(data_tensor)) print(type(data_numpy)) data_numpy[0] = 100 print(data_tensor) print(data_numpy)
numpy 转换为张量
- 使用 from_numpy 可以将 ndarray 数组转换为 Tensor,默认共享内存,使用 copy 函数避免共享。
- 使用 torch.tensor 可以将 ndarray 数组转换为 Tensor,默认不共享内存。
def test01(): data_numpy = np.array([2, 3, 4]) data_tensor = torch.from_numpy(data_numpy) data_tensor[0] = 100 print(data_tensor) print(data_numpy) def test02(): data_numpy = np.array([2, 3, 4]) data_tensor = torch.tensor(data_numpy) data_tensor[0] = 100 print(data_tensor) print(data_numpy)
标量张量和数字的转换
🔎对于只有一个元素的张量(shape没有限制,元素只有一个),使用 item 方法将该值从张量中提取出来。
data = torch.tensor([30,]) print(data.item()) data = torch.tensor(30) print(data.item()) data = torch.tensor([[30]]) print(data.item())
张量拼接操作
⚔️张量的拼接方式有两种:CAT、STACK
- CAT方法是将两个张量按照某一维度进行拼接(类似于积木拼接)
- STACK方法是将两个张量按照顺序垂直堆叠起来。
- STACK 方法主要用于将多个张量垂直堆叠在一起,形成一个新的、更高维度的张量。这在需要将来自不同来源或具有不同特征集的数据整合到一起时非常有用,例如在处理时间序列数据或多通道图像数据时。而 CAT 方法则是在同一维度上水平拼接张量,适用于需要扩展特征空间宽度的情况~
torch.cat() 该函数接受两个参数:输入张量列表和拼接的维度。以下是一个简单的示例:
import torch tensor1 = torch.tensor([[1, 2], [3, 4]]) tensor2 = torch.tensor([[5, 6], [7, 8]]) result = torch.cat((tensor1, tensor2), dim=0) print(result) result = torch.cat((tensor1, tensor2), dim=1) print(result)
我们可以打印每个张量的shape,来观察一下拼接所发生的变化:依次类推dim:0,1,2位置
import torch data1 = torch.randint(0, 10, [3, 5, 4]) data2 = torch.randint(0, 10, [3, 5, 4]) data1.cuda() data2.cuda() new_data = torch.cat([data1, data2], dim=0) print(new_data.shape)
torch.stack()
⚔️torch.stack函数用于将一系列张量堆叠到一个新的维度。(轴)
torch.stack的使用场景通常包括需要增加数据的一个维度时。比如在处理图像数据或者文本数据的时候,我们经常需要把二维的数据转换为三维的,这时候就可以使用torch.stack来完成这个操作。使用torch.stack可以保留两个信息:序列和张量矩阵信息。当我们需要把一系列的二维张量转换为三维的张量时,可以使用torch.stack来实现。例如,如果我们有两个形状为(3, 3)的二维张量A和B,我们可以通过指定dim=0来在它们的最前面增加一个新的维度,结果张量的形状就会变为(2, 3, 3)。这表明在新的维度上,张量的个数是2,其它两个维度的大小保持不变。
与torch.cat的区别主要在于,torch.cat是在现有的维度上进行拼接。
这意味着使用torch.cat时,输入的张量必须在除了拼接维度外的所有其他维度上具有相同的大小。而torch.stack则要求所有输入张量在所有维度上的大小都相同。此外,torch.cat不会增加张量的总维度数量,它仅仅是在一个指定的维度上扩展了张量的大小。例如,如果我们有两个形状为(2, 2, 3)的张量,当我们对它们应用torch.cat(dim=0)时,结果张量的形状会是(4, 2, 3),这里的4表示在指定的维度上,元素的数量从原来的2个扩展到了4个。
import torch A = torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) B = torch.tensor([[10, 11, 12], [13, 14, 15], [16, 17, 18]]) C = torch.stack((A, B), dim=0) print(C) tensor([[[ 1, 2, 3], [ 4, 5, 6], [ 7, 8, 9]], [[10, 11, 12], [13, 14, 15], [16, 17, 18]]])
我们可以再观察dim=1
表示在第二个维度上进行堆叠。
import torch A = torch.tensor([[1, 2, 3], [4, 5, 6]]) B = torch.tensor([[7, 8, 9], [10, 11, 12]]) C = torch.stack((A, B), dim=1) tensor([[[ 1, 2, 3], [ 7, 8, 9]], [[ 4, 5, 6], [10, 11, 12]]])
我们可以再观察dim=2
表示在第三个维度上进行堆叠。
data1= torch.randint(0, 10, [2, 3]) data2= torch.randint(0, 10, [2, 3]) new_data = torch.stack([data1, data2], dim=2) print(new_data) tensor([[[5, 6], [6, 0], [9, 2]], [[5, 1], [9, 4], [0, 1]]])
💥我们观察一下dim = 0时的cat与stack💥
import torch data1= torch.randint(0, 10, [2, 3]) data2= torch.randint(0, 10, [2, 3]) print(data1) print(data2) print('-'*30) new_data = torch.stack([data1, data2], dim=0) print(new_data) new_data = torch.cat([data1,data2],dim=0) print(new_data)
tensor([[9, 3, 5],
[0, 7, 7]])
tensor([[2, 1, 4],
[9, 0, 1]])
------------------------------
tensor([[[9, 3, 5],
[0, 7, 7]],
[[2, 1, 4],
[9, 0, 1]]])
tensor([[9, 3, 5],
[0, 7, 7],
[2, 1, 4],
[9, 0, 1]])
- 我们可以看出cat是在现有的维度上进行拼接,原本只有两个维度,所以dim = 0时将两个张量按行拼到一起了~ 💥
- 而stack是将其增加数据的一个维度,按照原本dim = 0,1,2进行堆叠,即按照第0维度堆叠成了[2,2,3]shape~ 💥
张量索引操作
张量索引操作允许我们对多维数组中的元素进行访问和操作。张量索引操作是处理多维数据的基础,它不仅能够让我们访问和修改数据,还能够帮助我们实现各种复杂的数据操作和算法。
我们来看一下张量索引基本操作:
🏹简单行、列索引
import torch data = torch.randint(0, 10, [4, 5]) print(data) tensor([[0, 7, 6, 5, 9], [6, 8, 3, 1, 0], [6, 3, 8, 7, 3], [4, 9, 5, 3, 1]])
- data[0] --- tensor([0, 7, 6, 5, 9])
- data[:, 0] --- tensor([0, 6, 6, 4])
- data[[0, 1], [1, 2]] :返回 (0, 1)、(1, 2) 两个位置的元素(tensor([7, 3]))
- data[[[0], [1]], [1, 2]] : 返回 0、1 行的 1、2 列共4个元素 (tensor([[7, 6], [8, 3]]))
🏹范围索引
print(data[:3, :2]) print(data[2:, :2]) tensor([[0, 7], [6, 8], [6, 3]]) tensor([[6, 3], [4, 9]])
🏹布尔索引
print(data[data[:, 2] > 5]) # data[:, 2] > 5返回了按照这个规则的一列布尔值,再套入到data求出来 类似于pandas求所有行的某一维度>5的所有行 print(data[:, data[1] > 5]) tensor([[0, 7, 6, 5, 9], [6, 3, 8, 7, 3]]) tensor([[0, 7], [6, 8], [6, 3], [4, 9]])
🏹多维索引
data = torch.randint(0, 10, [3, 4, 5]) print(data) print('-' * 50) print(data[0, :, :]) print(data[:, 0, :]) print(data[:, :, 0]) 结果: tensor([[[2, 4, 1, 2, 3], [5, 5, 1, 5, 0], [1, 4, 5, 3, 8], [7, 1, 1, 9, 9]], [[9, 7, 5, 3, 1], [8, 8, 6, 0, 1], [6, 9, 0, 2, 1], [9, 7, 0, 4, 0]], [[0, 7, 3, 5, 6], [2, 4, 6, 4, 3], [2, 0, 3, 7, 9], [9, 6, 4, 4, 4]]]) -------------------------------------------------- tensor([[2, 4, 1, 2, 3], [5, 5, 1, 5, 0], [1, 4, 5, 3, 8], [7, 1, 1, 9, 9]]) tensor([[2, 4, 1, 2, 3], [9, 7, 5, 3, 1], [0, 7, 3, 5, 6]]) tensor([[2, 5, 1, 7], [9, 8, 6, 9], [0, 2, 2, 9]])
💥我们下期一起学习张量的高阶操作💥