Python机器学习库笔记(6)——scikit-learn:分类模型

本文将介绍以下几种分类算法在scikit-learn中的使用方法:

基础模型:

  • 逻辑回归
  • 神经网络
  • 决策树
  • 支持向量机
  • KNN
  • 朴素贝叶斯

集成模型:

  • Bagging
  • 随机森林
  • 极端随机树
  • AdaBoost
  • GBDT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 测试用例:鸢尾花数据集
from sklearn.datasets import load_iris
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split

# 载入鸢尾花数据集
iris = load_iris()
X = iris.data
y = iris.target

# 标准化
X = StandardScaler().fit_transform(X)

# 分割训练集与测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

逻辑回归

LogisticRegressionCVLogisticRegression多出交叉验证求最佳正则项系数的功能,通常使用前者。其主要参数为:

  • Cs:浮点列表或者整型,如果为整型,则在1e-4和1e4间以对数步进取值。如同SVM中的C值,是正则项系数lambda的倒数,C越小,正则项对系数的惩罚性越强。
  • fit_intercept:布尔型,是否考虑截距项。默认为True
  • cv:交叉验证折数,默认None代表3(0.20版本)。
  • penalty:采用何种正则化,默认"l2",可选"l1",但注意使用"newton-cg""sag""lbfgs"这三种优化算法时仅支持"l2"
  • scoring:评分函数,默认使用"accuracy"准确度,详见《SKlearn模型评估》
  • solver:优化算法,可选"newton-cg""lbfgs"(默认)、"liblinear""sag""saga"。对于小数据集可选"liblinear",巨型数据集选择随机梯度下降"sag""saga"更快;此外,进行多分类任务尽量不选择"liblinear",因为其只能采用一对多的分类方式。
  • max_iter:优化算法的最大迭代次数。
  • class_weight:类别权重,默认视所有类别具有相同的权重,可选"balanced"自动按照类别频率分配权重,也可指定一个字典。
  • multi_class:多分类时的分类策略,可选"ovr"(默认)、"multinomial""auto""ovr"即一对多,迭代快、准确性不如多对多;"multinomial"为多对多,迭代慢、准确度高。当优化算法使用"liblinear"时无法使用"multinomial"
  • random_state:随机数种子。
1
2
3
4
5
6
from sklearn.linear_model import LogisticRegressionCV
clf = LogisticRegressionCV(Cs=10, fit_intercept=True, cv=5, dual=False, penalty="l2", scoring=None,
solver="lbfgs", tol=0.0001, max_iter=200, class_weight=None, n_jobs=None,
verbose=0, refit=True, multi_class="multinomial", random_state=None)
clf.fit(X_train, y_train)
clf.score(X_test, y_test)

神经网络

scikit-learn中的多层感知机,即全连接神经网络。其具有如下参数:

  • hidden_layer_sizes:一个元组,代表每个隐藏层的神经元数,默认为(100,)。
  • activation:激活函数,可选"identity""logistic""tanh""relu"(默认)。
  • solver:优化算法,可选"lbfgs""sgd""adam"(默认)。默认的"adam"算法适合处理大数据集,而对于小数据集采用"lbfgs"可以更快收敛。
  • alpha:L2正则项系数,默认为0.0001。
  • batch_size:每个batch的大小,如果优化算法选择"lbfgs"将不使用batch。默认"auto"取200和样本总量间的最小值。
  • learning_rate:优化算法选择"sgd"时有效,该参数用于控制学习率的衰减,默认"constant"采用恒定学习率,"invscaling"使用指数衰减,"adaptive"使用自适应学习率衰减。
  • learning_rate_init:优化算法选择"sgd""adam"时的初始学习率。默认为0.001。
  • power_t:优化算法选择"sgd"、学习率使用"invscaling"衰减时有效,用于设定迭代次数的指数。默认为0.5。
  • max_iter:最大迭代次数,默认为200,当损失函数低于tol或者迭代次数到达这个值时模型停止迭代。对于"sgd""adam"算法,该迭代次数是指整个数据集的迭代次数(epoch),而不是batch的迭代次数。
  • shuffle:仅在选择"sgd""adam"算法时有效,是否在每次迭代前对数据洗牌。默认为True
  • random_state:随机数种子。
  • tol:容差,默认为1e-4,当学习率衰减不设为"adaptive"时,若连续n_iter_no_change次迭代造成的损失函数或验证得分提高低于这个值,则停止迭代。
  • verbose:是否在标准输出中显示进度,默认为False
  • warm_start:是否热启动,默认为False,当选择True时会使用上一次拟合的参数作为初始参数。
  • momentum:仅在选择"sgd"算法时有效。Momentum梯度下降的动量参数,在0.和1.之间,默认0.9。
  • nesterovs_momentum:仅在选择"sgd"算法、momentum大于0时有效。是否使用Nesterov Momentum,默认为True
  • early_stopping:仅在选择"sgd""adam"算法时有效,当验证分数没有提高时是否提前终止训练。若选择True,它将自动留出10%的训练数据作为验证,并在连续n_iter_no_change次的验证分数没有至少提高tol时终止训练。默认为False
  • validation_fractionearly_stoppingTrue时有效,预留用于验证的训练数据的比例,默认0.1。
  • beta_1:仅在选择"adam"算法时有效,adam算法中的一阶矩估计的指数衰减率beta1,默认值0.9。
  • beta_2:仅在选择"adam"算法时有效,adam算法中的二阶矩估计的指数衰减率beta2,默认值0.999。
  • epsilon:仅在选择"adam"算法时有效,adam算法中的epsilon,默认值1e-8。
  • n_iter_no_change:仅在选择"sgd""adam"算法时有效,连续n_iter_no_change次迭代造成的损失函数或验证得分提高低于tol,则停止迭代。默认为10。
1
2
3
4
5
6
7
8
9
from sklearn.neural_network import MLPClassifier
clf = MLPClassifier(hidden_layer_sizes=(100, ), activation="relu", solver="adam", alpha=0.0001,
batch_size="auto", learning_rate="constant", learning_rate_init=0.001,
power_t=0.5, max_iter=1000, shuffle=True, random_state=None, tol=0.0001,
verbose=False, warm_start=False, momentum=0.9, nesterovs_momentum=True,
early_stopping=False, validation_fraction=0.1, beta_1=0.9, beta_2=0.999,
epsilon=1e-08, n_iter_no_change=10)
clf.fit(X_train, y_train)
clf.score(X_test, y_test)

决策树

CART用于分类,其参数与CART回归类似:

  • criterion:分枝的标准,默认"gini"为基尼不纯度,可选"entropy"信息增益。
  • splitter:分枝的策略,默认"best"在所有划分点中找出最优的划分点,适合样本量不大的情况。样本量巨大时建议选择"random",在部分划分点中找局部最优的划分点。
  • max_depth:限制树的最大深度,默认值为None,即分割至所有叶节点都是纯的或者少于min_samples_split个样本。如果样本和特征很多时可以适当限制树的最大深度。
  • min_samples_split:分割一个节点所需的最小样本数,默认为2,当样本量非常大时可以增加这个值。
  • min_samples_leaf:叶节点上所需的最小样本数,当某个叶节点样本数少于这个值时会被剪枝。默认为1,当样本量非常大时可以增加这个值。
  • min_weight_fraction_leaf:叶节点样本权重和所需的最小值,默认为0即视样本具有相同的权重。
  • max_features:分枝时考虑的特征数量最大值,默认None即该值等于特征数量。可以指定整数或者浮点数(表示占特征总数的比例)。也可选"sqrt"(特征数的开根)、"auto"(同前)、"log2"(特征数的以2为底的对数)。如果特征数较多可以考虑限制以加快模型拟合。
  • random_state:随机数种子。
  • max_leaf_nodes:叶节点数量最大值,默认None不对叶节点数量做限制,如果特征较多可以加以限制。
  • min_impurity_decrease:默认为0.,如果分枝导致不纯度的减少大于等于该值,则节点将被分枝。
  • min_impurity_split:默认为1e-7,如果某节点的不纯度超过这个阈值,则该节会分枝,否则该节点为叶节点。
  • class_weight:接收字典或字典的列表来指定各类别的的权重,也可指定为"balanced",使用类别出现频率的倒数作为权重。使用默认的None将视所有类别具有相同的权重。
  • presort:是否对数据进行预排序,以加快寻找最佳分割点。默认为False。当使用小数据集或对深度作限制时,设置为True可能会加速训练,但对于大型数据集则反而会变慢。

调参的主要对象为max_depthmin_samples_splitmin_samples_leafmax_features

1
2
3
4
5
6
7
from sklearn.tree import DecisionTreeClassifier
clf = DecisionTreeClassifier(criterion="gini", splitter="best", max_depth=None, min_samples_split=2,
min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features=None,
random_state=None, max_leaf_nodes=None, min_impurity_decrease=0.0,
min_impurity_split=None, class_weight=None, presort=False)
clf.fit(X_train, y_train)
clf.score(X_test, y_test)

支持向量机

部分参数如下:

  • C:惩罚系数C,默认值为1.0。
  • kernel:核函数,默认使用"rbf"径向基函数,可选"linear""poly""sigmoid""precomputed"或者一个可调用的函数。
  • degree:多项式核函数的维度d,仅在核函数选择"poly"时有效。默认值为3。
  • gamma"rbf""poly""sigmoid"的系数gamma,默认为"auto",取特征数量的倒数,如果使用"scale",则取特征数量乘以变量二阶矩再取倒数。
  • coef0:核函数中的独立项,仅在核函数选择"poly""sigmoid"时有效。默认值为0.0。
  • shrinking:是否使用shrinking heuristic方法,默认为True
  • probability:是否使用概率估计,默认为False
  • tol:停止训练的误差精度,默认值为1e-3。
  • cache_size:核函数缓存大小。
  • class_weight:接收字典或字典的列表来指定各类别的的权重,也可指定为"balanced",使用类别出现频率的倒数作为权重。使用默认的None将视所有类别具有相同的权重。
  • max_iter:最大迭代次数,默认为-1即无限制。
  • decision_function_shape:多分类策略,可选"ovo""ovr"(默认)。
  • random_state:随机数种子。

最重要的两个调参对象是gammaC。gamma越大,支持向量越少,gamma越小,支持向量越多。C可理解为逻辑回归中正则项系数lambda的倒数,C过大容易过拟合,C过小容易欠拟合。通常采用网格搜索法进行调参。

1
2
3
4
5
6
from sklearn.svm import SVC
clf = SVC(C=1.0, kernel="rbf", degree=3, gamma="auto", coef0=0.0, shrinking=True,
probability=False, tol=0.001, cache_size=200, class_weight=None, verbose=False,
max_iter=-1, decision_function_shape="ovr", random_state=None)
clf.fit(X_train, y_train)
clf.score(X_test, y_test)

KNN

部分参数如下:

  • n_neighbors:最近邻单元的个数K,默认为5。
  • weights:是否考虑邻居的权重,默认值"uniform"视每个邻居的权重相等,"distance"则给较近的单元更大的权重(取距离的倒数),也可以指定一个可调用的函数。
  • algorithm:计算最近邻的算法,默认"auto"自动挑选模型认为最合适的,可选"ball_tree""kd_tree""brute"
  • leaf_size:叶节点数量,默认值30,只有在algorithm选择球树或者KD树时有效。
  • p:闵式距离的度量,p=1时为曼哈顿距离,p=2时为欧式距离(默认)。

n_neighbors是最需要关注的超参数,其次weightsp也可以适当调整。

1
2
3
4
5
from sklearn.neighbors import KNeighborsClassifier
clf = KNeighborsClassifier(n_neighbors=5, weights="uniform", algorithm="auto", leaf_size=30,
p=2, metric="minkowski", metric_params=None, n_jobs=None)
clf.fit(X_train, y_train)
clf.score(X_test, y_test)

朴素贝叶斯

scikit-learn提供了以下三种朴素贝叶斯模型:

高斯模型

当特征是连续变量时常采用高斯模型。其参数:

  • priors:先验概率,如果指定为一个形如(n_classes, )的数组,则不根据数据调整先验概率。
  • var_smoothing:为稳定性而加入的方差,默认为1e-9。

多项式模型

当特征是离散变量时常采用多项式模型。其参数:

  • alpha:平滑参数,默认值为1.0。
  • fit_prior:是否要考虑先验概率,如果选择False,对所有类别使用一致的先验概率。
  • class_prior:先验概率,如果指定为一个形如(n_classes, )的数组,则不根据数据调整先验概率。

伯努利模型

当特征是布尔型变量时常采用伯努利模型。其参数:

  • alpha:平滑参数,默认值为1.0。
  • binarize:对特征进行二值化的阈值,默认为0.0,如果设为None则假定输入特征已经二值化。
  • fit_prior:是否要考虑先验概率,如果选择False,对所有类别使用一致的先验概率。
  • class_prior:先验概率,如果指定为一个形如(n_classes, )的数组,则不根据数据调整先验概率。
1
2
3
4
from sklearn.naive_bayes import GaussianNB
clf = GaussianNB(priors=None, var_smoothing=1e-09)
clf.fit(X_train, y_train)
clf.score(X_test, y_test)

集成模型:Bagging

Bagging

参数:

  • base_estimator:基模型,默认None代表决策树,可选择其它基础回归模型对象。
  • n_estimators:基模型的数量,默认为10。
  • max_samples:用于训练基模型的从X_train中抽取样本的数量,可以是整数代表数量,也可以是浮点数代表比例,默认为1.0。
  • max_features:用于训练基模型的从X_train中抽取特征的数量,可以是整数代表数量,也可以是浮点数代表比例,默认为1.0。
  • bootstrap:对于样本是否有放回抽样,默认为True
  • bootstrap_features:对于特征是否有放回抽样,默认为False
  • oob_score:是否使用包外样本估计泛化误差。
  • warm_start:默认为False,如果选择True,下一次训练以上一次模型的参数为初始参数。

对于所有的集成模型,最需要关注的超参数是n_estimators,即基模型的数量,通常需要使用网格搜索法寻找最优解;其他的参数通常保持默认即可取得较好的效果。

1
2
3
4
5
6
from sklearn.ensemble import BaggingClassifier
clf = BaggingClassifier(base_estimator=None, n_estimators=10, max_samples=1.0, max_features=1.0,
bootstrap=True, bootstrap_features=False, oob_score=False, warm_start=False,
n_jobs=None, random_state=None, verbose=0)
clf.fit(X_train, y_train)
clf.score(X_test, y_test)

随机森林

参数:

  • n_estimators:树的数量,默认为10。
  • criterion:分枝的标准,默认”gini”为基尼不纯度,可选”entropy”信息增益。
  • max_depth:限制树的最大深度,默认值为None,表示一直分枝直到所有叶节点都是纯的,或者所有叶节点的样本数小于min_samples_split
  • min_samples_split:分割一个节点所需的最小样本数,默认为2。
  • min_samples_leaf:叶节点上所需的最小样本数,叶节点样本数少于这个值时会被剪枝。默认为1。
  • min_weight_fraction_leaf:叶节点样本权重和所需的最小值,默认为0即视样本具有相同的权重。
  • max_features:分枝时考虑的特征数量最大值,默认"auto"相当于"sqrt"。可以指定整数或者浮点数(表示占特征总数的比例)。也可选"sqrt"(特征数的开根)、"log2"(特征数的对数)、None(等于特征数)。
  • max_leaf_nodes:叶节点数最大值,默认None不对叶节点数量做限制。
  • min_impurity_decrease:默认为0,如果分枝导致不纯度的减少大于等于该值,则节点将被分枝。
  • min_impurity_split:默认为1e-7,如果某节点的不纯度超过这个阈值,则该节会分枝,否则该节点为叶节点。
  • bootstrap:对于样本是否有放回抽样,默认为True。如果为False,则使用整个数据集构建每个树。
  • oob_score:是否使用包外样本估计R方。默认为False
  • random_state:随机数种子。
  • warm_start:默认为False,如果选择True,下一次训练以上一次模型的参数为初始参数。
  • class_weight:接收字典或字典的列表来指定各类别的的权重,也可指定为"balanced",使用类别出现频率的倒数作为权重;指定为"balanced_subsample"则每棵树使用其抽样样本计算权重。使用默认的None将视所有类别具有相同的权重。

除了n_estimators之外,还可以考虑适当调整max_depthmin_samples_splitmin_samples_leafmax_features这些决策树的参数。

1
2
3
4
5
6
7
8
from sklearn.ensemble import RandomForestClassifier
clf = RandomForestClassifier(n_estimators=10, criterion="gini", max_depth=None, min_samples_split=2,
min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features="auto",
max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None,
bootstrap=True, oob_score=False, n_jobs=None, random_state=None, verbose=0,
warm_start=False, class_weight=None)
clf.fit(X_train, y_train)
clf.score(X_test, y_test)

极端随机树

Extra Tree和随机森林的区别较小,参数几乎一致。

1
2
3
4
5
6
7
8
from sklearn.ensemble import ExtraTreesClassifier
clf = ExtraTreesClassifier(n_estimators=10, criterion="gini", max_depth=None, min_samples_split=2,
min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features="auto",
max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None,
bootstrap=False, oob_score=False, n_jobs=None, random_state=None,
verbose=0, warm_start=False, class_weight=None)
clf.fit(X_train, y_train)
clf.score(X_test, y_test)

集成模型:Boosting

AdaBoost

参数:

  • base_estimator:弱分类器,可指定为任意分类模型对象,默认为None,即DecisionTreeClassifiermax_depth=1)。
  • n_estimators:最大迭代次数,即弱学习器的最大个数,默认为50。
  • learning_rate:每个弱学习器的权重缩减系数,介于0.和1.之间,默认为1.。
  • algorithm:算法,可选"SAMME", "SAMME.R"。默认使用的SAMME.R算法收敛速度通常比SAMME算法快,在迭代次数较少的情况下能取得更低的测试误差。
  • random_state:随机数种子。

n_estimatorslearning_rate两个参数相互牵制,通常会一起进行调参。

1
2
3
4
5
from sklearn.ensemble import AdaBoostClassifier
clf = AdaBoostClassifier(base_estimator=None, n_estimators=50, learning_rate=1.0,
algorithm="SAMME.R", random_state=None)
clf.fit(X_train, y_train)
clf.score(X_test, y_test)

Gradient Boosting回归

其中决策树部分的参数不列举。

  • loss:损失函数,默认值"deviance"使用对数损失函数,可选"exponential",它是Adaboost的损失函数。
  • learning_rate:每棵树的权重缩减系数,默认为0.1,与n_estimators相互牵制,是调参的重点。
  • n_estimators:最大迭代次数,默认为100。
  • subsample:子采样率,用于训练每棵树的样本占样本总数的比例,默认为1.0,如使用小于1.0的值,该模型就为随机梯度提升,会减少方差、增大偏差。
  • init:默认为None,可指定具有fitpredict方法的预测器对象,它用于初始化参数。
1
2
3
4
5
6
7
8
9
from sklearn.ensemble import GradientBoostingClassifier
clf = GradientBoostingClassifier(loss="deviance", learning_rate=0.1, n_estimators=100, subsample=1.0,
criterion="friedman_mse", min_samples_split=2, min_samples_leaf=1,
min_weight_fraction_leaf=0.0, max_depth=3, min_impurity_decrease=0.0,
min_impurity_split=None, init=None, random_state=None, max_features=None,
verbose=0, max_leaf_nodes=None, warm_start=False, presort="auto",
validation_fraction=0.1, n_iter_no_change=None, tol=0.0001)
clf.fit(X_train, y_train)
clf.score(X_test, y_test)