zoukankan      html  css  js  c++  java
  • 零基础一步一步pytorch实现Logistic regression逻辑回归编程教程

    为什么我们需要了解Logistic regression逻辑回归?

    因为神经网络的一个神经元就是Logistic regression逻辑回归。

    Logistic regression(LR)逻辑回归是什么?

    它就是套一个概率分布模型上去。什么是模型?模型就是一个函数比如:f(x)=ax+b。至于逻辑回归套的那个概率分布模型是什么稍后再说,先说套概率分布模型上去有什么用?假如需要判断样本x是属于A类还是属于B类。在前面提到了模型就是一个函数,概率分布模型就是输入一个样本数据x,函数输出它属于A类的概率。逻辑回归只能分出两种类。x属于A类的概率大于0.5那就我们可以认为当前样本属于A类,如果概率小于0.5那就认为它属于B类。

    那么逻辑回归套的是什么函数呢?答:f(x)=11+ewTxf(x) = frac{1}{1+e^{-w^Tx}}。其中ww是待求解的参数,不同的数据是不一样的。那我们怎么根据当前已有的数据调整得到最优的参数ww?答:用梯度下降。
    如果你对梯度下降不理解可以参考这两篇文章:
    易懂的神经网络理论到实践(1):单个神经元+随机梯度下降学习逻辑与规则
    {高中生能看懂的}梯度下降是个啥?

    pytorch编程实践

    本文的实践会先介绍使用的数据是什么。然后介绍如何检验自己程序是否正确。然后介绍如何用pytorch的反向传播求导(求导结果是否正确可以我们自己手动计算下来检验),并用这个导数实现梯度下降。然后介绍如何我们自己求导实现梯度下降(我们自己写的导数是否计算正确检验方法1是可以用前面反向传播求导结果检验2是我们自己手动计算看程序运行结果是否正确)。

    使用pytorch自带的自动求导工具求导,然后实现梯度下降

    大家一定要注意机器学习必备下面那几个步骤。写程序一定要对这些步骤烂熟于心。

    1. 加载数据
    2. 输入样本计算模型的输出
    3. 计算损失函数对参数w的导数(梯度)
    4. 梯度下降调节参数w
    5. 重复2-4

    1.加载数据

    首先我们需要加载数据,这次我们想实现的是让逻辑回归识别逻辑异或(两个数字相同那就是0,两个数字不同那就是1)。
    所以数据(前面两个数字)与标签(最后那个数字)是:

    1 1 0
    1 0 1
    0 1 0
    0 0 1
    

    现在我们用代码实现加载数据

    # -*- coding:utf-8 -*-
    import torch
    import numpy as np
    '''
    用逻辑回归实现异或功能
    '''
    # 加载数据
    data = torch.tensor([[1,1],[1,0],[0,1],[0,0]],dtype=torch.float)
    label = torch.tensor([[0,1,1,0]],dtype=torch.float).t()
    

    计算模型的输出

    前面提到了逻辑回归的模型是f(x)=11+ewTxf(x) = frac{1}{1+e^{-w^Tx}}。我们首先需要先初始化参数w。然后输入一个样本x,然后根据公式f(x)=11+ewTxf(x) = frac{1}{1+e^{-w^Tx}}计算模型输出。接下来我们用代码实现它。很多同学不知道自己代码写的对不对,大家只需要自己算一下结果,然后看看程序输出是否符合自己计算结果

    # -*- coding:utf-8 -*-
    import torch
    import numpy as np
    '''
    用逻辑回归实现异或功能
    '''
    # 加载数据
    data = torch.tensor([[1,1],[1,0],[0,1],[0,0]],dtype=torch.float)
    label = torch.tensor([[0,1,1,0]],dtype=torch.float).t()
    w = torch.tensor([1,1],dtype=torch.float, requires_grad=True)
    
    # 加载一个数据,代入到公式中
    i = 0
    x = data[i]
    #f = 1/[1+e^(-wx)]
    f = 1/(1+torch.pow(np.e,-x.dot(w)))
    print(f) # 输出tensor(0.8808)
    

    利用pytorch反向传播自动求导工具计算损失函数对参数w的导数

    我们需要告诉pytorch损失函数,然后让它根据损失函数对参数w求导。接下来我们用代码实现。()

    # -*- coding:utf-8 -*-
    import torch
    import numpy as np
    '''
    用逻辑回归实现异或功能
    '''
    # 加载数据
    data = torch.tensor([[1,1],[1,0],[0,1],[0,0]],dtype=torch.float)
    label = torch.tensor([[0,1,1,0]],dtype=torch.float).t()
    w = torch.tensor([1,1],dtype=torch.float,requires_grad=True)
    
    
    # 加载一个数据,代入到公式中
    i = 0
    x = data[i]
    #f = 1/[1+e^(-wx)]
    f = 1/(1+torch.pow(np.e,-x.dot(w)))
    print(f) # 输出tensor(0.8808)
    
    loss = (f-label[i])**2 
    print(loss)# 输出:tensor([0.7758])
    loss.backward() # 使用反向传播求损失函数对参数w的导数值
    print(w.grad) # 损失函数对w的导数值tensor([0.1850, 0.1850])
    

    利用反向传播的导数实现梯度下降

    # -*- coding:utf-8 -*-
    import torch
    import numpy as np
    '''
    用逻辑回归实现异或功能
    '''
    # 加载数据
    data = torch.tensor([[1,1],[1,0],[0,1],[0,0]],dtype=torch.float)
    label = torch.tensor([[0,1,1,0]],dtype=torch.float).t()
    w = torch.tensor([1,1],dtype=torch.float,requires_grad=True)
    
    
    # 加载一个数据,代入到公式中
    i = 0
    x = data[i]
    #f = 1/[1+e^(-wx)]
    f = 1/(1+torch.pow(np.e,-x.dot(w)))
    print(f) # 输出tensor(0.8808)
    
    loss = (f-label[i])**2 
    print(loss)# 输出:tensor([0.7758])
    loss.backward() # 使用反向传播求损失函数对参数w的导数值
    print(w.grad) # 损失函数对w的导数值tensor([0.1850, 0.1850])
    
    learning_rate = 1e-2
    w = w - learning_rate*w.grad
    print('更新后的参数w',w)#更新后的参数w tensor([0.9982, 0.9982])
    

    我们自己手动计算导数,并实现梯度下降

    # -*- coding:utf-8 -*-
    import torch
    import numpy as np
    '''
    用逻辑回归实现异或功能
    '''
    # 加载数据
    data = torch.tensor([[1,1],[1,0],[0,1],[0,0]],dtype=torch.float)
    label = torch.tensor([[0,1,1,0]],dtype=torch.float).t()
    w = torch.tensor([1,1],dtype=torch.float,requires_grad=True)
    
    
    # 加载一个数据,代入到公式中
    i = 0
    x = data[i]
    #f = 1/[1+e^(-wx)]
    f = 1/(1+torch.pow(np.e,-x.dot(w)))
    print(f) # 输出tensor(0.8808)
    
    #loss = (f-label[i])**2 
    # 计算损失函数loss对w的导数
    # 我们把e^(-wx)这部分先存到一个变量里面
    e_wx = torch.pow(np.e,-x.dot(w))
    dloss_dw = 2*(f-label[i])*x*e_wx/(1+e_wx)**2
    print(dloss_dw)
    learning_rate = 1e-2
    w = w - learning_rate*dloss_dw
    print('更新后的参数w',w)#更新后的参数w tensor([0.9982, 0.9982])
    
  • 相关阅读:
    java oop第09章_JDBC02(CRUD操作)
    java 与日期转换相关的方法(java.util.date类型和java.sql.date类型互相转换)、随机字符串生成方法、UUID生产随机字符串
    Java oop第08章_JDBC01(入门)
    java 数组中的数值反转输出
    java oop第07章_集合框架
    Java oop创建自定义异常
    java oop遍历List和Map的几种方法
    java oop第06章_异常处理
    Java oop第05章_多态、接口
    信开发 新浪SAE开发平台 验证Token 一直失败
  • 原文地址:https://www.cnblogs.com/ailitao/p/11787550.html
Copyright © 2011-2022 走看看