机器学习——logistic回归

一、引言
      逻辑回归也被称为广义线性回归模型,它与线性回归模型最大的区别就在于它们的因变量不同,如果是连续的,就是多重线性回归;如果是二项分布,就是逻辑回归。
   逻辑回归(Logistic Regression)虽然名字里带“回归”,但是它实际上是一种分类方法,主要用于两分类问题(即输出只有两种,分别代表两个类别)。它是机器学习中最常见的一种用于二分类的算法模型,由于其数学原理简单易懂,作用高效,其实际应用非常广泛。

二、简介
1、定义
Logistic回归又称logistic回归分析,是一种广义线性回归(generalized linear model),常用于数据挖掘,疾病自动诊断,经济预测等领域。逻辑回归根据给定的自变量数据集来估计事件的发生概率,由于结果是一个概率,因此因变量的范围在 0 和 1 之间。

Logistic回归的因变量可以是二分类的,如是否患胃癌;也可以是多分类的,如 mnist 手写识别,但是二分类的更为常用,也更加容易解释。所以实际中最常用的就是二分类的Logistic回归。

2、线性回归
线性回归是一种使用特征属性的线性组合来预测响应的方法。它的目标是找到一个线性函数,以尽可能准确地描述特征或自变量(x)与响应值(y)之间的关系,使得预测值与真实值之间的误差最小化。

在数学上,线性回归要找的这个线性函数叫回归方程,其定义如下:

其中, 表示第i个样本的预测响应值。 和  是回归系数,分别代表回归线的y轴截距和斜率。这种形式通常见于特征只有单个属性的时候,也就是一元线性回归。

在机器学习中,通常每个样本都有 n 个特征属性,每个特征  都有一个对应的权值  ,此时我们需要的就是多元线性回归:

其中, 没有实义,只是为了方便写成矩阵的形式,  则等价于上式子中的 ,把  融入矩阵中,不仅为了看起来简洁,也是为了方便计算。 

我们的目标是要找到一组  ,使得预测值与回归值误差最小,即最小化均方误差。一般采用最小二乘法求 w(本文不多赘述,可以参考相关文章)

最终,线性回归模型可简写为

3、Sigmoid函数
我们知道逻辑回归的目标是训练一个分类器,该分类器可以对输入数据的类别做出决策。以二元逻辑回归为例,对于一个输入 ,我们希望分类器能够输出 y 是1(是某类的成员)或 0(不是某类的成员)。也就是说,我们想知道这个输入 x 是该类成员的概率 P(y=1|x)。

而线性回归 y 的值域为R,这样对决策很不友好,因为 y 的值有可能非常大。我们想要的函数应该是,能接受所有的输入然后预测出类别。例如,在两个类的情况下,上述函数输出 0 或 1 。

现在我们假设 p 为样本属于正类的概率,则样本属于负类的概率为 1-p,事件发生的几率是指该事件发生的概率与该事件不发生的概率的比值,取事件发生的几率的对数即为该事件的对数几率有:

将对数几率记为输入特征值的线性表达式:

对上式取反可得·:

这就是Sigmoid函数:

其中,

为了实现Logistic回归分类器,我们可以在每个特征上都乘以一个回归系数,然后把所有的结果值相加,将这个总和代入Sigmoid函数中,进而得到一个范围在0~1之间的数值。任何大于0.5的数据被分入1类,小于0.5即被归入0类。所以,Logistic回归也可以被看成是一种概率估计。

4、损失函数
 对上述式子进行整合:

在已知样本x和参数θ的情况下,样本x属性正样本(y=1)和负样本(y=0)的条件概率。理想状态下,根据上述公式,求出各个点的概率均为1,也就是完全分类都正确。

但是考虑到实际情况,样本点的概率越接近于1,其分类效果越好。

合并出来的Loss,就是损失函数(Loss Function)。当y等于1时,(1-y)项(第二项)为0;当y等于0时,y项(第一项)为0。

为了简化问题,可以对整个表达式求对数:

这个损失函数,是对于一个样本而言的。给定一个样本,就可以通过这个损失函数求出,样本所属类别的概率,而这个概率越大越好,所以也就是求解这个损失函数的最大值。既然概率出来了,那么最大似然估计也该出场了。假定样本与样本之间相互独立,那么整个样本集生成的概率即为所有样本生成概率的乘积,再将公式对数化,便可得到如下公式:

其中,m为样本的总数,表示第i个样本的类别,表示第i个样本,需要注意的是w是多维向量,也是多维向量。满足J(w)的最大的w值即是我们需要求解的模型。

J(w)的求导之后得到的梯度上升迭代公式:

将公式矢量化:

 

三、实现 
3.1加载数据集,并数据归一化
函数 loadDataSet 用于从文件中加载数据集,并将其转换为特征值列表和标签。函数 normalizedata 则是用于对数据进行归一化处理

# -*- coding:utf-8 -*-
 
 
import numpy as np
import matplotlib.pyplot as plt
 
def loadDataSet():
    dataMat = []  # 存储特征值
    labelMat = []  # 用于标签
    txt = open("C:\\Users\\lenovo\\Desktop\\t.txt")
    for line in txt.readlines():  # 逐行读取数据文件
        lineArr = line.strip().split()  # 将每行数据按空格分割并去除首尾空格
        # 将二维特征扩展到三维
        dataMat.append([1.0, float(lineArr[0]), float(lineArr[2])])
        labelMat.append(int(lineArr[3]))  # 将标签值加入到labelMat列表中
 
    return dataMat, labelMat  # 返回特征值列表和标签
mat1,mat2=loadDataSet()
 
 
def normalizedata(data):
    data = np.array(data)
    new_data=data[:,1:]
    # 计算每列的最大最小值
    min_vals = new_data.min(0)
    max_vals = new_data.max(0)
    ranges = max_vals - min_vals
 
    # 归一化数据
    normalized_data = (new_data - min_vals) / ranges
    normalized_data = np.insert(normalized_data, 0, 1, axis=1)
    return normalized_data
 
mat1 = normalizedata(mat1)
print(mat1)
print(mat2)
结果:

特征值:

标签值 

3.2 Sigmoid函数
将值映射到0~1,将输出映射到概率值

def sigmoid(inx):
    return 1.0 / (1 + np.exp(-inx))# 计算Sigmoid函数的值
3.3 损失函数
计算逻辑回归模型的损失值

def error_rate(h, label):
    label = label.reshape(-1, 1)  # 更改标签维度为n*1
    m = np.shape(h)[0]  # 预测值的个数
    sum_err = 0.0  # 初始化错误率
    for i in range(m):  # m个预测值迭代
        if h[i, 0] > 0 and (1 - h[i, 0]) > 0:  # 预测值切片
            sum_err -= (label[i, 0] * np.log(h[i, 0]) + (1 - label[i, 0]) * np.log(1 - h[i, 0]))  # 损失函数公式计算
        else:
            sum_err -= 0
    return sum_err / m
3.4梯度下降
运用梯度下降法计算权重

#梯度下降
def graddescent(datamat, classlabels):
    datamatrix = np.mat(datamat)
    labelmat = np.mat(classlabels).transpose()
    m, n = np.shape(datamatrix)
    alpha = 0.001# 学习率
    max = 5000 # 最大迭代次数
    weights = np.ones((n, 1))# 初始化为全1
    for k in range(max):
        h = sigmoid(datamatrix * weights) # 计算预测值
        error =  h- labelmat# 计算误差
        loss = error_rate(h, labelmat)#计算损失率
        if k % 100 == 0:  # 没迭代一百次进行一次
            print('\t--------迭代次数 = ' + str(k) + ',训练错误率 = ' +  str(loss))
        weights = weights - alpha * datamatrix.transpose() * error # 更新权重
    return weights.getA(),weights
3.5梯度上升
运用梯度上升法计算权重

#梯度上升
def gradAscent(datamat, classlabels):
    datamatrix = np.mat(datamat)
    labelmat = np.mat(classlabels).transpose()
    m, n = np.shape(datamatrix)
    alpha = 0.001# 学习率
    max = 5000# 最大迭代次数
    weights = np.ones((n, 1))
    loss_array = []
    for k in range(max):
        h = sigmoid(datamatrix * weights)# 计算预测值
        error = (labelmat - h)# 计算误差
        loss = error_rate(h, labelmat)#计算损失率
        if k % 100 == 0:  # 没迭代一百次进行一次
            print('\t--------迭代次数 = ' + str(k) + ',训练错误率 = ' + str(loss))
        weights = weights + alpha * datamatrix.transpose() * error  # 更新权重
    return weights.getA(),weights
3.6牛顿法
运用牛顿法计算权重

def Newton_method(datamat, classlabels):
    datamatrix = np.mat(datamat)
    labelmat = np.mat(classlabels).transpose()
    m, n = np.shape(datamatrix)
    max = 100 # 最大迭代次数
    weights = np.ones((n, 1))#权值
    for i in range(max):
        H = sigmoid(datamatrix*weights)
        J = np.dot(datamatrix.transpose(),(H - labelmat)) # 计算梯度
        #Hessian = np.dot(data_matrix.T, np.dot(np.diag(H * (1.0 - H)), data_matrix)) / m
        Hessian = np.dot(H.transpose(), datamatrix).dot(datamatrix.transpose()).dot((1.0 - H)) / m # 计算Hessian矩阵
        try:
            Hessian = np.mat(Hessian).I.tolist() # 对Hessian矩阵进行逆运算
        except:
            continue
        loss = error_rate(H, labelmat)  # 计算损失率
        if i % 10 == 0:  # 没迭代次进行一次
            print('\t--------迭代次数 = ' + str(i) + ',训练错误率 = ' + str(loss))
        weights -= np.dot(J, Hessian) # 更新权重
    return weights
3.7绘制图像
绘制逻辑回归的最佳拟合直线

def plotBestFit( weights,title,dataMat, labelMat):
 
    dataArr = np.array(dataMat)
    n = np.shape(dataArr)[0]
    x1 = []
    y1 = []
    x2 = []
    y2 = []
    # 将数据集按类别进行划分
    for i in range(n):
        if int(labelMat[i])== 1:
            x1.append(dataArr[i,1])
            y1.append(dataArr[i,2])
        else:
            x2.append(dataArr[i,1])
            y2.append(dataArr[i,2])
    fig = plt.figure()
    ax = fig.add_subplot(111)
    plt.title(title)
    ax.scatter(x1, y1, s=30, c='red', marker='s') # 绘制类别1的数据点
    ax.scatter(x2, y2, s=30, c='green')# 绘制类别2的数据点
    x = np.arange(0, 9, 0.1)
    y = (-weights[0]-weights[1]*x)/weights[2] # 根据权重参数计算决策边界
 
    ax.plot(x, y)
    plt.xlim(0, 1) # 设置x轴显示范围
    plt.ylim(0, 1) # 设置y轴显示范围
    plt.xlabel('X1')
    plt.ylabel('X2')
    plt.show()
 2.8分类预测
通过权值和特征向量和阈值来预测类别,1是正例,0是负例

def predict(x,weights,threshold=0.5):
    prob = sigmoid(sum(x*weights)) # 计算预测概率
    if prob > threshold:
        return 1
    else:
        return 0
(1)梯度下降法预测

weights = graddescent(mat1,mat2)[0]#计算权值
plotBestFit(weights,'graddescent',mat1,mat2)#绘制图像
data= [1.0, 97.0, 15.0]
print(predict(np.mat(data), weights))#输出预测结果
损失的结果:

绘图结果 :

预测结果:0

2)梯度上升法预测

weights2 = gradAscent(mat1,mat2)[0]#计算权值
plotBestFit(weights,'gradAscent',mat1,mat2)#绘制图像
print(predict(np.mat(data), weights))#输出预测结果
损失的结果:

绘图结果:

预测结果: 0

(3)牛顿法预测

weights3 = Newton_method(mat1,mat2)#计算权值
plotBestFit(weights,'Newton',mat1,mat2)#绘制图像
print(predict(np.mat(data), weights))#输出预测结果
损失结果:

绘图结果:

预测结果 

四、总结
4.1 线性回归与逻辑回归的区别
(1)逻辑回归能够用于分类,不过其本质还是线性回归。它仅在线性回归的基础上,在特征到结果的映射中加入了一层sigmoid函数(非线性)映射,即先把特征线性求和,然后使用sigmoid函数来预测。

(2)逻辑回归和线性回归首先都是广义的线性回归,其次经典线性模型的优化目标函数是最小二乘,而逻辑回归则是似然函数,另外线性回归在整个实数域范围内进行预测,敏感度一致,而分类范围,需要在[0,1]。逻辑回归就是一种减小预测范围,将预测值限定为[0,1]间的一种回归模型,因而对于这类问题来说,逻辑回归的鲁棒性比线性回归的要好。

(3)逻辑回归的模型本质上是一个线性回归模型,逻辑回归都是以线性回归为理论支持的。但线性回归模型无法做到sigmoid的非线性形式,sigmoid可以轻松处理0/1分类问题

4.2 逻辑回归优缺点
优点:

适合分类场景
计算代价不高,容易理解实现。
不用事先假设数据分布,这样避免了假设分布不准确所带来的问题。
不仅预测出类别,还可以得到近似概率预测。
目标函数任意阶可导。
缺点:

容易欠拟合,分类精度不高。
数据特征有缺失或者特征空间很大时表现效果并不好。
4.3 小结
     通过此处实验,让我对逻辑回归有了深刻理解,掌握了逻辑回归工作原理以及它与线性回归的区别。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值