zoukankan      html  css  js  c++  java
  • 模型的性能评估(二) 用sklearn进行模型评估

    在sklearn当中,可以在三个地方进行模型的评估

    1:各个模型的均有提供的score方法来进行评估。 这种方法对于每一种学习器来说都是根据学习器本身的特点定制的,不可改变,这种方法比较简单。这种方法受模型的影响,

    2:用交叉验证cross_val_score,或者参数调试GridSearchCV,它们都依赖scoring参数传入一个性能度量函数。这种方法就是我们下面讨论的使用scoring进行模型的性能评估

    3:Metric方法,Metric有为各种问题提供的评估方法。这些问题包括分类、聚类、回归等。这是我们下面的使用metrics进行模型评估

    总之,在进行模型评估的时候,我们总是使用上面的三种方法。第一种方法由于比较固定,而且容易使用,所以这里并不介绍。下面介绍第二种方法和第三种。

    使用scoring进行模型的性能评估

    在进行模型选择和评估的时候我们要使用一些策略,这些策略帮助我们更好的进行模型评估,在使用这些策略的时候需要传入一个scoring参数。比如上面的cross_val_score(使用sklearn进行交叉验证中有介绍)是用交叉验证的方法来对模型评分。 还有GridSearchCV和RandomizedSearchCV是用来进行参数选择的,也需要传入一个scoring参数,这个参数决定了我们使用什么样的方法来进行评分。当需要传入scoring参数的时候,我们可以有以下几种做法:

    直接指定评分函数的名称来进行评分

    评分函数的选择是很多的,如我们熟知的f1, recall ,precision等。在用scoring进行模型性能评估的时候直接指定这些就可以完成评分任务。

    输出结果如下:

    from sklearn import svm, datasets
    from sklearn.model_selection import cross_val_score
    iris = datasets.load_iris()
    
    X, y = iris.data, iris.target
    clf = svm.SVC(probability=True, random_state=0)
    #这里传入的为neg_log_loss
    # 观察y值,可以发现y有三个取值的范围,也就是说这是一个多分类问题,所以当scoring选precision,f1值的时候是不#可以的。 但是可以传入它们对于多分类问题的变形 如f1_micro, precison_macro等,更多详见官网
    print(cross_val_score(clf, X, y, scoring='neg_log_loss'))
    
    model = svm.SVC()
    #一旦模型传入一个错误的评分函数,会报错,并且系统会提示出哪些正确的评分函数可以选择
    cross_val_score(model, X, y, scoring='wrong_choice')
    [-0.0757138  -0.16816241 -0.07091847]、
    
    ValueError: 'wrong_choice' is not a valid scoring value. Valid options are ['accuracy', 'adjusted_mutual_info_score', 'adjusted_rand_score', 'average_precision', 'completeness_score', 'explained_variance', 'f1', 'f1_macro', 'f1_micro', 'f1_samples', 'f1_weighted', 'fowlkes_mallows_score', 'homogeneity_score', 'mutual_info_score', 'neg_log_loss', 'neg_mean_absolute_error', 'neg_mean_squared_error', 'neg_mean_squared_log_error', 'neg_median_absolute_error', 'normalized_mutual_info_score', 'precision', 'precision_macro', 'precision_micro', 'precision_samples', 'precision_weighted', 'r2', 'recall', 'recall_macro', 'recall_micro', 'recall_samples', 'recall_weighted', 'roc_auc', 'v_measure_score']

    使用metric函数来进行评分

    sklearn.metrics里面提供了一些函数来帮助我们进行评分。其中里面以_score结尾的函数的返回值越大,模型的性能越好。而以_error或_loss结尾的函数,返回值越小,表示模型性能越好。从命名上来看,这一点不难理解。

    metrics里面的很多函数名不直接传入scoring后面,因为有一些函数需要传入特定的参数才能够使用。比如在使用fbeta_score的时候需要传入bata参数等。 在这个时候,我们的做法是把函数名和参数封装一下,封装成为一个新的函数,然后传入scoring后面。封装的方法是使用metrics的make_scorer方法。

    下面是一个小例子:

    from sklearn.metrics import make_scorer, fbeta_score
    #我们用make_scorer封装了fbeta_score,它需要传入一个参数
    ftwo_score = make_scorer(fbeta_score, beta=2)
    from sklearn.model_selection import GridSearchCV
    from sklearn.svm import LinearSVC
    grid = GridSearchCV(LinearSVC(), param_grid={'C':[1, 10]}, scoring=ftwo_score)

    使用metrics的make_score方法,我们可以制定出我们自己的方法,这个方法需要满足下面一些条件:

    • 需要传入一个我们自定义的函数的名称
    • 需说明greater_is_better的值是True还是False。 当值为正的时候,返回的是score的值,值越高性能越好。当为False的时候,返回的为score的负值,值越低越好。
    • 是否是针对分类问题的。 传入needs_threshold=True来说明是针对分类问题的,默认情况为False。
    • 其余的参数。如在f1_score中的bata,labels。

    我们来看一段代码:

    import numpy as np
    from sklearn.metrics import make_scorer
    
    def my_custom_loss_func(ground_truth, predictions):
        diff = np.abs(ground_truth - predictions).max()
        return np.log(1 + diff)
    
    loss  = make_scorer(my_custom_loss_func, greater_is_better=False)
    score = make_scorer(my_custom_loss_func, greater_is_better=True)
    ground_truth = [[1], [1]]
    predictions  = [0, 1]
    from sklearn.dummy import DummyClassifier
    clf = DummyClassifier(strategy='most_frequent', random_state=0)
    clf = clf.fit(ground_truth, predictions)
    #这段代码的原理是这样的,我们的clf使用ground_truth 和predictions进行训练
    #使用clf.predict(ground_truth) 进行预测以后的结果为[0,0],
    #my_custom_loss_func(np.array([0,0], np.array[0,1]) 最后得到log(2) = 0.69314
    print(score(clf, ground_truth, predictions))
    print(loss(clf, ground_truth, predictions))

    输出结果如下:

    0.6931471805599453
    -0.6931471805599453

    我们用make_score封装了我们自己的函数my_custom_loss_func 来进行模型的评分。 score和loss的结果输出相反。

    我们还可以实现我们自己的评分对象

    为了实现更高的自由度,我们可以不使用上述的make_scorer方法,完全定制出来我们自己的评分对象,这需要遵循两点

    • 能够调用(estimater, X, y)参数,estimater是我们的模型,X为数据集, y为X数据集的真实结果。
    • 需要返回一个分数作为评分的结果。该分数能够从某个方面反映出我们模型的好坏。

    传入多个评分方法

    在GridSearchCV, RandomizedSearchCV 和 cross_validate 的scoring参数当中还可以传入多个评分方法,来从不同的角度来进行评分。有两种方法,一种是传入一个列表,另外一个是传入一个字典。

    传入列表:

    scoring = ['accuracy', 'precision']

    传入字典:

    from sklearn.metrics import accuracy_score
    from sklearn.metrics import make_scorer
    scoring = {'accuracy' : make_scorer(accuracy_score), 'prec':'precision'}

    传入字典中的方法既可以是一个字符串,也可以是一个封装的方法,这些方法需要返回一个值,返回多个值是是不允许的。

    from sklearn.svm import LinearSVC
    from sklearn import datasets
    from sklearn.metrics import accuracy_score
    from sklearn.metrics import make_scorer
    from sklearn.metrics import confusion_matrix
    
    X, y = datasets.make_classification(n_classes=2, random_state=0)
    '''
    从混淆矩阵当中定义出tn,fp,fn,tp的值,混淆矩阵的值如下,(官网当中的例子疑似错误):
    TN FP
    FN TP
    '''
    def tp(y_true, y_pred): return confusion_matrix(y_true, y_pred)[1, 1]
    def tn(y_true, y_pred): return confusion_matrix(y_true, y_pred)[0, 0]
    def fp(y_true, y_pred): return confusion_matrix(y_true, y_pred)[0, 1]
    def fn(y_true, y_pred): return confusion_matrix(y_true, y_pred)[1, 0]
    scoring = {'tp' : make_scorer(tp), 'tn' : make_scorer(tn),
                          'fp' : make_scorer(fp), 'fn' : make_scorer(fn)}
    
    svm = LinearSVC(random_state=0)
    from sklearn.model_selection import cross_validate
    #我们传入了一个字典来看这个模型的各种评分情况
    cv_result = cross_validate(svm.fit( X,y), X, y, scoring=scoring)
    print(cv_result['test_tp'])  #test后面跟scoring的可以,就可以打得到测试的结果
    print(cv_result['test_fp'])

    输出结果如下:

    [16 14  9]
    [5 4 1]

    使用metrics进行模型评估

    模型的性能评估 - 理论篇这篇文章中,我们介绍了accuracy、precision、混淆矩阵、F1参数、$F_{eta}$参数、ROC和AUC,均方误差。下面我们用metrics中的方法来实现一些这些。

    Accuracy score

    metrics中的accuracy_score方法可以帮助我们计算accuracy(准确率),也就是$frac{分类正确的样本个数}{所有的样本个数}$。 这个方法对于二分类问题、多分类问题、多标签分类问题都适合。例子如下:

    import numpy as np
    from sklearn.metrics import accuracy_score
    
    y_pred = [0, 2, 1, 3]
    y_true = [0, 2, 2, 3]
    print(accuracy_score(y_pred, y_true))

    结果为: 0.75

    Confusion matrix

    confusion_matrix是计算出混淆矩阵,矩阵中的第i行,第j列的值为:实际上是第i类,但是却预测为第j类的样本的个数。

    from sklearn.metrics import confusion_matrix
    y_true = [2, 0, 2, 2, 0, 1]
    y_pred = [0, 0, 2, 2, 0, 2]
    print(confusion_matrix(y_true, y_pred))

    结果如下:

    [[2 0 0]
     [0 0 1]
     [1 0 2]]

    对于二分类问题,混淆矩阵变为了

    tn,fp

    fn, tp

    from sklearn.metrics import confusion_matrix
    y_true = [0, 0, 0, 1, 1, 1, 1, 1]
    y_pred = [0, 1, 0, 1, 0, 1, 0, 1]
    tn, fp, fn, tp = confusion_matrix(y_true, y_pred).ravel()
    print(tn, fp, fn, tp)

    输出结果为 : 2 1 2 3

    Precision,Recall 和F-matures

    对于二分类问题,我们直接使用metrics里面的方法进行计算

    from sklearn import metrics
    y_pred = [0, 1, 0, 0]
    y_true = [0, 1, 0, 1]
    
    print( metrics.precision_score(y_true, y_pred) )
    print( metrics.recall_score(y_true, y_pred) )
    print( metrics.f1_score(y_true, y_pred) )
    print( metrics.fbeta_score(y_true, y_pred, beta=0.5) )
    print( metrics.fbeta_score(y_true, y_pred, beta=1) )
    print( metrics.fbeta_score(y_true, y_pred, beta=2) )

    输出的结果如下:

    1.0
    0.5
    0.6666666666666666
    0.8333333333333334
    0.6666666666666666
    0.5555555555555556

    这些函数用起来很简单,名称后面加上_score就可以了。

    还有一个方法,precision_recall_fscore_support 直接把precision、recall、fscore和support的值都显示出来,其中support是每个标签在y_true中出现的次数。 这里的标签是y的取值情况,在二分类问题中,标签为0和1两种情况。

    print( metrics.precision_recall_fscore_support(y_true, y_pred, beta=0.5)  )

    输出如下:第一列是0作为标签时候的四个值,第二列是1作为标签时候的四个值。

    (array([0.66666667, 1.        ]), array([1. , 0.5]), array([0.71428571, 0.83333333]), array([2, 2], dtype=int64))

    另外 classification_report 可以打印出来precision、recall、f1-score、support的值

    from sklearn.metrics import classification_report
    y_true = [0, 1, 2, 2, 0]
    y_pred = [0, 0, 2, 1, 0]
    target_names = ['class 0', 'class 1', ' class_2']
    print(classification_report(y_true, y_pred, target_names=target_names))

    结果如下:

                 precision    recall  f1-score   support
    
        class 0       0.67      1.00      0.80         2
        class 1       0.00      0.00      0.00         1
        class_2       1.00      0.50      0.67         2
    
    avg / total       0.67      0.60      0.59         5

    P-R曲线

    可以使用precision_recall_curve来计算出来在不同的阈值下P和R的值,

    import numpy as np
    from sklearn.metrics import precision_recall_curve
    from sklearn.metrics import average_precision_score
    
    y_true = np.array([0, 0, 1, 1])
    y_scores = np.array([0.1, 0.4, 0.34, 0.8])
    precision, recall , threshold = precision_recall_curve(y_true, y_scores)
    print(precision)
    print(recall)
    print(threshold)
    
    print(average_precision_score(y_true, y_scores))

    输出结果如下:

    [0.66666667 0.5        1.         1.        ]
    [1.  0.5 0.5 0. ]
    [0.34 0.4  0.8 ]
    0.8333333333333333

    当然,可以根据这个结果画出图形,

    import matplotlib.pyplot as plt
    plt.scatter(recall, precision)
    plt.ylim([0, 1.1])
    plt.show()

    Figure_1

                                        P-R图形

    ROC和AUC

    受试者工作特征曲线,可以使用roc_curve来实现

    import numpy as np
    from sklearn.metrics import roc_curve
    y = np.array([1, 1, 2, 2])
    scores = np.array([0.1, 0.4, 0.35, 0.8])
    fpr, tpr, thresholds = roc_curve(y, scores, pos_label=2)
    
    print(fpr)
    print(tpr)
    print(thresholds)

    输入结果如下:

    [0.  0.5 0.5 1. ]
    [0.5 0.5 1.  1. ]
    [0.8  0.4  0.35 0.1 ]

    同样,也可以画一张图

    import matplotlib.pyplot as plt
    plt.scatter(fpr, tpr)
    plt.ylim([0,1.1])
    plt.show()

    roc

                                            ROC图形

    使用roc_auc_score可以计算AUC的值

    import numpy as np
    from sklearn.metrics import roc_auc_score
    y_true = np.array([0, 0, 1, 1])
    y_scores = np.array([0.1, 0.4, 0.35, 0.8])
    print(roc_auc_score(y_true, y_scores))

    计算得到的结果为: 0.75

    mean square error

    这是评估回归问题所使用的方法:

    from sklearn.metrics import mean_squared_error
    y_true = [3, -0.5, 2, 7]
    y_pred = [2.5, 0.0, 2, 8]
    print(mean_squared_error(y_true, y_pred))

    结果是0.375

    总结

    sklearn有三个地方可以实现模型性能度量,我们介绍了两个。一个是交叉验证策略和参数选择策略中的scoring方法,传入我们的方法即可。另外一个是metrics里面的方法,我们需要的方法都可以在这里面找到。

    参考:

    Model evaluation: quantifying the quality of predictions

  • 相关阅读:
    查看jvm的cg情况
    什么是json
    httpclient工具类
    mysql 优化思路(1)
    mysql存取日期出问题
    springboot和tomcat jar包冲突
    递归
    如何去理解return?
    js BOM判断当前窗口是否最顶层。
    个人笔记,关于ajax 如果没有请求成功不允许再次请求的方法。
  • 原文地址:https://www.cnblogs.com/jiaxin359/p/8627530.html
Copyright © 2011-2022 走看看