pytorch 2 张量操作

发布于:2024-08-10 ⋅ 阅读:(158) ⋅ 点赞:(0)

张量的创建

直接创建

torch.tensor

torch.tensor(data,dtype=None,device=None,requires_grad=False,pin_memory=False)

  • data(array_like) - tensor的初始数据,可以是list, tuple, numpy array, scalar或其他类型。

  • dtype(torch.dtype, optional) - tensor的数据类型,如torch.uint8, torch.float, torch.long等

  • device (torch.device, optional) – 决定tensor位于cpu还是gpu。如果为None,将会采用默认值,默认值在torch.set_default_tensor_type()中设置,默认为 cpu。

  • requires_grad (bool, optional) – 决定是否需要计算梯度。

  • pin_memory (bool, optional) – 是否将tensor存于锁页内存。这与内存的存储方式有关,通常为False。

l = [[1,2,3],[4,5,6],[7,8,9]]  
t = torch.tensor(l)  
print(t)  
print(t.dtype)  
ll = [[1.,-1.],[1.,-1.]]  
t2 = torch.tensor(ll,dtype=torch.float64) 
print(t2)  
print(t2.dtype)  
t3 = torch.tensor(ll)  
print(t3)  
print(t3.dtype)

![[Pasted image 20240809213925.png]]
浮点数默认是torch.float32类型,可以指定参数dtype进行指定数据类型

arr = np.array([[1,2,3],[4,5,6]])
t_from_arr = torch.tensor(arr,dtype=torch.uint8)
print(t_from_arr)
torch.from_numpy

还有一种常用的通过numpy创建tensor方法是torch.from_numpy()。这里需要特别注意的是,创建的**tensor和原array共享同一块内存(**The returned tensor and ndarray share the same memory. ),即当改变array里的数值,tensor中的数值也会被改变。

arr = np.array([[1,2,3],[4,5,6],[7,8,9]])  
t_from_numpy = torch.from_numpy(arr)  
print("numpy array:",arr)  
print("torch tensor:",t_from_numpy)  
print("\n修改arr")  
arr[0,0]=0  
print("numpy array:",arr)  
print("torch tensor:",t_from_numpy)  
print("\n修改tensor")  
t_from_numpy[0,1]=1  
print("numpy array:",arr)  
print("torch tensor:",t_from_numpy)

![[Pasted image 20240809215934.png]]

依数值创建

torch.zeros

*torch.zeros(size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)

功能:依给定的size创建一个全0的tensor,默认数据类型为torch.float32(也称为torch.float)。

*size 是 Python 中的一种特殊语法,表示“可变长度参数”。
具体来说,*size 的作用是允许函数接收任意数量的参数,并将这些参数作为一个元组传递给函数。在 torch.zeros 中,size 表示张量的形状(即它的维度)。通过使用 *size,你可以传递一个或多个整数来指定张量的每一维的大小。

  1. 单个参数:

    torch.zeros(3)
    

    这会创建一个一维的张量,其大小为3。

  2. 多个参数:

    torch.zeros(3, 4)
    

    这会创建一个二维的张量,其形状为3x4。

  3. 使用元组解包:

    你也可以通过传递一个元组并使用 * 操作符解包参数:

    size = (3, 4, 5)
    torch.zeros(*size)
    

    这会创建一个三维的张量,其形状为3x4x5。

主要参数:

  1. out (tensor, optional)
  • 作用: out 参数允许你指定一个已有的张量,用于接收 torch.zeros 创建的张量结果。这意味着函数的输出不会生成一个新的张量,而是将结果直接存储到 out 参数指定的张量中。

  • 使用场景:

    • 内存优化: 在高效计算和节省内存分配方面非常有用。如果你已经有一个张量,并且希望在相同的内存位置存储新的数据(例如,全零的张量),可以使用 out 参数。
    • 避免不必要的内存分配: 对于大型张量,避免了重复分配内存的开销。
  • 使用示例:

existing_tensor = torch.empty(2, 3) # 创建一个未初始化的张量
torch.zeros(2, 3, out=existing_tensor) # 使用 out 参数将全零的张量结果存储在 existing_tensor 中
print(existing_tensor)

n = np.random.randint(0, 10, size=(3, 3)) #生成一个 3x3 的矩阵,每个元素是 [0, 10) 之间的随机整数
print(n)
#转为张量
nn = torch.from_numpy(n)
#使用 torch.zeros 并将结果存储在 nn 中
torch.zeros(3,3,out=nn)
print(nn)


![[Pasted image 20240809221307.png]]
2. `layout (torch.layout, optional)`

- **作用**: `layout` 参数决定张量在内存中的存储布局方式。PyTorch 支持不同的内存布局,适用于不同的计算需求。

- **常见布局**:
- **`torch.strided`**: 默认的内存布局。数据以密集格式存储,张量元素按照一定的步长(stride)在内存中排列。
- **`torch.sparse_coo`**: 稀疏张量的布局方式,适用于大部分元素为零的稀疏矩阵。这种布局只存储非零元素及其索引,节省内存。

- **使用场景**:
- **默认密集存储**: 如果你的数据是密集的(大多数元素非零),使用默认的 `torch.strided` 布局。
- **稀疏数据**: 如果你的数据是稀疏的(大多数元素为零),使用 `torch.sparse_coo` 布局更为高效。

- **使用示例**:

(1) 默认布局(连续存储):

```python
import torch

# 创建一个形状为 (2, 3) 的默认连续布局零张量
default_tensor = torch.zeros(2, 3)
print(default_tensor)
print(default_tensor.is_contiguous())  # 输出: True

![[Pasted image 20240809222238.png]]
(2) 指定 strided 布局:

# 创建一个形状为 (2, 3) 的 strided 布局零张量
strided_tensor = torch.zeros(2, 3, layout=torch.strided)
print(strided_tensor)
print(strided_tensor.is_contiguous())  # 输出: True

![[Pasted image 20240809222245.png]]
(3) 稀疏布局:

# 创建一个稀疏布局的零张量
sparse_tensor = torch.zeros(2, 3, layout=torch.sparse_coo)
print(sparse_tensor)
print(sparse_tensor.is_sparse)  # 输出: True

![[Pasted image 20240809222349.png]]
解释:
1. indices=tensor([], size=(2, 0)):
- 这表示稀疏张量中非零元素的索引。
- size=(2, 0) 表示这是一个2D张量,但目前没有任何索引(因为张量是空的)。
- 第一个维度 (2) 对应于张量的维数(在这里是2D)。
- 第二个维度 (0) 表示没有非零元素。

2. `values=tensor([], size=(0,))`: 
   - 这表示非零元素的值。
   - 当前为空,因为没有非零元素。

3. `size=(2, 3)`: 
   - 这是整个稀疏张量的形状。
   - 它表示这个稀疏张量在稠密形式下会是一个 2x3 的矩阵。

4. `nnz=0`: 
   - "nnz" 代表 "number of non-zero elements"(非零元素的数量)。
   - 这里为0,表示没有非零元素。

5. `layout=torch.sparse_coo`: 
   - 这指定了张量的布局。
   - `sparse_coo` 表示这是一个 COO(Coordinate)格式的稀疏张量。

(4) 使用 as_strided 创建非连续布局:

# 创建一个非连续布局的零张量
non_contiguous_tensor = torch.zeros(4, 4).as_strided((2, 2), (2, 1))
print(non_contiguous_tensor)
print(non_contiguous_tensor.is_contiguous())  # 输出: False

![[Pasted image 20240809222532.png]]
解释:

  1. torch.zeros(4, 4):

    • 首先,创建一个 4x4 的全零张量。
    • 这个张量在内存中是连续存储的。
  2. .as_strided((2, 2), (2, 1)):

    • 然后,使用 as_strided 方法重新解释这个张量的存储。

    • as_strided 接受两个主要参数:新的形状和新的步长(stride)。

    • 新的形状 (2, 2):
      这表示我们要将原来的 4x4 张量重新解释为一个 2x2 的张量。

    • 新的步长 (2, 1):

      • 步长定义了在内存中如何"跳跃"以获取下一个元素。
      • 2 表示在第一个维度上,每次需要跳过2个元素。
      • 1 表示在第二个维度上,每次只需要移动到下一个相邻元素。

结果是什么样的?

原始的 4x4 张量(用索引表示):

0  1  2  3
4  5  6  7
8  9  10 11
12 13 14 15

应用 as_strided((2, 2), (2, 1)) 后,我们得到:

0  1
4  5

这个新的 2x2 张量是通过以下方式从原始张量中"提取"的:

  • 第一行:取原始张量的 (0,0) 和 (0,1) 元素
  • 第二行:取原始张量的 (1,0) 和 (1,1) 元素

这个新张量是非连续的,因为它在内存中不是连续存储的。它跳过了原始张量中的一些元素。

使用 as_strided 可以创建对原始数据的新视图,而不需要复制数据。这在某些情况下可以提高效率,但也需要小心使用,因为不正确的使用可能导致意外的结果。

(5) 指定设备和数据类型:

# 在 CUDA 设备上创建一个 float16 类型的零张量
if torch.cuda.is_available():
    cuda_tensor = torch.zeros(2, 3, dtype=torch.float16, device='cuda', layout=torch.strided)
    print(cuda_tensor)
    print(cuda_tensor.device)  # 输出: cuda:0

![[Pasted image 20240809222710.png]]

torch.zeros_like

torch.zeros_like(input, dtype=None, layout=None, device=None, requires_grad=False)

功能:依input的size创建全0的tensor。

主要参数:

input(Tensor) - 创建的tensor与intput具有相同的形状。

除了创建全0还有创建全1的tensor,使用方法是一样的,这里就不赘述。

*torch.ones(size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)

功能:依给定的size创建一个全1的tensor。

torch.ones_like(input, dtype=None, layout=None, device=None, requires_grad=False)

功能:依input的size创建全1的tensor。

torch.full(size, fill_value, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)

功能:依给定的size创建一个值全为fill_value的tensor。

主要参数:

siz (int…) - tensor的形状。

fill_value - 所创建tensor的值

out(tensor, optional) - 输出的tensor,即该函数返回的tensor可以通过out进行赋值。

example:

import torch
print(torch.full((2, 3), 3.141592))

torch.full_like(input, fill_value, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)

torch.full_like之于torch.full等同于torch.zeros_like之于torch.zeros,因此不再赘述。

torch.arange(start=0, end, step=1, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)

功能:创建等差的1维张量,长度为 (end-start)/step,需要注意数值区间为[start, end)。

主要参数:

start (Number) – 数列起始值,默认值为0。the starting value for the set of points. Default: 0.

end (Number) – 数列的结束值。

step (Number) – 数列的等差值,默认值为1。

out (Tensor, optional) – 输出的tensor,即该函数返回的tensor可以通过out进行赋值。

example:

import torch
print(torch.arange(1, 2.51, 0.5))

torch.range()函数就不推荐了,因为官网说了“This function is deprecated in favor of torch.arange().”

torch.linspace(start, end, steps=100, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)

功能:创建均分的1维张量,长度为steps,区间为[start, end]。

主要参数:

start (float) – 数列起始值。

end (float) – 数列结束值。

steps (int) – 数列长度。

example:

print(torch.linspace(3, 10, steps=5))
print(torch.linspace(1, 5, steps=3))

torch.logspace(start, end, steps=100, base=10.0, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)

功能:创建对数均分的1维张量,长度为steps, 底为base。

主要参数:

start (float) – 确定数列起始值为base^start

end (float) – 确定数列结束值为base^end

steps (int) – 数列长度。

base (float) - 对数函数的底,默认值为10,此参数是在pytorch 1.0.1版本之后加入的。

example:

torch.logspace(start=0.1, end=1.0, steps=5)
torch.logspace(start=2, end=2, steps=1, base=2)

torch.eye(n, m=None, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)**

功能:创建单位对角矩阵。

主要参数:

n (int) - 矩阵的行数

m (int, optional) - 矩阵的列数,默认值为n,即默认创建一个方阵

example:

import torch
print(torch.eye(3))
print(torch.eye(3, 4))

*torch.empty(size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False, pin_memory=False)

功能:依size创建“空”张量,这里的“空”指的是不会进行初始化赋值操作。

主要参数:

size (int…) - 张量维度

pin_memory (bool, optional) - pinned memory 又称page locked memory,即锁页内存,该参数用来指示是否将tensor存于锁页内存,通常为False,若内存足够大,建议设置为True,这样在转到GPU时会快一些。

torch.empty_like(input, dtype=None, layout=None, device=None, requires_grad=False)

功能:torch.empty_like之于torch.empty等同于torch.zeros_like之于torch.zeros,因此不再赘述。

torch.empty_strided(size, stride, dtype=None, layout=None, device=None, requires_grad=False, pin_memory=False)

功能:依size创建“空”张量,这里的“空”指的是不会进行初始化赋值操作。

主要参数:

stride (tuple of python:ints) - 张量存储在内存中的步长,是设置在内存中的存储方式。

size (int…) - 张量维度

pin_memory (bool, optional) - 是否存于锁页内存。

依概率分布创建

总结

关于张量的创建方式以及是否会自动计算梯度的表格如下:

创建方式 描述 是否自动计算梯度
torch.tensor(data) 创建一个包含数据的张量,默认不启用梯度计算。 否(除非设置requires_grad=True
torch.zeros(size) 创建一个全0的张量,默认不启用梯度计算。 否(除非设置requires_grad=True
torch.ones(size) 创建一个全1的张量,默认不启用梯度计算。 否(除非设置requires_grad=True
torch.full(size, value) 创建一个张量,并用指定值填充,默认不启用梯度计算。 否(除非设置requires_grad=True
torch.arange(start, end) 创建一个包含从start到end的序列的张量,默认不启用梯度计算。 否(除非设置requires_grad=True
torch.linspace(start, end) 创建一个包含线性间隔的序列的张量,默认不启用梯度计算。 否(除非设置requires_grad=True
torch.rand(size) 创建一个包含均匀分布随机数的张量,默认不启用梯度计算。 否(除非设置requires_grad=True
torch.randn(size) 创建一个包含正态分布随机数的张量,默认不启用梯度计算。 否(除非设置requires_grad=True
torch.empty(size) 创建一个未初始化的张量,默认不启用梯度计算。 否(除非设置requires_grad=True
torch.eye(size) 创建一个单位矩阵张量,默认不启用梯度计算。 否(除非设置requires_grad=True
torch.autograd.Variable() 创建一个变量(旧版本),可以设置是否启用梯度计算(通过requires_grad=True)。 是(如果设置requires_grad=True
torch.from_numpy(ndarray) 将一个NumPy数组转换为张量,默认不启用梯度计算。 否(除非设置requires_grad=True
torch.tensor(data, requires_grad=True) 创建一个启用梯度计算的张量。

张量的操作

scater_

张量的随机种子

张量的数学操作

总结

参考

  1. https://tingsongyu.github.io/PyTorch-Tutorial-2nd/chapter-2/2.4-method-tensor.html#%E4%BE%9D%E6%95%B0%E5%80%BC%E5%88%9B%E5%BB%BA