机器学习项目流程及模型评估验证

作者: 刘开心_8a6c | 来源:发表于2017-04-11 21:22 被阅读946次

    4.9日到现在一直在做Udacity的P1项目——波士顿房价预测。这个项目让我收获最大的就是理清了机器学习解决问题的整体流程,搭起一个框架,学会了寻找模型的最优参数以及模型的评估和验证方法。

    机器学习项目流程思维导图.JPG

    numpy简单的统计分析整理

    import numpy as np
    a = np.array([1,2,3,4,5])
    # 最小值
    minimum_a = np.min(a)
    # 最大值
    maximum_a = np.max(a)
    # 平均值
    mean_a = np.mean(a)
    # 中位数
    median_a = np.median(a)
    # 标准差
    std_a = np.std(a)
    # 方差
    var_a = np.var(a)
    # 和
    sum_a = np.sum(a)
    

    pandas读取处理csv数据

    目前主要用的就是读取csv,然后从表中移除目标列,提取特征列。panda读出来之后是一个DataFrame。

    data = pd.read_csv('xxx')
    outcome = data['XXX'] # outcome是目标列
    features = data.drop('XXX', axis = 1) # features是移除目标列后剩下的特征
    

    模型评估验证

    误差来源

    模型误差常见来源:因模型无法表示基本数据的复杂度造成的偏差(bias)或者因模型对训练它所用的有限数据过度敏感造成的方差(Variance)

    偏差影响模型的正确性(欠拟合),方差影响模型的不确定性(过拟合)。
    sklearn的学习曲线learning_curve可以找到偏差和方差

    评估验证

    模型的评估验证分两步,首先选择性能指标,然后测试模型表现。机器学习有分类问题和回归问题两大类,这两类有不同的性能指标,分类问题的指标有accuracy、precision、recall、F1分数;回归问题有误差指标和分数指标,其中误差指标包括平均绝对误差和均方误差,分数指标包括R2分数和可释方差分数,误差指标越接近0越好,分数指标越接近1越好

    分类问题

    准确率(accuracy)

    在分类中,准确率被描述为特定类的所有项中正确分类的数量。

    准确率 = 正确识别的items数量 / 所有items数量

    准确率的缺陷在于不适用于skewed class,skewed class是指有很多数据点,大部分属于一个类,其余的小部分属于一个类,比如titanic生还问题,猜测全部死亡,accuracy也不会很低,一些算法算出来可能还不猜测全部死亡准确率高,同理猜测全部存活,accuracy就会很低,可能再怎么进行下一步判断也依然提高不了多少。
    sklearn有专门计算accuracy的函数:

    import numpy as np
    from sklearn.metrics import accuracy_score
    y_pred = [0,2,1,3]
    y_true = [0,1,2,3]
    accuracy_score = accuracy_score(y_true, y_pred)
    print(accuracy_score) # 0.5
    accuracy_score = accuracy_score(y_true, y_pred, normalize=False)
    print(accuracy_score) # 2
    
    精确率(precision)

    precision = true_positives / (true_positives + false_positives)

    精确率就是正确归为此类的占(正确归为此类的+误归为此类的)百分比。
    sklearn有专门计算precision的函数:

    >>> from sklearn.metrics import precision_score
    >>> y_true = [0, 1, 2, 0, 1, 2]
    >>> y_pred = [0, 2, 1, 0, 0, 1]
    >>> precision_score(y_true, y_pred, average='macro')  
    0.22...
    >>> precision_score(y_true, y_pred, average='micro')  
    0.33...
    >>> precision_score(y_true, y_pred, average='weighted')
    ... 
    0.22...
    >>> precision_score(y_true, y_pred, average=None)  
    array([ 0.66...,  0.        ,  0.        ])
    
    召回率(recall)

    recall = true_positives / (true_positives + false_negtives)

    召回率就是正确归为此类的占(正确归为此类的+本来是此类但是没有归为此类的)百分比。
    sklearn有专门计算precision的函数:

    >>> from sklearn.metrics import recall_score
    >>> y_true = [0, 1, 2, 0, 1, 2]
    >>> y_pred = [0, 2, 1, 0, 0, 1]
    >>> recall_score(y_true, y_pred, average='macro')  
    0.33...
    >>> recall_score(y_true, y_pred, average='micro')  
    0.33...
    >>> recall_score(y_true, y_pred, average='weighted')  
    0.33...
    >>> recall_score(y_true, y_pred, average=None)
    array([ 1.,  0.,  0.])
    
    F1分数

    F1 分数会同时考虑精确率和召回率,以便计算新的分数。可将 F1 分数理解为精确率和召回率的加权平均值,其中 F1 分数的最佳值为 1、最差值为 0:
    F1 = 2 x (精确率 x 召回率) / (精确率 + 召回率)

    >>> from sklearn.metrics import f1_score
    >>> y_true = [0, 1, 2, 0, 1, 2]
    >>> y_pred = [0, 2, 1, 0, 0, 1]
    >>> f1_score(y_true, y_pred, average='macro')  
    0.26...
    >>> f1_score(y_true, y_pred, average='micro')  
    0.33...
    >>> f1_score(y_true, y_pred, average='weighted')  
    0.26...
    >>> f1_score(y_true, y_pred, average=None)
    array([ 0.8,  0. ,  0. ])
    

    回归问题

    平均绝对误差

    将各个样本的绝对误差汇总,然后根据数据点数量求出平均误差。通过将模型的所有绝对值加起来,可以避免因预测值比真实值过高或或低抵消误差,并能获得用户评估模型的整体误差指标。

    >>> from sklearn.metrics import mean_absolute_error
    >>> y_true = [3, -0.5, 2, 7]
    >>> y_pred = [2.5, 0.0, 2, 8]
    >>> mean_absolute_error(y_true, y_pred)
    0.5
    >>> y_true = [[0.5, 1], [-1, 1], [7, -6]]
    >>> y_pred = [[0, 2], [-1, 2], [8, -5]]
    >>> mean_absolute_error(y_true, y_pred)
    0.75
    >>> mean_absolute_error(y_true, y_pred, multioutput='raw_values')
    array([ 0.5,  1. ])
    >>> mean_absolute_error(y_true, y_pred, multioutput=[0.3, 0.7])
    ... 
    0.849...
    
    均方误差

    与绝对误差相比,残差(预测值与真实值的差值)被求平方。对残差求平方的一些好处是,自动将所有的误差转为正数、注重较大的误差而不是较小的误差以及在微积分中是可微单(可让我们找到最大值和最小值)。

    >>> from sklearn.metrics import mean_squared_error
    >>> y_true = [3, -0.5, 2, 7]
    >>> y_pred = [2.5, 0.0, 2, 8]
    >>> mean_squared_error(y_true, y_pred)
    0.375
    >>> y_true = [[0.5, 1],[-1, 1],[7, -6]]
    >>> y_pred = [[0, 2],[-1, 2],[8, -5]]
    >>> mean_squared_error(y_true, y_pred)  
    0.708...
    >>> mean_squared_error(y_true, y_pred, multioutput='raw_values')
    ... 
    array([ 0.416...,  1.        ])
    >>> mean_squared_error(y_true, y_pred, multioutput=[0.3, 0.7])
    ... 
    0.824...
    
    R2分数
    >>> from sklearn.metrics import r2_score
    >>> y_true = [3, -0.5, 2, 7]
    >>> y_pred = [2.5, 0.0, 2, 8]
    >>> r2_score(y_true, y_pred)  
    0.948...
    >>> y_true = [[0.5, 1], [-1, 1], [7, -6]]
    >>> y_pred = [[0, 2], [-1, 2], [8, -5]]
    >>> r2_score(y_true, y_pred, multioutput='variance_weighted')  
    0.938...
    >>> y_true = [1,2,3]
    >>> y_pred = [1,2,3]
    >>> r2_score(y_true, y_pred)
    1.0
    >>> y_true = [1,2,3]
    >>> y_pred = [2,2,2]
    >>> r2_score(y_true, y_pred)
    0.0
    >>> y_true = [1,2,3]
    >>> y_pred = [3,2,1]
    >>> r2_score(y_true, y_pred)
    -3.0
    
    可释方差分数
    >>> from sklearn.metrics import explained_variance_score
    >>> y_true = [3, -0.5, 2, 7]
    >>> y_pred = [2.5, 0.0, 2, 8]
    >>> explained_variance_score(y_true, y_pred)  
    0.957...
    >>> y_true = [[0.5, 1], [-1, 1], [7, -6]]
    >>> y_pred = [[0, 2], [-1, 2], [8, -5]]
    >>> explained_variance_score(y_true, y_pred, multioutput='uniform_average')
    ... 
    0.983...
    

    网格搜索和交叉验证

    在Udacity的Reviewer督促下,终于搞懂了网格搜索和交叉验证以及它们是如何工作的。

    机器学习的很多算法需要寻找最优参数,进行模型改进,网格搜索可以找到算法的最有参数。
    网格搜索会遍历传入的参数字典中参数的所有可能情况,根据传入的scoring对参数进行打分,返回一个网格搜索类的对象,至于要用该对象的哪个值就视需要而定了。

    交叉验证可以让网格搜索在不碰测试集的前提下进行模型验证。交叉验证有很多种,比如k折交叉验证,它将训练集平均分成k份,其中1份做测试集,其余k-1份做训练集,运行k次,得出一个平均分作为打分。网格搜索结合交叉验证的思路就是:把网格搜索找到的所有参数在k份验证集上跑一遍,将分数最好的作为最优参数。用交叉验证最大的好处就是不碰测试集。

    下面代码是我在做Udacity的波士顿房价预测后面的可选问题——北京房价预测的代码。用的是k折交叉验证和网格搜索。

    def fit_model_k_fold(X, y):
        """ Performs grid search over the 'max_depth' parameter for a 
            decision tree regressor trained on the input data [X, y]. """
        
        # Create cross-validation sets from the training data
        # cv_sets = ShuffleSplit(n_splits = 10, test_size = 0.20, random_state = 0)
        k_fold = KFold(n_splits=10)
        
        # TODO: Create a decision tree regressor object
        regressor = DecisionTreeRegressor(random_state=80)
    
        # TODO: Create a dictionary for the parameter 'max_depth' with a range from 1 to 10
        params = {'max_depth':range(1,11)}
    
        # TODO: Transform 'performance_metric' into a scoring function using 'make_scorer' 
        scoring_fnc = make_scorer(performance_metric)
    
        # TODO: Create the grid search object
        grid = GridSearchCV(regressor, param_grid=params,scoring=scoring_fnc,cv=k_fold)
    
        # Fit the grid search object to the data to compute the optimal model
        grid = grid.fit(X, y)
    
        # Return the optimal model after fitting the data
        return grid.best_estimator_
    
    
    reg_k_fold = fit_model_k_fold(X_train, y_train)
    print "k_fold Parameter 'max_depth' is {} for the optimal model.".format(reg_k_fold.get_params()    ['max_depth'])
    # Show predictions
    for i, price in enumerate(reg_k_fold.predict(client_data)):
         print "k_fold Predicted selling price for Client {}'s home: ¥{:,.2f}万".format(i+1, price)
    

    相关文章

      网友评论

      • gofreehj:很不错的呢,思维导图可以分享一下么,或者告知一下用什么软件做的
        刘开心_8a6c:@gofreehj 用ipad 画的 就叫思维导图 很轻量级 用xmind也可以 所有操作系统都能用
      • Terence_Kwan:您好,想请教一个问题,如果用10折交叉验证来评价分类结果,对于分类的准确度,可以直接用10个模型的准确度求平均,但是如果想获得precision,recall,F1-measure,应该怎么做,也是直接求平均吗?因为搜了好多资料都只提到准确度求平均,对于其他评价结果没有提到,想知道如果用交叉验证的话,如何获得其他评价结果,也是直接把precision,recall,F1-measure求平均吗?谢谢!
        刘开心_8a6c:“对于分类的准确度,可以直接用10个模型的准确度求平均”,应该不是10个模型,是一个模型运行了10次,求平均。“如果想获得precision,recall,F1-measure,应该怎么做,也是直接求平均吗?”我认为是的。交叉验证只负责拆分训练集与验证集,查看KFold的[API](http://scikit-learn.org/stable/modules/generated/sklearn.model_selection.KFold.html#sklearn.model_selection.KFold)可以发现他的返回值是训练集和验证集,如果想要的评价标准是f1分数,就在拆分结果上运行10次,求平均数,作为模型的表现。但是其实这个作为模型最后的评价标准是不具有说服力的,训练集和验证集主要用来调参,所以你看我上面的介绍也是网格搜索加交叉验证配合起来调参,交叉验证拆分的数据集,结合网格搜索的参数及定义的评价指标,运行k次打分,最终输出比较好的参数。真正具有说服力的模型表现,应该在测试集上求accuracy或者f1score等
      • wotacid:敲代码的命令行界面不太老练,有变成自动复制到机器学习软件执行的人工智能软件吗?老兄使用什么机器学习软件的我使用斯洛文尼亚出品的橘子软件
        刘开心_8a6c: @wotacid 太感谢了! 我看看
        wotacid:@刘开心_8a6c http://www.jianshu.com/p/902b00157f79
        这里是我提到的机器学习软件橘子,有人工智能,SPSS是IBM数据挖掘软件
        机器学习能把斑马图变普通马花纹的
        https://github.com/junyanz/CycleGAN

        这里是个把图像变风格的软件,斑马变普通马花纹,下载了不会使用,没有计算消耗时间多少,不过里面有提到软件可以设置为可以进行多用户学习数据叠加
        刘开心_8a6c:@wotacid 机器学习的软件是指spss那类吗?我没有用过机器学习的软件。我平时写算法练习用的jupyter notebook
      • 朱红_fc5d:最有参数 改回 最优参数 吧。迟师兄论文里的交叉验证有新意,可以抽空看看
        刘开心_8a6c: @朱红_fc5d 好的👌👌
      • 朱红_fc5d:评价指标很系统,并且阐述得简单易懂,看来是理解透了
      • 大大大大大龙:👍
        刘开心_8a6c:@TykkiMikk 谢谢:smile:

      本文标题:机器学习项目流程及模型评估验证

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