理解并应用Logistic回归:一种实用的机器学习技术

      随着数据科学的不断发展,机器学习已经成为我们日常生活的一部分。今天,我想分享一下我对Logistic回归的理解和应用。Logistic回归是一种用于分类问题的统计方法,特别适用于二分类问题。

一、Logistic回归简介

  • logistics回归=线性回归+sigmoid函数。
  • 线性回归的形式z=w*x+b 
  • sigmoid函数  y=\frac{1}{1+e^{-z}}  将回归模型的连续的值映射到[0,1]之间,划分为离散的分类标准。 以下为sigmoid函数图像。
  • 对于二分类问题,当z>0.5时,归为1,z<0.5时,归为0.
  • 那么logistics回归的总体公式就是:y=\frac{1}{1+e^{-w*x+b}} 

       Logistic回归是一种广义线性模型,它通过一个转换函数将预测变量的线性组合转换为概率值。这个转换函数是逻辑函数,即S型曲线。因此,Logistic回归主要用于二分类问题,它可以处理分类变量和连续变量,同时也可以处理分类变量之间的相互作用。

二、Logistic回归的优点和缺点

Logistic回归的优点包括:

  1. 模型简单,易于实现。
  2. 结果易于解释。
  3. 可以处理不同类型的输入变量,包括连续变量和类别变量。
  4. 通过输出概率,提供了决策阈值的灵活性。

不过,Logistic回归也有其局限性:

  1. 假设特征和输出之间有线性关系。
  2. 对于非线性问题,可能需要特征工程来提高模型性能。
  3. 对于有多个类别的分类问题,需要进行扩展,如使用一对多或多项式Logistic回归

三、最佳回归系数的确定(极大似然估计+最优化方法)

       上一节我们已经确定了logisti分类函数,有了分类函数,我们输入特征向量就可以得出实例属于某个类别的概率。但这里有个问题,权重w(回归系数)我们是不确定的。正如我们想的那样,我们需要求得最佳的回归系数,从而使得分类器尽可能的精确。

       如何才能获得最佳的回归系数呢?这里就要用到最优化方法。前面我们提到过某件事情发生的概率为p,在logistics回归中所定义的损失函数就是定义一个似然函数做概率的连乘,数值越大越好,也就是某个样本属于其真实标记样本的概率越大越好。如,一个样本的特征x所对应的标记为1,通过逻辑斯蒂回归模型之后,会给出该样本的标记为1和为-1的概率分别是多少,我们当然希望模型给出该样本属于1的概率越大越好。既然是求最大值,那我们用到的最优化算法就是梯度上升,其实也就是与梯度下降相反而已。

  • 对于多分类问题: 

四、梯度上升法

梯度上升法基于的思想是:要找到某函数的最大值,最好的方法是沿着该函数的梯度方向探寻。如果梯度记为∇ ,则函数f(x,y)的梯度由下式表示:
                                        ▽f(x,y)=(\frac{\sigma f(x,y)}{\sigma x},\frac{\sigma f(x,y)}{\sigma y})

这个梯度意味着要沿x的方向移动▽\frac{\sigma f(x,y)}{\sigma x},沿y的方向移动▽\frac{\sigma f(x,y)}{\sigma y}。其中,函数f(x,y)必须要在待计算的点上有定义并且可微。一个具体的函数例子见下图。

         梯度上升算法到达每个点后都会重新估计移动的方向。从P0开始,计算完该点的梯度,函数就根据梯度移动到下一点P1。在P1点,梯度再次被重新计算,并沿新的梯度方向移动到P2.如此循环迭代,知道满足通知条件。迭代的过程中,梯度算子总是保证我们能选取到最佳的移动方向。

       上图中的梯度上升算法沿梯度方向移动了一步。可以看到,梯度算子总是指向函数值增长最快的方向。这里所说的是移动方向,而未提到移动量的大小。该量值称为步长,记作α 。用向量来表示的话,梯度上升算法的迭代公式如下:

                                              w=w+α▽wf(w)

该公式将一直迭代执行,直至达到某个停止条件为止,b比如迭代次数达到某个值或者算法达到某个可以允许的误差范围。

五、代码实现

import pandas as pd
# pd.read_csv("https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin.data")


# -*- coding:UTF-8 -*-
# {{{
import matplotlib.pyplot as plt
import numpy as np


# 加载波士顿房屋数据集
data_url = "boston.csv"
raw_df = pd.read_csv(data_url, sep="\s+", skiprows=22, header=None)
dataMat = np.hstack([raw_df.values[::2, :], raw_df.values[1::2, :2]])
labelMat = raw_df.values[1::2, 2]


def sigmoid(inX):
    return 1.0 / (1 + np.exp(-inX))


def gradAscent(dataMatIn, classLabels):
    """
    梯度上升算法

    :param dataMatIn: 数据矩阵
    :param classLabels: 标签矩阵
    :return: 最有参数数组
    """
    dataMatrix = np.mat(dataMatIn)
    """ 转置 """
    labelMat = np.mat(classLabels).transpose()

    """ 获取矩阵行数 m 和列数 n """
    m, n = np.shape(dataMatrix)
    """ 迭代步长 """
    alpha = 0.001
    """ 迭代次数 """
    maxCycles = 500
    # 初始化权重为全1的矩阵
    weights = np.ones((n, 1))
    '''在梯度下降算法中,我们计算的是误差函数关于权重的梯度(或者叫偏导数),并将其乘以学习率来更新权重。这里有两种常见的更新权重的方式: 1.
    直接使用误差与学习率的乘积来更新权重:'''
    for k in range(maxCycles):
        """ 带入数学公式求解 """
        h = sigmoid(dataMatrix * weights)
        # 更新权重,这里使用了dataMatrix的转置与误差相乘,然后乘以学习率alpha
        weights = weights + alpha * dataMatrix.transpose() * (labelMat - h)
    """ 转换为 array """
    return weights.getA()


def plotBestFit(weights):
    """
    绘制数据集与结果分类线

    :param weights: 权重参数数组
    :return:
    """
    # dataMat, labelMat = loadDataSet()
    dataArr = np.array(dataMat)

    """ 数据个数 """
    n = np.shape(dataMat)[0]

    """ 测试数据两组分类结果集 """
    xcord1 = []
    ycord1 = []
    xcord2 = []
    ycord2 = []

    """ 对数据进行分类 """
    for i in range(n):
        if int(labelMat[i]) == 1:
            xcord1.append(dataArr[i, 1])
            ycord1.append(dataArr[i, 2])
        else:
            xcord2.append(dataArr[i, 1])
            ycord2.append(dataArr[i, 2])

    """ 绘图 """
    fig = plt.figure()
    """ 分割画布为一整份,占据其中一整份 """
    ax = fig.add_subplot(111)
    """ 离散绘制分类结果为 1 的样本 """
    ax.scatter(xcord1, ycord1, s=20, c='red', marker='s', alpha=.5)
    """ 离散绘制分类结果为 0 的样本 """
    ax.scatter(xcord2, ycord2, s=20, c='green', alpha=.5)
    x1 = np.arange(-3.0, 3.0, 0.1)
    x2 = (-weights[0] - weights[1] * x1) / weights[2]
    ax.plot(x1, x2)
    plt.title('BestFit')
    plt.xlabel('X1')
    plt.ylabel('X2')
    plt.show()


if __name__ == '__main__':
    # dataMat, labelMat = loadDataSet()
    weights = gradAscent(dataMat, labelMat)
    plotBestFit(weights)
# }}}

结果为: 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值