ML入门4.0 手写逻辑斯蒂回归 (Logistic Regression)

逻辑斯蒂回归简介

Logistic Regression 即对数概率回归,是一种广义的线性回归分析模型,是一种应用于二分类问题的分类算法
常用于数据挖掘,疾病自动诊断,经济预测等领域。例如,探讨引发疾病的危险因素,并根据危险因素预测疾病发生的概率等。以胃癌病情分析为例,选择两组人群,一组是胃癌组,一组是非胃癌组,两组人群必定具有不同的体征与生活方式等。因此因变量就为是否胃癌,值为“是”或“否”,自变量就可以包括很多了,如年龄、性别、饮食习惯、幽门螺杆菌感染等。自变量既可以是连续的,也可以是分类的。然后通过logistic回归分析,可以得到自变量的权重,从而可以大致了解到底哪些因素是胃癌的危险因素。同时根据该权值可以根据危险因素预测一个人患癌症的可能性。百度百科

原理简介

逻辑回归解决二分类问题,所谓分类就是分割数据,那么逻辑回归的本质就是通过在数据集中学习,拟合出分类的决策边界(决策函数)

决策边界

两个条件属性(二维平面直角座标系中)决策边界为直线
三个条件属性(三维空间直角座标系中)决策边界为平面
四个条件属性(四维座标系中)决策边界为超平面

线性分割面的表达

二维:w0x0+w1x1+w2x2=0w_{0}x_{0} + w_{1}x_{1} + w_{2}x_{2} = 0 (PS:x01x_{0} \equiv 1

三维:w0x0+w1x1+w2x2+w3x3=0w_{0}x_{0} + w_{1}x_{1} + w_{2}x_{2} + w_{3}x_{3} = 0

四维:w0x0+w1x1+w2x2+w3x3+w4x4=0w_{0}x_{0} + w_{1}x_{1} + w_{2}x_{2} + w_{3}x_{3} + w_{4}x_{4} = 0

向量表达:
n维:XW\boldsymbol X \boldsymbol W (X为行向量,W为列向量)

学习与分类

Logistic Regression 的回归任务就是计算向量W
二分类:对于新的对象X’,计算X’W:结果小于0则为0类,否则为1类

损失函数

定义:度量预测结果和实际结果之间的差别

第一种损失函数

X={x1,...,xm}X=\{x_{1},...,x_{m}\} ,

MSE =1mi=1mH(xiw)yi\frac{1}{m}\sum_{i=1}^{m}|H(x_{i}w)-y{i}|

其中H(z)={0if z<012if z=01otherwise H(z)= \begin{cases} 0& \text{if z<0}\\ \frac{1}{2}& \text{if z=0}\\ 1& \text{otherwise} \end{cases}

H(xiw)H(x_{i}w)就是分类函数给出的标签,yiy_{i}是真实标签

优点:表达了错误率
缺点:函数H不连续,无法使用优化理论

第二种损失函数

MSE =1mi=1m12(yi^yi)2\frac{1}{m}\sum_{i=1}^{m}\frac{1}{2}(\widehat{y_{i}}-y_{i})^2

其中 yi^=σ(xiw)\widehat{y_{i}}=\sigma(x_{i}w),

σ(z)=11+ez\sigma(z) = \frac{1}{1+e^{-z}} ;

σ(z)=σ(z)(1σ(z))\sigma(z)' = \sigma(z)(1-\sigma(z))
在这里插入图片描述

缺点:非凸优化,多个局部最优解

第三种损失函数

因为0<σ(z)<10 < \sigma(z) < 1, 所以将分类函数强行看作概率。
假设:

P(yi=1xi;w)=σ(xiw)P (y_{i} = 1|x_{i}; w) = σ(x_{i}w)
$P (y_{i} = 0|x_{i}; w) = 1 - σ(x_{i}w)

综合两式可得
P(yixi;w)=(σ(xiw))yi(1σ(xiw))1yiP (y_{i}|x_{i}; w) = (σ(x_{i}w))^{y_{i}} (1 − σ(x_{i}w))^{1−y_{i}}

由此获得似然函数:

L(w)=P(YX;w)=i=1m(σ(xiw))yi(1σ(xiw))1yiL(w) = P (Y|X; w)=\prod_{i=1}^{m}(σ(x_{i}w))^{y_{i}} (1 − σ(x_{i}w))^{1−y_{i}}

因为log具有单调性

l(w)=logL(w)l(w) = log L(w)

优化目标为 :

minw1mi=1myilogσ(xiw)(1yi)log(1σ(xiw))min_{w}\frac{1}{m}\sum_{i=1}^{m} −y_{i}logσ(x_{i}w) − (1 − y_{i}) log(1 − σ(x_{i}w))

梯度下降法

l(w)wj=i=1m(yiσ(xiw))xij\frac{∂l(w)} {∂wj}=\sum_{i=1}^{m}(y_{i} − σ(x_{i}w))x_{ij}

通过求得优化目标的方向导数(梯度),来确定函数下降的最快方向,由此来更新W以获得最佳W

代码实现

Func1: LoadDataSet(paraFileName)加载数据集

def LoadDataSet(paraFileName):
    '''
    LoadDataSet
    :param paraFileName:
    :return: 特征&标签
    '''
    dataMat = []
    labelMat = []
    txt = open(paraFileName)
    for line in txt.readlines():
        tempValuesStringArray = np.array(line.replace("\n", "").split(','))
        tempValues = [float(tempValue) for tempValue in tempValuesStringArray]
        tempArray = [1.0] + [tempValue for tempValue in tempValues] # 相当于w0对应的x0
        tempX = tempArray[:-1]
        tempY = tempArray[-1]
        dataMat.append(tempX)
        labelMat.append(tempY)

    return dataMat, labelMat

Func2: sigmoid(paraX)分类函数实现

def sigmoid(paraX):
    '''
    sigmoid函数实现
    :param paraX:参数
    :return: 计算结果
    '''
    return 1.0/(1 + np.exp(-paraX))

Func3: gradAscent(dataMat, labelMat)梯度上升法(因为取了优化目标的相反数,所以要求上升最快的方向)求W

def gradAscent(dataMat, labelMat):
    '''
    用梯度上升法求得最优权重
    :param dataMat:
    :param labelMat:
    :return:
    '''
    X = np.mat(dataMat)
    Y = np.mat(labelMat) #transfer the input to matrix
    Y = Y.transpose()
    m, n = np.shape(X)
    alpha = 0.001 # 学习步长
    maxCycles = 1000
    W = np.ones( (n,1))
    for i in range(maxCycles):
        y = sigmoid(X * W)
        error = Y - y
        W = W + alpha * X.transpose() * error

    return W

Func4: STLogisticClassifierTest ()手写分类器

def STLogisticClassifierTest():
    '''
    Logistic 分类器
    '''
    X, Y = LoadDataSet('iris2condition2class.csv')

    tempStartTime = time.time()
    tempScore = 0
    numInstances = len(Y)
    weights = gradAscent(X, Y)

    tempPredicts = np.zeros((numInstances))

    for i in range(numInstances):
        tempPrediction = X[i] * weights
        if tempPrediction > 0:
            tempPredicts[i] = 1
        else:
            tempPredicts[i] = 0

    tempCorrect = 0
    for i in range(numInstances):
        if tempPredicts[i] == Y[i]:
            tempCorrect += 1

    tempScore = tempCorrect / numInstances
    tempEndTime = time.time()
    tempRunTime = tempEndTime - tempStartTime

    print('STLogistic Score: {}, runtime = {}'.format(tempScore, tempRunTime))

    rowWeights = np.transpose(weights).A[0]
    plotBestFit(rowWeights)

运行结果

在这里插入图片描述
在这里插入图片描述

GitHub地址

完整代码和数据集见github.

优缺点

优点:
1.适合需要得到一个分类概率的场景。2.计算代价不高,容易理解实现。LR在时间和内存需求上相当高效。它可以应用于分布式数据,并且还有在线算法实现,用较少的资源处理大型数据。3.LR对于数据中小噪声的鲁棒性很好,并且不会受到轻微的多重共线性的特别影响。

缺点
1.容易欠拟合,分类精度不高。2.数据特征有缺失或者特征空间很大时表现效果并不好。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章