Pytorch学习笔记(一)张量(Tensor)/ 变量(Variable)

张量(Tensor)

一个多维数组,它是标量、向量、矩阵的高维拓展
如图:

在这里插入图片描述

Tensor与Variable

Variable在 Pytorch0.4.0 之后就并入到了Tensor中。

torch.autograd.Variable 中的数据类型,主要用于封装Tensor,进行自动求导

  • data:被包装的Tensor
  • grad:data的梯度
  • grad_fn:创建Tensor时所用的方法function
  • requires_grad:指示是否需要梯度
  • is_leaf:指示是否是叶子结点(张量)

torch.Tensor:

  • dtype:张量的数据类型,如:
    • torch.FloatTensor
    • torch.cuda.FloatTensor
    • torch.DoubleTensor
    • torch.ShortTensor
    • torch.IntTensor
    • torch.LongTensor
  • shape:张量的形状,如,(64,3,224,224)
  • device:张量所在设备,GPU / CPU,是加速的关键

在这里插入图片描述

如何创建张量?

  • 直接创建
  • 依据数值创建
  • 依据概率创建

一、直接创建

(1)torch.tensor():从data创建tensor

  • data:数据,可以是list,numpy
  • dtype:数据类型,默认与data一致
  • device:所在设备,cuda / cpu
  • requires_grad:是否需要梯度
  • pin_memory:是否存于锁页内存

【CPU / GPU(cuda)上创建张量】

# 通过torch.tensor创建张量 在cpu设备上运行
import torch
import numpy as np
flag = True
if flag:
    arr = np.ones((3,3))
    print('ndarray的数据类型:',arr.dtype)

    # t = torch.tensor(arr,device = 'cuda')
    t = torch.tensor(arr)
    print(t)

在这里插入图片描述

# 通过torch.tensor创建张量
import torch
import numpy as np
flag = True
if flag:
    arr = np.ones((3,3))
    print('ndarray的数据类型:',arr.dtype)

    t = torch.tensor(arr,device = 'cuda') # GPU上,cuda
    # t = torch.tensor(arr)
    print(t)

在这里插入图片描述

(2)torch.from_numpy(ndarray):从numpy创建tensor

【注】
从tensor.from_numpy创建的tensor在原ndarray共享内存,当修改其中一个的数据,另外一个也将会被改动

flag = True
if flag:
    arr = np.array([[1,2,3],[4,5,6]])
    t = torch.from_numpy(arr)
    print("Numpy array:",arr)
    print("Tensor:",t)
    print()
    arr[0,0] = 7 # 共享内存,numpy和tensor一起变动
    print("Numpy array:", arr)
    print("Tensor:", t)
    print()
    t[0,0] = -2 # 共享内存,numpy和tensor一起变动
    print("Numpy array:", arr)
    print("Tensor:", t)

在这里插入图片描述
二、依据数值创建

(1)torch.zeros():依size创建全0张量

  • size:张量的形状,如,(3,3)、(3,224,224)等
  • out:输出的张量
  • layout:内存中布局形式,strided(默认),sparse_coo(稀疏张量情况)等
  • device:所在设备,GPU / CPU
  • requires_grad:是否需要梯度

在这里插入图片描述

flag = True
if flag:
    out_t = torch.tensor([1])

    t = torch.zeros((3,3),out = out_t)
    print(t,'\t',out_t)
    print(id(t),id(out_t),id(t) == id(out_t)) # 同一个内存地址

在这里插入图片描述
(2)torch.zeros_like():依input形状创建全0张量

  • input:创建与input形状相同的全0张量
  • dtype:数据类型
  • layout:内存中布局形式
    在这里插入图片描述

(3)torch.ones()
(4)torch.ones_like()

在这里插入图片描述
(5)torch.full()
在这里插入图片描述
(6)torch.full_like()

  • 依input形状创建全(数值几就是全几)张量
    • size:张量形状
    • fill_value:张量的值
t = torch.full((3,3),1)
    print(t)

在这里插入图片描述
(7)torch.arange():创建等差的1维张量

【注】数值区间为[start , end)(左闭右开:右边取不到)

  • start:数列起始值
  • end:数列“结束值”
  • step:数列公差,默认为1

在这里插入图片描述

t = torch.arange(2,10,2)
    print(t)

在这里插入图片描述
(8)torch.linspace():创建均分的1维张量

【注】数值区间为[start , end](两边都可以取到)

  • start:数列起始值
  • end:数列结束值
  • steps:数列长度
    在这里插入图片描述
    这里的步长s等于 e n d − s t a r t s t e p s − 1 \frac{end-start}{steps-1} steps1endstart
t = torch.linspace(2,10,6)
    print(t)

在这里插入图片描述
(9)torch.logspace():创建对数均分的1维张量

【注】长度为steps,底为base

  • start:数列起始值
  • end:数列结束值
  • steps:数列长度
  • base:对数函数的底,默认为10

在这里插入图片描述

t = torch.logspace(2,30,20,10)
    print(t)

在这里插入图片描述

(10)torch.eye():创建单位对角矩阵(2维张量)

【注】默认为方阵

  • n:矩阵行数
  • m:矩阵列数

在这里插入图片描述

t = torch.eye(3,3)
    print(t)

在这里插入图片描述

三、依概率分布创建张量

(1)torch.normal():生成正态分布(高斯分布)

  • mean:均值
  • std:标准差

四种模式:

  • mean为标量,std为标量
# mean:标量 std:标量
    t_normal = torch.normal(0.,1.,size = (4,)) # 长度为size的张量
    print(t_normal)

在这里插入图片描述

  • mean为标量,std为张量
# mean:标量 std:张量
    mean = 0
    std = torch.arange(1, 5, dtype=torch.float)
    t_normal = torch.normal(mean, std)
    print("mean:{}\nstd:{}".format(mean, std))
    print(t_normal)

在这里插入图片描述

  • mean为张量,std为标量
# mean:张量 std:标量
    mean = torch.arange(1,5,dtype = torch.float)
    std = 1
    t_normal = torch.normal(mean,std)
    print("mean:{}\nstd:{}".format(mean,std))
    print(t_normal)

在这里插入图片描述

  • mean为张量,std为张量
# mean:张量 std:张量
    mean = torch.arange(1,5,dtype = torch.float)
    std = torch.arange(1, 5, dtype=torch.float)
    t_normal = torch.normal(mean,std)
    print("mean:{}\nstd:{}".format(mean,std))
    print(t_normal)

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
(2)torch.randn() / torch.randn_like():生成标准正态分布

  • size:张量形状

(3)torch.randint() / torch.randint_like():区间[low , high]生成整数均匀分布

  • size:张量形状

在这里插入图片描述
(4)torch.randperm():生成从0~n-1的随机排列

  • n:张量的长度

(5)torch.bernoulli():以input为概率,生成伯努利分布(0-1分布、两点分布)

  • input:概率值

在这里插入图片描述

张量操作与线性回归

张量的操作

  • 拼接
  • 切分
  • 索引
  • 变换

一、张量的拼接与切分

1.torch.cat():将张量按维度dim进行拼接

  • tensors:张量序列
  • dim:要拼接的维度

2.torch.stack():在新创建的维度dim上进行拼接(会扩张张量的维度

  • tensors:张量序列
  • dim:要拼接的新的维度
    在这里插入图片描述
t = torch.IntTensor([[1,6,3],[5,2,9]])
t_stack1 = torch.stack([t,t,t],dim = 0) # 在第0维度上增加一个张量维度,然后拼接
t_stack2 = torch.stack([t,t,t],dim = 1) # 在第1维度上增加一个张量维度,然后拼接
t_stack3 = torch.stack([t,t,t],dim = 2) # 在第2维度上增加一个张量维度,然后拼接
print("t:{}\nshape:{}\n".format(t,t.shape))
print("t_stack1:{}\nshape:{}\n".format(t_stack1,t_stack1.shape))
print("t_stack2:{}\nshape:{}\n".format(t_stack2,t_stack2.shape))
print("t_stack3:{}\nshape:{}\n".format(t_stack3,t_stack3.shape))

在这里插入图片描述

【stack】
在这里插入图片描述
3.torch.chunk():将张量按维度dim进行平均切分,返回一个张量列表

【注】若不能整除,最后一份张量会小于其他张量

  • input:要切分的张量
  • chunks:要切分的份数
  • dim:要切分的维度

在这里插入图片描述

# 张量切分
t = torch.ones((2,7))
list_of_tensors = torch.chunk(t,dim = 1,chunks = 3) # 7 / 3 --向上取整

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

t = torch.ones((4,3))
list_of_tensors = torch.chunk(t,dim = 0,chunks = 4) # 7 / 3 --向上取整

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

在这里插入图片描述
在这里插入图片描述
4.torch.split():将张量按维度dim进行切分,返回一个张量列表

  • tensor:要切分张量
  • split_size_or_sections:
    • int:表示每一份长度
    • list:按list元素切分
  • dim:要切分的维度
    在这里插入图片描述
# 张量切分split
t = torch.ones((2,7))
list_of_tensors = torch.split(t,3,dim = 1)
for id,t1 in enumerate(list_of_tensors):
    print("第{}个张量:{},shape is {}".format(id + 1,t1,t1.shape))

list_of_tensors1 = torch.split(t,[1,4,2],dim = 1)
for id,t2 in enumerate(list_of_tensors1):
    print("第{}个张量:{},shape is {}".format(id + 1,t2,t2.shape))

在这里插入图片描述
在这里插入图片描述
二、张量的索引

1.torch.index_select():在维度dim上,按index索引数据,返回一个依index索引数据拼接的张量

  • input:要索引的张量
  • dim:要索引的维度
  • index:要索引数据的序号

在这里插入图片描述

t = torch.randint(0,9,size = (3,3))
id = torch.tensor([0,2],dtype = torch.long) # 数据类型必须指定long
t_select = torch.index_select(t,dim = 0,index = id)
print("t:\n{}\nt_select:\n{}".format(t,t_select))

在这里插入图片描述
2.torch.masked_select():按mask中的True进行索引,返回一维张量

  • input:要索引的张量
  • mask:与input同形状的布尔类型张量

在这里插入图片描述

t = torch.randint(0,9,size = (3,3))
mask = t.ge(5) # ge:大于等于 gt:大于  返回True or False
t_select = torch.masked_select(t,mask)
print("t:\n{}\nmask:\n{}\nt_select:\n{}".format(t,mask,t_select))

在这里插入图片描述
三、张量变换

1.torch.reshape():变换张量形状

【注】当张量在内存中是连续的时候,新张量与input共享数据内存

  • input:要变换的张量
  • shape:新张量的形状

在这里插入图片描述

t = torch.randperm(8)
t_reshape = torch.reshape(t,(2,4)) # 注意大小要匹配
print("t:\n{}\nt_reshape:\n{}".format(t,t_reshape))

在这里插入图片描述

t = torch.randperm(8)
t_reshape = torch.reshape(t,(-1,2,2)) # 注意大小要匹配 -1:维度由其他维度计算出来
print("t:\n{}\nt_reshape:\n{}".format(t,t_reshape))

在这里插入图片描述

t = torch.randperm(8)
t_reshape = torch.reshape(t,(-1,2,2)) # 注意大小要匹配 -1:维度由其他维度计算出来
print("t:\n{}\nt_reshape:\n{}".format(t,t_reshape))
t[0] = 1024
print("t:\n{}\nt_reshape:\n{}".format(t,t_reshape))
print('t.data 内存地址:{}'.format(id(t.data)))
print('t_reshape.data 内存地址:{}'.format(id(t_reshape.data)))

在这里插入图片描述
2.torch.transpose():交换张量的两个维度

  • input:要交换的变量
  • dim0:要交换的维度
  • dim1:要交换的维度

3.torch.t()

 2维张量转置,对矩阵而言,等价于torch.transpose(input , 0 , 1)
在这里插入图片描述

t = torch.rand((2,3,4))
t2 = torch.randint(0,5,size = (2,3))
t_transpose = torch.transpose(t,dim0 = 1,dim1 = 2) # c*h*w --> h*w*c 图像预处理
print("t shape:{}\nt_transpose shape:{}".format(t.shape,t_transpose.shape))
t_tt = torch.t(t2) # 矩阵转置
print("t shape:{}\nt_tt shape:{}".format(t_tt.shape,t_tt.shape))

在这里插入图片描述
4.torch.squeeze()压缩长度为1的维度(轴)

  • dim:
    • 若为None,则移除所有长度为1的轴
    • 指定维度,当且仅当该轴长为1时,可以被移除

5.torch.unsqueeze():依据dim扩展维度

  • dim:扩展的维度

在这里插入图片描述

t = torch.rand((1,2,3,1)) # 创建一个四维张量
t_sq = torch.squeeze(t) # 移除长度为1的轴
t_0 = torch.squeeze(t,dim = 0)
t_1 = torch.squeeze(t,dim = 1)
print(t.shape)
print(t_sq.shape)
print(t_0.shape)
print(t_1.shape)

在这里插入图片描述

张量的数学运算

  • 加减乘除
  • 对数、指数、幂函数
  • 三角函数

在这里插入图片描述
1.torch.add():逐元素计算 input + alpha * other
(深度学习中权重加权和会用到)

  • input:第一个张量
  • alpha:乘项因子
  • other:第二个张量

在这里插入图片描述

t_0 = torch.randn((3,3))
t_1 = torch.ones_like(t_0)
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))

在这里插入图片描述

【补】

  1. torch.addcdiv():加法+除法
    在这里插入图片描述

  2. torch.addcmul():加法+乘法
    在这里插入图片描述

线性回归模型举例

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

  • 因变量:y
  • 自变量:x
  • 关系:线性
  • 分析:求解w和b

求解步骤:

  1. 确定模型:Model: y = w x + b y=wx+b y=wx+b
  2. 选择损失函数:MSE: 1 m ∑ i = 1 m ( y i − y i ^ ) 2 \frac{1}{m}\sum_{i=1}^m(y_i-\hat{y_i})^2 m1i=1m(yiyi^)2
  3. 求解梯度并更新w,b:LR (学习率)
    w = w − L R ∗ w . g r a d w=w-LR*w.grad w=wLRw.grad
    b = b − L R ∗ w . g r a d b=b-LR*w.grad b=bLRw.grad

【训练一个线性回归模型】

#coding=utf-8
import torch
import numpy as np
import matplotlib.pyplot as plt
# 在需要生成随机数据的实验中,每次实验都需要生成数据。
# 设置随机种子是为了确保每次生成固定的随机数,
# 这就使得每次实验结果显示一致了,有利于实验的比较和改进。
torch.manual_seed(10)
lr = 0.01 # 学习率设置

# 创建训练数据 20个点
x = torch.rand(20,1) * 10
y = 2 * x + (5 + torch.randn(20,1)) # w=2 b=5 后面项是噪声

# 构建线性回归参数 (权值初始化)
w = torch.randn((1),requires_grad = True) # 正态分布初始化w
b = torch.zeros((1),requires_grad = True) # 初始化b为0

for iteration in range(1000): # 迭代
    # 前向传播
    wx = torch.mul(w,x)
    y_pred = torch.add(wx,b) # 得到预测值

    # 计算MSE loss  均方差
    loss = (0.5 * (y - y_pred) ** 2).mean() # 0.5为了消去系数而设置

    # 反向传播
    loss.backward()

    # 更新参数 梯度下降法
    b.data.sub_(lr * b.grad)
    w.data.sub_(lr * w.grad)

    # 绘图
    if iteration % 20 == 0: # 20次一轮结果
        plt.scatter(x.data.numpy(),y.data.numpy()) # 绘制20个点的散点图
        plt.plot(x.data.numpy(),y_pred.data.numpy(),'r-',lw = 5) # lw(linewidth) 线宽
        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: # 直到损失函数小于1停止迭代
            break

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值