【机器学习】逻辑回归

sxyhetao 2019-12-19


逻辑回归

原理

逻辑回归模型

逻辑回归模型(LR)是判别模型,可以用于二分类或多分类,模型如下:

二分类:

$$P(Y=1 | x)=\frac{\exp\left(w \cdot x\right)}{1+ \exp \left(w \cdot x\right)}$$

$$P(Y=0 | x)=\frac{1}{1+ \exp \left(w \cdot x\right)}$$

多分类:

$$P(Y=k | x)=\frac{\exp \left(w_{k} \cdot x\right)}{1+\sum_{k=1}^{K-1} \exp \left(w_{k} \cdot x\right)}, \quad k=1,2, \cdots, K-1$$

$$P(Y=K | x)=\frac{1}{1+\sum_{k=1}^{K-1} \exp \left(w_{k} \cdot x\right)}$$

对数几率

一个事件发生的几率,是该事件发生的概率与不发生的概率的比值,也就是样本为正例的相对可能性。在几率外面套个$log$的壳子,就变成了对数几率。对数几率可用线性函数表示,这正是线性回归模型的形式,故该模型也称为对数几率回归。$$\log\frac{P\left(Y=1|x\right)} {1-P\left(Y=1|x\right)}=w \cdot x$$

线性模型

线性模型不只有直线的样子,在$w \cdot x$的外面加上单调可微的函数就可以得到各种非线性的样子,这些模型称之为广义线性模型。线性模型的求解方法为基于均方误差的最小二乘法。

求解方法 

逻辑回归模型的参数估计可以应用极大似然估计法,首先列出对数似然函数:

设$p=P(Y=1 | x)$,有:

$$L(w)=\sum_{i=1}^{N} \left[y_{i}log \left(p\right)+\left(1-y_{i}\right)log \left(1-p\right)\right]$$

$$=\sum_{i=1}^{N} [y_{i}(w \cdot x)-log(1+exp(w \cdot x))]$$

 

采用梯度下降法估计$L(w)$的极值,对上式求导:

$$\frac{dL}{dw}=(y_{i}-\frac{1}{1+exp(w \cdot x)}) \cdot x$$

这就是梯度的方向,在每一轮迭代的时候沿着梯度下降的方向更新参数w,这个式子又叫交叉熵损失函数。

代码实现

 手动实现

class LogisticReressionClassifier:
    
    # 超参数有学习率和迭代轮数
    def __init__(self, max_iter=200, learning_rate=0.01):
        self.max_iter = max_iter
        self.learning_rate = learning_rate

    # 建立sigmoid函数
    def sigmoid(self, x):
        return 1 / (1 + exp(-x))
    
    # 给数据第一列加一列1.0,这个就是和后面的权重w相乘时得到的那个b
    def data_matrix(self, X):
        data_mat = []
        for d in X:
            data_mat.append([1.0, *d])
        return data_mat

    # 建立lr模型
    def fit(self, X, y):
        # label = np.mat(y)
        data_mat = self.data_matrix(X)  # m*n
        # 权重初始化,都设置为0
        self.weights = np.zeros((len(data_mat[0]), 1), dtype=np.float32)

        # 迭代Max_iter轮
        for iter_ in range(self.max_iter):
            # 每轮将样本一个个计算一遍
            for i in range(len(X)):
                # 预测值
                result = self.sigmoid(np.dot(data_mat[i], self.weights))
                # 误差
                error = y[i] - result
                # 更新参数
                self.weights += self.learning_rate * error * np.transpose(
                    [data_mat[i]])
        print(‘LogisticRegression Model(learning_rate={},max_iter={})‘.format(
            self.learning_rate, self.max_iter))

    # 进行预测
    def score(self, X_test, y_test):
        right = 0
        X_test = self.data_matrix(X_test)
        for x, y in zip(X_test, y_test):
            result = np.dot(x, self.weights)
            if (result > 0 and y == 1) or (result < 0 and y == 0):
                right += 1
        return right / len(X_test)

工具实现

from sklearn.linear_model import LogisticRegression

clf = LogisticRegression(max_iter=200)
clf.fit(X_train, y_train)
clf.score(X_test, y_test)

面试问题

逻辑回归相比于线性回归,有何异同?

不同点:

逻辑回归处理分类问题,线性回归处理回归问题。逻辑回归的因变量是离散的,线性回归因变量是连续的。

相同点:

二者都使用了极大似然估计对训练样本进行建模。

 

当使用逻辑回归处理多分类问题时,有哪些常见做法,分别应用于哪些场景,它们之间又有怎样的关系?

如果一个样本只对应于一个标签时,利用softmax进行分类。

如果一个样本属于多个标签的情况,可以训练多个二分类,对第i个标签进行预测。

 

写一下LR的损失函数,加上L1/L2正则化;然后解释原理,分析不同点,怎么用

L1正则:

$$L(w)=\frac{1}{m} \left[ \sum_{i=1}^{m} \left[y_{i}log \left(p\right)+\left(1-y_{i}\right)log \left(1-p\right)\right] + \lambda \sum_{j=1}^{n}|w_{j}| \right]$$

L2正则:

$$L(w)=\frac{1}{m} \left[ \sum_{i=1}^{m} \left[y_{i}log \left(p\right)+\left(1-y_{i}\right)log \left(1-p\right)\right] + \lambda \sum_{j=1}^{n}w_{j}^{2} \right]$$

对于特征约束强的需求下l1合适,否则l2。

 

LR是什么假设

逻辑回归假设数据服从伯努利分布(二项分布)

 

LR为什么要使用sigmoid

这个问题有点难,可以从对数几率角度、sigmoid求导特性、定义域从负无穷到正无穷且值域在0到1、概率分布等角度,可以参考:

https://www.zhihu.com/question/35322351

 

LR为什么用交叉熵作为损失函数而不用均方差?

如果使用均方差,对参数求导的时候公式中还保留着sigmoid的导数,而sigmoid的导数在头尾均接近于0,这使得参数更新的很慢(推导一下就知道了)。

而交叉熵损失函数求导后没有sigmoid的导数,只有sigmoid,且真实值与预测值差别越大,梯度越大,更新的速度也就越快,这正是我们想要的。

 

LR采用什么方式抽样?有放回还是无放回?为什么?

有放回抽样,每次概率相等(个人猜测)

 

假设有正负两类样本,用LR去划分有什么缺陷?

若正负样本不均衡,需要上采样或下采样。下采样会有数据利用不充分问题,有一个trick:采样多次,训练多个模型,跟随机森林一样,求个平均即可

 

如果有很多的特征高度相关或者说有一个特征重复了100遍,会造成怎样的影响?为什么要避免共线性?

如果在损失函数最终收敛的情况下,其实就算有很多特征高度相关也不会影响分类器的效果
每一个特征都是原来特征权重值的百分之一,线性可能解释性优点也消失了
增加训练收敛的难度及耗时,有限次数下可能共线性变量无法收敛,系数估计变得不可靠
泛化能力变差,训练是两列特征可能会共线性,当线上数据加入噪声后共线性消失,效果可能变差

为什么LR需要归一化或者取对数?

模型中对数据对处理一般都有一个标答是提升数据表达能力,也就是使数据含有的可分信息量更大。

工程角度:
加速收敛
提高计算效率
理论角度:
梯度下降过程稳定
使得数据在某类上更服从高斯分布,满足前提假设

在工业界,LR通常将连续值变为离散值输入,为什么?

离散特征的增加和减少都很容易,易于模型的快速迭代;

稀疏向量内积乘法运算速度快,计算结果方便存储,容易扩展;

离散化后的特征对异常数据有很强的鲁棒性:比如一个特征是年龄>30是1,否则0。如果特征没有离散化,一个异常数据“年龄300岁”会给模型造成很大的干扰;

逻辑回归属于广义线性模型,表达能力受限;单变量离散化为N个后,每个变量有单独的权重,相当于为模型引入了非线性,能够提升模型表达能力,加大拟合;

离散化后可以进行特征交叉,由M+N个变量变为M*N个变量,进一步引入非线性,提升表达能力;

特征离散化后,模型会更稳定,比如如果对用户年龄离散化,20-30作为一个区间,不会因为一个用户年龄长了一岁就变成一个完全不同的人。当然处于区间相邻处的样本会刚好相反,所以怎么划分区间是门学问;

特征离散化以后,起到了简化了逻辑回归模型的作用,降低了模型过拟合的风险。
李沐曾经说过:模型是使用离散特征还是连续特征,其实是一个“海量离散特征+简单模型” 同 “少量连续特征+复杂模型”的权衡。既可以离散化用线性模型,也可以用连续特征加深度学习。就看是喜欢折腾特征还是折腾模型了。通常来说,前者容易,而且可以n个人一起并行做,有成功经验;后者目前看很赞,能走多远还须拭目以待。

原来的单变量可扩展到n个离散变量,每个变量有单独的权重,相当于为模型引入了非线性,能够提升模型表达能力,加大拟合
离散后结合正则化可以进行特征筛选,更好防止过拟合
数据的鲁棒性更好,不会因为无意义的连续值变动导致异常因素的影响,(31岁和32岁的差异在哪呢?)
离散变量的计算相对于连续变量更快

 

LR的优缺点?

优点

  • 简单,易部署,训练速度快
  • 模型下限较高
  • 可解释性强

缺点

 

参考

西瓜书

李航统计学习方法

https://blog.csdn.net/slade_sha/article/details/103427059

https://mp.weixin.qq.com/s/71w0IN3gAYWxrKVM_lcYrQ

相关推荐