李林超博客
首页
归档
留言
友链
动态
关于
归档
留言
友链
动态
关于
首页
NLP
正文
05.Pytorch张量维度操作(一)
Leefs
2024-12-29 AM
96℃
0条
[TOC] ### 前言 在本文中,将介绍在Pytorch中如何进行张量的维度变换。张量是Pytorch中的核心数据结构,类似于多维数组,并且可以在GPU上进行加速运算。通过改变张量的维度,可以更灵活地处理数据,在机器学习和深度学习任务中具有重要意义。 ![05.Pytorch张量维度操作01.png](https://lilinchao.com/usr/uploads/2024/12/1403266350.png) ### 一、张量的维度与形状 张量为一组数的结构化表示。简单理解,向量就是一维数组,矩阵为二维数组,此外还可以定义更高维度的数组。 + **张量创建示例如下**: ```python # 一维向量 t1 = torch.tensor((1, 2)) # 二维向量 t2 = torch.tensor([[1, 2, 3], [4, 5, 6]]) # 三维向量 t3 = torch.tensor([[[1, 2], [3, 4]],[[5, 6], [7, 8]]]) ``` 接下来张量的维度与形状,相关示例代码都围绕着上方示例进行操作。 #### 1.1 查看张量维度 + `ndim`:查看张量维度 ```python print(t1.ndim, t2.ndim, t3.ndim, sep = ', ') ``` **输出结果** ```python 1, 2, 3 # 结果分析 # t1为1维向量 # t2为2维矩阵 # t3为3维张量 ``` #### 1.2 查看张量的形状 + `shape&size()` :查看张量的形状 ```python print(t1.shape, t2.shape, t3.shape, sep = ', ') print(t1.size(), t2.size(), t3.size(), sep = ', ') ``` **输出结果** ```python torch.Size([2]), torch.Size([2, 3]), torch.Size([2, 2, 2]) torch.Size([2]), torch.Size([2, 3]), torch.Size([2, 2, 2]) # 结果分析 t1 向量torch.Size([2])的理解:向量的形状是1行2列。 t2 矩阵torch.Size([2, 3])的理解:包含两个一维向量,每个一维向量的形状是1行3列。 t3 矩阵torch.Size([2, 2, 2])的理解:包含两个二维矩阵,每个二维矩阵的形状是2行2列。 ``` #### 1.3 查看张量中的元素个数 + `numel()` :查看张量中的元素个数 ```python print(t1.numel(), t2.numel(), t3.numel(), sep = ', ') ``` **输出结果** ```python 2, 6, 8 # t1向量中共有2个元素 # t2矩阵中共有6个元素 # t3张量中共有8个元素 ``` #### 1.4 形状相同的数组可创建一个高维张量 ```python import numpy as np a1 = np.array([[1, 2], [3, 4]]) a2 = np.array([[5, 6], [7, 8]]) t3 = torch.tensor([a1, a2]) print(t3) # tensor([[[1, 2], [3, 4]], [[5, 6], [7, 8]]]) ``` ### 二、拼接张量与切分 #### 2.1 拼接操作 张量的拼接主要通过cat()和stack()函数实现。 ##### (1)torch.cat() **功能**:沿指定的维度连接张量序列。这意味着,对于指定的维度,张量的尺寸会增加,但其他维度的尺寸必须相同。 ```python torch.cat(tensors, dim=0, out=None) → Tensor # 示例 # torch.cat([a, b], dim=n) ``` **参数说明** + **tensors**:张量序列 + **dim**:要拼接的维度 `cat()`函数中首先传入一个列表`[a, b, c…]`表示要合并的张量集合,然后传入一个维度`dim=n`,表示将这些张量在维度n上进行合并操作。 **注意** `concat`操作合并的维度上两个张量的维度大小可以不同,但是其余维度上必须具有相同的大小 例如`(3,4,5)`可以和`(2,4,5)`在0维度上`concat`合并为`(5,4,5)`。但是不能在1维度上合并,因为0维度上两个张量的维度大小不同,分别为3和2。 **代码示例** ```python import torch x = torch.tensor([[1, 2], [3, 4]]) y = torch.tensor([[5, 6]]) # 沿第0个维度(即行)连接 z = torch.cat([x, y], dim=0) print(z) # 输出: # tensor([[1, 2], # [3, 4], # [5, 6]]) ``` **完整示例代码** ```python import torch def test(): # 固定随机种子 torch.manual_seed(0) data1 = torch.randint(0,10,[3,4,5]) data2 = torch.randint(0,10,[3,4,5]) print(data1.shape) print(data2.shape) # 1. 按照0纬度进行拼接 new_data = torch.cat([data1,data2],dim=0) print(new_data.shape) # 2. 按照1纬度进行拼接 new_data = torch.cat([data1, data2], dim=1) print(new_data.shape) # 3. 按照2纬度进行拼接 new_data = torch.cat([data1, data2], dim=2) print(new_data.shape) # 注意: dim 必须保证是有效的 # new_data = torch.cat([data1, data2], dim=3) # print(new_data.shape) if __name__ == '__main__': test() ``` ##### (2)torch.stack() **功能**:在新的维度上堆叠多个张量。这意味着张量的总维数会增加1。为了使用 `torch.stack()`,所有张量都必须具有相同的形状。 ```python torch.stack(tensors, dim=0, out=None) → Tensor # 示例 # torch.stack([a, b], dim=0) ``` **参数说明** + **tensors**:连接的张量序列 + **dim**:要拼接的维度 拼接两个张量a,b时,在维度n之前生成一个新的维度。 **注意** `stack()`方法对于带拼接的两个张量形状要求更加严格,具体来说当使用`stack()`方法时,要保证拼接的两个张量形状是相同的,否则会报错。 **代码示例** ```python x = torch.tensor([1, 2]) y = torch.tensor([3, 4]) # 沿一个新的维度堆叠 z = torch.stack([x, y]) print(z) # 输出: # tensor([[1, 2], # [3, 4]]) ``` **完整示例代码** ```python import torch def test(): torch.manual_seed(0) data1 = torch.randint(0,10,[2,3]) data2 = torch.randint(0,10,[2,3]) print(data1) print(data2) print('-' * 50) # 将两个张量 stack 起来,像 cat 一样指定维度 # 1. 按照0纬度进行叠加 new_data = torch.stack([data1,data2],dim=0) print(new_data.shape) # print(new_data) print('-' * 50) # 2. 按照1纬度进行叠加 new_data = torch.stack([data1, data2], dim=1) print(new_data.shape) print(new_data) print('-' * 50) # 3. 按照2纬度进行叠加 new_data = torch.stack([data1, data2], dim=2) print(new_data.shape) print(new_data) print('-' * 50) if __name__ == '__main__': test() ``` #### 2.2 切分操作 张量的拆分主要通过split和chunk()函数实现。其中split()是在某维度上按照定义的间隔进行维度拆分的。 ##### (1)torch.split() split操作是对张量在指定维度上将张量进行分割,可以按给定长度等分,也可以通过列表传入分割方法。 ```python torch.split(tensor, split_size_or_sections, dim=0) ``` **参数说明** + **tensor**:要切分的张量 + **split_size_or_sections**:为int时,表示每一份的长度;为list时,按list元素切分 + **dim**: 要切分的维度 **代码示例一** ```python data = torch.randn(3, 4) # 把维度0按照长度[1,2]拆分,形成2个tensor,shape(1,4)和 shape(2,4) new_data = torch.split(data,[1, 2], dim=0) # 把维度1按照长度[2,2]拆分,形成2个tensor,shape(3,2)和shape(3,2) new_data = torch.split(data,[2, 2], dim=1) ``` **代码示例二** ```python data = torch.randn(3, 4) a, b, c = data.split(1, dim=0) print(a) # tensor([[0.0402, 0.4459, 0.9024, 1.0451]]) print(b) # tensor([[-0.0137, 0.9646, -0.8352, 0.1861]]) print(c) # tensor([[ 0.6316, 0.8991, -0.4199, -0.0832]]) print('-' * 50) a, b, c = data.split([1, 1, 1], dim=0) print(a) # tensor([[0.0402, 0.4459, 0.9024, 1.0451]]) print(b) # tensor([[-0.0137, 0.9646, -0.8352, 0.1861]]) print(c) # tensor([[ 0.6316, 0.8991, -0.4199, -0.0832]]) ``` 上方两种分割方式结果是相同的: + 第一种方式是将张量x在维度0上按照每一份长度为1进行等分; + 第二种方式是按照长度[1, 1, 1]的模式将张量x分成三份。 ##### (2)torch.chunk() **功能**:均等分的 split,但是当维度长度不能被等分份数整除时,虽然不会报错,但可能结果与预期的不一样,建议只在可以被整除的情况下运用。 ``` torch.chunk(input, chunks, dim=0) → List of Tensors ``` **参数说明** + **tensor**:要切分的张量 + **chunks**:要切分的份数 + **dim**: 要切分的维度 注意事项:若不能整除,最后一份张量小于其他张量 **代码示例** ```python data = torch.randn(3, 4) print(data) print('-' * 50) new_data = torch.chunk(data,3, dim=0) print(new_data) # new_data运行结果 # (tensor([[-0.5896, -0.1082, -0.3203, -0.3680]]), tensor([[-1.8426, -0.1778, 0.8243, 0.9248]]), tensor([[ 1.9667, -2.0165, 0.2435, -0.6722]])) ``` 上方示例中第二个参数代表要分割成的份数,第三个参数指定了在哪一个维度上分割。
标签:
pytorch
非特殊说明,本博所有文章均为博主原创。
如若转载,请注明出处:
https://lilinchao.com/archives/2945.html
上一篇
04.Pytorch张量类型转换
下一篇
06.Pytorch张量索引操作
评论已关闭
栏目分类
随笔
2
Java
326
大数据
229
工具
31
其它
25
GO
47
NLP
6
标签云
Redis
Eclipse
Java编程思想
ClickHouse
Tomcat
MyBatis
Docker
机器学习
Stream流
Map
Git
稀疏数组
Jquery
Java
Quartz
栈
Spring
Azkaban
并发编程
Golang基础
pytorch
前端
nginx
Java阻塞队列
Spark Core
二叉树
国产数据库改造
容器深入研究
Elastisearch
Jenkins
友情链接
申请
范明明
庄严博客
Mx
陶小桃Blog
虫洞
评论已关闭