美文网首页P数据分析
建模调参总结及实战项目(3)

建模调参总结及实战项目(3)

作者: 茶小美 | 来源:发表于2020-05-01 18:03 被阅读0次

    根据天池项目建模调参总结而出
    机器学习算法的基础知识详见:

    1.线性回归模型

    • 将训练集分为train_X特征变量,train_y结果变量
    train_X = train[continuous_feature_names]
    train_y = train['price']
    
    • 用sklearn进行线性模型训练
    from sklearn.linear_model import LinearRegression
    model = LinearRegression(normalize=True)
    model = model.fit(train_X, train_y)
    sorted(dict(zip(continuous_feature_names,model.coef_)).items(),key=lambda x:x[1],reverse=True)
    
    • 将train_y与模型预测出的值进行散点分布对比
    plt.scatter(x=train_X['v_9'][subsample_index],y=train_y[subsample_index],color='black')#真实y值
    plt.scatter(x=train_X['v_9'][subsample_index],y=model.predict(train_X.loc[subsample_index]),color='blue')#训练后的y值
    
    
    image.png
    • 可见真实值和训练值相差较大,因此模型存在问题。
      price是长尾分布,因为模型多数假设为正态分布,可以试着将其转换成正态分布
    train_y_ln = np.log((train_y)+1)
    sns.distplot(train_y_ln)
    
    • 将train_y与新的模型预测值进行散点图分布对比
    model = model.fit(train_X,train_y_ln)
    sorted(dict(zip(continuous_feature_names,model.coef_)).items(),key=lambda x:x[1],reverse=True)
    plt.scatter(x=train_X['v_9'][subsample_index],y=train_y[subsample_index],color='black')
    plt.scatter(x=train_X['v_9'][subsample_index],y=np.exp(model.predict(train_X.loc[subsample_index])),color='blue')
    
    image.png

    再次进行可视化,发现预测结果与真实值较为接近,且未出现异常状况

    2.交叉验证

    在进行训练时,通常会分为三组,训练集、验证集、测试集。测试集不参加训练,只测试训练结果。训练集和验证集是从训练数据中取出,为了使验证结果更加有效,使用交叉验证。K折交叉验证就是将训练数据分为K层,其中每一层有一次机会作为验证集,其他作为训练集,循环K次,返回评分数组,求该数组的均值。

    cross_val_score(estimator-训练对象如model, X, y=None, scoring=None调用方法, cv=None-K折, n_jobs=1, verbose=0, fit_params=None, pre_dispatch=‘2*n_jobs’)

    因为对价格标签做了对数变化,想对比变换前和变换后的得分,这时因为两者的数值区间不同,因此需要对未做变换的y和yhat预测进行log转换到同一个数值区间中,在进行比较。因此需要对MSE进行自定义log方法。

    • log变换前MSE得分(error:1.36)
    from sklearn.model_selection import cross_val_score
    from sklearn.metrics import mean_absolute_error,make_scorer#构造评估函数
    def log_transfer(func):
        def wrapper(y,yhat):
            result = func(np.log(y),np.nan_to_num(np.log(yhat)))
            return result
        return wrapper
    scores = cross_val_score(model,X=train_X,y=train_y,cv=5,scoring=make_scorer(log_transfer(mean_absolute_error))) 
    print('AVG:', np.mean(scores))
    个人理解:make_scorer构造评估函数,cross_val_score传两个值给scoring参数,一个是y,一个是根据model后的y即yhat。
    log_transfer的目的是对MSE方法进行改造,改成y和yhat均为log后的。
    
    • log变换后MSE得分(error:0.19)
    scores = cross_val_score(model,X=train_X,y=train_y_ln,cv=5,scoring=make_scorer(mean_absolute_error))
    print('AVG:', np.mean(scores))
    

    可以看出变换后效果还是有很大提升

    注意:考虑到事实上我们并不能通过2018年数据预测2017数据,因此可以采用时间顺序对数据进行分隔,这里采用的是靠前时间的4/5样本当作训练集,靠后时间的1/5当作验证集。

    split_point = len(sample_feature) // 5 * 4#分成4/5份
    model = model.fit(train_X, train_y_ln)
    mean_absolute_error(val_y_ln, model.predict(val_X))
    #mean_absolute_error(y_true验证集的y,y_pre验证集x放入训练模型得出的y)
    

    #mean_absolute_error(y_true验证集的y,y_pre验证集x放入训练模型得出的y)

    3. 绘制学习曲线

    学习曲线:一种用来判断训练模型的一种方法,通过观察绘制出来的学习曲线图,我们可以比较直观的了解到我们的模型处于一个什么样的状态,如:过拟合(overfitting)或欠拟合(underfitting)

    image.png
    (1)观察左上图,训练集准确率与验证集准确率收敛,但是两者收敛后的准确率远小于我们的期望准确率(上面那条红线),所以由图可得该模型属于欠拟合(underfitting)问题。由于欠拟合,所以我们需要增加模型的复杂度,比如,增加特征、增加树的深度、减小正则项等等,此时再增加数据量是不起作用的。

    (2)观察右上图,训练集准确率高于期望值,验证集则低于期望值,两者之间有很大的间距,误差很大,对于新的数据集模型适应性较差,所以由图可得该模型属于过拟合(overfitting)问题。由于过拟合,所以我们降低模型的复杂度,比如减小树的深度、增大分裂节点样本数、增大样本数、减少特征数等等

    (3)一个比较理想的学习曲线图应当是:低偏差、低方差,即收敛且误差小。
    未完待续?????稍后补充

    4.多模型对比

    嵌入特征选择直接在训练时进行特征筛选,嵌入式选择最常用的是L1正则化与L2正则化。在对线性回归模型加入两种正则化方法后,他们分别变成了岭回归与Lasso回归。简单来说,正则化的目的就是为了减少过拟合现象。

    from sklearn.linear_model import LinearRegression
    from sklearn.linear_model import Ridge
    from sklearn.linear_model import Lasso
    models = [LinearRegression(),
              Ridge(),
              Lasso()]
    result = dict()
    for model in models:
        model_name = str(model).split('(')[0]
        scores = cross_val_score(model, X=train_X, y=train_y_ln, verbose=0, cv = 5, scoring=make_scorer(mean_absolute_error))
        result[model_name] = scores
        print(model_name + ' is finished')
    result = pd.DataFrame(result)
    result.index = ['cv' + str(x) for x in range(1, 6)]
    result
    

    参考:
    https://tianchi.aliyun.com/notebook-ai/detail?spm=5176.12586969.1002.12.1cd8593auEGaCE&postId=95460源代码

    数据建模、调参、模型融合需要大量基础知识点,因此需要时间整理,所以本项目停更一段时间~感谢!

    相关文章

      网友评论

        本文标题:建模调参总结及实战项目(3)

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