机器学习|PyTorch之张量的相关操作大全

2023/09/14 机器学习 共 11197 字,约 32 分钟

Torch

1. 张量的创建

1.1 直接创建

1.1.1 torch.tensor

torch.tensor(data, dtype=None, device=None, requires_grad=False, pin_memory=False)
  • 功能:从data创建tensor
  • data: 数据,可以是list,numpy
  • dtype: 数据类型,默认与data的一致
  • device: 所在设备,cuda/cpu
  • requires_grad: 是否需要梯度
  • pin_memory: 是否存于锁页内存

样例:

torch.tensor([[0.2, 0.2], [1.2, 2.3], [3.2, 1.3]])
'''
tensor([[0.2, 0.2],
		[1.2, 2.3],
		[3.2, 1.3]])
'''

1.1.2 torch.from_numpy(ndarray)

torch.from_numpy(ndarray)
  • 功能:从numpy创建tensor
  • 注意事项:从torch.from_numpy创建的tensor于原ndarray共享内存,当修改其中一个数据,另一个也将会被改动。

样例:

array = numpy.array([1, 2, 3, 4])
t = torch.from_numpy(array)

1.2 依据数值创建

1.2.1 torch.zeros

torch.zeros(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
  • 功能:依size创建全0张量
  • size: 张量的形状,如(3, 3)、(3, 224, 224)
  • out: 输出的张量
  • layout: 内存中布局形式,有strided, sparse_coo等
  • device: 所在设备,gpu/cpu
  • requires_grad: 是否需要梯度

样例:

torch.zeros(2, 3)  # 2行3列
'''
tensor([[0, 0, 0],
		[0, 0, 0]])
'''

1.2.2 torch.zeros_like

torch.zeros_like(input, dtype=None, layout=None, device=None, requires_grad=False)
  • 功能:依input形状创建全0张量
  • input: 创建与input同形状的全0张量
  • dtype: 数据类型
  • layout: 内存中布局形式
  • device: 所在设备,gpu/cpu
  • requires_grad: 是否需要梯度

样例:

input = torch.empty(3, 2)
torch.zeros_like(input)
'''
tensor([[0, 0],
		[0, 0],
		[0, 0]])
'''

1.2.3 torch.ones

torch.ones(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
  • 功能:依size创建全1张量
  • size: 张量的形状,如(3, 3)、(3, 224, 224)
  • out: 输出的张量
  • layout: 内存中布局形式,有strided, sparse_coo等
  • device: 所在设备,gpu/cpu
  • requires_grad: 是否需要梯度

样例:

torch.ones(2, 3)  # 2行3列
'''
tensor([[1, 1, 1],
		[1, 1, 1]])
'''

1.2.4 torch.ones_like

torch.ones_like(input, dtype=None, layout=None, device=None, requires_grad=False)
  • 功能:依input形状创建全1张量
  • input: 创建与input同形状的全0张量
  • dtype: 数据类型
  • layout: 内存中局形式
  • device: 所在设备,gpu/cpu
  • requires_grad: 是否需要梯度

样例:

input = torch.empty(2, 3)
torch.ones_like(input)
'''
tensor([[1, 1, 1],
		[1, 1, 1]])
'''

1.2.5 torch.full

torch.full(size, fill_value, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
  • 功能:依size创建值全为fill_value的张量
  • size: 张量的形状,如(3, 3)、(3, 224, 224)
  • fill_value: 张量的值
  • out: 输出的张量
  • dtype: 数据类型
  • layout: 内存中布局形式,有strided, sparse_coo等
  • device: 所在设备,gpu/cpu
  • requires_grad: 是否需要梯度

样例:

torch.full((3, 2), 1.23)

'''
tensor([[1.23, 1.23],
		[1.23, 1.23],
		[1.23, 1.23]])
'''

1.2.6 torch.full_like

torch.full_like(input, dtype=None, layout=torch.strided, device=None, requires_grad=False)
  • 功能:依input形状创建指定数据的张量
  • dtype: 数据类型
  • layout: 内存中布局形式,有strided, sparse_coo等
  • device: 所在设备,gpu/cpu
  • requires_grad: 是否需要梯度

1.2.7 torch.arange

torch.arange(start=0, end. step=1, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
  • 功能:创建等差的1维张量
  • start: 数列起始值
  • end: 数列“结束值”
  • step: 数列公差,默认为1
  • 注意事项:数值区间为 [𝑠𝑡𝑎𝑟𝑡,𝑒𝑛𝑑) !!!!!

样例;

torch.arange(0, 3, 1)
'''
tensor([0, 1, 2])
'''

1.2.8 torch.linspace

torch.linspace(start, end, steps=100, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
  • 功能:创建均分的1维张量
  • start: 数列起始值
  • end: 数列“结束值”
  • step: 数列长度

样例:

torch.linspace(start=-5, end=5, steps=3)
'''
tensor([-5.,   0.,   5.])
'''

1.2.9 torch.logspace

torch.logspace(start, end, steps=100, base=10.0, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
  • 功能:创建对数均分的1维张量
  • start: 数列起始值
  • end: 数列“结束值”
  • step: 数列长度
  • base: 对数函数的底,默认为10
  • 注意事项:长度为steps,底为base

样例:

torch.logspace(start=0.1, end=1, steps=4)
'''
tensor([ 1.2589,  2.5119,  5.0119, 10.0000])
'''

1.2.10 torch.eye

torch.eye(n, m=None, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
  • 功能:创建单位对角矩阵(2维张量)
  • n: 矩阵行数
  • m: 矩阵列数
  • 注意事项:默认为方阵
torch.eye(3)
'''
tensor([[1., 0., 0.],
        [0., 1., 0.],
        [0., 0., 1.]])
'''

1.3 依概率分布创建张量

1.3.1 torch.normal

torch.normal(mean, std, out=None)
  • 功能:生成正态分布(高斯分布)
  • mean: 均值
  • std: 标准差
  • 四种模式:
    • mean为标量,std为标量
    • mean为标量,std为张量
    • mean为张量,std为标量
    • mean为张量,std为张量

样例:

# 1. mean为标量,std为标量
mean1 = torch.tensor([1.0])
std1 = torch.tensor([2.0])
normal1 = torch.normal(mean=mean1, std=std1)
print(f'mean为标量,std为标量:  {normal1}')
# 2. mean为标量,std为张量
mean2 = torch.tensor([1.0])
std2 = torch.arange(1, 0, -0.1)
normal2 = torch.normal(mean=mean2, std=std2)
print(f'mean为标量,std为张量:  {normal2}')
# 3. mean为张量,std为标量
mean3 = torch.arange(1, 0, -0.1)
std3 = torch.tensor([1.0])
normal3 = torch.normal(mean=mean3, std=std3)
print(f'mean为张量,std为标量:  {normal3}')
# 4. mean为张量,std为张量
mean4 = torch.arange(1., 11.)
std4 = torch.arange(1, 0, -0.1)
normal4 = torch.normal(mean=mean4, std=std4)
print(f'mean为张量,std为张量:  {normal4}')
'''
mean为标量,std为标量:  
	tensor([0.8404])
mean为标量,std为张量:  
	tensor([ 1.9674,  0.3015,  1.4441,  1.1592, -0.3160,  0.8436,  1.1548,  1.1149, 0.8569,  0.8924])
mean为张量,std为标量:  
	tensor([-1.1098,  0.0993,  0.7905,  1.5703, -0.2797, -0.5459, -0.7058, -1.1746, 0.1725,  1.2089])
mean为张量,std为张量:  
	tensor([-0.1302,  1.2099,  1.6807,  2.5063,  5.4447,  6.4120,  6.9074,  8.2245, 8.9090, 10.0049])
'''

1.3.2 torch.normal

torch.normal(mean, std, size, out=None)
  • 功能:生成一定大小的生成正态分布(高斯分布)
  • size: 张量的形状,如(3, 3)、(3, 224, 224)

样例:

torch.normal(3, 2, size=(1, 3))
'''
tensor([[3.6354, 3.2656, 3.2746]])
'''

1.3.3 torch.randn

torch.randn(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
  • 功能:生成标准正态分布
  • size: 张量的形状,如(3, 3)、(3, 224, 224)

样例:

torch.randn(3, 2)
'''
tensor([[0.2405, 1.3955],
        [1.3470, 2.4382],
        [0.2028, 2.4505]])
'''

1.3.4 torch.rand

torch.rand(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
  • 功能:在区间 [0,1) 上,生成均匀分布
  • size: 张量的形状,如(3, 3)、(3, 224, 224)

样例:

torch.normal(3, 2, size=(1, 3))
'''
tensor([[3.6354, 3.2656, 3.2746]])
'''

1.3.5 torch.randint

torch.randint(low=0, high, size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
  • 功能:区间 [𝑙𝑜𝑤,ℎ𝑖𝑔ℎ) 生成整数均匀分布
  • size: 张量的形状,如(3, 3)、(3, 224, 224)

样例:

torch.randint(1, 10, (2, 2))
'''
tensor([[8, 6],
        [1, 3]])
'''

1.3.6 torch.randperm

torch.randperm(n, out=None, dtype=torch.int64, layout=torch.strided, device=None, requires_grad=False)
  • 功能:生成从0到n-1的随机排列
  • n: 张量的长度

样例:

torch.randperm(6)
'''
tensor([2, 0, 4, 5, 1, 3])
'''

1.3.7 torch.bernoulli

torch.bernoulli(input, *, generator=None, out=None)
  • 功能:以input为概率,生成伯努利分布(0-1分布,两点分布)
  • input: 概率值

样例:

a = torch.empty(2, 2).uniform_(0, 1)  # 生成2×2的概率矩阵
torch.bernoulli(a)
'''
tensor([[0., 1.],
        [1., 0.]])
'''

2. 张量的操作

2.1 张量拼接与切分

2.1.1 torch.cat

torch.cat(tensors, dim=0, out=None)
  • 功能:将张量按维度dim进行拼接
  • tensors: 张量序列seq
  • dim: 要拼接的维度 dim=0按行拼接 dim=1按列拼接 dim=n按维度拼接
x = torch.randn(2, 3)
print(x.shape)
a = torch.cat((x, x, x), 1)
a.shape
'''
torch.Size([2, 3])
torch.Size([2, 9])
'''

2.1.2 torch.stack

torch.stack(tensors, dim=0, out=None)
  • 功能:对序列数据内部的张量进行扩维拼接,指定维度由程序员选择、大小是生成后数据的维度区间。
  • tensors: 张量序列seq
  • dim: 指定扩张的维度 dim=0按行扩张 dim=1按列扩张 dim=n按维度扩张 拼接后的tensor形状,会根据不同的dim发生变化。 Alt Text 参考:pytorch拼接函数:torch.stack()和torch.cat()详解
T1:
 tensor([[1, 2, 3],
         [4, 5, 6],
         [7, 8, 9]])
T2:
 tensor([[10, 20, 30],
         [40, 50, 60],
         [70, 80, 90]])
----------------------------------------------
R0 = torch.stack((T1, T2), dim=0)
'''
 tensor([[[1,  2,  3],
          [4,  5,  6],
          [7,  8,  9]],
         [[10, 20, 30],
          [40, 50, 60],
          [70, 80, 90]]])
torch.Size([2, 3, 3])
----------------------------------------------
'''
R1 = torch.stack((T1, T2), dim=1)
'''
 tensor([[[1,  2,  3],[10, 20, 30]],
         [[4,  5,  6],[40, 50, 60]],
         [[7,  8,  9],[70, 80, 90]]])
 torch.Size([3, 2, 3])
'''
----------------------------------------------
R2 = torch.stack((T1, T2), dim=2)
'''
 tensor([[[1, 10],[2, 20],[3, 30]],
         [[4, 40],[5, 50],[6, 60]],
         [[7, 70],[8, 80],[9, 90]]])
 torch.Size([3, 3, 2])
'''

R3 = torch.stack((T1, T2), dim=3)
'''
IndexError: Dimension out of range (expected to be in range of [-3, 2], but got 3)
'''

2.1.3 torch.chunk

torch.chunk(input, chunks, dim=0)
  • 功能:将张量按维度dim进行平均切分
  • 返回值: 张量列表
  • 注意事项:若不能整除,最后一份张量小于其他张量
  • input: 要切分的张量
  • chunks: 要切分的份数
  • dim: 要切分的维度 0按照列切分 1按照行切分
a = torch.arange(10).reshape(5,2)
torch.chunk(a, 2)
'''
tensor([[0, 1],
        [2, 3],
        [4, 5],
        [6, 7],
        [8, 9]])
(tensor([[0, 1],
         [2, 3],
         [4, 5]]),
 tensor([[6, 7],
         [8, 9]]))
'''
---------------------------------------
torch.chunk(a, 2, 1)
'''
(tensor([[0],
         [2],
         [4],
         [6],
         [8]]),
 tensor([[1],
         [3],
         [5],
         [7],
         [9]]))
'''

2.1.4 torch.split

torch.split(tensor, split_size_or_sections, dim=0)
  • 功能:将张量按维度dim进行切分
  • 返回值: 张量列表
  • tensor: 要切分的张量
  • split_size_or_sections: 为int时,表示每一份的长度;为list时,按list元素切分
  • dim: 要切分的维度 0按照列切分 1按照行切分
a = torch.arange(10).reshape(5,2)
torch.split(a, 2)
''' 
tensor([[0, 1],
        [2, 3],
        [4, 5],
        [6, 7],
        [8, 9]])
(tensor([[0, 1],
         [2, 3]]),
 tensor([[4, 5],
         [6, 7]]),
 tensor([[8, 9]]))
'''
torch.split(a, [3, 1, 1])
'''
(tensor([[0, 1],
         [2, 3],
         [4, 5]]),
 tensor([[6, 7]]),
 tensor([[8, 9]]))
'''

2.2 张量索引

2.2.1 torch.index_select

torch.index_select(input, dim, index, out=None)
  • 功能:在维度dim上,按index索引数据
  • 返回值: 依index索引数据拼接的张量
  • input: 要索引的张量
  • dim: 要索引的维度 0按照列切分 1按照行切分
  • index: 要索引数据的序号
x = torch.randn(3, 4)
indices = torch.tensor([0, 2])
torch.index_select(x, 0, indices)
'''
x: tensor([[-0.1468,  0.7861,  0.9468, -1.1143],
           [ 1.6908, -0.8948, -0.3556,  1.2324],
           [ 0.1382, -1.6822,  0.3177,  0.1328]])
indices: tensor([0, 2])
tensor([[-0.1468,  0.7861,  0.9468, -1.1143],
        [ 0.1382, -1.6822,  0.3177,  0.1328]])
'''

2.2.2 torch.masked_select

torch.masked_select(input, mask, out=None)
  • 功能:按mask中的True进行索引
  • 返回值: 一维张量
  • input: 要索引的张量
  • mask: 与input同形状的布尔类型张量
x = torch.randn(3, 4)
print('x:',x)
mask = x.ge(0.5)
print('mask:',mask)
torch.masked_select(x, mask)
'''
x: tensor([[ 0.1373,  0.2405,  1.3955,  1.3470],
           [ 2.4382,  0.2028,  2.4505,  2.0256],
           [ 1.7792, -0.9179, -0.4578, -0.7245]])
mask: tensor([[False, False,  True,  True],
              [ True, False,  True,  True],
              [ True, False, False, False]])
tensor([1.3955, 1.3470, 2.4382, 2.4505, 2.0256, 1.7792])
'''

2.3 张量变换

2.3.1 torch.reshape

torch.reshape(input, shape)
  • 功能变换张量形状
  • 注意事项: 当张量在内存中是连续时,新张量与input共享数据内存
  • input: 要变换的张量
  • shape: 新张量的形状
a = torch.arange(4.)
torch.reshape(a, (2, 2))
'''
tensor([0., 1., 2., 3.])
tensor([[0., 1.],
        [2., 3.]])
'''

2.3.2 torch.transpose

torch.transpose(input, dim0, dim1)
  • 功能交换张量的两个维度
  • input: 要交换的张量
  • dim0: 要交换的维度
  • dim1: 要交换的维度
x = torch.randn(2, 3)
torch.transpose(x, 0, 1)
'''
x:
tensor([[ 1.2799, -0.9941,  1.8150],
        [-0.6028,  1.6148,  1.9302]])
torch.Size([2, 3])
tensor([[ 1.2799, -0.6028],
        [-0.9941,  1.6148],
        [ 1.8150,  1.9302]])
torch.Size([3, 2])
'''
x = torch.randn(2, 3, 4)
print(x)
print(x.shape)
a = torch.transpose(x, 0, 2)
print(a)
print(a.shape)
'''
tensor([[[ 0.8885, -1.4867, -0.8898,  0.9005],
         [ 0.2615, -0.1494,  1.1523, -1.1309],
         [ 1.4025, -0.4167,  0.1655, -0.7157]],

        [[ 1.2425, -1.3332,  0.2961, -0.0937],
         [-0.7556, -0.1198,  0.9545,  0.1492],
         [ 1.6222,  0.1947, -1.5953,  0.5859]]])
torch.Size([2, 3, 4])
tensor([[[ 0.8885,  1.2425],
         [ 0.2615, -0.7556],
         [ 1.4025,  1.6222]],

        [[-1.4867, -1.3332],
         [-0.1494, -0.1198],
         [-0.4167,  0.1947]],

        [[-0.8898,  0.2961],
         [ 1.1523,  0.9545],
         [ 0.1655, -1.5953]],

        [[ 0.9005, -0.0937],
         [-1.1309,  0.1492],
         [-0.7157,  0.5859]]])
torch.Size([4, 3, 2])
'''

2.3.3 torch.t

torch.t(input)
  • 功能:2维张量转置,对矩阵而言,等价于torch.transpose(input, 0, 1)
x = torch.randn((2, 2))
print(x)
torch.t(x)
'''
tensor([[ 0.5740, -0.0798],
        [ 0.9674, -0.7761]])
tensor([[ 0.5740,  0.9674],
        [-0.0798, -0.7761]])
'''

2.3.4 torch.squeeze

torch.squeeze(input, dim=None, out=None)
  • 功能:压缩长度为1的维度(轴) 维度压缩
  • dim: 若为None,移除所有长度为1的轴;若指定维度,当且仅当该轴长度为1时,可以被移除
x = torch.zeros(2, 1, 2, 1, 2)
print(x)
print(x.shape)
y = torch.squeeze(x)
print(y)
print(y.shape)
'''
tensor([[[[[0., 0.]],

          [[0., 0.]]]],



        [[[[0., 0.]],

          [[0., 0.]]]]])
torch.Size([2, 1, 2, 1, 2])
tensor([[[0., 0.],
         [0., 0.]],

        [[0., 0.],
         [0., 0.]]])
torch.Size([2, 2, 2])
'''

2.3.5 torch.unsqueeze

torch.unsqueeze(input, dim, out=None)
  • 功能:依据dim扩展维度
  • dim: 扩展的维度 0行扩展 1列扩展 -1最后一个维度扩展
x = torch.tensor([1, 2, 3])
print(x.shape)
t0 = torch.unsqueeze(x, 0)
print(t0.shape)
t1 = torch.unsqueeze(x, 1)
print(t1.shape)
t2 = torch.unsqueeze(x, -1)
print(t2.shape)
t0, t1, t2
'''
x:
	torch.Size([3])
t0:
	tensor([[1, 2, 3]])
	torch.Size([1, 3])
t1: 
	tensor([[1],
	        [2],
	        [3]])
	torch.Size([3, 1])
t2:
	tensor([[1],
	        [2],
	        [3]]))
	torch.Size([3, 1])
'''

线性回归模型

  • 线性回归是分析一个变量与另外一(多)个变量之间关系的方法。
    • 因变量是$y$,自变量是$x$,关系线性:$y=w\times x + b$,任务是求解 $w$,$b$。
  • 我们的求解步骤是:
  • 确定模型:$Model \to y = w \times x + b$
  • 选择损失函数:这里用$MSE:\frac{1}{m}\sum_{i=1}^m(y_i-\hat y_i)^2$
  • 求解梯度并更新$w$,$b$: \(\begin{array}{lcl} w &=& w - lr \times w.grad \\ b &=& b - lr \times w.grad \end{array}\)
  • 下面我们开始写一个线性回归模型:
# 首先我们得有训练样本X,Y, 这里我们随机生成
x = torch.rand(20, 1) * 10
y = 2 * x + (5 + torch.randn(20, 1))

# 构建线性回归函数的参数
w = torch.randn((1), requires_grad=True)
b = torch.zeros((1), requires_grad=True)   # 这俩都需要求梯度

# 设置学习率lr为0.1
lr = 0.1

for iteration in range(100):
    # 前向传播
    wx = torch.mul(w, x)
    y_pred = torch.add(wx, b)
 
    # 计算loss  均方误差
    loss = (0.5 * (y-y_pred)**2).mean()
 
    # 反向传播
    loss.backward()
 
    # 更新参数
    b.data.sub_(lr * b.grad)    # 这种_的加法操作时从自身减,相当于-=
    w.data.sub_(lr * w.grad)

    # 梯度清零
    w.grad.data.zero_()
    b.grad.data.zero_()

print(w.data, b.data)

部分学习内容来自: 天池实验室

文档信息

Search

    Table of Contents