书接上文。机器学习建模全流程及资料总结(2)
四. 模型实验
这里我们补充一些数据分析的东西。
1. 数据分析及可视化相关
- 熟悉pandas的操作
- matplotlib/ seaborn 可视化分析
Matplotlib 基本函数就一个 plt.plot(x, y), 但是我们需要很多辅助功能和高级表示。
- matplotlib.pyplot.plot 详细使用 https://matplotlib.org/api/_as_gen/matplotlib.pyplot.plot.html
- 一图双y轴,也很实用于表达丰富的信息,关键函数:twinx() 【Python】matplotlib 双y轴绘制及合并图例
- 子图也是很重要的 matplotlib创建子图的三种方法
(数据科学学习手札62)详解seaborn中的kdeplot、rugplot、distplot与jointplot
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_proba support(需要 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
项目的核心实验部分就这些,下一篇再看对结果分析的相关内容。传送门 机器学习建模全流程及资料总结(4)