LOGISTIC REGRESSION

本来第二篇博客本来是要介绍一些基本概念,但是要考试啊!!!只能简单做一做,但也不能敷衍大家。

逻辑回归
属于简单二分类问题,是绝大多数回归的基础思想体现,你能把我提供数据散点的绘制成scotter,就能发现得到的回归模型其实就是一条回归线,也是最简单的一种超平面。两端一定距离外为两类散点集中分布的区域。
算法思想的几何核心目标:可以这样理解为使得两类点(分别以0、1代表)中里回归线最近的两点到回归线的距离最大。数形结合,很久没听到了吧,高中数学老师经常提的。
理论上我们需要的回归线方程为Wx+b=0,要注意这里W b是权重、偏置的向量,并非一个简单单值随机变量。
一般为了实现样本的映射至正确类别需要使用阈值函数sigmoid函数
(RELU、双曲正切据说效果更不错,你们也可以试试)
f(x)=1.0/1+exp(-x),只要训练好了W 、b的值,代入即可得到某样本的所属二分类别的概率,最终多取两者的较大者。概率公式如下,二者和为1:
P(r=1|X、W、b)=exp(-Wx+b)/(1+exp(-Wx+b))
P(r=0|X、W、b)=1/(1+exp(-Wx+b)),
之后用h代替exp(-Wx+b)
那如何训练得到一组好的权重、偏置参数呢,实质我们需要是利用大样本进行极大似然估计的方法,学过数理统计学的小伙伴是不是不陌生了。
我们可以构造似然函数然后取对数吧哈哈哈哈。
Lw,b=∏h^y(i) ×(1-h)^(1-y(i))
但接下可不是求偏导得似然方程的解。不然不就纯粹统计方法对吧。
Jw,b=ln(Lw,b)=-1/m×[y(i)log(h)+(1-y(i)log(1-h)],
这就是我们训练需要误差函数。
m是样本数量,y(i)是某个样本的预测值(只取0/1)。
类似与(1-x)log(x)+xlogx,是不是很像信息熵公式,这就是一种数学的广泛适用性的美丽所在。其实我们就是衡量预测分布、实际分布的相似度,误差最小也就是二者最为接近。
算法名义目标:J(w ,b)最小对应的W,b,数学上常用argmin 符号来denote,预测结果误差与实际分布误差最好接近0。
实际对于高维多分类数据用处不大的。当然你可以人工数据处理特征、或者会因子分解机就另当别论了。
后续的梯度下降求解优化参数方法就没啥好说了,个人理解。无非就凸优化下的偏导更新问题,这种方法常用,但不是唯一更不是最好的。后续这块我会重点介绍。
所以机器学习,不能不学好数学啊,否则就是一碰原理就是泰勒雅克比柯西费马懵逼啊
在这里插入图片描述

重点
网上原有的逻辑回归代码早已成堆飞满天,基本都是PYTHON2.0的版本,要在PYTHON3.0中运行还是有不少BUG的,我把99%BUG修复了,并增加很多注释供初学者参考,还有的靠你自己喽。如果需要数据集可以去我的资源也下载。
用途

判断某个人看到网页是否点击、某人去不去某地;
与非监督学习(聚类为主)结合,形成一个最终辅助型的分类器

个人思考
1.现有的机器学习、深度学习技术并没有想象中那么智能,XX%只是一个大概率找到近似精确解的好用工具。如果偏置、权重初始值都能智能推荐,那或许在智能化方面就进了一大步。
2.不应该过分要求误差过小,否则无法及时收敛,或者模型泛化能力不够。
3.误差小不一定好,我觉得还得看训练集、验证集的数据优劣、重要性、信度、时效性。一般会认为它们居于一个水平。但实际或许不一样,看大家自己的理解了。
4.引用我一位刘姓师兄的话:目前的深度学习,都是一种实际的数据库索引函数算法的包装。
5.数据驱动,有很多问题解决不了,更优质的方法,是模型+试验+数据
其实我们数据来源就是一次次自然(驾驶)试验的结果,我们得到它们,是省去了对试验步骤,试验要求的观测记录,而直接利用结果,自然也就得承受数据驱动后患,这是种辩证的因果关系。
代码如下:,涉及的特征只有2个。

# coding:UTF-8
'''
Date:20190105/20160901
@ORIGIN _author: zhaozhiyong
@XFXZ modify   for python 3.0
'''
import numpy as np

def load_data(file_name):
    '''导入训练数据
    input:  file_name(string)训练数据的位置
    output: feature_data(mat)特征
            label_data(mat)标签
    '''
    f = open(file_name)  # 打开文件,如果不和python一个目录,请加入路径
    feature_data = []
    label_data = []
    
    for line in f.readlines():
        feature_tmp = []
        lable_tmp = []
        lines = line.strip().split("\t")    # 去除每行前后空格,并区分空格符,将每行内容存为列表
        feature_tmp.append(1)  # 偏置项,后期需要调整
        
     for i in range(len(lines) - 1):
        feature_tmp.append(float(lines[i]))
        lable_tmp.append(float(lines[-1]))   #直接定位最后一个列表元素
        
        feature_data.append(feature_tmp)
        label_data.append(lable_tmp)
    f.close()  # 关闭文件
    return np.mat(feature_data), np.mat(label_data)  #mat变为矩阵

def sig(x):
    '''Sigmoid函数
    input:  x(mat):feature * w
    output: sigmoid(x)(mat):Sigmoid值
    '''
    return 1.0 / (1 + np.exp(-x))    #输入元素可以为数字、矩阵、列表均可

def lr_train_bgd(feature, label, maxCycle, alpha):   #函数为普通的形参函数,未设定默认参数
    '''利用梯度下降法训练LR模型
    input:  feature(mat)特征
            label(mat)标签
            maxCycle(int)最大迭代次数
            alpha(float)学习率
    output: w(mat):权重矩阵
    '''
    n = np.shape(feature)[1]  # 特征个数,feature的列数就是特征数,PYTHON 索引,0开始/-1结束
    w = np.mat(np.ones((n, 1)))  # 初始化权重,生成n行,1列矩阵存储
    i = 0
    while i <= maxCycle:  # 在最大迭代次数的范围内
        i += 1  # 当前的迭代次数加1
        h = sig(feature * w)  # 计算Sigmoid值
        err = label - h    # 计算当前误差
        if i % 100 == 0:
            print( "\t---------iter=" + str(i) + \
            " , train error rate= " + str(error_rate(h, label)))  #100次后输出当前误差
        w = w + alpha * feature.T * err  # 权重修正      #alpha是学习率,可固定,也可以随迭代次数而递减,feature(1*N)需要转置才可以而error(N*1)矩阵作乘积,保证维度一致
    return w

def error_rate(h, label):
    '''计算当前的损失函数值
    input:  h(mat):预测值
            label(mat):实际值
    output: err/m(float):错误率
    '''
    m = np.shape(h)[0]
    
    sum_err = 0.0
    for i in range(m):   #python2都是xrange,我都改回来了range
        if h[i, 0] > 0 and (1 - h[i, 0]) > 0:
            sum_err -= (label[i,0] * np.log(h[i,0]) + \
                        (1-label[i,0]) * np.log(1-h[i,0]))    #实质信息熵的公式,衡量h预测与label实际分布的差异,对符合条件条件才进行,-=代表x=x-
        else:
            sum_err -= 0
    return sum_err / m            #平均损失率

def save_model(file_name, w):
    '''保存最终的模型
    input:  file_name(string):模型保存的文件名
            w(mat):LR模型的权重
    '''
    m = np.shape(w)[0]
    f_w = open(file_name, "w")   #自己定义写入的文件名喽,如已经存在将必须替换原来的,没有则新建,,'w'
    w_array = []
    for i in range(m):
        w_array.append(str(w[i, 0]))
    f_w.write("\t".join(w_array))  #join连接字符串数组。将字符串、元组、列表中的元素以指定的字符(分隔符)连接生成一个新的字符串
    f_w.close()           

if __name__ == "__main__":   #前面都是定义,以下为代码段,不可放到前面,if__name__=="__main__"表示执行当前PYTHON文件代码的模块,而非导入的模块
    # 1、导入训练数据
    print "---------- 1.load data ------------"
    feature, label = load_data("data.txt")
    # 2、训练LR模型
    print "---------- 2.training ------------"
    w = lr_train_bgd(feature, label, 1000, 0.01)
    # 3、保存最终的模型
    print "---------- 3.save model ------------"
    save_model("weights", w)    #恕我直言可能有BUG,小问题留给你自己解决,不要当完全的伸手党,那样难以进步。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值