逻辑回归
原理
逻辑回归模型
逻辑回归模型(LR)是判别模型,可以用于二分类或多分类,模型如下:
二分类:
$$P(Y=1 | x)=frac{expleft(w cdot x ight)}{1+ exp left(w cdot x ight)}$$
$$P(Y=0 | x)=frac{1}{1+ exp left(w cdot x ight)}$$
多分类:
$$P(Y=k | x)=frac{exp left(w_{k} cdot x ight)}{1+sum_{k=1}^{K-1} exp left(w_{k} cdot x ight)}, 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 ight)}$$
对数几率
一个事件发生的几率,是该事件发生的概率与不发生的概率的比值,也就是样本为正例的相对可能性。在几率外面套个$log$的壳子,就变成了对数几率。对数几率可用线性函数表示,这正是线性回归模型的形式,故该模型也称为对数几率回归。$$logfrac{Pleft(Y=1|x ight)} {1-Pleft(Y=1|x ight)}=w cdot x$$
线性模型
线性模型不只有直线的样子,在$w cdot x$的外面加上单调可微的函数就可以得到各种非线性的样子,这些模型称之为广义线性模型。线性模型的求解方法为基于均方误差的最小二乘法。
求解方法
逻辑回归模型的参数估计可以应用极大似然估计法,首先列出对数似然函数:
设$p=P(Y=1 | x)$,有:
$$L(w)=sum_{i=1}^{N} left[y_{i}log left(p ight)+left(1-y_{i} ight)log left(1-p ight) ight]$$
$$=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,这个式子又叫交叉熵损失函数。
代码实现
手动实现
1 class LogisticReressionClassifier: 2 3 # 超参数有学习率和迭代轮数 4 def __init__(self, max_iter=200, learning_rate=0.01): 5 self.max_iter = max_iter 6 self.learning_rate = learning_rate 7 8 # 建立sigmoid函数 9 def sigmoid(self, x): 10 return 1 / (1 + exp(-x)) 11 12 # 给数据第一列加一列1.0,这个就是和后面的权重w相乘时得到的那个b 13 def data_matrix(self, X): 14 data_mat = [] 15 for d in X: 16 data_mat.append([1.0, *d]) 17 return data_mat 18 19 # 建立lr模型 20 def fit(self, X, y): 21 # label = np.mat(y) 22 data_mat = self.data_matrix(X) # m*n 23 # 权重初始化,都设置为0 24 self.weights = np.zeros((len(data_mat[0]), 1), dtype=np.float32) 25 26 # 迭代Max_iter轮 27 for iter_ in range(self.max_iter): 28 # 每轮将样本一个个计算一遍 29 for i in range(len(X)): 30 # 预测值 31 result = self.sigmoid(np.dot(data_mat[i], self.weights)) 32 # 误差 33 error = y[i] - result 34 # 更新参数 35 self.weights += self.learning_rate * error * np.transpose( 36 [data_mat[i]]) 37 print('LogisticRegression Model(learning_rate={},max_iter={})'.format( 38 self.learning_rate, self.max_iter)) 39 40 # 进行预测 41 def score(self, X_test, y_test): 42 right = 0 43 X_test = self.data_matrix(X_test) 44 for x, y in zip(X_test, y_test): 45 result = np.dot(x, self.weights) 46 if (result > 0 and y == 1) or (result < 0 and y == 0): 47 right += 1 48 return right / len(X_test)
工具实现
1 from sklearn.linear_model import LogisticRegression 2 3 clf = LogisticRegression(max_iter=200) 4 clf.fit(X_train, y_train) 5 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 ight)+left(1-y_{i} ight)log left(1-p ight) ight] + lambda sum_{j=1}^{n}|w_{j}| ight]$$
L2正则:
$$L(w)=frac{1}{m} left[ sum_{i=1}^{m} left[y_{i}log left(p ight)+left(1-y_{i} ight)log left(1-p ight) ight] + lambda sum_{j=1}^{n}w_{j}^{2} ight]$$
对于特征约束强的需求下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的优缺点?
优点
- 简单,易部署,训练速度快
- 模型下限较高
- 可解释性强
缺点
- 只能线性可分
- 数据不平衡需要人为处理,weight_class/有哪些常见的采样方法
- 模型上限较低
参考
西瓜书
李航统计学习方法