栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

pytorch自动求导机制与逻辑回归实现-笔记

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

pytorch自动求导机制与逻辑回归实现-笔记

import torch
import numpy as np
import matplotlib.pyplot as plt
torch.manual_seed(1100)

# ========================= example 1-1 =======================

"""
torch.autograd.backward()
1.功能:自动求取梯度
2.参数
tensors,通常是求导张量,如loss;
retain_graph,保存图;
create_graph,创建图,用于高阶求导
grad_tensors,多梯度权重
"""
# 使用retain_graph保存图
flag = False
# flag = True
if flag:
    w = torch.tensor([1.], requires_grad=True)
    x = torch.tensor([2.], requires_grad=True)

    a = torch.add(w, x)
    # 如果想保存a的张量梯度
    b = torch.add(w, 1)
    y = torch.mul(a, b) # y0 = (x+w) * (w+1)

    y.backward(retain_graph=True)
    print(w.grad)

# ========================= example 1-2 =======================
# grad_tensors
flag = False
# flag = True
if flag:
    w = torch.tensor([1.], requires_grad=True)
    x = torch.tensor([2.], requires_grad=True)

    a = torch.add(w, x)
    # 如果想保存a的张量梯度
    b = torch.add(w, 1)
    y0 = torch.mul(a, b) # y0 = (x+w) * (w+1)
    y1 = torch.add(a,b)  # y1 = (x+w) + (w+1) dy1/dw = 2

    loss = torch.cat([y0,y1],dim=0)
    grad_tensors = torch.tensor([1.,2.]) # 设置权重
    # w.grad = w1*y0+w2*y1=1*5+2*2=9

    loss.backward(gradient=grad_tensors)
    print(w.grad)


# ========================= example 1-3 =======================
"""
torch.autograd.grad()
1.功能:求取梯度
2.参数
outputs,通常是求导张量,如loss;
inputs,需要求梯度张量
retain_graph,保存图;
create_graph,创建图,用于高阶求导
grad_tensors,多梯度权重
"""
# autograd.grad实现二阶导的求导过程
flag = False
# flag = True
if flag:
    x = torch.tensor([3.],requires_grad=True)
    y = torch.pow(x,2) # y = x**2

    grad_1 = torch.autograd.grad(outputs=y,inputs=x,create_graph=True)
    # y是output x是input create_graph一定要变成True才能实现高阶求导
    # grad_1 = dy / dx = 2x = 2 * 3 = 6
    print(grad_1)

    grad_2 = torch.autograd.grad(grad_1[0],x)
    # grad_2 = d(dy/dx)/dx = d(2x)/dx = 2
    print(grad_2)

# ========================= tips:1 =======================
# 为什么有时候要导数清零
flag = False
# flag = True
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)
        """
        不清零
        tensor([5.])
        tensor([10.])
        tensor([15.])
        tensor([20.])
        """
        w.grad.zero_()
        # _下划线的意思:原味操作
        """
        清零
        tensor([5.])
        tensor([5.])
        tensor([5.])
        tensor([5.])
        """

# ========================= tips:2 =======================
# 依赖于叶子节点的节点,requires_grad 默认 True
flag = False
# flag = True
if flag:
    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 = torch.mul(a,b)
    print(a.requires_grad,b.requires_grad,y.requires_grad)



# ========================= tips:3 =======================
# 叶子节点不可执行in-place
flag = False
# flag = True
if flag:
    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 = torch.mul(a,b)

    w.add_(1) # 在反向传播前,改变w的值
    """
    会报错:如下
    RuntimeError: a leaf Variable that requires grad is being used in an in-place operation.
    """
    y.backward()


# what is in-place操作:在原始内存当中,去改变这个数据
flag = False
# flag = True
if flag:

    a = torch.ones((1,))
    print(id(a),a)

    a = a + torch.ones((1,)) # 表明分配了新的一个内存给a,即非in-place操作
    print(id(a),a)

    a += torch.ones((1,)) # += 操作后,地址没改变,即原位操作,in-palce操作
    print(id(a),a)

    """
    2443338884264 tensor([1.])
    2443561213288 tensor([2.])
    2443561213288 tensor([3.])
    """


# ========================= 实践案例:logistics regression =======================
# y = f(wx+b)
# f(x) = sigmoid(y)
# 线性2分类模型  0 0.5>y| 1 0.5<=y

# 训练步骤:【获取数据+模型+损失函数+优化器】-迭代训练
import torch.nn as nn

# ----------------------------- setp 1/5 生成数据 ----------------------------------------
sample_nums = 100
mean_value = 1.7
bias = 1
n_data = torch.ones(sample_nums,2)
x0 = torch.normal(mean_value*n_data,1) + bias
y0 = torch.zeros(sample_nums)
x1 = torch.normal(-mean_value*n_data,1) + bias
y1 = torch.ones(sample_nums)
train_x = torch.cat((x0,x1),0)
train_y = torch.cat((y0,y1),0)

# ----------------------------- setp 2/5 选择模型 ----------------------------------------
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() # 实例化逻辑回归模型

# ----------------------------- setp 3/5 损失函数 ----------------------------------------
loss_fn = nn.BCELoss()

# ----------------------------- setp 4/5 选择优化器 ----------------------------------------
lr = 0.01 # learning rate
optimizer = torch.optim.SGD(lr_net.parameters(),lr=lr,momentum=0.9)

# ----------------------------- setp 5/5 模型训练 ----------------------------------------
for iteration in range(1000):

    # 前向传播
    y_pred = lr_net(train_x)

    # 计算loss
    loss = loss_fn(y_pred.squeeze(),train_y)

    # 反向传播
    loss.backward()

    # 更新参数
    optimizer.step()

    # 绘图
    if iteration % 200 == 0:
        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,7)
        plt.ylim(-7, 7)
        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
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1010215.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号