全栈工程师开发手册 (作者:栾鹏)

python数据挖掘系列教程

逻辑分类的相关的知识内容可以参考
http://blog.csdn.net/luanpeng825485697/article/details/78957577

参数

penalty : str, ‘l1’ or ‘l2’

LogisticRegression和LogisticRegressionCV默认就带了正则化项。penalty参数可选择的值为"l1"和"l2",分别对应L1的正则化和L2的正则化,默认是L2的正则化。

在调参时如果我们主要的目的只是为了解决过拟合,一般penalty选择L2正则化就够了。但是如果选择L2正则化发现还是过拟合,即预测效果差的时候,就可以考虑L1正则化。

另外,如果模型的特征非常多,我们希望一些不重要的特征系数归零,从而让模型系数稀疏化的话,也可以使用L1正则化。

penalty参数的选择会影响我们损失函数优化算法的选择。即参数solver的选择,如果是L2正则化,那么4种可选的算法{‘newton-cg’, ‘lbfgs’, ‘liblinear’, ‘sag’}都可以选择。

但是如果penalty是L1正则化的话,就只能选择‘liblinear’了。这是因为L1正则化的损失函数不是连续可导的,而{‘newton-cg’, ‘lbfgs’,‘sag’}这三种优化算法时都需要损失函数的一阶或者二阶连续导数。而‘liblinear’并没有这个依赖。

dual : bool

对偶或者原始方法。Dual只适用于正则化相为l2 liblinear的情况,通常样本数大于特征数的情况下,默认为False

tol : float, optional

迭代终止判据的误差范围。

C : float, default: 1.0

C为正则化系数λ的倒数,通常默认为1。设置越小则对应越强的正则化。

fit_intercept : bool, default: True

是否存在截距,默认存在

intercept_scaling : float, default 1.

仅在正则化项为"liblinear",且fit_intercept设置为True时有用。

class_weight : dict or ‘balanced’, default: None

class_weight参数用于标示分类模型中各种类型的权重,可以不输入,即不考虑权重,或者说所有类型的权重一样。如果选择输入的话,可以选择balanced让类库自己计算类型权重,

或者我们自己输入各个类型的权重,比如对于0,1的二元模型,我们可以定义class_weight={0:0.9, 1:0.1},这样类型0的权重为90%,而类型1的权重为10%。

如果class_weight选择balanced,那么类库会根据训练样本量来计算权重。某种类型样本量越多,则权重越低;样本量越少,则权重越高。

当class_weight为balanced时,类权重计算方法如下:n_samples / (n_classes * np.bincount(y))

n_samples为样本数,n_classes为类别数量,np.bincount(y)会输出每个类的样本数,例如y=[1,0,0,1,1],则np.bincount(y)=[2,3] 0,1分别出现2次和三次

那么class_weight有什么作用呢?

在分类模型中,我们经常会遇到两类问题:

第一种是误分类的代价很高。比如对合法用户和非法用户进行分类,将非法用户分类为合法用户的代价很高,我们宁愿将合法用户分类为非法用户,这时可以人工再甄别,但是却不愿将非法用户分类为合法用户。这时,我们可以适当提高非法用户的权重。

第二种是样本是高度失衡的,比如我们有合法用户和非法用户的二元样本数据10000条,里面合法用户有9995条,非法用户只有5条,如果我们不考虑权重,则我们可以将所有的测试集都预测为合法用户,这样预测准确率理论上有99.95%,但是却没有任何意义。

这时,我们可以选择balanced,让类库自动提高非法用户样本的权重。

random_state : int, RandomState instance or None, optional, default: None

随机数种子,默认为无,仅在正则化优化算法为sag,liblinear时有用。

solver : {‘newton-cg’, ‘lbfgs’, ‘liblinear’, ‘sag’, ‘saga’}

solver参数决定了我们对逻辑回归损失函数的优化方法,有4种算法可以选择,分别是:

a) liblinear:使用了开源的liblinear库实现,内部使用了坐标轴下降法来迭代优化损失函数。

b) lbfgs:拟牛顿法的一种,利用损失函数二阶导数矩阵即海森矩阵来迭代优化损失函数。

c) newton-cg:也是牛顿法家族的一种,利用损失函数二阶导数矩阵即海森矩阵来迭代优化损失函数。

d) sag:即随机平均梯度下降,是梯度下降法的变种,和普通梯度下降法的区别是每次迭代仅仅用一部分的样本来计算梯度,适合于样本数据多的时候,SAG是一种线性收敛算法,这个速度远比SGD快。

从上面的描述可以看出,newton-cg, lbfgs和sag这三种优化算法时都需要损失函数的一阶或者二阶连续导数,因此不能用于没有连续导数的L1正则化,只能用于L2正则化。而liblinear则既可以用L1正则化也可以用L2正则化。

同时,sag每次仅仅使用了部分样本进行梯度迭代,所以当样本量少的时候不要选择它,而如果样本量非常大,比如大于10万,sag是第一选择。但是sag不能用于L1正则化,所以当你有大量的样本,又需要L1正则化的话就要自己做取舍了

max_iter : int, optional

仅在正则化优化算法为newton-cg, sag and lbfgs 才有用,算法收敛的最大迭代次数。

multi_class : str, {‘ovr’, ‘multinomial’}, default: ‘ovr’

OvR的思想很简单,无论你是多少元逻辑回归,我们都可以看做二元逻辑回归。具体做法是,对于第K类的分类决策,我们把所有第K类的样本作为正例,除了第K类样本以外的所有样本都作为负例,然后在上面做二元逻辑回归,得到第K类的分类模型。

其他类的分类模型获得以此类推。

而MvM则相对复杂,这里举MvM的特例one-vs-one(OvO)作讲解。如果模型有T类,我们每次在所有的T类样本里面选择两类样本出来,不妨记为T1类和T2类,把所有的输出为T1和T2的样本放在一起,把T1作为正例,T2作为负例,进行二元逻辑回归,

得到模型参数。我们一共需要T(T-1)/2次分类。

可以看出OvR相对简单,但分类效果相对略差(这里指大多数样本分布情况,某些样本分布下OvR可能更好)。而MvM分类相对精确,但是分类速度没有OvR快。如果选择了ovr,则4种损失函数的优化方法liblinear,newton-cg,lbfgs和sag都可以选择。

但是如果选择了multinomial,则只能选择newton-cg, lbfgs和sag了。

verbose : int, default: 0

warm_start : bool, default: False

n_jobs : int, default: 1

如果multi_class =‘ovr’“,并行数等于CPU内核数量。当“solver”设置为“liblinear”时,无论是否指定“multi_class”,该参数将被忽略。如果给定值-1,则使用所有内核。

这里只讲述sklearn中如何使用逻辑回归进行分类预测。包含2种分类结果

# -*- coding: UTF-8 -*-

import numpy as np # 快速操作结构数组的工具
import pandas as pd # 数据分析处理工具


# 样本数据集,第一列为x1,第二列为x2,第三列为分类(二种类别)
data=[
    [-0.017612,14.053064,0],
    [-1.395634,4.662541,1],
    [-0.752157,6.538620,0],
    [-1.322371,7.152853,0],
    [0.423363,11.054677,0],
    [0.406704,7.067335,1],
    [0.667394,12.741452,0],
    [-2.460150,6.866805,1],
    [0.569411,9.548755,0],
    [-0.026632,10.427743,0],
    [0.850433,6.920334,1],
    [1.347183,13.175500,0],
    [1.176813,3.167020,1],
    [-1.781871,9.097953,0],
    [-0.566606,5.749003,1],
    [0.931635,1.589505,1],
    [-0.024205,6.151823,1],
    [-0.036453,2.690988,1],
    [-0.196949,0.444165,1],
    [1.014459,5.754399,1]
]


#生成X和y矩阵
dataMat = np.mat(data)
y = dataMat[:,2]   # 类别变量
b = np.ones(y.shape)  # 添加全1列向量代表b偏量
X = np.column_stack((b, dataMat[:,0:2]))  # 特征属性集和b偏量组成x
X = np.mat(X)

# 特征数据归一化
# import sklearn.preprocessing as preprocessing   #sk的去均值和归一化
# scaler=preprocessing.StandardScaler()
# X = scaler.fit_transform(X)   # 对特征数据集去均值和归一化,可以加快机器性能
# X = np.mat(X)
# # print(X)
# ========逻辑回归========

from sklearn import metrics
from sklearn.linear_model import LogisticRegression
model = LogisticRegression()
model.fit(X, y)
print('逻辑回归模型:\n',model)
# 使用模型预测
predicted = model.predict(X)   #预测分类
answer = model.predict_proba(X)  #预测分类概率
print(answer)



import matplotlib.pyplot as plt

# 绘制边界和散点
# 先产生x1和x2取值范围上的网格点,并预测每个网格点上的值。
h = 0.02
x1_min, x1_max = X[:,1].min() - .5, X[:,1].max() + .5
x2_min, x2_max = X[:,2].min() - .5, X[:,2].max() + .5
xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, h), np.arange(x2_min, x2_max, h))
testMat = np.c_[xx1.ravel(), xx2.ravel()]   #形成测试特征数据集
testMat = np.column_stack((np.ones(((testMat.shape[0]),1)),testMat))  #添加第一列为全1代表b偏量
testMat = np.mat(testMat)
Z = model.predict(testMat)

# 绘制区域网格图
Z = Z.reshape(xx1.shape)
plt.pcolormesh(xx1, xx2, Z, cmap=plt.cm.Paired)


# 绘制散点图 参数:x横轴 y纵轴,颜色代表分类。x图标为样本点,.表示预测点
plt.scatter(X[:,1].flatten().A[0], X[:,2].flatten().A[0],c=y.flatten().A[0],marker='x')   # 绘制样本数据集
plt.scatter(X[:,1].flatten().A[0], X[:,2].flatten().A[0],c=predicted.tolist(),marker='.') # 绘制预测数据集

# 绘制x轴和y轴坐标
plt.xlabel("x")
plt.ylabel("y")

# 显示图形
plt.show()

输出结果为如下矩阵,第一列表示对象属于分类1的概率,第2列表示对象属于分类2的概率

[[ 0.95516819 0.04483181]
[ 0.22866334 0.77133666]
[ 0.39179119 0.60820881]
[ 0.49491521 0.50508479]
[ 0.81868509 0.18131491]
[ 0.39458788 0.60541212]
[ 0.90687605 0.09312395]
[ 0.52035976 0.47964024]
[ 0.6779141 0.3220859 ]
[ 0.7854767 0.2145233 ]
[ 0.35582843 0.64417157]
[ 0.91239261 0.08760739]
[ 0.07671224 0.92328776]
[ 0.73553143 0.26446857]
[ 0.29669744 0.70330256]
[ 0.03904873 0.96095127]
[ 0.31388094 0.68611906]
[ 0.07853207 0.92146793]
[ 0.02871742 0.97128258]
[ 0.2323216 0.7676784 ]]

输出结果图为

这里写图片描述

根据分类概率和分类图可以看出
大体上满足分类需求,但是由于数据量少导致会有部分中间节点的分类错误,分类概率差别不明显。

我们再来看看sklear使用逻辑分类实现多分类,仍然使用上面的函数。

将数据集data换成

data=[
        [-2.68420713, 0.32660731, 0],[-2.71539062, -0.16955685, 0],[-2.88981954, -0.13734561, 0],[-2.7464372, -0.31112432, 0],[-2.72859298, 0.33392456, 0],
        [-2.27989736, 0.74778271, 0],[-2.82089068, -0.08210451, 0],[-2.62648199, 0.17040535, 0],[-2.88795857, -0.57079803, 0],[-2.67384469, -0.1066917, 0],
        [-2.50652679,0.65193501,0],[-2.61314272,0.02152063,0],[-2.78743398,-0.22774019,0],[-3.22520045,-0.50327991,0],[-2.64354322,1.1861949,0],
        [-2.38386932,1.34475434,0],[-2.6225262,0.81808967,0],[-2.64832273,0.31913667,0],[-2.19907796,0.87924409,0],[-2.58734619,0.52047364,0],
        [1.28479459, 0.68543919, 1],[0.93241075, 0.31919809, 1],[1.46406132, 0.50418983, 1],[0.18096721, -0.82560394, 1],[1.08713449, 0.07539039, 1],
        [0.64043675, -0.41732348, 1],[1.09522371, 0.28389121, 1],[-0.75146714, -1.00110751, 1],[1.04329778, 0.22895691, 1],[-0.01019007, -0.72057487, 1],
        [-0.5110862,-1.26249195,1],[0.51109806,-0.10228411,1],[0.26233576,-0.5478933,1],[0.98404455,-0.12436042,1],[-0.174864,-0.25181557,1],
        [0.92757294,0.46823621,1],[0.65959279,-0.35197629,1],[0.23454059,-0.33192183,1],[0.94236171,-0.54182226,1],[0.0432464,-0.58148945,1],
        [2.53172698, -0.01184224, 2],[1.41407223, -0.57492506, 2],[2.61648461, 0.34193529, 2],[1.97081495, -0.18112569, 2],[2.34975798, -0.04188255, 2],
        [3.39687992, 0.54716805, 2],[0.51938325, -1.19135169, 2],[2.9320051, 0.35237701, 2],[2.31967279, -0.24554817, 2],[2.91813423, 0.78038063, 2],
        [1.66193495,0.2420384,2],[1.80234045,-0.21615461,2],[2.16537886,0.21528028,2],[1.34459422,-0.77641543,2],[1.5852673,-0.53930705,2],
        [1.90474358,0.11881899,2],[1.94924878,0.04073026,2],[3.48876538,1.17154454,2],[3.79468686,0.25326557,2],[1.29832982,-0.76101394,2],
]

结果为

这里写图片描述

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐