分类回归及预测性能评估(通过python的scikit-learn实现)

作者: 梁斌炜 分类: 应用,数学分析            发布时间: 05月24日 11:36

回归要拟合或者预测的因变量是一个连续变量,而分类要拟合或者预测的因变量是一个离线变量。如通过一系列的特征(收入、工作年限、公司规模、是否有房、是否有车、是否有贷款)来预测一个信用卡申请人是否可以发放信用卡(因变量,取值为0或者1)。
分类和回归区别仅仅在于因变量是否连续性,分类可以是二分类或者多分类。分类问题的核心也是如何找到合适的特征。

 

逻辑回归

 

针对分类问题,最经典的就是逻辑(logistic)回归,逻辑回归是一个二分类回归模型,**回归所得到的数值可以看做属于类别1的概率**

这个回归看起来y值不应该是离散的,它的图像是下面这样的。

看上图,y的值接近0或者接近1的概率是非常大的,所以回归得到的y值是分类为1的概率,一般我们认为小于0.5就把它归类的0,大于0.5归类到1,这个区间如何划分,可以根据具体业务进行调整。

二分类如何扩展到多分类

有一种叫One vs Rest (OvR)的方法来利用逻辑回归拓展到多分类,具体是这样的。

  1. 为每一个类别分别建立一个二分类逻辑回归
  2. 训练每一个回归,得到该分类的概率和不是该分类的概率
  3. 在所有二分类中,选择概率最高的那个类别

使用logistic进行多分类,Scikit-learn默认会采用OvR方式。我们不需要关心logistic是否是二分类,scikit-learn会自动处理的。

Scikit-learn的logistic回归

接下来我们看看如何在scikit-learn中是如何使用logistic回归的。包括训练、拟合、性能评估的核心代码如下:

from sklearn import linear_model
lm = linear_model.LogisticRegression()
model = lm.fit(X,y)
corss_val_score(lm,X,y,cv=5,scoring='accuracy')

看用法和线性回归几乎一模一样,看代码就是在线性模型里面调用了logistic模型。交叉检验用法几乎一样,只是打分的方法不同,因为逻辑回归的结果只有正确和不正常,所以这里的打分函数是准确率accuracy,就是在我们的测试集中有多少样本的分类被正确预测了。

我们开始进行实际的分析过程。先导入一下模块和准备好数据。

from sklearn import linear_model 
import pandas from sklearn.model_selection 
import cross_val_score 
import numpy iris = pandas.read_csv('http://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data',header=None) 
iris.columns=['SepalLengthCm','SepalWidthCm','PetalLengthCm','PetalWidthCm','Species']

接下来我们开始进行建模、拟合和评估。

lm = linear_model.LinearRegression()
features = ['PetalLengthCm']
X = iris[features]
y = iris['Species']
model = lm.fit(X,y)
score = numpy.mean(-cross_val_score(lm,X,y,cv=5,scoring='accuracy'))

运行后,报错。这里我有意给一个错误和大家分享的。

ValueError: could not convert string to float: ‘Iris-virginica’

就是说我们的因变量Species是字符型,不能转化为float,虽然我们认为类别就应该是字符串,但对于sklearn来说,分类也需要用数字来表示。我们对Species属性做一些预处理,sklearn提供一个预处理的工具LabelEncoder,它会自动的帮忙把字符串类型转换为离散的数值型。

from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
y = le.transform(iris['Species'])

这样y就自动把Species的三个文本分类改为数值型0 1 2。接下来我们就可以进行logistic回归了。

le = LabelEncoder()
le.fit(iris['Species'])
lm = linear_model.LogisticRegression()
features = ['PetalLengthCm']
X = iris[features]
y = le.transform(iris['Species'])
model = lm.fit(X,y)
score = numpy.mean(cross_val_score(lm,X,y,cv=5,scoring='accuracy'))
print('平均性能得分:'+str(score))

平均性能得分:0.786666666667

我们尝试遍历四个特征的所有组合进行分类回归,看看预测的性能得分。

第一步,定义一个遍历所有特征的函数

def combinations(ls):
    n=1<<len(ls)
    tmp=[]
    for i in range(n):
        bits=[i>>offset&1 for offset in range(len(ls)-1,-1,-1)]
        if numpy.sum(bits)>0:
            current=[ls[index] for (index,bit) in enumerate(bits) if bit==1]
            tmp= tmp+[current]
    return tmp

我们看看四个特征的所有组合,是否正确。

group =  ['PetalLengthCm', 'SepalLengthCm', 'SepalWidthCm','PetalWidthCm']
group_combinations = combinations(group)

每一个组合都遍历了。我们循环一次,每循环一次进行性能评估。

for v in group_combinations:
    X = iris[v]
    y = le.transform(iris['Species'])
    model = lm.fit(X,y)
    score = numpy.mean(cross_val_score(lm,X,y,cv=5,scoring='accuracy'))
    print('特征'+str(v) +'的平均得分:'+ '%.4f' % score)

结果如下:

可以看出我们把四个特征同时作为自变量,性能得分是最高的。预测准确率达到96%。

至此我们的分类回归就完成。 关于cross_val_score交叉检验,请看我的《回归分析及预测性能评估(通过python的scikit-learn实现)》文章的后半部分有详细介绍。

全部代码

from sklearn import linear_model
import pandas
from sklearn.model_selection import cross_val_score
import numpy
from sklearn.preprocessing import LabelEncoder


iris = pandas.read_csv('http://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data',header=None)
iris.columns=['SepalLengthCm','SepalWidthCm','PetalLengthCm','PetalWidthCm','Species']

le = LabelEncoder()
le.fit(iris['Species'])
lm = linear_model.LogisticRegression()
features = ['PetalLengthCm']
X = iris[features]
y = le.transform(iris['Species'])
model = lm.fit(X,y)
score = numpy.mean(cross_val_score(lm,X,y,cv=5,scoring='accuracy'))
print('平均性能得分:'+str(score))


def combinations(ls):
    n=1<<len(ls)
    tmp=[]
    for i in range(n):
        bits=[i>>offset&1 for offset in range(len(ls)-1,-1,-1)]
        if numpy.sum(bits)>0:
            current=[ls[index] for (index,bit) in enumerate(bits) if bit==1]
            tmp= tmp+[current]
    return tmp

cv=5
group =  ['PetalLengthCm', 'SepalLengthCm', 'SepalWidthCm','PetalWidthCm']
group_combinations = combinations(group)

for v in group_combinations:
    X = iris[v]
    y = le.transform(iris['Species'])
    model = lm.fit(X,y)
    score = numpy.mean(cross_val_score(lm,X,y,cv=5,scoring='accuracy'))
    print('特征'+str(v) +'的平均得分:'+ '%.4f' % score)

 

如果觉得我的文章对您有用,请随意赞赏。您的支持将鼓励我继续创作!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

技术交流、最新案例学习

请关注我的微信公众号