在 scikit-learn 中,逻辑回归的类主要是 LogisticRegression
和 LogisticRegressionCV
。两者主要区别是 LogisticRegressionCV 使用了交叉验证来选择正则化系数 C;而 LogisticRegression 需要自己每次指定一个正则化系数。
除了交叉验证,以及选择正则化系数 C 以外,两者的使用方法基本相同。
示例
先直接上一个示例,以 sklearn 自带的乳腺癌分类数据集作为样本进行 lr 分类训练如下:
# -*- coding: UTF-8 -*-
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report, roc_auc_score
# 加载 sklearn 自带的乳腺癌(分类)数据集
X, y = load_breast_cancer(return_X_y=True)
# 以指定比例将数据集分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(
X, y,
train_size=0.875, test_size=0.125, random_state=188
)
# 使用 lr 类,初始化模型
clf = LogisticRegression(
penalty="l2", C=1.0, random_state=None, solver="lbfgs", max_iter=3000,
multi_class='ovr', verbose=0,
)
# 使用训练数据来学习(拟合),不需要返回值,训练的结果都在对象内部变量中
clf.fit(X_train, y_train)
# 使用测试数据来预测,返回值预测分类数据
y_pred = clf.predict(X_test)
# 打印主要分类指标的文本报告
print('--- report ---')
print(classification_report(y_test, y_pred))
# 打印模型的参数
print('--- params ---')
print(clf.coef_, clf.intercept_)
# 打印 auc
print('--- auc ---')
print(roc_auc_score(y_test, y_pred))
在 python 控制台打印如下:
--- report --- precision recall f1-score support 0 0.96 0.96 0.96 27 1 0.98 0.98 0.98 45 accuracy 0.97 72 macro avg 0.97 0.97 0.97 72 weighted avg 0.97 0.97 0.97 72 --- params --- [[ 0.94182486 0.18658076 -0.32283933 0.02633855 -0.16594944 -0.20684851 -0.54529162 -0.28280863 -0.24272732 -0.02880495 -0.07652661 1.18478849 0.14227278 -0.11060698 -0.02434753 0.06101177 -0.04856501 -0.03546664 -0.03674337 0.01472488 0.22382396 -0.46773163 -0.07606581 -0.01616209 -0.33500001 -0.6739626 -1.49501891 -0.57136267 -0.71535533 -0.07954869]] [29.34423853] --- auc --- 0.9703703703703705
参数
sklearn 的 lr 主要的参数设置在 LogisticRegression 构造函数和 fit
拟合函数。
solver
solver
是 LogisticRegression 构造函数的参数,用它来指定逻辑回归损失函数的优化方法,可选项如下:
newton-cg
:也是牛顿法家族的一种,利用损失函数二阶导数矩阵,即海森矩阵来迭代优化损失函数。lbfgs
:拟牛顿法的一种,利用损失函数二阶导数矩阵,即海森矩阵来迭代优化损失函数。liblinear
:使用了开源的 liblinear 库实现,内部使用了坐标轴下降法来迭代优化损失函数。sag
:即随机平均梯度下降(stochastic average gradient descent),是梯度下降法的变种,和普通梯度下降法的区别是每次迭代仅仅用一部分的样本来计算梯度,适合于样本数据多的时候。该优化算法是 2013 年,Mark Schmidt、Nicolas Le Roux 和 Francis Bach 三人在法国国家信息与自动化研究所(INRIA)技术报中发表的论文《Minimizing finite sums with the stochastic average gradient》。saga
:优化的,无偏估计的 sag 方法,它是 2014 年由 Aaron Defazio、Francis Bach 和 Simon Lacoste-Julien 发表的论文《SAGA: A Fast Incremental Gradient Method With Support for Non-Strongly Convex Composite Objectives》。
对于少量的样本数据,'liblinear' 是很好的选择,而 'sag' 和 'saga' 对大量样本训练速度更快。
对于多分类问题,只有 'newton-cg'、'sag'、'saga' 和 'lbfgs' 能够处理多项损失,而 'liblinear' 面对多分类问题,得先把一种类别作为一个类别,剩余的所有类别作为另外一个类别。依次类推,遍历所有类别,进行分类。
'newton-cg', 'lbfgs', 'sag' 和 'saga' 支持正则(penalty)参数 l2
和 none
。
'liblinear' 和 'saga' 支持正则(penalty)参数 l1
。
'saga' 支持 elasticnet
正则参数。
sag 是 0.17 版本开始支持的。
saga 是 0.19 版本开始支持的。
从 0.22 版本开始 solver 的默认值从 'liblinear' 改为 'lbfgs'。
penalty
penalty
是 LogisticRegression 构造函数的参数,它是正则惩罚参数,可选项如下:
l1
:'liblinear' 和 'saga' 支持 l1。l2
:'newton-cg', 'lbfgs', 'sag' 和 'saga' 支持 l2。elasticnet
:'saga' 支持 elasticnet。none
:'newton-cg', 'lbfgs', 'sag' 和 'saga' 支持正则参数设定 none。
默认值为 l2。
dual
dual
是 LogisticRegression 构造函数的参数,是否选择对偶,是一个布尔类型,默认为 False;dual 只适用于正则化项为 l2 的 'liblinear' 的情况,通常样本数大于特征数的情况下。
tol
tol
是 LogisticRegression 构造函数的参数,表示停止迭代求解的阈值。
- 该参数是浮点类型(float),默认为 1e-4,即 0.0001。
C
C
是 LogisticRegression 构造函数的参数,正则化系数的倒数,必须为正的浮点数,默认为 1.0,这个值越小,说明正则化效果越强。换句话说,这个值越小,越训练的模型更泛化,但也更容易欠拟合。
fit_intercept
fit_intercept
是 LogisticRegression 构造函数的参数,表示是否在拟合样本时保留截距,布尔类型,默认为 True。
intercept_scaling
intercept_scaling
是 LogisticRegression 构造函数的参数,它是给特征向量添加的一个常量,比如原本的向量是 [x],那么添加后就变成 [x, intercept_scaling];这个参数仅在 solver 参数为 liblinear,fit_intercept 参数为 True 的时候生效。该参数是浮点类型(float),默认值为 1.0。
class_weight
class_weight
是 LogisticRegression 构造函数的参数,顾名思义它指定分类的权重。
- 参数支持的类型有字典(dict)或字符串值
'balanced'
,默认值为None
。 - 如果不指定该参数,即 None,表示不对样本做任何处理,也就是对所有样本都有相同的权重。
- class_weight 为 balanced 时,样本权重会根据分类样本比例进行自适应,具体权重公式为
n_samples / (n_classes * np.bincount(y))
,其中 bincount 函数是对各个 label 的样本个数计数。
0.17 版本开始支持 class_weight='balanced'。
random_state
random_state
是 LogisticRegression 构造函数的参数,设置随机数种子。
- 参数支持的类型有 int 或 RandomState 实例对象,默认值为
None
。 - 该参数只有当 solver 为 sag、saga 或 liblinear 时生效。当设置固定的随机种子时,才会可以每次训练得到相同的结果(可以复现),否则,随机梯度下降优化算法每次训练结果都会有所不同。
max_iter
max_iter
是 LogisticRegression 构造函数的参数,设置最大的迭代次数。
- 该参数类型为 int,默认为 100。
multi_class
multi_class
是 LogisticRegression 构造函数的参数,该参数决定分类方式的选择。
- 参数可选项为 {
'auto'
,'ovr'
,'multinomial'
},默认为'auto'
。 - 'ovr' 指的是 one-vs-rest,这种就是用二分类的方法解决多分类的问题;如要分类为 A,B,C 三类,那么就可以把 A 当作正向数据,B 和 C 当作负向数据来处理。
- 'multinomial' 指的是 many-vs-many,它会选择一部分类别的样本和另一部分类别的样本来做逻辑回归二分类;如要分类为 A,B,C 三类,将 A,B 作为正向数据,C 作为负向数据,训练出一个分模型,再将 A,C 作为正向数据,B 作为负向数据,训练出一个分类模型,最后 B,C 作为正向数据,C 作为负向数据,训练出一个模型,通过这三个模型就能实现多分类。
- 'auto' 顾名思义根据实际情况,自动选择,它主要依据 solver 参数来决定,具体可以看源码的
_check_multi_class
函数,逻辑为如果 solver 为 liblinear,multi_class 为 ovr,如果分类类别大于 2,multi_class 为 multinomial,否则为 ovr。完整代码如下:def _check_multi_class(multi_class, solver, n_classes): if multi_class == 'auto': if solver == 'liblinear': multi_class = 'ovr' elif n_classes > 2: multi_class = 'multinomial' else: multi_class = 'ovr' if multi_class not in ('multinomial', 'ovr'): raise ValueError("multi_class should be 'multinomial', 'ovr' or " "'auto'. Got %s." % multi_class) if multi_class == 'multinomial' and solver == 'liblinear': raise ValueError("Solver %s does not support " "a multinomial backend." % solver) return multi_class
0.18 版本开始 solver 为 sag 和 saga 开始支持 multinomial。
0.22 版本开始默认值从 ovr 改为 auto。