ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

PyTorch Week 1

2021-10-05 15:31:30  阅读:182  来源: 互联网

标签:Week tensor data torch 张量 PyTorch grad mean


PyTorch Week 1

目录

本篇记录在深度之眼学习到的Pytorch基础操作

一、张量简介与创建

Tensor 与 Variable

0.4.0 Variable并入Tensor
data, requires_grad, grad, grad_fn, is_leaf(叶子节点)
dtype, shape, device

张量的创建

1、直接创建
(1)torch.tensor()

torch.tensor(data,
					dtype=None,
					device=None,
					requires_grad=Falsem,#是否需要梯度
					pin_memory=False#是否存于锁页内存,与转换效率有关,通常False)

将tensor存入GPU

torch.tensor(data,device='cuda')

(2)从numpy数组创建torch.from_numpy(ndarray)
注意: 变量t与arr指向同一个内存。

arr = np.array([[1,2,3],[4,5,6]])
t = torch.from_numpy(arr)

2、依据数值创建
全零张量:torch.zeros()、torch.zeros_like()

torch.zeros(*size
			out = None,#输出的张量名
			layout=torch.strided,#内存中的布局形式
			device=None,
			requires_grad=False)			
out_t = torch.tensor([1])
t = torch.zeros((3,3), out=out_t)#id(t)==id(out_t)

全“1”张量:

torch.ones()、torch.ones_like()

自定义全值张量:

torch.full(size, fill_vlaue)、forch.full_like()

等差数列张量:

torch.arange(start,end,step)#step:公差

线性均分张量:

torch.linespace(start,end,step)#step:长度

对数均分张量:

torch.logspace(start,end,step,base)#step:长度,base:底数

对角矩阵张量:

torch.eye(n, m)#n:行数, m:列数

2、依据概率分布创建张量
高斯分布

torch.normal(mean, std)
torch.normal(mean, std, size)
torch.randn(*size)

标准正态分布

torch.randn()
torch.randn_like()

均匀分布

torch.rand()
torch.rand_like()

均匀整数分布

torch.randint()
torch.randint_like()

乱序的随机排列

torch.randperm(n)#n:长度

伯努利分布

torch.bernoulli(input)#input为概率值

二、张量操作与线性回归

张量拼接与切分

1 拼接

torch.cat()#在现有维度拼接
torch.stack()#在新的维度拼接

2 chunk按dim平均切分

torch.chunk(input,
			chunks,#份数,不能整除的话最后一维小于
			 dims)#指定维度

3 split按维度切分

torch.split(tensor,
			split_size_or_sections,#int或者list,按整数均分或者按list元素切分
			dim)#

张量索引

1 在第dim个维度上按index索引

torch.index_select(input,
					dim,
					index)#必须是torch.long

2 按mask中的True进行索引,返回一维张量

t = torch.randint(0,9,size=(3,3))
mask = t.ge(5)
t_select = torch.masked_select(t,mask)#
t:
tensor([[4,5,0],
		[5,7,1],
		[2,5,8]])
mase:
tensor([[False, True, False],
		[True,  True, False],
		[False, True, True]])
t_select:
tensor([5, 5, 7, 5, 8])

张量变换

1 形状

torch.reshape()

2 维度交换

torch.transpose()#
torch.t()#二维

3 压缩维度

torch.squeeze(input,
			dim=None)#
torch.unsqueeze(input,
			dim=None)#

张量运算

torch.add()
torch.addcdiv()
torch.addcmul()

线性回归

torch.manual_seed(10)
lr = 0.1 # 学习率

# 创建训练数据
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)

for iteration in range(1000):

    #forward
    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)

    #绘图
    if iteration%20 == 0:
        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)
        # plt.show()

        if loss.data.numpy()<1:
            break

三、计算图与动态图机制

计算图

结点(Node):数据,如向量,矩阵,张量等
边(Edge):运算,加减乘除卷积等
叶子节点:用户创建的节点
is_leaf:指示张量是否是叶子节点
grad_fn:记录创建该张量时所用的方法,叶子节点None

import torch

w = torch.tensor([1.], requires_grad=True)
x = torch.tensor([2.], requires_grad=True)

a = torch.add(w, x)
a.retain_grad()#保存非叶子节点的梯度
b = torch.add(w, 1)
y = torch.mul(a,b)

y.backward()
print(w.grad)

#叶子节点
print("is_leaf:\n", w.is_leaf, x.is_leaf, a.is_leaf, b.is_leaf, y.is_leaf)

#查看梯度
print("gradient:\n",w.grad, x.grad, a.grad, b.grad, y.grad)
tensor([5.])
is_leaf:
 True True False False False
gradient:
 tensor([5.]) tensor([2.]) tensor([2.]) None None #a.retain_grad()保存非叶子节点的梯度
grad_fn:
 None None <AddBackward0 object at 0x0000019AA3A837C0> <AddBackward0 object at 0x0000019AA3B38E80> <MulBackward0 object at 0x0000019AA3B384F0> #w,x是用户创建的叶子节点

动态图 VS 静态图

运算与搭建同时 VS 先搭建,后运算

四、autograd

1 torch.gutograd.backward 反向传播

torch.gutograd.backward(tensors,#用于求导的张量,y,loss
						grad_tensors = None,#多梯度权重
						retain_graph = None,#默认计算图求导后自动释放,保存计算图
						create_graph = False)#创建导数计算图,用于高阶求导
#========================retain_graph===========================#						
w = torch.tensor([1.], requires_grad=True)
x = torch.tensor([2.], requires_grad=True)
a = torch.add(w, x)
b = torch.add(w, 1)
y.backward(retain_graph=True)#保存计算图
y.backward()
#========================gradient===========================#
y0 = torch.mul(a,b)
y1 = torch.add(a,b)
loss = torch.cat([y0, y1], dim=0)#loss是向量
grad_tensors = torch.tensor([1., 1.])#设计loss中y0和y1的权重
loss.backward(gradient=grad_tensors)#

2 torch.autograd.grad 求取梯度

torch.autograd.grad(outputs,
					inputs,
					grad_outputs=None,
					retain_graph=None,
					create_graph=False)
#========================create_graph===========================#
x = torch.tensor([3.], requires_grad=True)
y = torch.pow(x,2)

grad_1 = torch.autograd.grad(y,x,create_graph=True)#grad_1是元组
grad_2 = torch.autograd.grad(grad_1[0],x)

3 autograd的几个特点

  • 梯度不会自动清零,
#========================梯度不会自动清零===========================#
flag = True
# flag = False
if flag:
    w = torch.tensor([1.], requires_grad=True)
    x = torch.tensor([2.], requires_grad=True)

    for i in range(4):
        a = torch.add(w, x)
        b = torch.add(w, 1)
        y = torch.mul(a,b)

        y.backward()
        print(w.grad)
        #w.grad.zero_() :'_'表示in-place操作,对节点进行in-place操作,重置节点的值
tensor([5.])
tensor([10.])
tensor([15.])
tensor([20.])
  • 依赖于叶子结点的节点,requires_grad默认为True
  • 叶子节点不可执行in-place
    前向传播记录了叶子节点的地址,以供反向传播通过地址调用值。对叶子节点进行in-place操作会改变地址储存的值,导致求导出错

五、逻辑回归

线性二分类模型
y = f(WX+b)
f为sigmoid函数,也称Logistic函数

对数几率回归与线性回归

逻辑回归与线性回归

机器学习模型训练步骤

数据、模型、损失函数、优化器

# -*- coding: utf-8 -*-
"""
# @file name  : Logsitic-Regression-norm.py
# @author     : TingsongYu https://github.com/TingsongYu
# @date       : 2019-09-08 10:08:00
# @brief      :
"""
import torch
import torch.nn as nn
import matplotlib.pyplot as plt
import numpy as np
torch.manual_seed(10)

lr = 0.01  # 学习率

# 生成虚拟数据
sample_nums = 100#样本数量
mean_value = 1.7#均值
bias = 5         #偏差
n_data = torch.ones(sample_nums, 2)#全“1”矩阵,100个样本,每个样本有2个特征
x0 = torch.normal(mean_value * n_data, 1) + bias      # 类别0 数据 shape=(100, 2)
y0 = torch.zeros(sample_nums)                         # 类别0 标签 shape=(100, 1)
x1 = torch.normal(-mean_value * n_data, 1) + bias     # 类别1 数据 shape=(100, 2)
y1 = torch.ones(sample_nums)                          # 类别1 标签 shape=(100, 1)
train_x = torch.cat((x0, x1), 0)
train_y = torch.cat((y0, y1), 0)
#y0是一组围绕点a(mean_value+bias,mean_vale+bias)的数据
#y1是一组围绕点b(-mean_value+bias,-mean_vale+bias)的数据
#改变mean_value会改变a,b两点间的距离,使得两数据簇分布的更近或更远,距离相近的数据簇会难以得到较好的分类,分布较远的数据簇会得到较好的分类
#改变bias只会改变a,b在空间中的位置,不会改变a,b的相对位置,不会影响分类效果


# 定义模型
class LR(nn.Module):
    def __init__(self):
        super(LR, self).__init__()
        self.features = nn.Linear(2, 1)
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        x = self.features(x)
        x = self.sigmoid(x)
        return x


lr_net = LR()

# 定义损失函数与优化器
loss_fn = nn.BCELoss()
optimizer = torch.optim.SGD(lr_net.parameters(), lr=0.01, momentum=0.9)

for iteration in range(1000):

    # 前向传播
    y_pred = lr_net(train_x)

    # 计算 MSE loss
    loss = loss_fn(y_pred, train_y.unsqueeze(1))
    """
    如果不加unsqueeze(1),会产生如下报错 ,可思考是为什么,也可查看官方BCELoss文档,或者等到第四周的课再研究
    Using a target size (torch.Size([200])) that is different to the input size (torch.Size([200, 1])) is deprecated. 
    Please ensure they have the same size.
    """

    # 反向传播
    loss.backward()

    # 更新参数
    optimizer.step()

    # 清空梯度
    optimizer.zero_grad()

    # 绘图
    if iteration % 40 == 0:
        plt.clf()

        mask = y_pred.ge(0.5).float().squeeze()  # 以0.5为阈值进行分类
        correct = (mask == train_y).sum()  # 计算正确预测的样本个数
        acc = correct.item() / train_y.size(0)  # 计算精度

        plt.scatter(x0.data.numpy()[:, 0], x0.data.numpy()[:, 1], c='r', label='class 0')
        plt.scatter(x1.data.numpy()[:, 0], x1.data.numpy()[:, 1], c='b', label='class 1')

        w0, w1 = lr_net.features.weight[0]
        w0, w1 = float(w0.item()), float(w1.item())
        plot_b = float(lr_net.features.bias[0].item())
        plot_x = np.arange(-6, 6, 0.1)
        plot_y = (-w0 * plot_x - plot_b) / w1

        plt.xlim(-5, 10)
        plt.ylim(-7, 10)
        plt.plot(plot_x, plot_y)

        plt.text(-5, 5, 'Loss=%.4f' % loss.data.numpy(), fontdict={'size': 20, 'color': 'red'})
        plt.title("Iteration: {}\nw0:{:.2f} w1:{:.2f} b: {:.2f} accuracy:{:.2%}".format(iteration, w0, w1, plot_b, acc))
        plt.legend()

        plt.show()
        plt.pause(0.5)

        if acc > 0.99:
            break

作业1

  1. 安装anaconda,pycharm, CUDA+CuDNN(可选),虚拟环境,pytorch,并实现hello pytorch查看pytorch的版本
    
  2. 张量与矩阵、向量、标量的关系是怎么样的?
    

都属于不同阶数的张量,标量、向量、矩阵分别是0阶、1阶、2阶张量

  1. Variable“赋予”张量什么功能?
    

由以下几个模块共同组成了自动求导功能
data:被包装的Tensor
requires_grad:是否需要求梯度,依赖于叶子节点的默认为True
grad:data的梯度
grad_fn:创建该节点使用的方法,函数
is_leaf:只是张量是否是叶子节点
叶子节点:用户创建的

  1. List item采用torch.from_numpy创建张量,并打印查看ndarray和张量数据的地址;
    

from_numpy会使得创建的Tensor包括多个属性,其中data属性指向ndarray的地址,其他属性储存在Tensor的地址中。

arr = np.array([[1,2,3],[4,5,6]])
t = torch.from_numpy(arr)
print(arr)
print(t)
print("id(t):{} id(arr):{}".format(id(t), id(arr)))
print(id(t)==id(arr))

arr[0,0] = 4
print(arr)
print(t)
print("id(t):{} id(arr):{}".format(id(t), id(arr)))
print(id(t) == id(arr))
[[1 2 3]
 [4 5 6]]
tensor([[1, 2, 3],
        [4, 5, 6]], dtype=torch.int32)
id(t):2162806604160 id(arr):2162710427376
False
[[4 2 3]
 [4 5 6]]
tensor([[4, 2, 3],
        [4, 5, 6]], dtype=torch.int32)
id(t):2162806604160 id(arr):2162710427376
False
  1. 实现torch.normal()创建张量的四种模式。
#mean标量, std标量
mean = torch.tensor(1.)
std = torch.tensor(1)
t = torch.normal(mean,std,(4,))
print(t)
# mean标量, std张量
mean = torch.tensor(1.)
std = torch.tensor([1, 2, 3, 4])
t = torch.normal(mean, std)
print(t)
# mean张量, std标量
mean = torch.tensor([1.,2.,3.,4.])
std = torch.tensor(1.)
t = torch.normal(mean, std)
print(t)
# mean标量, std标量
mean = torch.tensor([1.,2.,3.,4.])
std = torch.tensor([1, 2, 3, 4])
t = torch.normal(mean, std)
print(t)
tensor([0.6691, 2.3742, 0.3446, 0.6620])
tensor([2.7141, 2.5079, 0.3724, 5.7675])
tensor([1.4993, 3.2231, 4.4613, 5.4309])
tensor([-0.9941,  1.0040,  6.4833,  5.8631])

作业2

  1.  调整线性回归模型停止条件以及y = 2*x + (5 + torch.randn(20, 1))中的斜率,训练一个线性回归模型;
    

梯度下降可视化代码,非常清晰
2. 计算图的两个主要概念是什么?
节点和边,节点是数据,边是运算

  1.  动态图与静态图的区别是什么?
    

动态图是边构建计算图边计算,静态图是先构建完计算图再计算

作业3

  •  逻辑回归模型为什么可以进行二分类?
    

逻辑回归

  • 线性回归解决的是回归问题;逻辑回归解决的是二分类问题。
  • 线性回归的目的是学习一个线性模型,使得预测值拟合真实值;逻辑回归就是用线性模型,使得预测的几率去拟合真实的几率。(概率是事情发生的次数/所有事情的次数,几率是事情发生的概率/事情不发生的概率。)
  • 逻辑回归又称对数几率回归,Logit = log it ,it值得是几率,it = y/(1-y)
  • 根据公式推导,对数几率回归最终化为sigmoid函数的形势,将x映射至(0,1),可用于分类。
    参考1
    参考2
  1.  采用代码实现逻辑回归模型的训练,并尝试调整数据生成中的mean_value,将mean_value设置为更小的值,例如1,或者更大的值,例如5,会出现什么情况?再尝试仅调整bias,将bias调为更大或者负数,模型训练过程是怎么样的?
    
  • 当mean_value=1时,两团数据簇距离更近,相互渗透,逻辑回归的分类效果变差;当mean_value=5时,数据簇距离更远,界线分明,逻辑回归的分类效果变好
  • bias决定了两团数据簇在全体数据空间中的绝对位置,不改变其相对位置。在不限制迭代次数,并不改变学习率的情况下,bias的改变不影响最终分类效果,但分类速度取决于参数的初始化值与bias的距离,两者距离越近,分类越快,距离越远,分类越慢。在限制迭代次数,并不改变学习率的情况下,最终分类效果取决于参数的初始化值与bias的距离,两者距离越近,分类效果越好,距离越远,分类效果越差。 通过sigmoid函数曲线理解,当bias非常大时,wx+b很大,导致 f(wx+b) 落在一个导数几乎为0的区间内,更新速度非常慢。从这个角度去考虑BN的作用,标准化数据使输入落在0周围的一个几乎线性的区间内,避免梯度爆炸或者梯度消失,有助于反向传播。
    sigmoid

标签:Week,tensor,data,torch,张量,PyTorch,grad,mean
来源: https://blog.csdn.net/yandonglv/article/details/120604508

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有