李林超博客
首页
归档
留言
友链
动态
关于
归档
留言
友链
动态
关于
首页
NLP
正文
02.Pytorch张量的创建
Leefs
2024-11-30 PM
1704℃
0条
[TOC] ### 前言 PyTorch 是一个 Python 深度学习框架,它将数据封装成张量(Tensor)来进行运算。 PyTorch 中的张量就是元素为同一种数据类型的多维矩阵。在 PyTorch 中,张量以 "类" 的形式封装起来,对张量的一些运算、处理的方法被封装在类中。 ### 一、理解 Tensor Tensor 可以简单理解为是标量、向量、矩阵的高维扩展。 你可以把张量看作多维数组,但相较于ndarray,Tensor 包含了grad、requires_grad、grad_fn、device 等属性,是为服务于神经网络而设计的类型。 标量可以看作是零维张量、向量可以看作是一维张量、矩阵可以看作是二维张量。 若把二维张量看作一个平面,三维张量就是多个二维张量平面两两平行摆放。 灰度图像是典型的二维张量,RGB图像是典型的三维张量(channel, height, width)。  那怎么理解四维张量、五维张量等高维张量? 在之后的深度学习过程中,我们处理图像时会经常遇到四维张量(batch_size, channel, height, width),表示有 batch_size 个 RGB 图像。 更高维的张量无非是在前面添加 batch, 如五维张量(batch', batch, c, h, w)。batch 是高维张量的单位。 下面通过简图理解一下高维张量:  将三维张量看成零维张量,那四维张量不就是一维张量,五维张量不就是二维张量了吗!张量的升维其实也是在降维!!! ### 二、基本创建方式 #### 2.1 直接从数据来创建张量 > **torch.tensor** 根据指定数据创建张量 ```python torch.tensor(data, dtype=None, device=None, requires_grad=False) ``` PyTorch中的tensor函数是一个创建张量的工厂函数,可以用来快速创建各种类型的张量。 **参数说明** - **data**: 数据,像数组的类型都可以,如list、tuple、numpy.ndarray等 - **dtype**: 数据类型,默认与data的数据类型一致 - **device**: 指定张量所在的设备,例如CPU或GPU - **requires_grad**: 指定是否需要计算梯度,默认为False***注意,整形张量不支持求梯度。*** **示例** ```python # 创建一个标量(零维张量) scalar_tensor = torch.tensor(42) print(scalar_tensor) # 创建一个一维张量 vector_tensor = torch.tensor([1, 2, 3]) print(vector_tensor) # 创建一个二维张量 matrix_tensor = torch.tensor([[1, 2], [3, 4]]) print(matrix_tensor) ``` #### 2.2 从numpy数据创建张量 在PyTorch中,`from_numpy`函数是用于从NumPy数组创建张量的工厂函数之一。这个函数将`NumPy数组`转换为`PyTorch张量`,在转换时`不会复制数据`,因此可以`节省内存`和`时间`。 > from_numpy函数 ```python torch.from_numpy(ndarray) ``` 以下是该函数的参数及其解释: + `numpy_array`:要转换为张量的NumPy数组。 + `requires_grad`:指定是否需要计算梯度,默认为False。 利用该方法创建的tensor与原ndarray共享内存,当修改其中一个数据,另外一个也会被更新。 **示例代码** ```python import numpy as np import torch # 创建一个numpy数组 numpy_array = np.array([[1, 2, 3], [4, 5, 6]]) # 从numpy数组创建一个Tensor,并保持数据共享(更改Tensor内容会同时改变numpy数组) tensor_from_numpy = torch.from_numpy(numpy_array) print(tensor_from_numpy) # 输出: # tensor([[1, 2, 3], # [4, 5, 6]], dtype=torch.int32) # 修改tensor,array也会被修改 print("# -----------修改tensor--------------*") t[0, 0] = -1 print("numpy array: ", arr) # 输出: # numpy array: [[-1 2 3] # [ 4 5 6]] print("tensor : ", t) # 输出: # tensor([[-1, 2, 3], # [4, 5, 6]], dtype=torch.int32) ``` 可以看到,通过使用`from_numpy`函数,可以轻松地将NumPy数组转换为PyTorch张量,并且不需要进行任何额外的操作。 此外,由于PyTorch张量与NumPy数组共享底层内存,因此对其中一个的更改可能会影响另一个的值。 #### 2.3 根据形状创建张量 > **torch.Tensor** 根据形状创建张量, 其也可用来创建指定数据的张量(不建议使用) 关于torch.Tensor()函数,现在一般很少使用,或者说并不建议使用,其相对于`torch.tensor()`的优势在于可以指定张量形状进行创建 ```python import torch data1 = torch.Tensor(2, 3) print(data1) # tensor([[-2.1118e+14, 1.5905e-42, 0.0000e+00], # [ 0.0000e+00, 0.0000e+00, 0.0000e+00]]) ``` 可以看到上述代码创建了一个两行三列的随机张量,这里的随机并不符合均匀分布或者正态分布,而是其内存位置上的原本任意值。 同样torch.Tensor()也支持传入数据进行张量转换,但是要注意,这里并不支持传入整形或者浮点型数据,只能传入列表、元组或者ndarray类型数据 ```python import torch data1 = torch.Tensor(3) print(data1) data2 = torch.Tensor(2.0) print(data2) # tensor([-1.4512e+25, 2.1398e-42, 0.0000e+00]) # Traceback (most recent call last): # File "D:\Pythonproject\teach_day_01\demo01.py", line 5, in
# data2 = torch.Tensor(2.) # ^^^^^^^^^^^^^^^^ # TypeError: new(): data must be a sequence (got float) ``` **说明** 由上述代码可以看出data1在创建的时候参数3被识别为了要创建一个一维随机张量,长度为3,而data2在创建的时候可以看到报错中要求data要为一个序列,所以并不支持单数值作为参数使用 ```python import torch import numpy as np data1 = torch.Tensor([1, 2, 3]) print(data1, data1.dtype) data2 = torch.Tensor((1, 2, 3)) print(data2, data2.dtype) data3 = torch.Tensor(np.array([1, 2, 3])) print(data3, data3.dtype) # tensor([1., 2., 3.]) torch.float32 # tensor([1., 2., 3.]) torch.float32 # tensor([1., 2., 3.]) torch.float32 ``` 上述代码演示了由列表、元组和ndarray作为参数的时候的情况,***可以注意到的一点是,torch.Tensor()不会主动识别参数的数据类型,并且没有dtype参数设置来改变数据类型,所有数据最后都会变成float32数据类型,这也是目前不推荐使用Tensor()创建张量的原因。*** #### 2.4 创建指定类型的张量 > **torch.IntTensor**、**torch.FloatTensor**、**torch.DoubleTensor** 创建指定类型的张量 张量的基本数据类型基本包括如下几种数据类型: + ShortTensor + IntTensor + LongTensor + FloatTensor + DoubleTensor 上面五种类型分别对应`torch.int16`,`torch.int32`,`torch.int64`,`torch.float32`,`torch.float64`。 可以使用这几种类型进行指定进行张量的实例化 ```python import torch data1 = torch.ShortTensor([1.2, 2.3, 3.4]) data2 = torch.IntTensor([1.2, 2.3, 3.4]) data3 = torch.LongTensor([1.2, 2.3, 3.4]) data4 = torch.FloatTensor([1, 2, 3]) data5 = torch.DoubleTensor([1, 2, 3]) print(data1) print(data2) print(data3) print(data4) print(data5) # tensor([1, 2, 3], dtype=torch.int16) # tensor([1, 2, 3], dtype=torch.int32) # tensor([1, 2, 3]) # tensor([1., 2., 3.]) # tensor([1., 2., 3.], dtype=torch.float64) ``` 注意,上述的五个张量创建函数,都不支持在定义的时候设置`requires_grad`,都需要在定义完张量后再设置 ```python import torch data1 = torch.FloatTensor([1, 2, 3]) data1.requires_grad = True print(data1) # tensor([1., 2., 3.], requires_grad=True) ``` #### 2.5 完整使用示例 ```python import torch import numpy as np # 1. 根据已有的数据创建张量 def test01(): # 1.1 创建标量 data = torch.tensor(10) print(data) # 1.2 使用numpy数组来创建张量 data = np.random.randn(2,3) data = torch.tensor(data) print(data) # 1.3 使用list列表来创建张量 # tensor默认小数类型是float32 # 数字后面加".",表示是小数类型 data = [[10.,20.,30.],[40.,50.,60.]] data = torch.tensor(data) print(data) # 2. 创建指定形状的张量 def test02(): # 2.1 创建2行3列的张量 data = torch.Tensor(2, 3) print(data) # 2.2 可以创建指定值的张量 # 注意: 传递列表 data = torch.Tensor([2, 3]) print(data) data = torch.Tensor([10]) print(data) # 3. 创建指定类型的张量 def test03(): # 前面创建的张量都是使用默认类型或者元素类型 # 创建一个 int32 类型的张量 data = torch.IntTensor(2,3) print(data) # torch.ShortTensor(2, 3) # 表示创建的是 int16 类型张量 # torch.LongTensor(2, 3) # 表示创建的是 int32 类型的张量 # torch.FloatTensor(2, 3) # 表示创建的是 float32 张量 # 注意: 如果创建指定类型的张量,但是传递的数据不匹配,会发生类型转换 data = torch.IntTensor([2.5, 3.5]) print(data) if __name__ == '__main__': # test01() # test02() test03() ``` ### 三、创建线性和随机张量 #### 3.1 创建线性张量 > `torch.arange` 、 `torch.linspace` 和`torch.logspace`创建线性张量 **(1)创建等差的一维张量** ```python torch.arange(start=0, end, step=1, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) ``` **参数说明** + **start**:数列起始值,默认为0 + **end**:数列结束值,开区间,取不到结束值 + **step**:数列公差,默认为1 **示例** ```python import torch t = torch.arange(2, 10, 2) print(t) # tensor([2, 4, 6, 8]) ``` + **注意区间为:[start,end)**。 **(2)创建均分的一维张量** ```python torch.linspace(start, end, steps=100, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) ``` **参数说明** + **step**:数列长度(元素个数) **示例** ```python import torch t = torch.linspace(2, 10, 3) print(t) # tensor([ 2., 6., 10.]) ``` + **注意区间为:[start,end]**。 **(3)创建对数均分的一维张量** ```python torch.logspace(start, end, steps, base=10, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) ``` **参数说明** + **step**:数列长度(元素个数) + **base**:对数函数的底,默认为 10 **示例** ```python import torch t = torch.logspace(2, 4, 3) print(t) # tensor([100., 1000., 10000.]) ``` + **注意区间为:[start,end]。** #### 3.2 创建随机张量 > `torch.random.init_seed` 和 `torch.random.manual_seed` 随机种子设置 > > ##### `torch.rand`、`torch.randn`、`torch.randint`、`torch.empty` 创建随机张量 **(1)torch.rand()** ```python torch.rand(*size, *, generator=None, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False, pin_memory=False) ``` **作用** + 创建0-1区间内**均匀分布**的随机值 **参数说明** + **size**:为形状,高维可以使用列表或元组形式,也可不使用括号 **示例** ```python import torch #torch.rand(4) #torch.rand(2, 3) data1 = torch.rand(2, 3, device="cuda", dtype=torch.float64, requires_grad=True) print(data1) # tensor([[0.1615, 0.7415, 0.6346], # [0.3183, 0.6323, 0.9578]], device='cuda:0', dtype=torch.float64, # requires_grad=True) ``` **(2)torch.randn()** ```python torch.randn(*size, *, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False, pin_memory=False) ``` **作用** + 生成标准正态分布的随机浮点数向量 **示例** ```python import torch #torch.randn(4) #torch.randn(2, 3) data1 = torch.randn(2, 3, device="cuda", dtype=torch.float64, requires_grad=True) print(data1) # tensor([[-1.1177, -0.6240, -1.4654], # [-0.6016, 0.1243, -0.2280]], device='cuda:0', dtype=torch.float64, # requires_grad=True) ``` **(3)torch.randint** ```python def randint(low: int, high: int, size: Size | List[int] | Tuple[int, ...], *, dtype: dtype | None = None, device: device | str | None = None, requires_grad: bool = False) -> Tensor ``` **作用** + 用于生成指定范围指定形状的随机整形张量,设计的主要参数包括low,high,size,分布对应了生成数值的下限,上限,和形状。 *注意,这里的生成范围为[low,high)也就是不包括上限的,并且生成的数据符合均匀分布* **示例** ```python import torch data1 = torch.randint(0, 10, (2, 3), device="cuda") print(data1) # tensor([[9, 0, 0], # [6, 4, 2]], device='cuda:0') ``` **(4)torch.empty()** ```python def empty(size: Size | List[int] | Tuple[int, ...], *, names: List[str | None] | None, memory_format: memory_format | None = None, out: Tensor | None = None, dtype: dtype | None = None, layout: layout = strided, device: device | str | None = None, requires_grad: bool = False) -> Tensor ``` **作用** + 生成指定形状的未初始化的随机张量,其值取决于先前内存中存储的随机值 **示例** ```python import torch data1 = torch.empty(2, 3, requires_grad=True) print(data1) # tensor([[0., 0., 0.], # [0., 0., 0.]], requires_grad=True) ``` 还有 torch.rand_like()、torch.randperm()、torch.bernoulli()等。 #### 3.3 完整示例代码 ```python import torch # 1. 创建线性空间的张量 def test01(): # 1. 在指定区间按照步长生成元素 [start,end,step) # 第一个参数: 开始值 # 第二个参数: 结束值 # 第三个参数: 步长 data = torch.arange(0,10,2) print(data) # 2. 在指定区间指定元素个数 # 第一个参数: 开始值 # 第二个参数: 结束值 # 第三个参数: 创建元素的个数 data = torch.linspace(0,10,10) print(data) # 2. 创建随机张量 def test02(): # 1. 创建随机张量 data = torch.randn(2, 3) # 创建2行3列张量 print(data) # 2. 随机数种子设置 print('随机数种子:',torch.random.initial_seed()) torch.random.manual_seed(100) print('随机数种子:',torch.random.initial_seed()) if __name__ == '__main__': # test01() test02() ``` ### 四、创建01张量 #### 4.1 创建全0张量 > torch.zeros 和 torch.zeros_like 创建全0张量 **(1)torch.zeros()** ``` torch.zeros(*size, *, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) ``` **作用** + 创建指定形状的全0张量,参数为创建张量的形状以及包括tensor()中的device,dtype,requires_grad参数 **参数说明** - **size(int...)**: 张量的形状 - **out(Tensor)**: 输出张量,将新建的张量写入 out 张量中 - **layout**: 内存中布局形式,有strided、sparse_coo 等。当是稀疏矩阵时,设置为 sparse_coo 可以减少内存占用 - **device**:张量所在的设备(cuda或cpu) - **requires_grad**:是否需要梯度 **示例** ```python import torch data1 = torch.zeros([2, 3]) print(data1) data2 = torch.zeros(2, 3) print(data2) # tensor([[0., 0., 0.], # [0., 0., 0.]]) # tensor([[0., 0., 0.], # [0., 0., 0.]]) ``` 注意形状参数如为高维可以使用元组或者列表的形式,也可以不加括号 ```python import torch data1 = torch.zeros(2, 3, device="cuda", requires_grad=True, dtype=torch.float64) print(data1) # tensor([[0., 0., 0.], # [0., 0., 0.]], device='cuda:0', dtype=torch.float64, # requires_grad=True) ``` **(2)torch.zeros_like()** ``` torch.zeros_like(input, *, dtype=None, layout=None, device=None, requires_grad=False, memory_format=torch.preserve_format) ``` **作用** + 区别于`torch.zeros()`在于第一个参数,`zeros()`是形状,`zeros_like()`的第一个参数是另一个张量,作用是创建与其形状相同的全0张量,其余参数设置与`zeros()`相同 **示例** ```python import torch data1 = torch.tensor([1, 2, 3]) data2 = torch.zeros_like(data1, dtype=torch.float32, device="cuda", requires_grad=True) print(data1) print(data2) # tensor([1, 2, 3]) # tensor([0., 0., 0.], device='cuda:0', requires_grad=True) ``` #### 4.2 创建全1张量 > `torch.ones` 和 `torch.ones_like` 创建全1张量 **(1)torch.ones()** 详情与torch.zeros()类似,区别为创建的是全1张量 **示例** ```python import torch data1 = torch.ones(2, 3, requires_grad=True, dtype=torch.float32, device="cuda") print(data1) # tensor([[1., 1., 1.], # [1., 1., 1.]], device='cuda:0', requires_grad=True) ``` **(2)torch.ones_like()** 详情与torch.zeros_like()类似,区别为创建的是全1张量 ```python import torch data1 = torch.tensor([1, 2, 3]) data2 = torch.ones_like(data1, requires_grad=True, dtype=torch.float32, device="cuda") print(data2) # tensor([1., 1., 1.], device='cuda:0', requires_grad=True) ``` #### 4.3 创建全为指定值张量 > torch.full 和 torch.full_like 创建全为指定值张量 **(1)torch.full()** ```python torch.full(size, fill_value, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) ``` **作用** + 用于创建全指定值元素的张量,注意函数前两个参数分别为`size`和`fill_value`,所以这里的size若为高维需要使用元组或列表的形式,否则可能造成参数错位。 **参数说明** + **size**:张量的形状,可以是一个整数或一个元组或者一个列表。 + **fill_value**:要填充到新张量中的数值。 + **dtype**:新张量的数据类型,默认为float32。 + **device**:新张量所在的设备,例如CPU或GPU。 + **requires_grad**:指定是否需要计算梯度,默认为False。 **示例** ```python import torch data1 = torch.full((2, 3), 10, device="cuda", dtype=torch.float32, requires_grad=True) print(data1) # tensor([[10., 10., 10.], # [10., 10., 10.]], device='cuda:0', requires_grad=True) ``` **(2)torch.full_like()** ```python def full_like(self: Tensor, fill_value: int | float | bool, *, memory_format: memory_format | None = None, dtype: dtype | None = None, layout: layout = strided, device: device | str | None = None, requires_grad: bool = False) -> Tensor ``` **作用** + 用于创建与另一张量相同形状的全指定值张量,与full()的区别在于第一个参数需要设置为用于模仿形状的张量 **示例** ```python import torch data1 = torch.tensor([1, 2, 3]) data2 = torch.full_like( data1, 10, device="cuda", dtype=torch.float32, requires_grad=True ) print(data2) # tensor([10., 10., 10.], device='cuda:0', requires_grad=True) ``` #### 4.4 完整代码示例 ```python import torch # 创建全为0的张量 def test01(): # 1.1 创建指定形状全为 0 的张量 data = torch.zeros(2, 3) print(data) # 1.2 根据其他张量的形状去创建全 0 张量 data = torch.zeros_like(data) print(data) # 创建全为1的张量 def test02(): # 2.1 创建指定形状全为 1 的张量 data = torch.ones(2, 3) print(data) # 2.2 根据其他张量的形状去创建全 1 张量 data = torch.ones_like(data) print(data) # 3. 创建全为指定值的张量 def test03(): # 3.1 创建形状为2行3列,值全部为10的张量 data = torch.full([2,3],100) print(data) # 3.2 创建一个形状和data一样,但是值全部为200的张量 data = torch.full_like(data,200) print(data) if __name__ == '__main__': # test01() # test02() test03() ``` ### 五、Tensor数据类型和元素类型转换 #### 5.1 Tensor数据类型 torch.dtype属性标识了torch.Tensor的数据类型。PyTorch有八种不同的数据类型:  使用 PyTorch 中的 `dtype` 属性可以获取 Tensor 的数据类型。例如: ```python x = t.randn(3, 4) # 创建一个随机的 FloatTensor print(x.dtype) # 输出 torch.float32 ``` ##### Tensor所在设备  如图所示,可以看到每种类型的数据都有一个CPU和一个GPU版本,因此对张量进行处理的时候需要指定一个设备,它要么是CPU要么是GPU,这是数据被分配的位置,这决定了给定张量的张量计算位置。 Pytorch支持多种设备的使用,可以用torch.device来创建一个设备,并指定索引,例如: ``` device=torch.device('cuda:0') ``` 输出结果为:device(type=‘cuda’,index=0),可看到类型为’cuda’,即GPU,索引0表示为第一个GPU。 #### 5.2 Tensor元素类型转换 张量在创建之后也是支持元素类型的转换的,通常有两种方式: + 通过tensor.type()函数进行类型转换 + 通过对应类型方法直接进行类型转换 + 具体的方法有short(),int(),long(),float(),double(),分别对应torch.int16,torch.int32,torch.int64,torch.float32,torch.float64的转换。 + 要注意,该方法不会修改并覆盖原数据,需要重新赋值。 **示例代码** ```python import torch data1 = torch.tensor([1, 2, 3]) data1 = data1.float() print(data1, data1.dtype) data1 = data1.short() print(data1, data1.dtype) data1 = data1.int() print(data1, data1.dtype) data1 = data1.double() print(data1, data1.dtype) data1 = data1.long() print(data1, data1.dtype) # tensor([1., 2., 3.]) torch.float32 # tensor([1, 2, 3], dtype=torch.int16) torch.int16 # tensor([1, 2, 3], dtype=torch.int32) torch.int32 # tensor([1., 2., 3.], dtype=torch.float64) torch.float64 # tensor([1, 2, 3]) torch.int64 ``` #### 5.3 完整示例代码 ```python import torch # 1. type 函数进行转换 def test01(): data = torch.full([2,3],10) print(data.dtype) # 注意: 返回一个新的类型转换过的张量 data = data.type(torch.DoubleTensor) print(data.dtype) # 转换为其他类型 # data = data.type(torch.ShortTensor) # data = data.type(torch.IntTensor) # data = data.type(torch.LongTensor) # data = data.type(torch.FloatTensor) # 2. 使用具体类型函数进行转换 def test02(): data = torch.full([2,3],10) print(data.dtype) # 转换成 float64 类型 data = data.double() print(data.dtype) # data = data.short() # 将张量元素转换为 int16 类型 # data = data.int() # 将张量转换为 int32 类型 # data = data.long() # 将张量转换为 int64 类型 # data = data.float() # 将张量转换为 float32 if __name__ == '__main__': # test01() test02() ``` ### 六、Tensor形状属性 张量具有如下形状属性: - `Tensor.ndim`:张量的维度,例如向量的维度为1,矩阵的维度为2。 - `Tensor.shape`:张量每个维度上元素的数量。 - `Tensor.shape[n]`:张量第n维的大小。第n维也称为轴(axis)。 - `Tensor.numel`:张量中全部元素的个数。 如下是创建一个四维Tensor,并通过图形直观表达以上几个概念的关系。 ```python import torch Tensor=torch.ones([2,3,4,5]) print("Number of dimensions:", Tensor.ndim) print("Shape of Tensor:", Tensor.shape) print("Elements number along axis 0 of Tensor:", Tensor.shape[0]) print("Elements number along the last axis of Tensor:", Tensor.shape[-1]) print('Number of elements in Tensor: ', Tensor.numel()) #用.numel表示元素个数 ```  Tensor的axis、shape、dimension、ndim之间的关系如下图所示。 
标签:
pytorch
非特殊说明,本博所有文章均为博主原创。
如若转载,请注明出处:
https://lilinchao.com/archives/2937.html
上一篇
01.Pytorch在Windows10系统安装教程
下一篇
03.Pytorch张量数值计算
评论已关闭
栏目分类
随笔
2
Java
326
大数据
229
工具
35
其它
25
GO
48
NLP
8
标签云
SpringBoot
MyBatis
MySQL
Livy
CentOS
nginx
Shiro
Zookeeper
Linux
微服务
FastDFS
Golang
Stream流
递归
SpringCloudAlibaba
HDFS
数据结构和算法
排序
散列
Java工具类
二叉树
机器学习
Nacos
队列
正则表达式
ClickHouse
高并发
哈希表
数学
设计模式
友情链接
申请
范明明
庄严博客
Mx
陶小桃Blog
虫洞
评论已关闭