机器学习建模全流程及资料总结(3)

书接上文。

四. 模型实验

这里我们补充一些数据分析的东西。

1. 数据分析及可视化相关

  • 熟悉pandas的操作
  • matplotlib/ seaborn 可视化分析

(数据科学学习手札62)详解seaborn中的kdeplot、rugplot、distplot与jointplot

seaborn库调色板color设置【知识整理】

matplotlib在同一座标系上绘制多条曲线 及在多个子图上绘图

将数据/特征中的规律,可视化出来,也是很重要的。

 

下面的实验部分,从交叉验证,实验和评估三个部分介绍

2.  交叉验证 cross valid

1)分三类功能,一是简易实验和学习用的,直接获取交叉验证的结果;

from sklearn.model_selection import cross_val_score, ShuffleSplit, cross_validate, train_test_split

# 简易分割 不测试模型
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.4, random_state=0)

# 简易用法,交叉验证模型效果
scores = cross_val_score(clf, iris.data, iris.target, cv=5)
cv = ShuffleSplit(n_splits=5, test_size=0.3, random_state=0)
cross_val_score(clf, iris.data, iris.target, cv=cv)

# 允许指定多个指标进行评估, 返回内容更丰富
scoring = ['precision_macro', 'recall_macro']
clf = svm.SVC(kernel='linear', C=1, random_state=0)
scores = cross_validate(clf, iris.data, iris.target, scoring=scoring, cv=5)

2)接下来的部分用于生成索引标号,用于在不同的交叉验证策略中生成数据划分的工具。

留一和留P 似乎有重要的意义,但是目前看项目中,几折交叉验证即可

from sklearn.model_selection import KFold, LeaveOneOut, LeavePOut, ShuffleSplit
# K折交叉验证
kf = KFold(n_splits=5)
for train, test in kf.split(X):
    print("%s  %s" % (train, test))
# 留一
loo = LeaveOneOut()
for train, test in loo.split(X):
    print("%s  %s" % (train, test))
# 留P
lpo = LeavePOut(p=2)
for train, test in lpo.split(X):
    print("%s  %s" % (train, test))
# 随机
ss = ShuffleSplit(n_splits=3, test_size=0.25, random_state=0)
for train_index, test_index in ss.split(X):
    print("%s  %s" % (train_index, test_index))

3)基于类标签、具有分层的交叉验证迭代器

这一类方法在项目中具有重要的意义,我们最好是分层的划分数据集

from sklearn.model_selection import StratifiedKFold, StratifiedShuffleSplit

skf = StratifiedKFold(n_splits=3)
for train, test in skf.split(X, y):
    print("%s  %s" % (train, test))

此外,还有一类用于分组数据的交叉验证迭代器,GroupKFold等。

数据划分进行交叉验证十分重要,第一类模型训练过程不可控,只适用于学习。

对于我们的项目,为了统一交叉验证的手法,就采用的5 cv ,对ID 取余 %5,相当于自己写一个简单的 split方法。

 

3. 模型评估

模型训练的时候肯定要指定评估方法,先介绍一下:

https://sklearn.apachecn.org/docs/master/32.html

下面的文字说,评估指标 可以用在模型(LR,SVM,Xgboost)的参数中,模型评估工具(如cross_val_score)的参数中,或者metrics模块里的工具的参数中。到处都用得到,必须熟悉。

有 3 种不同的 API 用于评估模型预测的质量:

  • Estimator score method(估计器得分的方法): Estimators(估计器)有一个 score(得分) 方法,为其解决的问题提供了默认的 evaluation criterion (评估标准)。 在这个页面上没有相关讨论,但是在每个 estimator (估计器)的文档中会有相关的讨论。
  • Scoring parameter(评分参数): Model-evaluation tools (模型评估工具)使用 cross-validation(如 model_selection.cross_val_score 和 model_selection.GridSearchCV) 依靠 internal scoring strategy (内部 scoring(得分) 策略)。这在 scoring 参数: 定义模型评估规则 部分讨论。
  • Metric functions(指标函数)metrics 模块实现了针对特定目的评估预测误差的函数。这些指标在以下部分部分详细介绍 分类指标多标签排名指标回归指标 和 聚类指标 。

这部分要了解两方面:一是指定所需指标名称,二是了解各类问题的评估指标的含义。

Scoring(得分) Function(函数) Comment(注解)
Classification(分类)    
‘accuracy’ metrics.accuracy_score  
‘average_precision’ metrics.average_precision_score  
‘f1’ metrics.f1_score for binary targets(用于二进制目标)
‘f1_micro’ metrics.f1_score micro-averaged(微平均)
‘f1_macro’ metrics.f1_score macro-averaged(宏平均)
‘neg_log_loss’ metrics.log_loss requires predict_probasupport(需要 predict_proba支持)
‘precision’ etc. metrics.precision_score suffixes apply as with ‘f1’(后缀适用于 ‘f1’)
‘recall’ etc. metrics.recall_score suffixes apply as with ‘f1’(后缀适用于 ‘f1’)
‘roc_auc’ metrics.roc_auc_score
Regression(回归)    
‘explained_variance’ metrics.explained_variance_score  
‘neg_mean_absolute_error’ metrics.mean_absolute_error  
‘neg_mean_squared_error’ metrics.mean_squared_error  
‘neg_mean_squared_log_error’ metrics.mean_squared_log_error  
‘neg_median_absolute_error’ metrics.median_absolute_error  
‘r2’ metrics.r2_score

4. 模型训练

模型训练的框架就是交叉验证,模型器及参数和评估构成的,下面我们直接列出一份框架的例子。

def xgb_train_process(trail_code, valid_id, selected_modeling_data, delq_data, delq_label):
    if not path.exists(trail_code):
        makedirs(trail_code)
    print(len(valid_id))
    print(len(selected_modeling_data.columns))
    train_result = list()
    feature_rank_all = dict()
    for i in range(5):
        gc.collect()
        train_id = np.array(valid_id)
        sub_train_id = train_id[train_id % 5 != i]
        sub_test_id = train_id[train_id % 5 == i]
        print(len(sub_train_id), len(sub_test_id))
        xgtrain = selected_modeling_data.reindex(sub_train_id)
        xgtrain = xgb.DMatrix(xgtrain, label=delq_data.reindex(sub_train_id)[delq_label].values)
        gc.collect()
        xgtest = selected_modeling_data.reindex(sub_test_id)
        xgtest = xgb.DMatrix(xgtest, label=delq_data.reindex(sub_test_id)[delq_label].values)
        gc.collect()

        params = {'booster': 'gbtree',
                  'objective': 'binary:logitraw',
                  'objective': 'binary:logistic',
                  'tree_method': 'hist',
                  'max_depth': 3,  # 树的最大深度
                  'subsample': 0.70,  # 随机采样得到样本训练模型,采样的样本数占总样本数的比例
                  'colsample_bytree': 0.70,  # 构建树时对特征采样的比例(随机选取k个属性对样本进行训练)
                  'silent': 1,  # 不实时显示程序运行情况
                  'eta': 0.02,  # 学习率
                  'seed': 200,  # 随机数的种子
                  'eval_metric': 'auc',
                  'alpha': 1,
                  'lambda': 1.6,
    #               'gamma': 0.1,
                  'min_child_weight': 100,
    #               'nthread': 32
                  }
        # 非均衡数据集 设置样本权重
        params['scale_pos_weight'] = float((xgtrain.get_label() == 0).sum()) / (xgtrain.get_label() == 1).sum()
        params['base_score'] = np.mean(xgtrain.get_label())
        watchlist = [(xgtrain, 'train'), (xgtest, 'test')]
        # 训练模型
        num_rounds = 1000
        model = xgb.train(params, xgtrain, num_rounds, watchlist, early_stopping_rounds=100, verbose_eval=200)

        # 预测
        xgb_sub_train = util.give_prediction(model, xgtrain, sub_train_id)
        xgb_sub_test = util.give_prediction(model, xgtest, sub_test_id)
        # 本轮对 所有数据对预测,实际上测试集部分预测有意义
        xgb_sub_train.append(xgb_sub_test).to_csv(trail_code + '/score_'+str(num_rounds)+'_'+str(i)+'.csv')

        # 保存训练结果
        train_result.append([i, num_rounds, model.best_iteration,
                             metrics.roc_auc_score(xgtrain.get_label(),xgb_sub_train['xgb'].values),
                             metrics.roc_auc_score(xgtest.get_label(), xgb_sub_test['xgb'].values)])

        # 特征排序大集合
        model_feature_rank = model.get_fscore()
        for key in model_feature_rank:
            if key not in feature_rank_all:
                feature_rank_all[key] = model_feature_rank[key]
            else:
                feature_rank_all[key] += model_feature_rank[key]
        # 保存模型
        util.save_model(model, trail_code + '/' + str(i), save_feature=False)

    open(trail_code + '/feature.txt', 'w').writelines([x+'\n' for x in selected_modeling_data])
    open(trail_code + '/train_result.txt', 'w').writelines([','.join([str(xx) for xx in x])+'\n' for x in train_result])
    feature_rank_all = sorted(feature_rank_all.items(), key=lambda x: x[1], reverse=True)
    feature_rank_all_rec = [' '.join([str(idx), str(item)])+'\n' for idx, item in enumerate(feature_rank_all)]
    open(trail_code + '/feature_rank_all.txt', 'w') .writelines(feature_rank_all_rec)

def give_prediction(model, xgdata, accountid):
    return pd.DataFrame({'loanaccountid': accountid, 'xgb': model.predict(xgdata)}).set_index('loanaccountid')

def save_model(model, filepath, save_feature=True):
    model.dump_model(filepath + '_tree.txt')
    model.save_model(filepath + '_model.model')
    if save_feature:
        open(filepath + '_feature.txt', 'w').writelines([x+'\n' for x in model.feature_names])

做项目建议有一个util文件,保存常用函数。

最后是 预测值获取及auc:

xgb_score = util.get_5cv_score("path")  # 为df对象
delq = delq_data.reindex(xgb_score.index)[label7].tolist()
auc = metrics.roc_auc_score(delq, xgb_score['xgb'])

def get_5cv_score(trail_code):
    files = [x for x in listdir(trail_code) if x[0: 5] == 'score']
    rounds_set = set([x.split('.')[0].split('_')[1] for x in files])
    folds_set = set([x.split('.')[0].split('_')[2] for x in files])
    if len(rounds_set) == 1:
        return get_5cv_score_sub(trail_code, list(rounds_set)[0], folds_set)
    else:
        xgb_score_dict = dict()
        for round_set in sorted(rounds_set):
            xgb_score_dict[round_set] = get_5cv_score_sub(trail_code, round_set, folds_set)
        return xgb_score_dict


def get_5cv_score_sub(trail_code, round_set, folds_set):
    for fold_set in sorted(folds_set):
        xgb_score_one = pd.read_csv(trail_code + '/score_'+round_set+'_'+fold_set+'.csv', index_col='loanaccountid')
        xgb_score_one = xgb_score_one[xgb_score_one.index%5 == int(fold_set)]
        if fold_set == '0':
            xgb_score = xgb_score_one
        else:
            xgb_score = xgb_score.append(xgb_score_one)
    return xgb_score

 项目的核心实验部分就这些,下一篇再看对结果分析的相关内容。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章