pytorch——张量操作与线性回归

1、张量的操作:拼接、切分、索引和变换

一、张量拼接与切分

1.1 torch.cat() (cat()不会拓展张量的维度)

功能:将张量按维度dim进行拼接

  • tensors:张量序列
  • din:要拼接的维度
torch.cat(tensors,
          dim=0,
          out=None)

代码实际操作如下:

import numpy as np
import torch

flag = True 
if flag:
    t = torch.ones((2, 3))

    t_0 = torch.cat([t, t], dim=0)  #在第一维度上进行拼接,拼接后的维度是(4,3)
    t_1 = torch.cat([t, t], dim=1)  #在第二维度上进行拼接,拼接后的维度是(2,6)
    t_2 = torch.cat([t, t, t], dim=1)  #在第二维度上进行拼接,拼接后的维度是(2,9)

    print("t_0:{} shape:{}\nt_1:{} shape:{}\nt_2:{} shape:{}".format(t_0, t_0.shape, t_1, t_1.shape, t_2, t_2.shape))

1.2 torch.stack() (stack() 会拓展张量的维度)

功能:在新创建的维度dim上进行拼接。
举个例子,如果要求将[2,3]矩阵的内容在dim=1上进行拼接,则需要将[2,3]矩阵的内容转换为[2,1,3]的形式之后再使用和torch.cat()一样的拼接方式进行拼接,看到的一些比较好的对于torch.stack()的拼接的解释的文章可以参考一下这一篇(点击)。

  • tensors:张量序列
  • dim:要拼接的维度
torch.stack(tensors,
            dim=0,
            out=None)

具体的代码实现如下:

import numpy as np
import torch

flag = True
# flag = False

if flag:
    t = torch.ones((2, 3))
    s = torch.zeros((2, 3))

    t_stack = torch.stack([t, s], dim=0)   #对两个矩阵的第0维进行拓展
    print("\nt_stack:{} shape:{}".format(t_stack, t_stack.shape))   #拓展后的矩阵为(2,2,3)
    tensor([[[1., 1., 1.],
             [1., 1., 1.]],
            [[0., 0., 0.],
             [0., 0., 0.]]]) 

    t_stack = torch.stack([t, s], dim=1)   #对两个矩阵的第1维进行拓展
    print("\nt_stack:{} shape:{}".format(t_stack, t_stack.shape))   #拓展后的矩阵为(2,2,3)
    tensor([[[1., 1., 1.],
             [0., 0., 0.]],
            [[1., 1., 1.],
             [0., 0., 0.]]])

    t_stack = torch.stack([t, s], dim=2)   #对两个矩阵的第2维进行拓展
    print("\nt_stack:{} shape:{}".format(t_stack, t_stack.shape))   #拓展后的矩阵为(2,3,2)
    tensor([[[1., 0.],
             [1., 0.],
             [1., 0.]],
            [[1., 0.],
             [1., 0.],
             [1., 0.]]]) 

1.3 torch.chunk()

功能:将张量按维度dim进行平均切分
返回值:张量列表
注意事项:若不能整除,最后一份张量小于其他张量

  • input:要切分的张量
  • chunks:要切分的份数
  • dim:要切分的维度
torch.chunk(input,
            chunks,
            dim=0)

具体的代码示例如下:

import numpy as np
import torch

flag = True
# flag = False

if flag:
    a = torch.ones((2, 5))  #创建一个矩阵
    list_of_tensors = torch.chunk(a, dim=1, chunks=2)  #从第一维度将矩阵划分为两部分,因为5不能被2整除,所以得到的两个矩阵中,一个矩阵为(2,3),一个矩阵为(2,2)

    for idx, t in enumerate(list_of_tensors):
        print("第{}个张量:{}, shape is {}".format(idx+1, t, t.shape))

1.4 torch.split()

功能:将张量按维度dim进行切分
返回值:张量列表

  • tensors:要切分的张量
  • split_size_or_sections:为int时,表示每一份的长度;为list时,按list元素切分
  • dim:要切分的维度
torch.split(tensor,
            split_size_or_sections,
            dim=0)

具体的代码示例如下:

import numpy as np
import torch
flag = True
# flag = False

if flag:
    t = torch.ones((2, 5))

    list_of_tensors = torch.split(t, 2, dim=1)  #2表示每一份的长度,最后得到划分后的三份矩阵,分别为(2,2),(2,2),(2,1)
    for idx, t in enumerate(list_of_tensors):
        print("第{}个张量:{}, shape is {}".format(idx+1, t, t.shape))
import numpy as np
import torch
flag = True
# flag = False

if flag:
    t = torch.ones((2, 5))
    
    list_of_tensors = torch.split(t, [2, 1, 2], dim=1)  #根据列表进行划分,划分后的三个矩阵的形状分别为(2,2),(2,1),(2,2)
    for idx, t in enumerate(list_of_tensors):
        print("第{}个张量:{}, shape is {}".format(idx + 1, t, t.shape))

二、张量索引

2.1 torch.index_select()

功能:在维度dim上,按index索引数据
返回值:依index索引数据拼接的张量

  • input:要索引的张量
  • dim:要索引的维度
  • index:要索引数据的序号
torch.index_select(input,
                   dim,
                   index,
                   out=None)

具体的代码示例如下:

import numpy as np
import torch
flag = True
# flag = False

if flag:
    t = torch.randint(0, 9, size=(3, 3))  #随机生成(3,3)的二维矩阵
    idx = torch.tensor([0, 2], dtype=torch.long)   #要索引的序列,注意dtype必须是torch.long不能是torch.float
    t_select = torch.index_select(t, dim=0, index=idx)  #以第0维为索引的维度,最后得到的矩阵为(2,3)
    print("t:\n{}\nt_select:\n{}".format(t, t_select))

2.2 torch.masked_select()

功能:按mask中的True进行索引
返回值:一维张量

  • input:要索引的张量
  • mask:与input同形状的布尔类型张量
torch.masked_select(input,
                    mask,
                    out=None)

具体的代码示例如下:

import numpy as np
import torch
flag = True
# flag = False

if flag:

    t = torch.randint(0, 9, size=(3, 3))
    mask = t.ge(5) #ge的意思是大于等于,greater than or equal,同样的有gt:greater than 和le、lt,ge的作用是找t中大于等于5的数赋值为True,小于5的数赋值为False
    t_select = torch.masked_select(t, mask)  #按mask中的True进行索引返回一个一维矩阵
    print("t:\n{}\nmask:\n{}\nt_select:\n{}".format(t, mask, t_select))

三、张量变换

3.1 torch.reshape()

功能:变换张量形状
注意事项:当张量在内存中是连续时,新张量与input共享数据内存

  • input:要变换的张量
  • shape:新张量的形状
torch.reshape(input,
              shape)

具体的代码示例如下:

import numpy as np
import torch
flag = True
# flag = False

if flag:
    t = torch.randperm(8)   #0-8之间随机排列的8个数
    t_reshape = torch.reshape(t, (-1, 2, 2))    #一维矩阵被重新reshape为(2,2,2)形式
    print("t:{}\nt_reshape:\n{}".format(t, t_reshape))

    t[0] = 1024   #将t[0]的值进行修改
    print("t:{}\nt_reshape:\n{}".format(t, t_reshape))  
    print("t.data 内存地址:{}".format(id(t.data)))  #t.data的内存地址和t_reshape的内存地址是一样的
    print("t_reshape.data 内存地址:{}".format(id(t_reshape.data )))

3.2 torch.transpose()

功能:交换张量的两个维度

  • input:要交换的张量
  • dim0:要交换的维度
  • dim1:要交换的维度
torch.transpose(input,
                dim0,
                dim1)

具体的代码示例如下:

import numpy as np
import torch
flag = True
# flag = False

if flag:
    t = torch.rand((2, 3, 4))
    t_transpose = torch.transpose(t, dim0=0, dim1=1)   #经过交换后张量的维度变为(3,2,4)
    print("t shape:{}\nt_transpose shape:{}".format(t.shape, t_transpose.shape))

3.3 torch.t()

功能:2维张量转置,对矩阵而言,等价于torch.transpose(input,0,1)

torch.t(input)

3.4 torch.squeeze()

功能:压缩长度为1的维度(轴)

  • dim:若为None,移除所有长度为1的轴;若指定维度,当且仅当该轴长度为1时,可以被移除
torch.squeeze(input,
              dim=None,
              out=None)

具体示例代码如下:

import numpy as np
import torch
flag = True
# flag = False

if flag:
    t = torch.rand((1, 2, 3, 1))
    t_sq = torch.squeeze(t)  #将所有轴长为1的都去掉,t_sq变为(2,3)
    t_0 = torch.squeeze(t, dim=0)   #第0维如果是1,则将第0维去掉,t_0变为(2,3,1)
    t_1 = torch.squeeze(t, dim=1)   #第1维是2,不是1,所以不能删除,t_1仍然为(1,2,3,1)
    print(t.shape)
    print(t_sq.shape)
    print(t_0.shape)
    print(t_1.shape)

3.5 torch.unsqueeze()

功能:依据dim扩展维度

  • dim:扩展的维度
torch.usqueeze(input,
               dim,
               out=None)

2、张量的数学运算

一、加减乘除

torch.add()

功能:逐元素计算 input + alpha x other (这里面add不仅仅有加法的功能还有乘法的功能,因为在深度学习中经常需要用到这样的情况)。类似的用法还有:
torch.addcdiv() : out = input + value x tensor1 / tensor2
torch.addcmul() : out = input + value x tensor1 x tensor2

  • input:第一个张量
  • alpha:乘项因子
  • other:第二个张量
torch.add(input,
          alpha=1,
          other,
          out=None)

具体的代码示例如下:

import numpy as np
import torch
flag = True
# flag = False

if flag:

    t_0 = torch.randn((3, 3))  #创建一个(3,3)正态分布的矩阵
    t_1 = torch.ones_like(t_0)  #创建一个(3,3)的全1矩阵
    t_add = torch.add(t_0, 10, t_1)  

    print("t_0:\n{}\nt_1:\n{}\nt_add_10:\n{}".format(t_0, t_1, t_add))

torch.addcdiv()
torch.addcmul()

torch.addcuml(input,
              value=1,
              tensor1,
              tensor2,
              out=None)

torch.sub()
torch.div()
torch.mul()

二、对数,指数,幂函数

torch.log(input,out=None)
torch.log10(input,out=None)
torch.log2(input,out=None)
torch.exp(input,out=None)
torch.pow()

三、三角函数

torch.abs(input,out=None)
torch.acos(input,out=None)
torch.cosh(input,out=None)
torch.cos(input,out=None)
torch.asin(input,out=None)
torch.atan(input,out=None)
torch.atan2(input,other,out=None)

3、线性回归

线性回归是分析一个变量与另外一(多)个变量之间关系的方法

因变量:Y 自变量:x 关系:线性 y = wx + b 分析:求解w,b

求解步骤

1、确定模型 model: y = wx + b
2、选择损失函数 MSE,均方误差
3、求解梯度并更新w,b

使用pytorch的一个具体线性回归公式推导代码:

import torch
import matplotlib.pyplot as plt
torch.manual_seed(10)

lr = 0.05  # 学习率

# 创建训练数据
x = torch.rand(20, 1) * 10  # x data (tensor), shape=(20, 1)  rand是生成均匀分布的20个点,再乘于10,范围就是0-10之间
y = 1*x + (5 + torch.randn(20, 1))  # y data (tensor), shape=(20, 1),torch.randn(20, 1)是噪声,符合正态分布

# 构建线性回归参数
w = torch.randn((1), requires_grad=True)  #线性函数中只有一个w,先随机初始化一个w
b = torch.zeros((1), requires_grad=True)  #线性回归中只有一个b,先随机初始化b的值为0

for iteration in range(1000):

    # 前向传播
    wx = torch.mul(w, x)  #将w和x的值相乘
    y_pred = torch.add(wx, b)   #计算wx + b的值

    # 计算 MSE loss
    loss = (0.5 * (y - y_pred) ** 2).mean()   #计算损失函数

    # 反向传播
    loss.backward()    #使用自带的梯度求导模块

    # 更新参数
    b.data.sub_(lr * b.grad)
    w.data.sub_(lr * w.grad)
    b.grad.zero_()    #将张量梯度清零
    w.grad.zero_()    #将张量梯度清零

    # 绘图
    if iteration % 20 == 0:   #每迭代20次进行一次输出

        plt.scatter(x.data.numpy(), y.data.numpy())
        plt.plot(x.data.numpy(), y_pred.data.numpy(), 'r-', lw=5)
        plt.text(2, 20, 'Loss=%.4f' % loss.data.numpy(), fontdict={'size': 20, 'color':  'red'})
        plt.xlim(1.5, 10)
        plt.ylim(8, 28)
        plt.title("Iteration: {}\nw: {} b: {}".format(iteration, w.data.numpy(), b.data.numpy()))
        plt.pause(0.5)

        if loss.data.numpy() < 1:   #如果损失函数的值小于0.8则停止循环
            break

最后得到的线性回归拟合公式如下图所示:
pytorch——张量操作与线性回归_第1张图片
————————————————
本篇幅的所有内容是基于深度之眼的pytorch课程的视频进行摘录的,所有代码均来自视频中余老师的讲解,如有侵权,请联系我进行删除。

你可能感兴趣的:(pytorch)