logistic回归——PYTHON实现

概述:

logistic回归又称logistic回归分析,是一种线性回归模型。logistic回归应用最广泛的是处理二分类问题。比如,探讨引发疾病的危险因素,判断该病人是否患有该病;探讨房价的涨跌,进而给出在何时购买房子的最优决策。在logistic回归中,自变量可以是连续的,也可以是分立的。

​ 以预测房价涨跌为例,选择两种不同类型的房子,一种是涨价组,另一组是非涨价组,两组房子必定具有不同的占地面积、房屋位置、建筑年限等特征,因此因变量为是否涨价,自变量可以包括很多不同的特征,比如所在城市、占地面积等不同特征。

​ 通过logistic回归,可以得到自变量的权重,从而大致了解影响疾病发作、股票走势、房价涨跌的因素,同时根据这些权重值,预测发生某件事情的可能性。

​ 本文首先会介绍logistic回归所用到的基本的数学知识,接着会给出logistic回归在PYTHON中的编程实现。最后,会在大众比较熟悉且感兴趣的领域——股票预测方面应用logistic回归,观察其在量化投资方面的应用

logistic回归与线性回归:

​ logistic回归与线性回归均属于广义的线性模型,只不过logistic回归将输出又输入到sigmoid函数中,通过引入非线性因素,给出二分类问题中不同类别的概率值。

logistic回归所用到的基本数学原理:

​ 首先,与一般的机器学习算法一样,在输入参数时,首先应该选择输入的特征。比如,在预测房屋价格涨跌时,房屋面积可能是一个比较优秀的特征选择,而房屋所处小区的保安年龄可能就不是一个好的特征选择。因为特征提取、特征选择等特征工程是机器学习中的另一研究问题,本文在此不做赘述,仅选择能够获取到的数据当作其特征。

​ 选取好特征后,我们就可以构建一个线性函数:
y = w 0 + w 1 x 1 + w 2 x 2 + . . . + w k x k y = w_0+w_1x_1+w_2x_2+...+w_kx_k y=w0+w1x1+w2x2+...+wkxk
其中, w w w 为我们要寻找的各个参数值 x x x 为我们选取的各个特征值

​ 此时,假设我们已经寻找到所有 w w w 值,则可以将特征空间 x 1 , x 2 , . . . , x k x_1,x_2,...,x_k x1,x2,...,xk 上样本的特征值通过 w 1 , w 2 , . . . , w k w_1,w_2,...,w_k w1,w2,...,wk 映射到值域空间 y y y 上,但此时 y y y 可能为某巨大的数,也可能为某负数,因此,我们引入一个非线性函数,将 y y y映射 ( 0 , 1 ) (0,1) (0,1) 范围内的一个值。sigmoid函数如下图所示。

在这里插入图片描述s

`于是,我们就建立了概率值 P P P y y y关系:
l n ( P 1 − P ) = y P = e y 1 + e y ln(\frac{P}{1-P})=y \\ P=\frac{e^y}{1+e^y} ln(1PP)=yP=1+eyey
​ 最终,我们就可以通过这样一个计算计算出某个类别的概率值:
在这里插入图片描述

​ 但是,目前我们只是应用了 W W W 的值,我们并没有通过大量样本计算其值。因此,我们引入一个新的概念——梯度下降,来计算,准确来说是纠正这个向量的值。

​ 梯度下降法,顾名思义,计算过程就是沿梯度下降的方向求解极小值。

​ 现在我们又有一个问题,何为极小值?准确来说,这个值到底是怎么算出来的?在机器学习中,对于每个算法,我们都会引入一个函数,称其为代价函数。该代价函数衡量了我们训练的模型的好坏,衡量了这个算法的性能。代价函数最小为0,最大为正无穷,当代价函数为0时,该算法在训练集上的准确度为100%,但我们在训练时不应让代价函数为0,因为当代价函数为0时,模型会将训练集中的噪声也学习进去,因而在测试集上可能表现并不好。

​ 介绍完代价函数的作用,代价函数到底该怎么选取?对于一般的拟合模型,在不考虑噪声的情况下,最优的结果即为通过那些点的一条曲线。当通过这些点时,拟合值与真实值相等,形象的说就是目标与当前所处位置重合。因此,在定义代价函数时,我们遵循的是:目前状态与当前状态之间的距离差。(该处类似于评估模型TOPSIS法中某方案与最优方案的相对接近程度,也就是TOPSIS中的评估值)

​ 对于这个问题,我们先定义一个样本的损失函数如下:
L ( y ^ , y ) = − y l o g ( y ^ ) − ( 1 − y ) l o g ( 1 − y ^ ) L(\hat{y},y)=-ylog(\hat{y})-(1-y)log(1-\hat{y}) L(y^,y)=ylog(y^)(1y)log(1y^)
​ 然后定义算法的代价函数如下:
J ( w ) = 1 k ∑ L ( y ^ ( i ) , y ( i ) ) J(w)=\frac{1}{k}\sum{L(\hat{y}^{(i)},y^{(i)})} J(w)=k1L(y^(i),y(i))
​ 该代价函数衡量了训练集整体的混乱度,即信息熵

所以,梯度下降法就是沿着梯度的方向,寻找一个最优的权重向量 W W W ,使得代价函数的函数值最小(但不是越小越好)。

​ 至此,我们介绍完了logistic回归所要应用的所有数学公式。下面,展示logistic编程与调包。

编程:

# -*- coding: utf-8 -*-
import numpy as np

class Logistic():
    def __init__(self):
        # 生成训练样本,其中a为特征值,b为标签
        a=[[0.50, 0.75, 1.00, 1.25, 1.50, 1.75, 1.75, 2.00, 2.25,2.50, 2.75, 3.00, 3.25, 3.50, 4.00, 4.25, 4.50, 4.75, 5.00, 5.50]]
        a=np.array(a)
        a=a.T
        ones=np.ones((a.shape[0],1))

        a=np.column_stack((ones,a))
        b=[[0,0,0,0,0,0,0,0,1,0,0,1,1,1,1,1,1,1,1,1]]
        b=np.array(b)
        b=b.T
        self.data_set=a
        self.data_target=b
        self.feature_size=self.data_set.shape[1]
        self.number_size=self.data_set.shape[0]
        self.W=np.random.randn(self.feature_size)
        pass

    def LG_Linear(self):
        #线性层,将特征空间映射为值域空间
        y=np.dot(self.data_set,self.W.transpose())
        y=np.array([y])
        y=y.T
        return y
        pass

    def LG_sigmoid(self,y):
        #非线性层,将值域空间映射为(0,1)
        P=np.exp(y)/(1+np.exp(y))
        return P
        pass

    def LG_cost(self,P,target):
        #损失函数
        cost=-target*np.log(P)-(1-target)*np.log(1-P)
        return cost
        pass

    def BP(self,P,target):
        #反向传播函数
        learningrate=0.05
        for i in range(self.number_size):
            dz=P[i][0]-target[i][0]
            #dz为代价函数求导所得
            dw=self.data_set[i][:]*dz
            self.W=self.W-learningrate*dw
            print(self.W)
        return self.W
        pass

    def predict(self,x):
        #预测函数
        pre=np.dot(self.W,x.transpose())
        pre=self.LG_sigmoid(pre)
        return pre
        pass
    pass
def main():
    lg=Logistic()
    y=lg.LG_Linear()
    P=lg.LG_sigmoid(y=y)
    # lg.LG_cost(P=P,target=lg.data_target)
    for _ in range(10):
        lg.BP(P=P,target=lg.data_target)
    pre=lg.predict(np.array([[1,5]]))
    print(lg.W)
    print(pre)
    pass


if __name__ == '__main__':
    main()

调包:

# -*- coding: utf-8 -*-

# 导包
import numpy as np
from sklearn.linear_model import LogisticRegression

# 加载数据

a = [[0.50, 0.75, 1.00, 1.25, 1.50, 1.75, 1.75, 2.00, 2.25, 2.50, 2.75, 3.00, 3.25, 3.50, 4.00, 4.25, 4.50, 4.75, 5.00,
      5.50]]
a = np.array(a)
a = a.T
b = [[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1]]
b = np.array(b)
b = b.T
x=a
y=b

lr = LogisticRegression()

# 训练数据
lr.fit(x,y)

#求出w斜率和b截距的值
w = lr.coef_
b = lr.intercept_
print(w, b)

# 预测一下概率
predict= lr.predict_proba([[3]])
print(predict)
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐