一、数据操作


数据操作


前言

  • 无论使用那个深度学习框架,我们都要使用到张量(tensor),与我们之前学的 Numpy 的 ndarray 类似。
  • 但深度学习框架又比Numpy的ndarray多一些重要功能: .
    • 首先,GPU很好地支持加速计算,而NumPy仅支持CPU计算;
    • 其次,张量类支持自动微分。

一、张量是什么?

  • 张量,英文为Tensor,是机器学习的基本构建模块,是以数字方式表示数据的形式。
  • 例如,图像可以表示为形状为 [3, 224, 224] 的张量,这意味着 [colour_channels, height, width] ,因为图像具有 3 颜色通道(红色、绿色、蓝色),高度为 224 像素,宽度为 224 像素。
  • 在张量语言(用于描述张量的语言)中,张量将具有三个维度,一个维度表示 colour_channels 、 height 和 width 。

二、张量的基本类型

代码如下(示例):

# 0维张量:标量(scalar)
scalar = torch.tensor(7)         
print(scalar.ndim)  # 0

# 1维张量:向量(vector)
vector = torch.tensor([7, 7])        
print(vector.ndim)  # 1

# 2维张量:矩阵(matrix)
MATRIX = torch.tensor([[7, 8], 
                       [9, 10]])
print(MATRIX .ndim)  # 2

# 多维张量
TENSOR = torch.tensor([[[1, 2, 3],
                        [3, 6, 9],
                        [2, 4, 5]]])
print(TENSOR .ndim)  # 3

三、张量的创建

3.1 torch.tensor() 根据指定数据创建张量

代码如下(示例):

import torch
import numpy as np

# 1. 创建张量标量
data = torch.tensor(10)
print(data)  # tensor(10)


# 2. numpy 数组, 由于 data 为 float64, 下面代码也使用该类型
data = np.random.randn(2, 3)
data = torch.tensor(data)
print(data)  # tensor([[ 0.1345,  0.1149,  0.2435],
             #         [ 0.8026, -0.6744, -1.0918]], dtype=torch.float64)


# 3. 列表, 下面代码使用默认元素类型 float32
data = [[10., 20., 30.], [40., 50., 60.]]
data = torch.tensor(data)
print(data)   # tensor([[10., 20., 30.],
              #         [40., 50., 60.]])

3.2 torch.Tensor() 根据指定形状创建张量,也可以用来创建指定数据的张量

代码如下(示例):

# 1. 创建2行3列的张量, 默认 dtype 为 float32
# 将创建一个形状为 (2, 3) 的张量,但其中的值将是未定义的(即它们可能包含任意数据,取决于内存的状态)
# 这在某些情况下可能不是你想要的行为,因为它可能导致难以追踪的错误。
data = torch.Tensor(2, 3)
print(data)
>>> tensor([[0.0000e+00, 3.6893e+19, 2.2018e+05],
            [4.6577e-10, 2.4158e-12, 1.1625e+33]])

# 2. 注意: 如果传递列表, 则创建包含指定元素的张量
data = torch.Tensor([10])
print(data)
>>> tensor([10.])

data = torch.Tensor([10, 20])
print(data)
>>> tensor([10., 20.])

3.3 torch.IntTensor()、torch.FloatTensor()、torch.DoubleTensor() 创建指定类型的张量

代码如下(示例):

# 1. 创建2行3列, dtype 为 int32 的张量
data = torch.IntTensor(2, 3)
print(data)
>>> tensor([[ 0, 1610612736, 1213662609],
            [ 805308409,  156041223,  1]], dtype=torch.int32)

# 2. 注意: 如果传递的元素类型不正确, 则会进行类型转换
data = torch.IntTensor([2.5, 3.3])
print(data)
>>> tensor([2, 3], dtype=torch.int32)

# 3. 其他的类型
data = torch.ShortTensor()  # int16
data = torch.LongTensor()   # int64
data = torch.FloatTensor()  # float32
data = torch.DoubleTensor() # float64

四、线性张量和随机张量

4.1 torch.arange()、torch.linspace() 创建线性张量

代码如下(示例):

# 1. # 1.arange[开始, 结束, 步长)
# 左闭右开区间, 不写步长 默认是1
data = torch.arange(0, 10, 2)
print(data)
>>> tensor([0, 2, 4, 6, 8])

# 2. 在指定区间按照元素个数生成 [start, end, steps]
# 2. linspace[开始, 结束, 数量]
# 左闭右闭区间, 数量必须写, 意思是一共在这个区间产生几个数
data = torch.linspace(0, 11, 10)
print(data)
>>> tensor([0.0000, 1.2222, 2.4444, 3.6667, 4.8889, 6.1111, 7.3333, 8.5556, 9.7778, 11.0000])

4.2 随机种子操作

代码如下(示例):

# 1. 设置随机种子
# 1.1 创建随机张量
data = torch.randn(2, 3)  # 创建2行3列张量
print(data)
>>> tensor([[-0.5209, -0.2439, -1.1780],
            [ 0.8133,  1.1442,  0.6790]])
            
# 1.2 查看随机种子
print('查看随机种子为:', torch.random.initial_seed()) # 3893177850043400

# 3.2 设置随机种子
torch.random.manual_seed(100) # 设置随机种子为100, 这样在这个文件中,每次生成的tensor就会一样
data2 = torch.randn(2, 3)
print(data2)
print('设置随机种子后:', torch.random.initial_seed()) # 100

五、创建 0-1 张量

5.1 torch.zeros()、torch.zeros_like() 创建全0张量

代码如下(示例):

import torch
import numpy as np

# 1 创建全是 0 的张量
# 1.1 创建1维全是 0 的张量, 一共五个
print(torch.zeros(5))  # tensor([0., 0., 0., 0., 0.])
# 1.2 创建指定形状的全是 0 的张量
data = torch.zeros(2, 3)
print(data)    # tensor([[0., 0., 0.],
               #         [0., 0., 0.]])

# 1.3 根据张量形状创建全是0 的张量
data1 = torch.zeros_like(data)
print(data1)   # tensor([[0., 0., 0.],
               #         [0., 0., 0.]])

5.2 torch.ones()、torch.ones_like() 创建全1张量

代码如下(示例):

# 2 创建全是 1 的张量
# 2.1 创建1维全是 1 的张量, 一共五个
print(torch.ones(5))    # tensor([1., 1., 1., 1., 1.])
# 2.2 创建指定形状的全是 1 的张量
data = torch.ones(2, 3) 
print(data)        # tensor([[1., 1., 1.],
                   #         [1., 1., 1.]])

# 1.3 根据张量形状创建全是 1 的张量
data1 = torch.ones_like(data)
print(data1)     # tensor([[1., 1., 1.],
                 #         [1., 1., 1.]])

5.3 torch.full()、torch.full_like() 创建全为指定值张量

代码如下(示例):

# 3 创建 指定值 的张量
# 3.1 创建指定形状的全是 10 的张量, 传的是 整型 或者 浮点型 的数据, 张量就是什么类型
data = torch.full([3, 2], 10.)
print(data)     # tensor([[10., 10.],
                #         [10., 10.],
                #         [10., 10.]])
                
# 3.2 根据张量形状创建全是 20 的张量, 传进来的数据是什么类型,那么新的张量就是什么类型
data1 = torch.full_like(data, 20)
print(data1)   # tensor([[20., 20.],
               #         [20., 20.],
               #         [20., 20.]])

六、张量里的元素类型转换

6.1 data.type(torch.DoubleTensor)

代码如下(示例):

data = torch.full([2, 3], 10)
print(data.dtype)
>>> torch.int64

# 将 data 元素类型转换为 float64 类型
data = data.type(torch.DoubleTensor)
print(data.dtype)
>>> torch.float64

# 转换为其他类型
# data = data.type(torch.ShortTensor)   # int16
# data = data.type(torch.IntTensor)    # int32
# data = data.type(torch.LongTensor)   # int64
# data = data.type(torch.FloatTensor)  # float32

6.2 data.double()

代码如下(示例):

data = torch.full([2, 3], 10)
print(data.dtype)
>>> torch.int64

# 将 data 元素类型转换为 float64 类型
data = data.double()
print(data.dtype)
>>> torch.float64

# 转换为其他类型
# data = data.short()
# data = data.int()
# data = data.long()
# data = data.float()

七、张量的类型转换

7.1 张量转换为Numpy数组

  • 使用 Tensor.numpy 函数可以将张量转换为 ndarray 数组,但是共享内存,可以使用 copy 函数避免共享。

代码如下(示例):

# 1. 将张量转换为 numpy 数组
data_tensor = torch.tensor([2, 3, 4])
# 使用张量对象中的 numpy 函数进行转换
data_numpy = data_tensor.numpy()
print(type(data_tensor))
>>> <class 'torch.Tensor'>

print(type(data_numpy))
>>> <class 'numpy.ndarray'>

# 注意: data_tensor 和 data_numpy 共享内存
# 修改其中的一个,另外一个也会发生改变
# data_tensor[0] = 100
data_numpy[0] = 100
print(data_tensor)
>>> tensor([100,   3,   4])

print(data_numpy)
>>> [100   3   4]

# 2. 对象拷贝避免共享内存
data_tensor = torch.tensor([2, 3, 4])
# 使用张量对象中的 numpy 函数进行转换,通过copy方法拷贝对象
data_numpy = data_tensor.numpy().copy()
print(type(data_tensor))
>>> <class 'torch.Tensor'>

print(type(data_numpy))
>>> <class 'numpy.ndarray'>

# 注意: data_tensor 和 data_numpy 此时不共享内存
# 修改其中的一个,另外一个不会发生改变
# data_tensor[0] = 100
data_numpy[0] = 100
print(data_tensor)
>>> tensor([2, 3, 4])

print(data_numpy)
>>> [100   3   4]

7.2 Numpy数组转换为张量

7.2.1 使用 from_numpy

  • 使用 from_numpy 可以将 ndarray 数组转换为 Tensor,默认共享内存,使用 copy 函数避免共享

代码如下(示例):

data_numpy = np.array([2, 3, 4])
# 将 numpy 数组转换为张量类型
# 1. from_numpy
# 2. torch.tensor(ndarray)
data_tensor = torch.from_numpy(data_numpy)
# nunpy 和 tensor 共享内存
# data_numpy[0] = 100
data_tensor[0] = 100
print(data_tensor)
>>> tensor([100,   3,   4], dtype=torch.int32)

print(data_numpy)
>>> [100   3   4]

7.2.1 使用 torch.tensor

  • 使用 torch.tensor 可以将 ndarray 数组转换为 Tensor,默认不共享内存

代码如下(示例):

data_numpy = np.array([2, 3, 4])
data_tensor = torch.tensor(data_numpy)
# nunpy 和 tensor 不共享内存
# data_numpy[0] = 100
data_tensor[0] = 100
print(data_tensor)
>>> tensor([100,   3,   4], dtype=torch.int32)

print(data_numpy)
>>> [2 3 4]

7.3 pandas转成tensor

代码如下(示例):

import pandas as pd
# pandas读取csv文件
data = pd.read_csv('文件路径')

data = data.to_numpy(dtype=float)

tensor_data = torch.tensor(data)

7.4 标量张量和数字转换

  • 对于只有一个元素的张量,使用item()函数将该值从张量中提取出来

代码如下(示例):

# 当张量只包含一个元素时, 可以通过 item() 函数提取出该值
data = torch.tensor([30,])
print(data.item())
>>> 30

data = torch.tensor(30)
print(data.item())
>>> 30

八、张量的计算

8.1 加减乘除取负号

  • add、sub、mul、div、neg
  • add_、sub_、mul_、div_、neg_(其中带下划线的版本会修改原数据)

代码如下(示例):

data = torch.randint(0, 10, [2, 3])
print(data)
>>> tensor([[3, 7, 4],
            [0, 0, 6]])

# 1. 不修改原数据
new_data = data.add(10)  # 等价 new_data = data + 10
print(new_data)
>>> tensor([[13, 17, 14],
            [10, 10, 16]])

# 2. 直接修改原数据 注意: 带下划线的函数为修改原数据本身
data.add_(10)  # 等价 data += 10
print(data)
>>> tensor([[13, 17, 14],
            [10, 10, 16]])

# 3. 其他函数
print(data.sub(100))
>>> tensor([[-87, -83, -86],
            [-90, -90, -84]])

print(data.mul(100))
>>> tensor([[1300, 1700, 1400],
            [1000, 1000, 1600]])

print(data.div(100))
>>> tensor([[0.1300, 0.1700, 0.1400],
            [0.1000, 0.1000, 0.1600]])

print(data.neg())
>>> tensor([[-13, -17, -14],
            [-10, -10, -16]])

8.2 张量点乘运算

  • 点乘指(Hadamard)的是两个同维矩阵对应位置的元素相乘,使用mul 和运算符 * 实现

代码如下(示例):

data1 = torch.tensor([[1, 2], [3, 4]])
>>> tensor([[1, 2],
            [3, 4]])

data2 = torch.tensor([[5, 6], [7, 8]])
>>> tensor([[5, 6],
            [7, 8]])
            
# 第一种方式
data = torch.mul(data1, data2)
print(data)
>>> tensor([[ 5, 12],
            [21, 32]])

# 第二种方式
data = data1 * data2
print(data)
>>> tensor([[ 5, 12],
            [21, 32]])

8.3 张量矩阵乘法运算

  • 矩阵乘法运算要求第一个矩阵 shape: (n, m),第二个矩阵 shape: (m, p), 两个矩阵点积运算 shape 为: (n, p)。
  • 运算符 @ 用于进行两个矩阵的乘积运算
  • torch.matmul 对进行乘积运算的两矩阵形状没有限定.对数输入的 shape 不同的张量, 对应的最后几个维度必须符合矩阵运算规则

代码如下(示例):

# 点积运算
data1 = torch.tensor([[1, 2], [3, 4], [5, 6]])
>>> data1--> tensor([[1, 2],
                     [3, 4],
                     [5, 6]])
                     
data2 = torch.tensor([[5, 6], [7, 8]])
>>> data2--> tensor([[5, 6],
                     [7, 8]])

# 方式一:
data3 = data1 @ data2
print("data3-->", data3)
>>> data3--> tensor([[19, 22],
                     [43, 50],
                     [67, 78]])

# 方式二:
data4 = torch.matmul(data1, data2)
print("data4-->", data4)
>>> data4--> tensor([[19, 22],
                     [43, 50],
                     [67, 78]])

九、张量的运算函数

9.1 均值

代码如下(示例):

import torch

data = torch.randint(0, 10, [2, 3], dtype=torch.float64)
print(data)
>>> tensor([[4., 0., 7.],
            [6., 3., 5.]], dtype=torch.float64)

# 1. 计算均值
# 注意: tensor 必须为 Float 或者 Double 类型
print(data.mean())
>>> tensor(4.1667, dtype=torch.float64)

print(data.mean(dim=0))  # 按列计算均值
>>> tensor([5.0000, 1.5000, 6.0000], dtype=torch.float64)

print(data.mean(dim=1))  # 按行计算均值
>>> tensor([3.6667, 4.6667], dtype=torch.float64)

9.2 求和

代码如下(示例):

# 2. 计算总和
print(data.sum())
>>> tensor(25., dtype=torch.float64)

print(data.sum(dim=0))   # 对列求和
>>> tensor([10.,  3., 12.], dtype=torch.float64)

print(data.sum(dim=1))   # 对行求和
>>> tensor([11., 14.], dtype=torch.float64)

9.3 平方 pow()

代码如下(示例):

print(torch.pow(data,2))
>>> tensor([[16.,  0., 49.],
            [36.,  9., 25.]], dtype=torch.float64)

9.4 平方根 sqrt()

代码如下(示例):

print(data.sqrt())
>>> tensor([[2.0000, 0.0000, 2.6458],
            [2.4495, 1.7321, 2.2361]], dtype=torch.float64)

9.5 指数计算 exp()

代码如下(示例):

print(data.exp())
>>> tensor([[5.4598e+01, 1.0000e+00, 1.0966e+03],
            [4.0343e+02, 2.0086e+01, 1.4841e+02]], dtype=torch.float64)

9.6 对数计算

代码如下(示例):

print(data.log())  # 以 e 为底
>>> tensor([[1.3863,   -inf, 1.9459],
            [1.7918, 1.0986, 1.6094]], dtype=torch.float64)

print(data.log2())
>>> tensor([[2.0000,   -inf, 2.8074],
            [2.5850, 1.5850, 2.3219]], dtype=torch.float64)

print(data.log10())
>>> tensor([[0.6021,   -inf, 0.8451],
            [0.7782, 0.4771, 0.6990]], dtype=torch.float64)

十、张量的索引操作

# 准备数据
import torch
# 随机生成数据
data = torch.randint(0, 10, [4, 5])
print(data)
>>> tensor([[0, 7, 6, 5, 9],
            [6, 8, 3, 1, 0],
            [6, 3, 8, 7, 3],
            [4, 9, 5, 3, 1]])

10.1 简单行列索引的使用

代码如下(示例):

print(data[0])  # 取第一行的数据
>>> tensor([0, 7, 6, 5, 9])

print(data[:, 0])  # 所有的行都要, 取 0 列的数据
>>> tensor([0, 6, 6, 4])

10.2 列表索引的使用

代码如下(示例):

# 返回 (0, 2)、(1, 3) 两个位置的元素
print(data[[0, 1], [2, 3]])
>>> tensor([6, 1])

# 返回 0、1 行的 1、2 列共4个元素
print(data[[[0], [1]], [1, 2]])
>>> tensor([[7, 6],
            [8, 3]])

10.3 范围索引的使用

代码如下(示例):

# 前3行的前2列数据
print(data[:3, :2])
>>> tensor([[0, 7],
            [6, 8],
            [6, 3]])

# 第2行到最后的前2列数据
print(data[2:, :2])
>>> tensor([[6, 3],
            [4, 9]])

# 第0行、第2行的第0、1两列数据
print(data[0:3:2, :2])
>>>tensor([[0, 7],
            [6, 3]])

10.4 布尔索引的使用

代码如下(示例):

# 第三列大于5的行数据
print(data[data[:, 2] > 5])
>>> tensor([[0, 7, 6, 5, 9],
            [6, 3, 8, 7, 3]])

# 第二行大于5的列数据
# 所有的行都要,列要选第二行大于5的列
print(data[:, data[1] > 5]) 
>>> tensor([[0, 7],
            [6, 8],
            [6, 3],
            [4, 9]])

10.5 多维索引的使用

代码如下(示例):

data = torch.randint(0, 10, [3, 4, 5])
print(data)
>>> tensor([[[2, 4, 1, 2, 3],
             [5, 5, 1, 5, 0],
             [1, 4, 5, 3, 8],
             [7, 1, 1, 9, 9]],

            [[9, 7, 5, 3, 1],
             [8, 8, 6, 0, 1],
             [6, 9, 0, 2, 1],
             [9, 7, 0, 4, 0]],

            [[0, 7, 3, 5, 6],
             [2, 4, 6, 4, 3],
             [2, 0, 3, 7, 9],
             [9, 6, 4, 4, 4]]])

# 获取0轴上的第一个数据
# 要第一个通道的所有行和列
print(data[0, :, :])
>>> tensor([[2, 4, 1, 2, 3],
            [5, 5, 1, 5, 0],
            [1, 4, 5, 3, 8],
            [7, 1, 1, 9, 9]])

# 获取1轴上的第一个数据
# 要所有通道上的 第一行的所有列的数据
print(data[:, 0, :])
>>> tensor([[2, 4, 1, 2, 3],
            [9, 7, 5, 3, 1],
            [0, 7, 3, 5, 6]])

# 获取2轴上的第一个数据
# 要所有通道上的 第一列的所有行的数据
print(data[:, :, 0])
>>> tensor([[2, 5, 1, 7],
            [9, 8, 6, 9],
            [0, 2, 2, 9]])

十一、张量的形状操作

方法单行描述
torch.reshape(input, shape)重塑 input 到 shape (如果兼容),也可以使用 torch.Tensor.reshape()
tensor.view(shape)返回不同 shape 中的原始张量视图,但与原始张量共享相同的数据
tensor.contiguous()将张量转换到整块内存上
torch.stack(tensors, dim=0)沿着新的维度(dim)连接 tensors 的序列,所有 tensors 必须具有相同的大小
torch.squeeze(input)挤压 input 以移除值为 1 的所有尺寸
torch.unsqueeze(input, dim)返回在 dim 处添加了维度值 1 的 input
torch.transpose(input,dim1,dim2)实现交换张量形状的指定维度
torch.permute(input, dims)返回原始 input 的视图,其尺寸被置换(重新排列)为 dims

11.1 reshape

  • reshape 函数可以在保证张量数据不变的前提下改变数据的维度,将其转换成指定的形状

代码演示:

# 构建数据
import torch
x = torch.arange(1., 15.)
print(x)
>>> tensor([ 1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10., 11., 12., 13., 14.])

print(x.shape)
>>> torch.Size([14])

# 演示reshape
# 增加一个维度
x_reshaped = x.reshape(1, 14)
print(x_reshaped)
>>> tensor([[ 1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10., 11., 12., 13., 14.]])

print(x_reshaped.shape)
>>> torch.Size([1, 14])

# torch.reshape() 改变张量的形状
x_reshaped = x.reshape(2, 7)
print(x_reshaped)
>>> tensor([[ 1.,  2.,  3.,  4.,  5.,  6.,  7.],
            [ 8.,  9., 10., 11., 12., 13., 14.]])

print(x_reshaped.shape)
>>> torch.Size([2, 7])

11.2 view / contiguous

  • view 函数也可以用于修改张量的形状,只能用于存储在整块内存中的张量
  • 在 PyTorch 中,有些张量是由不同的数据块组成的,它们并没有存储在整块的内存中,view 函数无法对这样的张量进行变形处理。例如: 一个张量经过了 transpose 或者 permute 函数的处理之后,就无法使用 view 函数进行形状操作。
  • 此时需要先使用 contiguous 函数转换为整块内存的张量,再使用 view 函数

代码演示:

# 2 view / contiguous
# 注意:1) 一个张量经过了 transpose 或者 permute 函数的处理之后,就无法使用 view 函数进行形状操作
#         若要使用view函数, 需要使用contiguous() 变成连续以后再使用view函数
#      2) 判断张量是否使用整块内存

# 构造数据
data = torch.tensor([[10, 20, 30],
                     [40, 50, 60]])
print('data--->', data, data.shape)
>>> data---> tensor([[10, 20, 30],
                     [40, 50, 60]]) torch.Size([2, 3])

# 2.1 判断是否使用整块内存
print(f'判断data内存使用情况:{data.is_contiguous()}')
>>> 判断data内存使用情况:True

# 2.2 使用view
data1 = data.view(3, 2)
print(f'使用view后的数据{data1}')
>>> 使用view后的数据tensor([[10, 20],
        					[30, 40],
       						[50, 60]])

# 2.3 判断view后的数据是否使用的整块内存
print(f'使用view后的整块内存情况:{data1.is_contiguous()}')
>>> 使用view后的整块内存情况:True

# 2.4 使用 transpose 函数改变形状
data2 = torch.transpose(data, 0, 1)
print(f'使用transpose后的数据{data2}')
>>> 使用transpose后的数据tensor([[10, 40],
        					     [20, 50],
        						 [30, 60]])
print(f'使用transpose后的整块内存情况:{data2.is_contiguous()}')
>>> 使用transpose后的整块内存情况:False

# 2.5 先使用contiguous函数转换为整块内存的张量,再使用 view 函数
data3 = data2.contiguous().view(2, 3)
print(f'先使用contiguous变成整块内存,再使用view:{data3}')
>>> 先使用contiguous变成整块内存,再使用view:tensor([[10, 40, 20],
        											[50, 30, 60]])

11.3 stack

  • 如果想将新张量堆叠五次,使用 torch.stack() 来实现
  • torch.stack(tensors, dim=0, *, out=None)
    • tensors (sequence of tensors): 要堆叠的张量序列。这些张量必须有相同的形状。
    • dim (int): 新的维度索引。这个参数指定了新堆叠的维度应该放在哪个位置。默认值是0,意味着新的维度会被添加到最前面。
    • out (Tensor, optional): 输出张量。这是一个可选参数,通常不需要指定。

代码演示:

# 3.1 对同一个数据进行拼接
# 构造数据
data = torch.arange(1, 7)
print(data)
>>> tensor([1, 2, 3, 4, 5, 6])
>
# 新张量堆叠五次, 前面放要堆叠的tensor 可以是多个,使用列表传参
# dim=0 按照行堆叠  dim=1 按照列堆叠
data4 = torch.stack([data, data, data, data, data], dim=1)
print(f'同一个数据经过stack堆叠的数据:{data4}')
>>> 同一个数据经过stack堆叠的数据:tensor([[1, 1, 1, 1, 1],
        								  [2, 2, 2, 2, 2],
        								  [3, 3, 3, 3, 3],
        								  [4, 4, 4, 4, 4],
        								  [5, 5, 5, 5, 5],
        								  [6, 6, 6, 6, 6]])

# 3.2 对不同数据进行堆叠
# 创建三个形状为 (2, 3) 的张量
tensor1 = torch.tensor([[1, 2, 3], [4, 5, 6]])
tensor2 = torch.tensor([[7, 8, 9], [10, 11, 12]])
tensor3 = torch.tensor([[13, 14, 15], [16, 17, 18]])

# 使用 torch.stack() 沿着第0维堆叠
stacked_tensor = torch.stack([tensor1, tensor2, tensor3], dim=0)

print(f'不同数据经过stack堆叠:{stacked_tensor}')
 不同数据经过stack堆叠:tensor([[[ 1,  2,  3],
             					[ 4,  5,  6]],
             
            				   [[ 7,  8,  9],
             					[10, 11, 12]],

            				   [[13, 14, 15],
            				    [16, 17, 18]]])

11. 4 squeeze / unsqueeze

  • squeeze 函数删除形状为 1 的维度(降维),unsqueeze 函数添加形状为1的维度(升维)。

代码演示:

mydata1 = torch.tensor([1, 2, 3, 4, 5])             
print('mydata1--->', mydata1.shape, mydata1) # 一个普通的数组 1维数据
>>> mydata1---> torch.Size([5]) tensor([1, 2, 3, 4, 5])

mydata2 = mydata1.unsqueeze(dim=0)
print('在0维度上 拓展维度:', mydata2, mydata2.shape)  #1*5
>>>0维度上 拓展维度: tensor([[1, 2, 3, 4, 5]]) torch.Size([1, 5])

mydata3 = mydata1.unsqueeze(dim=1)
print('在1维度上 拓展维度:', mydata3, mydata3.shape)  #5*1
>>>1维度上 拓展维度: tensor([[1],
                              [2],
                              [3],
                              [4],
                              [5]]) torch.Size([5, 1])


mydata4 = mydata1.unsqueeze(dim=-1)
print('在-1维度上 拓展维度:', mydata4, mydata4.shape) #5*1
>>>-1维度上 拓展维度: tensor([[1],
                               [2],
                               [3],
                               [4],
                               [5]]) torch.Size([5, 1])

mydata5 = mydata4.squeeze()
print('压缩维度:', mydata5, mydata5.shape)  #1*5
>>> 压缩维度: tensor([1, 2, 3, 4, 5]) torch.Size([5])

11. 5 transpose / permute

  • transpose 函数可以实现交换张量形状的指定维度, 例如: 一个张量的形状为 (2, 3, 4) 可以通过 transpose 函数把 3 和 4 进行交换, 将张量的形状变为 (2, 4, 3) 。
  • permute 函数可以一次交换更多的维度。

代码演示:

data = torch.tensor(np.random.randint(0, 10, [3, 4, 5]))
print('data shape:', data.size())
>>> data shape: torch.Size([3, 4, 5])

# 1 交换1和2维度
mydata2 = torch.transpose(data, 1, 2)
print('mydata2.shape--->', mydata2.shape)
>>> mydata2.shape---> torch.Size([3, 5, 4])

# 2 将data 的形状修改为 (4, 5, 3), 需要变换多次
mydata3 =  torch.transpose(data, 0, 1)
mydata4 = torch.transpose(mydata3, 1, 2)
print('mydata4.shape--->', mydata4.shape)
>>> mydata4.shape---> torch.Size([4, 5, 3])

# 3 使用 permute 函数将形状修改为 (4, 5, 3)
# 3-1 方法1
mydata5 = torch.permute(data, [1, 2, 0])
print('mydata5.shape--->', mydata5.shape)
>>> mydata5.shape---> torch.Size([4, 5, 3])

# 3-2 方法2
mydata6 = data.permute([1, 2, 0])
print('mydata6.shape--->', mydata6.shape)
>>> mydata6.shape---> torch.Size([4, 5, 3])

十二、张量的拼接操作

  • torch.cat()
import torch
data1 = torch.randint(0, 10, [1, 2, 3])
data2 = torch.randint(0, 10, [1, 2, 3])
print(data1)
>>> tensor([[[7, 8, 7],
         [6, 3, 6]]])


print(data2)
>>> tensor([[[3, 6, 5],
         [7, 5, 0]]])


# 1. 按0维度拼接
new_data = torch.cat([data1, data2], dim=0)
print(new_data)
>>> tensor([[[7, 8, 7],
             [6, 3, 6]],

            [[3, 6, 5],
             [7, 5, 0]]])

print(new_data.shape)
>>> torch.Size([2, 2, 3])

# 2. 按1维度拼接
new_data = torch.cat([data1, data2], dim=1)
print(new_data)
>>> tensor([[[7, 8, 7],
             [6, 3, 6],
             [3, 6, 5],
             [7, 5, 0]]])

print(new_data.shape)
>>> torch.Size([1, 4, 3])

# 3. 按2维度拼接
new_data = torch.cat([data1, data2], dim=2)
print(new_data)
>>> tensor([[[7, 8, 7, 3, 6, 5],
             [6, 3, 6, 7, 5, 0]]])

print(new_data.shape)
>>> torch.Size([1, 2, 6])

十三、自动微分

13.1 输入为标量的梯度计算

代码演示:

import torch
# 1. 当X为标量时梯度的计算
def test01():
    x = torch.tensor(5)
    # 目标值
    y = torch.tensor(0.)
    # 设置要更新的权重和偏置的初始值
    w = torch.tensor(1., requires_grad=True, dtype=torch.float32)
    b = torch.tensor(3., requires_grad=True, dtype=torch.float32)
    # 设置网络的输出值
    z = x * w + b  # 矩阵乘法
    # 设置损失函数,并进行损失的计算
    loss = torch.nn.MSELoss()
    loss = loss(z, y)
    # 自动微分
    loss.backward()
    # 打印 w,b 变量的梯度
    # backward 函数计算的梯度值会存储在张量的 grad 变量中
    print("W的梯度:", w.grad)
    >>> W的梯度: tensor(80.)
    print("b的梯度", b.grad)   
	>>> b的梯度 tensor(16.)

13.2 输入为多维张量时的梯度计算

代码演示:

import torch
def test02():
    # 输入张量 2*5
    x = torch.ones(2,5)
    # 目标值是 2*3
    y = torch.zeros(2,3)
    # 设置要更新的权重和偏置的初始值
    w = torch.randn(5, 3,requires_grad=True)
    b = torch.randn(3, requires_grad=True)
    # 设置网络的输出值
    z = torch.matmul(x, w) + b  # 矩阵乘法
    # 设置损失函数,并进行损失的计算
    loss = torch.nn.MSELoss()
    loss = loss(z, y)
    # 自动微分
    loss.backward()
    # 打印 w,b 变量的梯度
    # backward 函数计算的梯度值会存储在张量的 grad 变量中
    print("W的梯度:", w.grad)
    >>> W的梯度: tensor(
					[[ 0.0757, 0.6087, -0.6538], 
 	     			 [ 0.0757, 0.6087, -0.6538], 
         			 [ 0.0757, 0.6087, -0.6538], 
 					 [ 0.0757, 0.6087, -0.6538], 
 					 [ 0.0757, 0.6087, -0.6538]]) 
    print("b的梯度", b.grad)
    >>>  b的梯度 tensor([ 0.0757, 0.6087, -0.6538])

总结

  • 深度学习存储和操作数据的主要接口是张量(n维数组)。它提供了各种功能,包括基本数学运算、广播、索引、切片、内存节省和转换其他Python对象。
  • 所以张量是学习深度学习的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值