逻辑斯蒂回归_逻辑斯蒂回归(LR)模型python复现 - 随机梯度下降法;SGDM;RMSProp;Adam...

d658f1f9192a744d56642fb021976422.png

本文包括:

  1. 随机梯度下降法
  2. SGDM
  3. RMSProp
  4. Adam
  5. 其它有关数据分析,机器学习的文章及社群

逻辑斯蒂回归理论知识:

舟晓南:统计学习方法 - 逻辑斯蒂回归解析 | 数据分析,机器学习,学习历程全记录

数据集mnist下载地址(csv格式),以及完整代码:

Zhouxiaonnan/machine-learning-notesandcode

如果觉得对您有帮助,还烦请点击上面的链接,帮忙github点个star~谢谢~


Talk is cheap, let's check the code ^_^

逻辑斯蒂回归 - 随机梯度下降法:

'''
逻辑斯蒂回归 - 随机梯度下降法
-------------------------------------
数据集:Mnist
训练集数量:60000
测试集数量:10000
---------------------------------
训练结果:
迭代次数:100
训练时间:3.54s
测试时间:0.53s
正确率:0.76
'''

import numpy as np
import time
from itertools import islice
import random


'''
readlines方法读取训练数据
--------
输入:
file:数据地址
--------
输出:
data:转换后的数据
label:转换后的标记
'''
def LoadData(file):
    
    # 打开数据文件
    fr = open(file, 'r')
    
    # 准备两个list存储data和label
    data = []
    label = []
    
    # 逐行读取数据,使用islice可以直接跳过第一行表头进行逐行读取
    for line in islice(fr,1,None):
        
        # 对每一行消去空格,并根据','进行分割
        splited = line.strip().split(',')
        
        # 逐行存储数据,此处对特征进行归一化
        data.append([int(num)/255 for num in splited[1:]])
        
        # 因为逻辑斯蒂回归是二分类问题,我们将大于4的类归为1,小于4的类归为0
        a = int(splited[0])
        if a > 4:
            label.append(1)
        else:
            label.append(0)
    
    # 采用书中的方法,我们将b作为一个元素放在w向量的最后一个
    # 同样也需要在每个特征向量后面加上一个1
    SampleNum = len(data)
    for i in range(SampleNum):
        data[i].append(1)
            
    # 返回数据的特征部分和标记部分
    return data, label

'''
预测
-------
输入:
w:目前的权值向量
x:一条样本的特征向量
-----------
输出:类别
'''
def predict(w, x):
    
    exp_wx = np.exp(np.dot(w, x))
    P = exp_wx / (1 + exp_wx)
    if P > 0.5:
        return 1
    return 0

'''
逻辑斯蒂回归 - 随机梯度下降法
--------------
输入:
data:训练集数据
label:训练集标记
itertime:迭代次数
-------------
输出:
w:最优化的权值向量
'''
def Logistic(data, label, itertime):
    
    # 初始化w
    FeatureNum = np.shape(data)[1]
    w = np.zeros(FeatureNum)
    
    # 设定学习率
    h = 0.001
    
    # 样本数
    SampleNum = len(data)
    
    # 将data转换成ndarray格式,方便后续的计算
    data = np.array(data)
    
    # 迭代
    for i in range(itertime):
        
        # 随机选择误分类点
        a = 0
        while a == 0:
            
            # 随机选择
            s = random.sample(range(0, SampleNum - 1),1)[0]
            
            # 得到该样本的特征向量和标记
            xi = data[s]
            yi = label[s]
            
            # 如果分类错误,更新w
            if predict(w, xi) != yi:
                          
                exp_wxi = np.exp(np.dot(w,xi))
                w += h * (xi * yi - (xi * exp_wxi) / (1 + exp_wxi))

                # 进行下一次迭代
                a = 1
             
    return w

'''
模型测试
------------
输入:
data:测试集数据
label:测试集标记
w:最优化的权值向量
-----------
输出:
Acc:正确率
'''

def Classifier(data, label, w):
    
    # 样本数
    SampleNum = len(data)
    
    # 初始化错误分类的数量
    errorCnt = 0
    
    # 遍历每一个样本
    for i in range(SampleNum):
        
        # 对该样本的分类
        result = predict(w, data[i])
        
        # 判断是否分类正确
        if result != label[i]:
            
            # 分类错误,errorCnt+1
            errorCnt += 1
    
    # 计算正确率
    Acc = 1 - errorCnt / SampleNum
    
    return Acc

'''测试模型'''
if __name__ == "__main__":

    print('start loading')
    # 输入训练集
    train_data, train_label = LoadData('E:/我的学习笔记/统计学习方法/实战/训练数据/mnist_train.csv')

    # 输入测试集
    test_data, test_label = LoadData('E:/我的学习笔记/统计学习方法/实战/训练数据/mnist_test.csv')
    print('end loading')
    
    # 最优化参数
    print('start training')
    start = time.time()
    w = Logistic(train_data, train_label, 200)
    print('end training')
    end = time.time()
    print('training time: ', end - start)

    # 进行分类
    start = time.time()
    print('start testing')
    accurate = Classifier(test_data, test_label, w)
    print('end testing')
    end = time.time()
    print('testing time: ', end - start)
    print(accurate)

逻辑斯蒂回归比较简单,可以与感知机模型进行对比学习,并且也比较适合一些梯度下降法的改进形式,这里给出SGDM;RMSProp;Adam三种梯度下降的改进方法,更简单的梯度下降法和Adagrad已经在感知机模型中给出:

舟晓南:感知机模型python复现 - 随机梯度下降法;梯度下降法;adagrad;对偶形式

持续更新其它梯度下降法改进形式,待更新:SWATS;AMSGrad;AdaBound;Cyclical LR;SGDR;One-Cycle LR;RAdam;Nadam;Lookahead等。


逻辑斯蒂回归 - SGDM:

接下来的SGDM;RMSProp;Adam三种梯度下降法的改进形式,基本上只需要将训练的部分修改一下就行,篇幅所限,这里仅贴出修改后的模型训练部分。

'''
逻辑斯蒂回归 - SGDM
-------------------------------------
数据集:Mnist
训练集数量:60000
测试集数量:10000
---------------------------------
训练结果:
迭代次数:400
训练时间:171s
测试时间:1s
正确率:0.86
'''

'''
逻辑斯蒂回归 - SGDM
--------------
输入:
data:训练集数据
label:训练集标记
itertime:迭代次数
-------------
输出:
w:最优化的权值向量
'''
def Logistic(data, label, itertime):
    
    # 初始化w
    FeatureNum = np.shape(data)[1]
    w = np.zeros(FeatureNum)
    
    # 设定学习率
    h = 0.001
    
    # 样本数
    SampleNum = len(data)
    
    # 将data转换成ndarray格式,方便后续的计算
    data = np.array(data)
    
    # 初始化动量
    momentum = np.zeros(FeatureNum)
    
    # 设置超参数,用于设置动量中对前一次动量和速度的依赖程度
    beita = 0.9
    
    # 迭代
    for i in range(itertime):
        
        # 初始化梯度
        v = np.zeros(FeatureNum)
        
        # 遍历每一个样本点
        for j in range(SampleNum):
            
            # 得到该样本的特征向量和标记
            xi = data[j]
            yi = label[j]
            
            # 如果分类错误,更新w_i
            if predict(w, xi) != yi:
                
                # 计算梯度
                exp_wxi = np.exp(np.dot(w,xi))
                v += xi * yi - (xi * exp_wxi) / (1 + exp_wxi)
                
        # 记录动量,其中beita是超参数
        momentum = beita * momentum + (1 - beita) * v

        # 更新w
        w += h * momentum

    return w

逻辑斯蒂回归 - RMSProp:

'''
逻辑斯蒂回归 - RMSProp
-------------------------------------
数据集:Mnist
训练集数量:60000
测试集数量:10000
---------------------------------
训练结果:
迭代次数:400
训练时间:157s
测试时间:0.59s
正确率:0.86
'''

'''
逻辑斯蒂回归 - RMSProp
--------------
输入:
data:训练集数据
label:训练集标记
itertime:迭代次数
-------------
输出:
w:最优化的权值向量
'''
def Logistic(data, label, itertime):
    
    # 初始化w
    FeatureNum = np.shape(data)[1]
    w = np.zeros(FeatureNum)
    
    # 设定学习率
    h = 0.001
    
    # 样本数
    SampleNum = len(data)
    
    # 将data转换成ndarray格式,方便后续的计算
    data = np.array(data)
    
    # 设置超参数,用于设置动量中对前一次动量和速度的依赖程度
    beita = 0.9
    
    # 初始化分母项
    v_i = np.zeros(FeatureNum)
    
    # 迭代
    for i in range(itertime):
        
        # 初始化梯度
        v = np.zeros(FeatureNum)
        
        # 遍历每一个样本点
        for j in range(SampleNum):
            
            # 得到该样本的特征向量和标记
            xi = data[j]
            yi = label[j]
            
            # 如果分类错误,更新w_i
            if predict(w, xi) != yi:
                
                # 计算梯度
                exp_wxi = np.exp(np.dot(w,xi))
                v += xi * yi - (xi * exp_wxi) / (1 + exp_wxi)
        
        # 梯度的均方根
        v2 = np.square(v)
        
        # 计算分母项
        v_i = beita * v_i + (1 - beita) * v2

        # 更新w
        w += h * v / (np.sqrt(v_i) + 1e-8)

    return w

逻辑斯蒂回归 - Adam:

'''
逻辑斯蒂回归 - Adam
-------------------------------------
数据集:Mnist
训练集数量:60000
测试集数量:10000
---------------------------------
训练结果:
迭代次数:400
训练时间:148s
测试时间:0.56s
正确率:0.85
'''

'''
逻辑斯蒂回归 - Adam
--------------
输入:
data:训练集数据
label:训练集标记
itertime:迭代次数
-------------
输出:
w:最优化的权值向量
'''
def Logistic(data, label, itertime):
    
    # 初始化w
    FeatureNum = np.shape(data)[1]
    w = np.zeros(FeatureNum)
    
    # 设定学习率
    h = 0.001
    
    # 样本数
    SampleNum = len(data)
    
    # 将data转换成ndarray格式,方便后续的计算
    data = np.array(data)
    
    # 设置超参数,用于设置动量中对前一次动量和速度的依赖程度
    beita1 = 0.9
    beita2 = 0.999
    
    # 初始化分母项
    v_i = np.zeros(FeatureNum)
    momentum = np.zeros(FeatureNum)
    
    # 迭代
    for i in range(itertime):
        
        # 初始化梯度
        v = np.zeros(FeatureNum)
        
        # 遍历每一个样本点
        for j in range(SampleNum):
            
            # 得到该样本的特征向量和标记
            xi = data[j]
            yi = label[j]
            
            # 如果分类错误,更新w_i
            if predict(w, xi) != yi:
                
                # 计算梯度
                exp_wxi = np.exp(np.dot(w,xi))
                v += xi * yi - (xi * exp_wxi) / (1 + exp_wxi)
        
        # 梯度的均方根
        v2 = np.square(v)
        
        # 计算分母项
        v_i = beita2 * v_i + (1 - beita2) * v2
        v_i_hat = v_i / (1 - np.power(beita2, i + 1))
        
        # 计算动量
        momentum = beita1 * momentum + (1 - beita1) * v
        momentum_hat = momentum / (1 - np.power(beita1, i + 1))

        # 更新w
        w += h * momentum_hat / (np.sqrt(v_i_hat) + 1e-8)

    return w

github:

如果觉得对您有帮助,还烦请点击下面的链接,帮忙github点个star~谢谢~

Zhouxiaonnan/machine-learning-notesandcode

欢迎关注专栏:

学习笔记:数据分析,机器学习,深度学习​zhuanlan.zhihu.com
2399ecb553dbdb9fea45515ab2a741d3.png

机器学习模型Python复现:

舟晓南:感知机模型python复现 - 随机梯度下降法;梯度下降法;adagrad;对偶形式

舟晓南:k近邻(KNN)模型python复现 - 线性扫描;带权值的近邻点优化方法

舟晓南:朴素贝叶斯(Bayes)模型python复现 - 贝叶斯估计;下溢出问题

舟晓南:决策树(Decision Tree)模型python复现 - ID3;C4.5;CART;剪枝

机器学习模型理论部分:

舟晓南:统计学习方法 - 感知机模型解读 | 数据分析,机器学习,学习历程全记录

舟晓南:统计学习方法 - 感知机模型的收敛性解读 | 数据分析,机器学习,学习历程全记录

舟晓南:统计学习方法 - k近邻模型解读 | 数据分析,机器学习,学习历程全记录

舟晓南:统计学习方法 - 朴素贝叶斯模型解读 | 数据分析,机器学习,学习历程全记录

舟晓南:统计学习方法 - 朴素贝叶斯之后验概率最大化的含义 | 数据分析,机器学习,学习历程全记录

舟晓南:统计学习方法 - 决策树,CART决策树解析 | 数据分析,机器学习,学习历程全记录

舟晓南:统计学习方法 - 逻辑斯蒂回归解析 | 数据分析,机器学习,学习历程全记录

舟晓南:统计学习方法 - 最大熵模型解析 | 数据分析,机器学习,学习历程全记录

舟晓南:统计学习方法 - 改进的迭代尺度法IIS解析 | 数据分析,机器学习,学习历程全记录

舟晓南:统计学习方法 - 线性可分支持向量机解析 | 数据分析,机器学习,学习历程全记录

舟晓南:统计学习方法 - 线性支持向量机解析 | 数据分析,机器学习,学习历程全记录

舟晓南:统计学习方法 - 非线性支持向量机解析 | 数据分析,机器学习,学习历程全记录

舟晓南:统计学习方法 - 序列最小最优化算法(SMO)解析 | 数据分析,机器学习,学习历程全记录

舟晓南:统计学习方法 - 提升算法Adaboost解析 | 数据分析,机器学习,学习历程全记录

舟晓南:统计学习方法 - 提升树算法解析 | 数据分析,机器学习,学习历程全记录

舟晓南:统计学习方法 - EM算法解析 | 数据分析,机器学习,学习历程全记录

MySQL:

舟晓南:转行数据分析师如何开始学习SQL | 工科生三个月转行数据分析学习心得

舟晓南:MySQL的执行逻辑和表的结构 | 数据分析学习历程全记录

舟晓南:MySQL优化查询1:索引及其使用技巧 | 数据分析学习历程全记录

舟晓南:MySQL优化查询2:如何查找低效率语句 | 数据分析学习历程全记录

舟晓南:MySQL优化查询3:explain和show profiles | 数据分析学习历程全记录

舟晓南:MySQL优化查询4:24种查询优化的具体方法 | 数据分析学习历程全记录

转行数据分析相关:

舟晓南:如何转行和学习数据分析 | 工科生三个月成功转行数据分析心得浅谈

舟晓南:求职数据分析师岗位,简历应该如何写?|工科生三个月成功转行数据分析心得浅谈


数据分析,机器学习学习社群正式启动~

需要学习资料,想要加入社群均可私信~

在这里会分享各种数据分析相关资源,技能学习技巧和经验等等~

详情私信,一起进步吧!

写于成都 2020-10-1

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值