逻辑回归概述+逻辑回归的优点+sklearn中的逻辑回归算法+逻辑回归中的特征工程+梯度下降+二元回归与多元回归+样本不平衡与参数class_weight

1512-高同学

发表文章数:46

热门标签

, ,
首页 » 算法 » 正文

1、逻辑回归概述

逻辑回归,是一种名为“回归”的线性分类器,其本质是由线性回归变化而来的,一种广泛使用于分类问题中的广义回归算法。要理解逻辑回归从何而来,得要先理解线性回归。线性回归是机器学习中最简单的的回归算法,它写作一个几乎人人熟悉的方程:
逻辑回归概述+逻辑回归的优点+sklearn中的逻辑回归算法+逻辑回归中的特征工程+梯度下降+二元回归与多元回归+样本不平衡与参数class_weight
逻辑回归概述+逻辑回归的优点+sklearn中的逻辑回归算法+逻辑回归中的特征工程+梯度下降+二元回归与多元回归+样本不平衡与参数class_weight
逻辑回归概述+逻辑回归的优点+sklearn中的逻辑回归算法+逻辑回归中的特征工程+梯度下降+二元回归与多元回归+样本不平衡与参数class_weight
逻辑回归概述+逻辑回归的优点+sklearn中的逻辑回归算法+逻辑回归中的特征工程+梯度下降+二元回归与多元回归+样本不平衡与参数class_weight
逻辑回归概述+逻辑回归的优点+sklearn中的逻辑回归算法+逻辑回归中的特征工程+梯度下降+二元回归与多元回归+样本不平衡与参数class_weight
逻辑回归概述+逻辑回归的优点+sklearn中的逻辑回归算法+逻辑回归中的特征工程+梯度下降+二元回归与多元回归+样本不平衡与参数class_weight
逻辑回归概述+逻辑回归的优点+sklearn中的逻辑回归算法+逻辑回归中的特征工程+梯度下降+二元回归与多元回归+样本不平衡与参数class_weight

2、为什么需要逻辑回归?

(1)逻辑回归对线性关系的拟合效果好到丧心病狂,特征与标签之间的线性关系极强的数据,比如金融领域中的 信用卡欺诈,评分卡制作,电商中的营销预测等等相关的数据,都是逻辑回归的强项。虽然现在有了梯度提 升树GDBT,比逻辑回归效果更好,也被许多数据咨询公司启用,但逻辑回归在金融领域,尤其是银行业中的 统治地位依然不可动摇(相对的,逻辑回归在非线性数据的效果很多时候比瞎猜还不如,所以如果你已经知 道数据之间的联系是非线性的,千万不要迷信逻辑回归);

(2) 逻辑回归计算快:对于线性数据,逻辑回归的拟合和计算都非常快,计算效率优于SVM和随机森林,亲测表示在大型数据上尤其能够看得出区别;

(3)**逻辑回归返回的分类结果不是固定的0,1,而是以小数形式呈现的类概率数字:**我们因此可以把逻辑回归返 回的结果当成连续型数据来利用。比如在评分卡制作时,我们不仅需要判断客户是否会违约,还需要给出确 定的”信用分“,而这个信用分的计算就需要使用类概率计算出的对数几率,而决策树和随机森林这样的分类 器,可以产出分类结果,却无法帮助我们计算分数(当然,在sklearn中,决策树也可以产生概率,使用接口 predict_proba调用就好,但一般来说,正常的决策树没有这个功能)。

另外,逻辑回归还有抗噪能力强的优点。福布斯杂志在讨论逻辑回归的优点时,甚至有着“技术上来说,最佳模型 的AUC面积低于0.8时,逻辑回归非常明显优于树模型”的说法。并且,逻辑回归在小数据集上表现更好,在大型的 数据集上,树模型有着更好的表现。

由此,我们已经了解了逻辑回归的本质,它是一个返回对数几率的,在线性数据上表现优异的分类器,它主要被应 用在金融领域。其数学目的是求解能够让模型对数据拟合程度最高的参数 的值,以此构建预测函数 ,然后将 特征矩阵输入预测函数来计算出逻辑回归的结果y。注意,虽然我们熟悉的逻辑回归通常被用于处理二分类问题, 但逻辑回归也可以做多分类。

3、sklearn中的逻辑回归

逻辑回归概述+逻辑回归的优点+sklearn中的逻辑回归算法+逻辑回归中的特征工程+梯度下降+二元回归与多元回归+样本不平衡与参数class_weight
逻辑回归概述+逻辑回归的优点+sklearn中的逻辑回归算法+逻辑回归中的特征工程+梯度下降+二元回归与多元回归+样本不平衡与参数class_weight
逻辑回归概述+逻辑回归的优点+sklearn中的逻辑回归算法+逻辑回归中的特征工程+梯度下降+二元回归与多元回归+样本不平衡与参数class_weight

4、损失函数

逻辑回归概述+逻辑回归的优点+sklearn中的逻辑回归算法+逻辑回归中的特征工程+梯度下降+二元回归与多元回归+样本不平衡与参数class_weight
逻辑回归概述+逻辑回归的优点+sklearn中的逻辑回归算法+逻辑回归中的特征工程+梯度下降+二元回归与多元回归+样本不平衡与参数class_weight

5、重要参数penatly&C

(1)正则化
逻辑回归概述+逻辑回归的优点+sklearn中的逻辑回归算法+逻辑回归中的特征工程+梯度下降+二元回归与多元回归+样本不平衡与参数class_weight

逻辑回归概述+逻辑回归的优点+sklearn中的逻辑回归算法+逻辑回归中的特征工程+梯度下降+二元回归与多元回归+样本不平衡与参数class_weight
逻辑回归概述+逻辑回归的优点+sklearn中的逻辑回归算法+逻辑回归中的特征工程+梯度下降+二元回归与多元回归+样本不平衡与参数class_weight
L1正则化和L2正则化虽然都可以控制过拟合,但它们的效果并不相同。当正则化强度逐渐增大(即C逐渐变小), 参数的取值会逐渐变小,但L1正则化会将参数压缩为0,L2正则化只会让参数尽量小,不会取到0。

在L1正则化在逐渐加强的过程中,携带信息量小的、对模型贡献不大的特征的参数,会比携带大量信息的、对模型 有巨大贡献的特征的参数更快地变成0,所以L1正则化本质是一个特征选择的过程,掌管了参数的“稀疏性”。L1正 则化越强,参数向量中就越多的参数为0,参数就越稀疏,选出来的特征就越少,以此来防止过拟合。

相对的,L2正则化在加强的过程中,会尽量让每个特征对模型都有一些小的贡献,但携带信息少,对模型贡献不大 的特征的参数会非常接近于0。通常来说,如果我们的主要目的只是为了防止过拟合,选择L2正则化就足够了。但 是如果选择L2正则化后还是过拟合,模型在未知数据集上的效果表现很差,就可以考虑L1正则化。

from sklearn.datasets import load_breast_cancer
from sklearn.metrics import accuracy_score
from sklearn.linear_model import LogisticRegression as LR
from sklearn.model_selection import train_test_split
import numpy as np
import matplotlib.pyplot as plt


data = load_breast_cancer()
#print(data)
x = data.data
y = data.target

#print(x)
#print('###########################33')
#print(y)

lr1 = LR(penalty='l1', solver='liblinear', C=0.5, max_iter=1000)
lr2 = LR(penalty='l2', solver='liblinear', C=0.5, max_iter=1000)

#逻辑回归的重要属性coef_,查看每个特征对应的参数
lrl1 = lr1.fit(x, y)
#print(lrl1.coef_)
#print((lrl1.coef_ != 0).sum()) #10

lrl2 = lr2.fit(x, y)
#print(lrl2.coef_)
#print((lrl2.coef_ != 0).sum())  #30

l1 = []
l2 = []
l1test = []
l2test = []

xtrain, xtest, ytrain, ytest = train_test_split(x, y, test_size=0.3, random_state=0)

for i in np.linspace(0.5, 1, 19):
    lrl1 = LR(penalty='l1', solver='liblinear', C=i, max_iter=1000)
    lrl2 = LR(penalty='l2', solver='liblinear', C=i, max_iter=1000)

    lrl1 = lrl1.fit(xtrain, ytrain)
    l1.append(accuracy_score(lrl1.predict(xtrain), ytrain))
    l1test.append(accuracy_score(lrl1.predict(xtest), ytest))

    lrl2 = lrl2.fit(xtrain, ytrain)
    l2.append(accuracy_score(lrl2.predict(xtrain), ytrain))
    l2test.append(accuracy_score(lrl2.predict(xtest), ytest))

graph = [l1, l2, l1test, l2test]
color = ['green', 'black', 'red', 'blue']
label = ['L1', 'L2', 'L1test', 'L2test']

plt.figure(figsize=(10, 8))
for i in range(4):
    plt.plot(np.linspace(0.5, 1, 19), graph[i], color[i], label=label[i])

plt.legend(loc=4)
plt.show()

6、逻辑回归中的特征工程

业务选择

说到降维和特征选择,首先要想到的是利用自己的业务能力进行选择,肉眼可见明显和标签有关的特征就是需要留 下的。当然,如果我们并不了解业务,或者有成千上万的特征,那我们也可以使用算法来帮助我们。或者,可以让 算法先帮助我们筛选过一遍特征,然后在少量的特征中,我们再根据业务常识来选择更少量的特征。

PCA和SVD一般不用

逻辑回归是由线性回归演变而来,线性回归的一个核心目的是通过求解参数来探究特征X与标签y之间的 关系,而逻辑回归也传承了这个性质,我们常常希望通过逻辑回归的结果,来判断什么样的特征与分类结果相关, 因此我们希望保留特征的原貌。PCA和SVD的降维结果是不可解释的,因此一旦降维后,我们就无法解释特征和标 签之间的关系了。当然,在不需要探究特征与标签之间关系的线性数据上,降维算法PCA和SVD也是可以使用的。

统计方法可以使用,但不是非常必要

逻辑回归对数据的要求低于线性回归,由于我们不是使用最小二乘法来求解,所以逻辑回归对数据的总体分布和方差没有要求,也不需要排除特征之间的共线性,但如果我 们确实希望使用一些统计方法,比如方差,卡方,互信息等方法来做特征选择,也并没有问题。过滤法中所有的方法,都可以用在逻辑回归上。

高效的嵌入法embedded

但是更有效的方法,毫无疑问会是我们的embedded嵌入法。我们已经说明了,由于L1正则化会使得部分特征对应的参数为0,因此L1正则化可以用来做特征选择,结合嵌入法的模块SelectFromModel,我们可以很容易就筛选出让模型十分高效的特征。注意,此时我们的目的是,尽量保留原数据上的信息,让模型在降维后的数据上的拟合效果保持优秀,因此我们不考虑训练集测试集的问题,把所有的数据都放入模型进行降维。

from sklearn.linear_model import LogisticRegression as LR
from sklearn.model_selection import cross_val_score
from sklearn.feature_selection import  SelectFromModel
from sklearn.datasets import load_breast_cancer
import numpy as np
import matplotlib.pyplot as plt

data = load_breast_cancer()
x = data.data
y = data.target
#print(x.shape)  #(569, 30) 有30个特征
#print(y.shape)  #(569,)

LR_ = LR(solver='liblinear', C=0.9, random_state=0)
score = cross_val_score(LR_, x, y, cv=10).mean()  #0.9508145363408522
#print(score)

#x_embedded = SelectFromModel(LR_, norm_order=1).fit_transform(x, y)
#print(x_embedded.shape)  #(569, 9)  #降到9维了

coef_list = LR_.fit(x, y).coef_
coef_abs = abs((coef_list))
coef_max = coef_abs.max()
#print(coef_max) #1.9937460483274254

fullx = []
fsx = []
threshold = np.linspace(0, abs((LR_.fit(data.data,data.target).coef_)).max(), 20)
k = 0

for i in threshold:
    X_embedded = SelectFromModel(LR_, threshold=i).fit_transform(data.data, data.target)
    fullx.append(cross_val_score(LR_, data.data, data.target, cv=5).mean())
    fsx.append(cross_val_score(LR_, X_embedded, data.target, cv=5).mean())
    print((threshold[k], X_embedded.shape[1]))
    k += 1
    
plt.figure(figsize=(20, 5))
plt.plot(threshold, fullx, label="full")
plt.plot(threshold, fsx, label="feature selection")
plt.xticks(threshold)
plt.legend()
plt.show()

逻辑回归概述+逻辑回归的优点+sklearn中的逻辑回归算法+逻辑回归中的特征工程+梯度下降+二元回归与多元回归+样本不平衡与参数class_weight

for i in threshold:
    X_embedded = SelectFromModel(LR_, threshold=i).fit_transform(data.data, data.target)
    score_1 = cross_val_score(LR_, data.data, data.target, cv=5).mean()
    fullx.append(score_1)
    score_2 = cross_val_score(LR_, X_embedded, data.target, cv=5).mean()
    fsx.append(score_2)
    print((threshold[k], X_embedded.shape[1]))
    k += 1

plt.figure(figsize=(20, 5))
plt.plot(threshold, fullx, label="full")
plt.plot(threshold, fsx, label="feature selection")
plt.xticks(threshold)
plt.legend()
plt.show()

逻辑回归概述+逻辑回归的优点+sklearn中的逻辑回归算法+逻辑回归中的特征工程+梯度下降+二元回归与多元回归+样本不平衡与参数class_weight

fullx = []
fsx = []
C = np.arange(0.01, 10.01, 0.5)
#rint(C)


for i in C:
    LR_ = LR(solver='liblinear', C=i, random_state=0)
    score_1 = cross_val_score(LR_, x, y, cv=10).mean()
    fullx.append(score_1)
    x_embedded = SelectFromModel(LR_, norm_order=1).fit_transform(x, y)
    score_2 = cross_val_score(LR_, x_embedded, y, cv=10).mean()
    fsx.append(score_2)

print(max(fsx), C[fsx.index(max(fsx))])
#0.9543546365914788 5.01

plt.figure(figsize=(20, 5))
plt.plot(C, fullx, label='full')
plt.plot(C, fsx, label='feature selection')
plt.xticks(C)
plt.legend()
plt.show()

逻辑回归概述+逻辑回归的优点+sklearn中的逻辑回归算法+逻辑回归中的特征工程+梯度下降+二元回归与多元回归+样本不平衡与参数class_weight

fullx = []
fsx = []
C = np.arange(3.5, 4.5, 0.005)

for i in C:
    LR_ = LR(solver='liblinear', C=i, random_state=0)
    score_1 = cross_val_score(LR_, x, y, cv=10).mean()
    fullx.append(score_1)
    x_embedded = SelectFromModel(LR_, norm_order=1).fit_transform(x, y)
    score_2 = cross_val_score(LR_, x_embedded, y, cv=10).mean()
    fsx.append(score_2)

print(max(fsx), C[fsx.index(max(fsx))])
#0.9543546365914788 3.6049999999999978
plt.figure(figsize=(25, 5))
plt.plot(C, fullx, label='full')
plt.plot(C, fsx, label='feature selection')
plt.xticks(C)
plt.legend()
plt.show()

验证最佳C值

LR_ = LR(solver='liblinear', C=3.6049999999999978, random_state=0)
print(cross_val_score(LR_, x, y, cv=10).mean())
#0.9473057644110275

LR_ = LR(solver='liblinear', C=3.6049999999999978, random_state=0)
x_embedded = SelectFromModel(LR_, norm_order=1).fit_transform(x, y)
print(cross_val_score(LR_, x_embedded, y, cv=10).mean())
#0.9543546365914788

比较麻烦的系数累加法

系数累加法的原理非常简单。在PCA中,我们通过绘制累积可解释方差贡献率曲线来选择超参数,在逻辑回归中我们可以使用系数coef_来这样做,并且我们选择特征个数的逻辑也是类似的:找出曲线由锐利变平滑的转折点,转
折点之前被累加的特征都是我们需要的,转折点之后的我们都不需要。不过这种方法相对比较麻烦,因为我们要先对特征系数进行从大到小的排序,还要确保我们知道排序后的每个系数对应的原始特征的位置,才能够正确找出那些重要的特征。如果要使用这样的方法,不如直接使用嵌入法来得方便。

简单快速的包装法

相对的,包装法可以直接设定我们需要的特征个数,逻辑回归在现实中运用时,可能会有”需要5~8个变量”这种需求,包装法此时就非常方便了。不过逻辑回归的包装法的使用和其他算法一样,并不具有特别之处,因此在这里就
不在赘述,具体大家可以参考03期:数据预处理和特征工程中的代码。

7、梯度下降

(1)梯度下降的概念

逻辑回归概述+逻辑回归的优点+sklearn中的逻辑回归算法+逻辑回归中的特征工程+梯度下降+二元回归与多元回归+样本不平衡与参数class_weight
逻辑回归概述+逻辑回归的优点+sklearn中的逻辑回归算法+逻辑回归中的特征工程+梯度下降+二元回归与多元回归+样本不平衡与参数class_weight
逻辑回归概述+逻辑回归的优点+sklearn中的逻辑回归算法+逻辑回归中的特征工程+梯度下降+二元回归与多元回归+样本不平衡与参数class_weight
逻辑回归概述+逻辑回归的优点+sklearn中的逻辑回归算法+逻辑回归中的特征工程+梯度下降+二元回归与多元回归+样本不平衡与参数class_weight

(2)步长的概念

逻辑回归概述+逻辑回归的优点+sklearn中的逻辑回归算法+逻辑回归中的特征工程+梯度下降+二元回归与多元回归+样本不平衡与参数class_weight
逻辑回归概述+逻辑回归的优点+sklearn中的逻辑回归算法+逻辑回归中的特征工程+梯度下降+二元回归与多元回归+样本不平衡与参数class_weight
max_iter学习曲线

from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.linear_model import LogisticRegression as LR
from matplotlib import  pyplot as plt
import numpy as np

data = load_breast_cancer()
x = data.data
y = data.target
#print(x.shape)  #(569, 30)
#print(y.shape)  #(569,)

xtrain, xtest, ytrain, ytest = train_test_split(x, y, test_size=0.3, random_state=0)

lr1 = []
lr1test = []
for i in range(1, 201, 10):
    LR_ = LR(penalty='l1', solver='liblinear', C=0.8, max_iter=i)
    lr = LR_.fit(xtrain, ytrain)
    score_1 = accuracy_score(lr.predict(xtrain), ytrain)
    lr1.append(score_1)
    l1test = LR_.fit(xtest, ytest)
    score_2 = accuracy_score(lr.predict(xtest), ytest)
    lr1test.append(score_2)

graph = [lr1, lr1test]
color = ['black', 'red']
label = ['l1', 'l1test']
plt.figure(figsize=(20, 5))
for i in range(2):
    plt.plot(np.arange(1, 201, 10), graph[i], color[i], label=label[i])
plt.legend()
plt.xticks(np.arange(1, 201, 10))
plt.show()

逻辑回归概述+逻辑回归的优点+sklearn中的逻辑回归算法+逻辑回归中的特征工程+梯度下降+二元回归与多元回归+样本不平衡与参数class_weight

8、二元回归与多元回归:重要参数solver & multi_class

这种方法被称为"一对多"(One-vs-rest),简称OvR,在sklearn中表示为“ovr"。又或者,我们可以把好几个分类类型划为1,剩下的几个分类类型划为0值,这是一种”多对多“(Many-vs-Many)的方法,简称MvM,在sklearn中表示为"Multinominal"。
逻辑回归概述+逻辑回归的优点+sklearn中的逻辑回归算法+逻辑回归中的特征工程+梯度下降+二元回归与多元回归+样本不平衡与参数class_weight
求解器的选择,由参数"solver"控制,共有五种选择。其中“liblinear”是二分类专用,也是现在的默认求解器。
逻辑回归概述+逻辑回归的优点+sklearn中的逻辑回归算法+逻辑回归中的特征工程+梯度下降+二元回归与多元回归+样本不平衡与参数class_weight

from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression as LR
import numpy as np

data = load_iris()
x = data.data
y = data.target

for i in ('multinomial', 'ovr'):
    clf = LR(solver='sag', max_iter=100, random_state=42, multi_class=i).fit(x, y)
    print("training score : %.3f (%s)" % (clf.score(x, y), i))
#training score : 0.987 (multinomial)
#training score : 0.960 (ovr)

9、样本不平衡与参数class_weight

样本不平衡是指在一组数据集中,标签的一类天生占有很大的比例,或误分类的代价很高,即我们想要捕捉出某种特定的分类的时候的状况。什么情况下误分类的代价很高?例如,我们现在要对潜在犯罪者和普通人进行分类,如果没有能够识别出潜在犯罪者,那么这些人就可能去危害社会,造成犯罪,识别失败的代价会非常高,但如果,我们将普通人错误地识别成了潜在犯罪者,代价却相对较小。所以我们宁愿将普通人分类为潜在犯罪者后再人工甄别,但是却不愿将潜在犯罪者分类为普通人,有种"宁愿错杀不能放过"的感觉。再比如说,在银行要判断“一个新客户是否会违约”,通常不违约的人vs违约的人会是99:1的比例,真正违约的人其实是非常少的。这种分类状况下,即便模型什么也不做,全把所有人都当成不会违约的人,正确率也能有99%,这使得模型评估指标变得毫无意义,根本无法达到我们的“要识别出会违约的人”的建模目的。

因此我们要使用参数class_weight对样本标签进行一定的均衡,给少量的标签更多的权重,让模型更偏向少数类,向捕获少数类的方向建模。该参数默认None,此模式表示自动给与数据集中的所有标签相同的权重,即自动1:1。当误分类的代价很高的时候,我们使用”balanced“模式,我们只是希望对标签进行均衡的时候,什么都不填就可以解决样本不均衡问题。

但是,sklearn当中的参数class_weight变幻莫测,大家用模型跑一跑就会发现,我们很难去找出这个参数引导的模型趋势,或者画出学习曲线来评估参数的效果,因此可以说是非常难用。我们有着处理样本不均衡的各种方法,其中主流的是采样法,是通过重复样本的方式来平衡标签,可以进行上采样(增加少数类的样本),比如SMOTE,或者下采样(减少多数类的样本)。对于逻辑回归来说,上采样是最好的办法。在案例中,会给大家详细来讲如何在逻辑回归中使用上采样。

分享到:
赞(0) 打赏

评论 抢沙发

评论前必须登录!

  注册



长按图片转发给朋友

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏

Vieu3.3主题
专业打造轻量级个人企业风格博客主题!专注于前端开发,全站响应式布局自适应模板。

登录

忘记密码 ?

您也可以使用第三方帐号快捷登录

Q Q 登 录
微 博 登 录