美文网首页
分类器的不确定度估计

分类器的不确定度估计

作者: 编程回忆录 | 来源:发表于2019-10-30 23:07 被阅读0次

    在实际应用中,我们感兴趣的不仅是分类器会预测一个测试点属于哪个类别,还包括对这个预测的置信程度。在实践中,不同类型的错误会在现实应用中导致非常不同的结果。想象一个用于测试癌症的医疗应用。假阳性预测可能只会让患者接受额外的测试,但假阴性预测却可能导致重病没有得到治疗。
    scikit-learn中有两个函数可用于获取分类器的不确定度估计:decision_function和predict_prob。大多数分类器(但不是全部)都至少有其中一个函数,很多分类器两个都有。我们来构建一个GradientBoostingClassifier分类器(同时拥有decision_function和predict_prob两个方法)。看一下这两个函数对一个模拟的二维数据集的作用:

    import sys
    print("Python version:{}".format(sys.version))
    
    import pandas as pd
    print("pandas version:{}".format(pd.__version__))
    
    import matplotlib
    print("matplotlib version:{}".format(matplotlib.__version__))
    import matplotlib.pyplot as plt
    
    import numpy as np
    print("Numpy version:{}".format(np.__version__))
    
    import scipy as sp
    print("Scipy version:{}".format(sp.__version__))
    
    import IPython
    print("IPython version:{}".format(IPython.__version__))
    
    import sklearn
    print("scikit-learn version:{}".format(sklearn.__version__))
    
    import mglearn
    import graphviz
    

    Python version:3.7.1 (default, Dec 10 2018, 22:54:23) [MSC v.1915 64 bit (AMD64)]
    pandas version:0.23.4
    matplotlib version:3.0.2
    Numpy version:1.15.4
    Scipy version:1.1.0
    IPython version:7.2.0
    scikit-learn version:0.20.1

    from sklearn.ensemble import GradientBoostingClassifier
    from sklearn.datasets import make_circles
    from sklearn.model_selection import train_test_split
    
    X,y=make_circles(noise=0.25,factor=0.5,random_state=1)
    
    # 为了便于说明,我们将两个类别重命名为“blue”和“red”
    y_named=np.array(["blue","red"])[y]
    
    # 我们可以对任意个数组调用train_test_split
    # 所有的数组的划分方式都是一致的
    X_train,X_test,y_train_named,y_test_named,y_train,y_test=train_test_split(X,y_named,y,random_state=0)
    
    # 构建梯度提升模型
    gbrt=GradientBoostingClassifier(random_state=0)
    gbrt.fit(X_train,y_train_named)
    

    GradientBoostingClassifier(criterion='friedman_mse', init=None,
    learning_rate=0.1, loss='deviance', max_depth=3,
    max_features=None, max_leaf_nodes=None,
    min_impurity_decrease=0.0, min_impurity_split=None,
    min_samples_leaf=1, min_samples_split=2,
    min_weight_fraction_leaf=0.0, n_estimators=100,
    n_iter_no_change=None, presort='auto', random_state=0,
    subsample=1.0, tol=0.0001, validation_fraction=0.1,
    verbose=0, warm_start=False)

    决策函数

    对于二分类情况,decision_function返回值的形状是(n_samples),为每个样本都返回一个浮点数:

    print("X_test.shape:{}".format(X_test.shape))
    print("Decision function shape:{}".format(gbrt.decision_function(X_test).shape))
    

    X_test.shape:(25, 2)
    Decision function shape:(25,)
    对于类别1来说,这个值表示模型对该数据点属于“正”类的置信程度。正值表示对正类的偏好,负值表示对“反类”(其他类)的偏好:

    # 显示decision_function的前几个数
    print("Decision function:\n{}".format(gbrt.decision_function(X_test)[:6]))
    

    Decision function:
    [ 4.13592629 -1.7016989 -3.95106099 -3.62599351 4.28986668 3.66166106]
    我们可以通过仅查看决策函数的正负号来再现预测值:

    print("Thresholded decision function:\n{}".format(gbrt.decision_function(X_test)>0))
    print("Prediction:\n{}".format(gbrt.predict(X_test)))
    

    Thresholded decision function:
    [ True False False False True True False True True True False True
    True False True False False False True True True True True False
    False]
    Prediction:
    ['red' 'blue' 'blue' 'blue' 'red' 'red' 'blue' 'red' 'red' 'red' 'blue'
    'red' 'red' 'blue' 'red' 'blue' 'blue' 'blue' 'red' 'red' 'red' 'red'
    'red' 'blue' 'blue']
    对于二分类问题,“反”类始终是classes_属性的第一个元素,“正”类是classes_的第二个元素。因此,如果你想要完全再现predict的输出,需要利用classes_属性:

    # 将布尔值True/False转换成0和1
    greater_zero=(gbrt.decision_function(X_test)>0).astype(int)
    # 利用0和1作为classes_的索引
    pred=gbrt.classes_[greater_zero]
    # pred与gbrt.predict的输出完全相同
    print("pred is equal to predictions:\n{}".format(np.all(pred==gbrt.predict(X_test))))
    

    pred is equal to predictions:
    True
    decision_function可以在任意范围取值,这取决于数据与模型参数:

    decision_function=gbrt.decision_function(X_test)
    print("Decision function minimum:{:.2f} maximum:{:.2f}".format(np.min(decision_function),np.max(decision_function)))
    

    Decision function minimum:-7.69 maximum:4.29
    由于可以任意缩放,因此decision_function的输出往往很难解释。
    在下面的例子中,我们利用颜色编码在二维平面中画出所有点的decision_function,还有决策边界|。我们将训练点画成圆,将测试数据画成三角:

    fig,axes=plt.subplots(1,2,figsize=(13,5))
    mglearn.tools.plot_2d_separator(gbrt,X,ax=axes[0],alpha=.4,fill=True,cm=mglearn.cm2)
    scores_image=mglearn.tools.plot_2d_scores(gbrt,X,ax=axes[1],alpha=.4,cm=mglearn.ReBl)
    
    for ax in axes:
        # 画成训练点和测试点
        mglearn.discrete_scatter(X_test[:,0],X_test[:,1],y_test,markers='^',ax=ax)
        mglearn.discrete_scatter(X_train[:,0],X_train[:,1],y_train,markers='o',ax=ax)
        ax.set_xlabel("Feature 0")
        ax.set_ylabel("Feature 1")
    cbar=plt.colorbar(scores_image,ax=axes.tolist())
    axes[0].legend(["Test class 0","Test class 1","Train class 0","Train class 1"],ncol=4,loc=(.1,1.1))
    
    image.png

    既给出预测结果,又给出分类器的置信程度,这样给出的信息量更大。但在上面的图像中,很难分辨出两个类别之间的边界。

    预测概率

    predict_prob的输出是每个类别的概率,通常比decision_function的输出更容易理解。对于二分类问题,它的形状始终是(n_samples,2):

    print("Shape of probabilities:{}".format(gbrt.predict_proba(X_test).shape))
    

    Shape of probabilities:(25, 2)
    每行的第一个元素是第一个类别的估计概率,第二个元素是第二个类别的估计概率。由于predict_proba的输出是一个概率,因此总是在0和1之间,两个类别的元素之和始终为1:

    # 显示predict_proba的前几个元素
    print("Predicted probabilities:\n{}".format(gbrt.predict_proba(X_test[:6])))
    

    Predicted probabilities:
    [[0.01573626 0.98426374]
    [0.84575649 0.15424351]
    [0.98112869 0.01887131]
    [0.97406775 0.02593225]
    [0.01352142 0.98647858]
    [0.02504637 0.97495363]]
    由于两个类别的概率之和为1,因此只有一个类别的概率超过50%。这个类别就是模型的预测结果。
    如果模型给出的不确定度符合实际情况,那么这个模型被称为校正(calibratd)模型。在校正模型中,如果预测有70%的确定度,那么它在70%的情况下正确。

    fig,axes=plt.subplots(1,2,figsize=(13,5))
    
    mglearn.tools.plot_2d_separator(gbrt,X,ax=axes[0],alpha=.4,cm=mglearn.cm2)
    scores_image=mglearn.tools.plot_2d_scores(gbrt,X,ax=axes[1],alpha=.5,cm=mglearn.ReBl,function='predict_proba')
    
    for ax in axes:
        # 画出训练点和测试点
        mglearn.discrete_scatter(X_test[:,0],X_test[:,1],y_test,markers='^',ax=ax)
        mglearn.discrete_scatter(X_train[:,0],X_train[:,1],y_train,markers='o',ax=ax)
        ax.set_xlabel("Feature 0")
        ax.set_ylabel("Feature 1")
    cbar=plt.colorbar(scores_image,ax=axes.tolist())
    axes[0].legend(["Test class 0","Test class 1","Train class 0","Train class 1"],ncol=4,loc=(.1,1.1))
    
    image.png

    上图中的边界更加 明确,不确定的小块区域清晰可见。

    相关文章

      网友评论

          本文标题:分类器的不确定度估计

          本文链接:https://www.haomeiwen.com/subject/ijzavctx.html