torch as_strided函数详解

本文深入探讨了numpy.lib.stride_tricks.as_strided函数的使用,通过实例解析了如何利用该函数将矩阵转换为指定形状的小矩阵,并详细解释了strides属性在内存布局中的作用。内容包括不同数据类型占用字节数的计算以及如何根据原始矩阵内容推断strides参数。此外,还展示了as_strided函数在处理卷积操作中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

假设有一个矩阵X

[ 1 2 3 4 5 6 7 8 9 ] \left[\begin{matrix} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \end{matrix}\right] 147258369
如果卷积核大小是2*2,stride为1,那么就需要把矩阵转换为如下4个小矩阵的新矩阵
[ [ 1 2 4 5 ] [ 2 3 5 6 ] [ 4 5 6 7 ] [ 5 6 7 8 ] ] \left[\begin{matrix} \left[\begin{matrix} 1 & 2 \\ 4 & 5 \\ \end{matrix}\right]\left[\begin{matrix} 2 & 3 \\ 5 & 6 \\ \end{matrix}\right] \\ \left[\begin{matrix} 4 & 5 \\ 6 & 7 \\ \end{matrix}\right]\left[\begin{matrix} 5 & 6 \\ 7 & 8 \\ \end{matrix}\right] \\ \end{matrix}\right] [1425][2536][4657][5768]
而as_strided就是进行这种操作,查看一下对于as_strided参数的描述

numpy.lib.stride_tricks.as_strided(x, shape=None, strides=None, subok=False, writeable=True)

x就是我们要分割的矩阵,可以当做是一个蓝图,shape,strides都是新矩阵的属性,也就是说这个函数按照给定的shape和strides来划分x,返回一个新的矩阵,最后两个参数不讨论,可以看numpy官方手册的描述
shape很好理解,用的也比较多
比如矩阵X的shape:(3, 3);矩阵A的shape:(2,2,2,2)
至于strides属性,先看下面的代码:

a = np.arange(9, dtype=np.int32).reshape(3,3)
print(a)
'''
[[0 1 2]
 [3 4 5]
 [6 7 8]]
 '''
print(a.strides)
'''
(12, 4)
'''

这里12为从a[0][0]到a[1][0]的维度,4为从a[0][0]到a[0][1]的维度
因为np.int32为4B,从a[0][0]到a[1][0]即从数值0到数值3跨越了3个数值,所以strides= 3 ∗ 4 B = 12 B 3*4B=12B 34B=12B。a[0][0]到a[0][1]即从数值0到数值1跨越了1个数值,所以strides= 1 ∗ 4 B = 4 B 1*4B=4B 14B=4B
注意:strides的单位始终为字节。
同类的例子如下:

b = np.arange(16,dtype=np.float).reshape(4,4)
print(b.strides)
#(32,8)
c = np.arange(27,dtype=np.float).reshape(3,3,3)
print(c.strides)
#(36,12,4)

当数值为0~15的时候
[ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ] \left[\begin{matrix} 1 & 2 & 3 & 4\\ 5 & 6 & 7 & 8\\ 9 & 10 & 11 &12\\ 13 & 14 & 15 &16 \end{matrix}\right] 15913261014371115481216
由于np.float一次占据8B,所以b.strides[0]为由[0][0] = 1到[1][0] = 5,跨越了 4 ∗ 8 B = 32 B 4*8B = 32B 48B=32B,b.strides[1]为由[0][0] = 1到[0][1] = 2,跨越了 1 ∗ 8 B = 8 B 1*8B = 8B 18B=8B,所以b.strides = (32,8)
同理矩阵c的内容为
[ [ 1 2 3 4 5 6 7 8 9 ] [ 10 11 12 13 14 15 16 17 18 ] [ 19 20 21 22 23 24 25 26 27 ] ] \left[\begin{matrix} \left[\begin{matrix} 1 & 2 & 3\\ 4 & 5 & 6\\ 7 & 8 & 9\\ \end{matrix}\right]\\ \left[\begin{matrix} 10 & 11 & 12\\ 13 & 14 & 15\\ 16 & 17 & 18\\ \end{matrix}\right]\\ \left[\begin{matrix} 19 & 20 & 21\\ 22 & 23 & 24\\ 25 & 26 & 27\\ \end{matrix}\right]\\ \end{matrix}\right] 147258369101316111417121518192225202326212427
这里如果从a[0][0][0]到a[1][0][0],即从1到10的位置,一个float类型的数据占据4B,所以 c . s t r i d e s [ 0 ] = 4 B ∗ 9 = 36 B c.strides[0] = 4B*9 = 36B c.strides[0]=4B9=36B。如果从a[0][0][0]到a[0][1][0],即从1到4的位置,这里 c . s t r i d e s [ 1 ] = 4 B ∗ 3 = 12 B c.strides[1] = 4B*3 = 12B c.strides[1]=4B3=12B。如果从a[0][0][0]到a[0][0][1],即从1到2的过程,这里 c . s t r i d e s [ 2 ] = 4 B c.strides[2] = 4B c.strides[2]=4B,综上c.strides = (36,12,4)。
接下来看从X得到A的as_strided函数

A = as_strided(X,shape=(2,2,2,2),strides)

原向量X的内容为
[ 1 2 3 4 5 6 7 8 9 ] \left[\begin{matrix} 1 & 2 & 3\\ 4 & 5 & 6\\ 7 & 8 & 9\\ \end{matrix}\right] 147258369
结果为
[ [ 1 2 4 5 ] [ 2 3 5 6 ] [ 4 5 7 8 ] [ 5 6 8 9 ] ] \left[\begin{matrix} \left[\begin{matrix} 1 & 2\\ 4 & 5 \end{matrix}\right] \left[\begin{matrix} 2 & 3\\ 5 & 6 \end{matrix}\right]\\ \left[\begin{matrix} 4 & 5\\ 7 & 8\\ \end{matrix}\right] \left[\begin{matrix} 5 & 6\\ 8 & 9\\ \end{matrix}\right]\\ \end{matrix}\right] [1425][2536][4758][5869]
这里的matrix[0][0][0][0]->matrix[1][0][0][0]:1->4,
search original matrix
[ 1 2 3 4 5 6 7 8 9 ] \left[\begin{matrix} 1 & 2 & 3\\ 4 & 5 & 6\\ 7 & 8 & 9\\ \end{matrix}\right] 147258369
s t r i d e s [ 0 ] = 4 B ∗ 3 = 12 B strides[0] = 4B*3=12B strides[0]=4B3=12B
matrix[0][0][0][0]->matrix[0][1][0][0]:1->2,
search original matrix
[ 1 2 3 4 5 6 7 8 9 ] \left[\begin{matrix} 1 & 2 & 3\\ 4 & 5 & 6\\ 7 & 8 & 9\\ \end{matrix}\right] 147258369
s t r i d e s [ 1 ] = 4 B ∗ 1 = 4 B strides[1] = 4B*1 = 4B strides[1]=4B1=4B
matrix[0][0][0][0]->matrix[0][0][1][0]:1->4
search original matrix
[ 1 2 3 4 5 6 7 8 9 ] \left[\begin{matrix} 1 & 2 & 3\\ 4 & 5 & 6\\ 7 & 8 & 9\\ \end{matrix}\right] 147258369
s t r i d e s [ 2 ] = 4 B ∗ 3 = 12 B strides[2] = 4B*3=12B strides[2]=4B3=12B
matrix[0][0][0][0]->matrix[0][0][0][1]:1->2
search original matrix
[ 1 2 3 4 5 6 7 8 9 ] \left[\begin{matrix} 1 & 2 & 3\\ 4 & 5 & 6\\ 7 & 8 & 9\\ \end{matrix}\right] 147258369
s t r i d e s [ 2 ] = 4 B ∗ 1 = 4 B strides[2] = 4B*1=4B strides[2]=4B1=4B
final output

X = np.arange(9, dtype=np.int32).reshape(3,3)
print(X)
'''
[[0 1 2]
 [3 4 5]
 [6 7 8]]
'''
A = np.lib.stride_tricks.as_strided(X, shape=(2,2,2,2), strides=(12,4,12,4))
print(A)
'''
[[[[0 1]
   [3 4]]

  [[1 2]
   [4 5]]]


 [[[3 4]
   [6 7]]

  [[4 5]
   [7 8]]]]
'''
<think>好的,用户现在想了解libtorchtorch::from_blob函数的详细用法和参数说明。我需要先回忆一下这个函数的作用和常见用法,然后结合用户提供的引用内容来组织回答。 首先,用户之前的问题是关于深度学习中steps_per_epoch的计算,现在转向libtorch的具体函数,这可能是在实际开发中遇到了数据处理或模型转换的问题。用户提供的引用[1]中有一个C++的示例代码,涉及到张量的创建,而引用[2]和[3]则关于TorchScript转换和强化学习的代码结构。这说明用户可能在将PyTorch模型部署到C++环境时遇到了问题,需要处理数据加载或张量创建,因此需要了解from_blob的用法。 torch::from_blob的作用是将现有的内存块转换为libtorch张量,而无需复制数据,这对于性能优化很重要。参数方面,需要明确数据指针、形状、步长、设备等。用户可能关心如何正确传递参数,避免内存问题,以及不同数据类型的处理。 接下来要详细说明函数的参数:data_ptr是内存指针,sizes是形状,strides是步长,options包括数据类型和设备,requires_grad是否需要梯度。需要给出每个参数的类型和示例,比如如何从OpenCV的Mat对象创建张量,这在引用[1]中有涉及,用户可能在做图像处理,所以结合OpenCV的例子会很有帮助。 另外,需要注意内存管理,用户必须确保张量使用期间内存有效。可能用户在使用时遇到悬垂指针的问题,所以需要提醒他们注意生命周期。 然后,提供示例代码,展示如何将不同来源的数据转换为张量,比如数组、OpenCV Mat,并说明不同数据类型的处理。这能帮助用户理解实际应用场景,比如在引用[1]中用户已经使用了libtorch和OpenCV,所以结合这些库的例子更贴切。 最后,生成相关问题,帮助用户深入理解相关主题,如内存管理、与PyTorch的接口差异、数据预处理等。这些扩展问题能引导用户进一步学习,解决可能遇到的后续问题。 总结回答结构:先介绍函数作用,参数详解,使用示例,注意事项,再相关问题。确保内容清晰,符合用户要求的步骤和真实可靠。</think>在LibTorch中,`torch::from_blob` 是一个关键函数,用于将现有的内存数据转换为张量(Tensor),**无需复制底层数据**。这在处理图像、音频等外部数据源时特别有用[^1]。 --- ### 一、函数原型 ```cpp torch::Tensor torch::from_blob( void* data_ptr, // 内存指针 torch::IntArrayRef sizes, // 张量形状 torch::IntArrayRef strides = {}, // 步长(可选) const torch::TensorOptions& options = torch::TensorOptions(), // 数据类型和设备 bool requires_grad = false // 是否需要梯度 ); ``` --- ### 二、参数详解 1. **`data_ptr`** - 类型:`void*` - 作用:指向已分配内存的指针,支持`int`、`float`等原生数据类型 - 注意:**必须保证张量生命周期内数据有效**,避免悬垂指针 2. **`sizes`** - 类型:`torch::IntArrayRef`(如`{height, width, channels}`) - 作用:定义输出张量的维度形状 - 示例:`{640, 480, 3}` 表示图像张量的高度、宽度和通道数 3. **`strides`** (可选) - 类型:`torch::IntArrayRef` - 作用:定义内存中数据的步长(每个维度相邻元素的字节偏移量) - 默认值:根据`sizes`自动计算连续内存的步长 4. **`options`** (可选) - 类型:`torch::TensorOptions` - 常用设置: ```cpp torch::TensorOptions().dtype(torch::kFloat32).device(torch::kCPU) ``` - 支持数据类型:`kFloat32`, `kUInt8`, `kInt8`等(参考引用[1]中的张量类型) 5. **`requires_grad`** (可选) - 类型:`bool` - 默认:`false` - 作用:是否启用梯度计算(用于反向传播) --- ### 三、使用示例 #### 1. 从C++数组创建张量 ```cpp float raw_data[] = {1.1, 2.2, 3.3, 4.4}; auto tensor = torch::from_blob( raw_data, {2, 2}, // 形状为2x2 torch::TensorOptions().dtype(torch::kFloat32) ); ``` #### 2. 从OpenCV Mat创建张量(引用[1]结合) ```cpp cv::Mat image = cv::imread("image.jpg"); // 假设为BGR格式的3通道图像 auto tensor = torch::from_blob( image.data, {image.rows, image.cols, 3}, // 形状 HxWxC torch::TensorOptions().dtype(torch::kUInt8) ); ``` #### 3. 指定非连续内存步长 ```cpp int data[6] = {1,2,3,4,5,6}; // 内存布局为每行间隔2个元素(步长=2) auto tensor = torch::from_blob(data, {2,3}, {2,1}, torch::kInt32); ``` --- ### 四、注意事项 1. **内存所有权** - LibTorch不会接管内存管理,需手动确保数据有效性 - 若需自动管理,可结合`torch::Tensor`的`clone()`方法复制数据 2. **数据类型匹配** - 确保`options.dtype()`与实际数据类型一致(如引用[1]中`kI8`对应`int8_t`) 3. **设备一致性** - 默认在CPU上,若需GPU加速需设置`.device(torch::kCUDA)` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值