如何用单次操作从多维张量中按行提取不同起始位置的变长切片

冬静酱_7112

冬静酱_7112

2026-07-04

539人浏览

原创

如何用单次操作从多维张量中按行提取不同起始位置的变长切片

本文介绍如何在 PyTorch 中仅通过一次张量操作,从高维张量(如 (100, 50, 3))中按指定行索引和各自独立的起始/长度提取连续子序列,并合并为统一结果,避免显式循环或多次索引拼接。

本文介绍如何在 pytorch 中仅通过一次张量操作,从高维张量(如 `(100, 50, 3)`)中按指定行索引和各自独立的起始/长度提取连续子序列,并合并为统一结果,避免显式循环或多次索引拼接。

在实际深度学习与数据处理中,常需从批量样本(如 batch × seq_len × feature_dim)中对每个样本提取不同起始位置、但相同长度的子序列(例如:第0个样本取 [5:10],第1个样本取 [10:15])。若使用传统方式——先索引再逐个切片最后拼接——不仅代码冗余,还无法充分利用 GPU 并行性。PyTorch 提供了更高效、可微分的解决方案:基于 torch.gather 的向量化索引。

核心思路是:将“每行不同起始位置 + 固定长度”的切片需求,转化为一个二维索引矩阵(形状为 [N, L]),再将其广播扩展至目标维度,最后沿指定轴 gather 原张量。

以下为完整实现步骤(以原始张量 arr = torch.randint(0, 9, (100, 50, 3)) 为例):

Omma
Omma

Omma是一款AI文本写作工具,Spline 推出的 AI 3D 内容智能创作平台。

下载
import torch

# 原始张量:(100, 50, 3)
arr = torch.randint(0, 9, (100, 50, 3))

# 目标行索引(第一维)和对应起始位置
row_indices = torch.tensor([5, 55])     # 取第5行和第55行 → shape: [2]
start_indices = torch.tensor([5, 10])    # 各自行的起始偏移 → shape: [2]
length = 5                               # 每行提取长度(必须一致)

# 步骤1:构造相对偏移序列 [0, 1, ..., length-1]
offsets = torch.arange(length, device=arr.device)  # shape: [5]

# 步骤2:广播相加,生成绝对列索引矩阵
# start_indices[:, None] + offsets[None, :] → shape: [2, 5]
idx_2d = start_indices.unsqueeze(1) + offsets.unsqueeze(0)  # 或写作: start_indices[:, None] + offsets[None, :]

# 步骤3:扩展至第三维(特征维度),适配 gather 输入要求
# idx_2d.shape = [2, 5] → 扩展为 [2, 5, 3],使每个 (i,j) 对应全部3个通道
idx_3d = idx_2d.unsqueeze(-1).expand(-1, -1, arr.size(-1))  # shape: [2, 5, 3]

# 步骤4:在 dim=1(即序列维度)上 gather —— 注意:arr[row_indices] 后 shape 为 [2, 50, 3]
partial_arr = arr[row_indices]  # shape: [2, 50, 3]
result = partial_arr.gather(1, idx_3d)  # shape: [2, 5, 3]

# 最终结果:若需展平为 [10, 3](即 cat([first_result, second_result]) 效果)
final_result = result.view(-1, arr.size(-1))  # shape: [10, 3]

✅ 关键要点说明:

  • torch.gather 要求 index 张量与 input 在除 dim 外其余维度一致;因此需将二维索引 idx_2d 显式扩展至三维以匹配 partial_arr 的通道数。
  • 所有操作均为向量化、无 Python 循环,支持 CUDA 加速与梯度回传(gather 是可微操作)。
  • 限制条件:各子序列长度必须相同(因 torch.arange(length) 生成统一 offset 序列);若长度不等,需 padding 或分组处理,无法单次 gather 完成。

? 进阶提示:若需动态长度,可结合 torch.nn.utils.rnn.pad_sequence 预处理,或使用 torch.scatter 反向构建掩码,但复杂度显著上升。对于绝大多数序列抽取任务(如 NLP 中的 span extraction、时序模型中的 sliding window),固定长度 + gather 是最优实践。

综上,通过 unsqueeze、expand 与 gather 的组合,我们成功将原本需三次独立索引+拼接的操作,压缩为一次全张量运算——兼顾简洁性、性能与可扩展性。

相关专题

更多
python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

2023.07.20

1571

4

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

2023.07.25

3784

7

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.31

1589

3

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

2023.08.03

21697

23

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.04

2667

5

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.04

2727

5

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

1103

5

python合并两个列表
python合并两个列表

Python是一种强大的编程语言,具有许多方便的功能和工具。在Python中,有多种方法可以合并两个列表。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.10

596

4

python是前端还是后端
python是前端还是后端

Python属于前端也属于后端,其灵活性和丰富的生态系统使得开发人员能够在不同的领域中灵活运用。本专题为大家提供python相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

2103

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.6万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 133.2万人学习