机器学习:Logistic回归介绍

Logistic回归定义

简单来说, 逻辑回归(Logistic Regression)是一种用于解决二分类(0 or 1)问题的机器学习方法,用于估计某种事物的可能性。比如某用户购买某商品的可能性,某病人患有某种疾病的可能性,以及某广告被用户点击的可能性等。 注意,这里用的是“可能性”,而非数学上的“概率”。logisitc回归的结果并非数学定义中的概率值,不可以直接当做概率值来用。该结果往往用于和其他特征值加权求和,而非直接相乘。通过给定的n组数据(训练集)来训练模型,并在训练结束后对给定的一组或多组数据(测试集)进行分类。其中每一组数据都是由p 个指标构成。

这里举一个例子来说明Logistic回归处理数据并对其进行二分类的过程。

我们给出一个人的 [身高,体重] 这两个指标,然后判断这个人是属于”胖“还是”瘦“这一类。对于这个问题,我们可以先测量n个人的身高、体重以及对应的指标”胖“,"瘦”,把胖和瘦分别用0和1来表示,把这n组数据输入模型进行训练。训练之后再把待分类的一个人的身高、体重输入模型中,看这个人是属于“胖”还是“瘦”。

如果数据是有两个指标,可以用平面的点来表示数据,其中一个指标为x轴,另一个为y轴;如果数据有三个指标,可以用空间中的点表示数据;如果是p维的话(p>3),就是p维空间中的点。

从本质上来说,逻辑回归训练后的模型是平面的一条直线(p=2),或是平面(p=3),超平面(p>3)。并且这条线或平面把空间中的散点分成两半,属于同一类的数据大多数分布在曲线或平面的同一侧。

如上图所示,其中点的个数是样本个数,两种颜色代表两种指标。这个直线可以看成经这些样本训练后得出的划分样本的直线。那么对于之后的样本的p1与p2的值,就可以根据这条直线来判断它属于哪一类了。

基于Logistic回归和Sigmoid函数的分类

首先,我们处理二分类问题。由于分成两类,我们便让其中一类标签为0,另一类为1。我们需要一个函数,对于输入的每一组数据,都能映射成0~1之间的数。并且如果函数值大于0.5,就判定属于1,否则属于0。而且函数中需要待定参数,通过利用样本训练,使得这个参数能够对训练集中的数据有很准确的预测。

这个函数就是Sigmoid函数,形式为\sigma (z)=\frac{1}{1+e^{-z}}。其函数曲线如下:

从上图可以看到sigmoid函数是一个s形的曲线,它的取值在[0, 1]之间,在远离0的地方函数的值会很快接近0或者1。它的这个特性对于解决二分类问题十分重要。

Sigmoid函数的输入记为z,z=w^{T}x+b,其中向量x是分类器的输入数据,向量w也就是我们要找到的最佳系数,b为常数。代入Sigmoid函数中得到\sigma (z)=\frac{1}{1+e^{-(w^{T}+b)}}

至此我们便可以输入数据代入z中再由Sigmoid函数映射到0~1之间,得到一个这样的数值之后就可以进行分类,大于0.5的分入1类,反之分入0类。

现在的问题就在于最佳回归系数是多少?即w和b。

基于最优化方法的最佳回归系数确定

确定最佳回归系数的最优化方法有梯度下降法与梯度上升法等。这里我们重点介绍梯度上升法。

梯度上升法

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

这个梯度意味着要沿x的方向移动∂ f ( x , y ) /∂ x,沿y的方向移动∂ f ( x , y ) /∂ y。其中,函数f(x,y)必须要在待计算的点上有定义并且可微。如下图:


 

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

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

以下用一个跟简单的例子说明梯度上升的含义:

设函数f(x)=-x^2+4x,函数图如下。则f'(x)=-2x+4,令导数为0,可求出x=2即取得函数f(x)的极大值。极大值等于f(2)=4。

但是真实环境中的函数不会像上面这么简单,就算求出了函数的导数,也很难精确计算出函数的极值。此时我们就可以用迭代的方法来做。就像爬坡一样,一点一点逼近极值。这种寻找最佳拟合参数的方法,就是最优化算法。爬坡这个动作用数学公式表达即为:

其中,α为步长,也就是学习速率,控制更新的幅度。效果如下图所示:

比如从(0,0)开始,迭代路径就是1->2->3->4->…->n,直到求出的x为函数极大值的近似值,停止迭代。

下动图为模拟梯度下降法,将其反转后即为梯度上升法。

python代码实现梯度下降法:

数据集结构如下:

代码如下:


import matplotlib.pyplot as plt
from numpy import *
import math

#加载数据集
def loadDataSet():
    '''数据集的前两个值分别为X1和X2,第三个值是数据对应的类别标签,为了方便计算,把X0的值设置成了1.0'''
    dataMat = []
    labelMat = []
    fr = open('D:/系统默认/桌面/深度学习/testSet.txt') #打开logistics regression 数据集).txt文件 
                                                                               # 一定要输入正确的数据集文件所在的地址目录
    for line in fr.readlines():                                                #逐行读取
        lineArr = line.strip().split()
        dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])]) #因为线性回归化式为 H(x) = W0 + W1*X1 + W2*X2即为 (W0, W1, W2)*(1, X1, X2),
                                                            # 其中 (W0, W1, W2) 即为所求回归系数 W。 为了方便计算, 读出 X1, X2 后要在前面补上一个 1.0
        labelMat.append(int(lineArr[2]))
    return dataMat, labelMat

#分类器的分类(转换)函数
def sigmoid(inX):
    return 1.0 / (1 + exp(-inX))  ##计算 sigmoid 函数

#梯度上升算法,用来计算出最佳回归系数
def gradAscent(dataMatIn, classLabels):
    '''第一个参数是2维数组,每列代表每个不同特征,每行代表每个训练样本
       第二个参数是类别标签,1*100的行向量,为便于计算,将其转换为列向量,即进行转置,并赋值给labelMat
    '''
    dataMatrix = mat(dataMatIn)  # convert to NumPy matrix  获得输入数据并将其转换为Numpy矩阵数据类型
    labelMat = mat(classLabels).transpose()  # convert to NumPy matrix 获得输入数据并将其转换为Numpy矩阵数据类型
    m, n = shape(dataMatrix)     #shape函数是numpy.core.fromnumeric中的函数,它的功能是查看矩阵或者数组的维数
    alpha = 0.001    #步长,向函数增长最快的方向的移动量,即学习率
    maxCycles = 500 #迭代次数
    weights = ones((n, 1))  #生成n行一列的元素为1的矩阵赋给weihts,即回归系数初始化为1
 
    #循环 maxCycles次, 每次都沿梯度向真实值 labelMat 靠拢
    for k in range(maxCycles):  # heavy on matrix operations
        h = sigmoid(dataMatrix * weights)  # matrix multiplication 矩阵相乘 包含了300次的乘积
        error = (labelMat - h)  # vector subtraction 向量减法,计算真实类别与预测类别的差值,h是一个列向量,列向量的元素个数等于样本数,即为100
        weights = weights + alpha * dataMatrix.transpose() * error  # matrix multiplication 矩阵相乘,dataMatrix.transpose()* error 就是梯度f(w),按照该差值的方向调整回归系数
    return weights

#输出运用梯度上升优化算法后得到的最理想的回归系数的值
def GetResult():
    dataMat, labelMat = loadDataSet()
    weights = gradAscent(dataMat, labelMat)
    print(weights)
    plotBestFit(weights)

#画出数据集和Logistic回归最佳拟合直线
def plotBestFit(weights):
 
    #画点
    dataMat, labelMat = loadDataSet()
    dataArr = array(dataMat)
    n = shape(dataArr)[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)
    ax.scatter(xcord1, ycord1, s=30, c='red', marker='s')
    ax.scatter(xcord2, ycord2, s=30, c='green')
 
    # 画线
    x = arange(-3.0, 3.0, 0.1)
    y = (0.48 * x + 4.12414) / (0.616)
    # y = (-weights[0]-weights[1]*x)/weights[2]
    ax.plot(x, y)
    plt.xlabel('X1')
    plt.ylabel('X2')
    plt.show()      #显示

GetResult()

输出最佳回归系数如下:

画出决策边界:

可以看出分类效果还是不错的。

基于逻辑回归的鸢尾花分类预测 

下面我们通过训练鸢尾花数据集对Logistic回归模型进行简单的评估。(鸢尾花数据集介绍) 

因为我们只讨论二分类问题故只选择数据集中类别为0和1的样本。

1.导入相应包

##  基础函数库
import numpy as np 
import pandas as pd

## 绘图函数库
import matplotlib.pyplot as plt
import seaborn as sns

2.读取数据集

## 我们利用 sklearn 中自带的 iris 数据作为数据载入,并利用Pandas转化为DataFrame格式
from sklearn.datasets import load_iris
data = load_iris() #得到数据特征
iris_target = data.target #得到数据对应的标签
iris_features = pd.DataFrame(data=data.data, columns=data.feature_names) #利用Pandas转化为DataFrame格式

3.利用逻辑回归模型在二分类上进行训练,计算最佳回归系数

## 为了正确评估模型性能,将数据划分为训练集和测试集,并在训练集上训练模型,在测试集上验证模型性能。
from sklearn.model_selection import train_test_split

## 选择其类别为0和1的样本 (不包括类别为2的样本)
iris_features_part = iris_features.iloc[:100]
iris_target_part = iris_target[:100]

## 测试集大小为20%, 80%/20%分
x_train, x_test, y_train, y_test = train_test_split(iris_features_part, iris_target_part, test_size = 0.2, random_state = 2020)

## 从sklearn中导入逻辑回归模型
from sklearn.linear_model import LogisticRegression

## 定义 逻辑回归模型 
clf = LogisticRegression(random_state=0, solver='lbfgs')

# 在训练集上训练逻辑回归模型
clf.fit(x_train, y_train)

## 查看其对应的w
print('the weight of Logistic Regression:',clf.coef_)

## 查看其对应的w0
print('the intercept(w0) of Logistic Regression:',clf.intercept_)

输出最佳回归系数:

4.预测模型准确率

## 在训练集和测试集上分布利用训练好的模型进行预测
train_predict = clf.predict(x_train)
test_predict = clf.predict(x_test)

from sklearn import metrics

## 利用accuracy(准确度)【预测正确的样本数目占总预测样本数目的比例】评估模型效果
print('The accuracy of the Logistic Regression is:',metrics.accuracy_score(y_train,train_predict))
print('The accuracy of the Logistic Regression is:',metrics.accuracy_score(y_test,test_predict))

## 查看混淆矩阵 (预测值A和真实值的各类情况统计矩阵)
confusion_matrix_result = metrics.confusion_matrix(test_predict,y_test)
print('The confusion matrix result:\n',confusion_matrix_result)

输出准确率与混淆矩阵:

可以看出准确率为1,这说明训练集与测试集中的数据均预测成功,Logistic回归模型对于该数据集的二分类效果良好。

Logistic回归模型的优缺点

优点:

(1)对率函数任意阶可导,具有很好的数学性质,许多现有的数值优化算法都可以用来求最优解,训练速度快;

(2)简单易理解,模型的可解释性非常好,从特征的权重可以看到不同的特征对最后结果的影响;

(3)适合二分类问题,不需要缩放输入特征;

(4)内存资源占用小,因为只需要存储各个维度的特征值;

(5)直接对分类可能性进行建模,无需事先假设数据分布,避免了假设分布不准确所带来的问题

(6)以概率的形式输出,而非知识0.1判定,对许多利用概率辅助决策的任务很有用

缺点:

(1)不能用逻辑回归去解决非线性问题,因为Logistic的决策面试线性的;

(2)对多重共线性数据较为敏感;

(3)很难处理数据不平衡的问题;

(4)准确率并不是很高,因为形式非常的简单(非常类似线性模型),很难去拟合数据的真实分布;

(5)逻辑回归本身无法筛选特征,有时会用gbdt来筛选特征,然后再上逻辑回归。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值