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

逻辑斯蒂回归简介

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

原理简介

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

决策边界

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

线性分割面的表达

二维: w 0 x 0 + w 1 x 1 + w 2 x 2 = 0 w_{0}x_{0} + w_{1}x_{1} + w_{2}x_{2} = 0 (PS: x 0 1 x_{0} \equiv 1

三维: w 0 x 0 + w 1 x 1 + w 2 x 2 + w 3 x 3 = 0 w_{0}x_{0} + w_{1}x_{1} + w_{2}x_{2} + w_{3}x_{3} = 0

四维: w 0 x 0 + w 1 x 1 + w 2 x 2 + w 3 x 3 + w 4 x 4 = 0 w_{0}x_{0} + w_{1}x_{1} + w_{2}x_{2} + w_{3}x_{3} + w_{4}x_{4} = 0

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

学习与分类

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

损失函数

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

第一种损失函数

X = { x 1 , . . . , x m } X=\{x_{1},...,x_{m}\} ,

MSE = 1 m i = 1 m H ( x i w ) y i \frac{1}{m}\sum_{i=1}^{m}|H(x_{i}w)-y{i}|

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

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

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

第二种损失函数

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

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

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

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

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

第三种损失函数

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

P ( y i = 1 x i ; w ) = σ ( x i w ) P (y_{i} = 1|x_{i}; w) = σ(x_{i}w)
$P (y_{i} = 0|x_{i}; w) = 1 - σ(x_{i}w)

综合两式可得
P ( y i x i ; w ) = ( σ ( x i w ) ) y i ( 1 σ ( x i w ) ) 1 y i P (y_{i}|x_{i}; w) = (σ(x_{i}w))^{y_{i}} (1 − σ(x_{i}w))^{1−y_{i}}

由此获得似然函数:

L ( w ) = P ( Y X ; w ) = i = 1 m ( σ ( x i w ) ) y i ( 1 σ ( x i w ) ) 1 y i L(w) = P (Y|X; w)=\prod_{i=1}^{m}(σ(x_{i}w))^{y_{i}} (1 − σ(x_{i}w))^{1−y_{i}}

因为log具有单调性

l ( w ) = l o g L ( w ) l(w) = log L(w)

优化目标为 :

m i n w 1 m i = 1 m y i l o g σ ( x i w ) ( 1 y i ) l o g ( 1 σ ( x i w ) ) 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 ) w j = i = 1 m ( y i σ ( x i w ) ) x i j \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.数据特征有缺失或者特征空间很大时表现效果并不好。

猜你喜欢

转载自blog.csdn.net/weixin_39956363/article/details/106330041