模型
- Xgboost
import xgboost as xgb def xgb_model(X_t, X_v, y_t, y_v, test): print("XGB model start") xgb_val = xgb.DMatrix(X_v, label=y_v) xgb_train = xgb.DMatrix(X_t, label=y_t) xgb_test = xgb.DMatrix(test) params = { 'booster': 'gbtree', 'objective': 'binary:logistic', 'eval_metric': 'auc', # 'gamma': 0.1, # 用于控制是否后剪枝的参数,越大越保守,一般0.1、0.2这样子。 # 'max_depth': 8, # 构建树的深度,越大越容易过拟合 # 'alpha': 0, # L1正则化系数 'lambda': 10, # 控制模型复杂度的权重值的L2正则化项参数,参数越大,模型越不容易过拟合。 'subsample': 0.7, # 随机采样训练样本 # 'colsample_bytree': 0.5, # 生成树时进行的列采样 # 'min_child_weight': 3, # 这个参数默认是 1,是每个叶子里面 h 的和至少是多少,对正负样本不均衡时的 0-1 分类而言 # ,假设 h 在 0.01 附近,min_child_weight 为 1 意味着叶子节点中最少需要包含 100 个样本。 # 这个参数非常影响结果,控制叶子节点中二阶导的和的最小值,该参数值越小,越容易 overfitting。 'silent': True, # 设置成1则没有运行信息输出,最好是设置为0. 'eta': 0.01, # 如同学习率 # 'seed': 1000, 'n_jobs': -1, # cpu 线程数 # 'missing': 1, # 'scale_pos_weight': (np.sum(y==0)/np.sum(y==1)) # 用来处理正负样本不均衡的问题,通常取:sum(negative cases) / sum(positive cases) } plst = list(params.items()) num_rounds = 5000 # 迭代次数 watchlist = [(xgb_train, 'train'), (xgb_val, 'val')] # 训练模型并保存 # early_stopping_rounds 当设置的迭代次数较大时,early_stopping_rounds 可在一定的迭代次数内准确率没有提升就停止训练 model = xgb.train(plst, xgb_train, num_rounds, watchlist, early_stopping_rounds=200) res = model.predict(xgb_test) print('test prediction finished') return res
- Catboost
from catboost import CatBoostClassifier def cb_model(X_t, X_v, y_t, y_v, test): print('cb_model start') category=[] # c_list = ['user_id','Product_id','seller']# ,'day' for index,value in enumerate(X_t.columns): if(value in c_list): category.append(index) continue model= CatBoostClassifier(iterations=1000,learning_rate=0.04,cat_features=category, loss_function='Logloss', logging_level='Verbose',eval_metric='AUC') model.fit(X_t,y_t,eval_set=(X_v,y_v),early_stopping_rounds=100) res=model.predict_proba(test)[:,1] # importance=model.get_feature_importance(prettified=True)# 显示特征重要程度 # print(importance) return res
- LightGBM
import lightgbm as lgb def lgb_model(X_t, X_v, y_t, y_v, test): print('lgb start') lgb_train = lgb.Dataset(X_t, y_t) lgb_eval = lgb.Dataset(X_v, y_v, reference=lgb_train) # 参数 params = { 'boosting_type': 'gbdt', # 设置提升类型 'objective': 'regression', # 目标函数 'metric': {'l2', 'auc'}, # 评估函数 # 'num_leaves': 31, # 叶子节点数 'learning_rate': 0.01, # 学习速率 'feature_fraction': 0.9, # 建树的特征选择比例 'bagging_fraction': 0.8, # 建树的样本采样比例 'bagging_freq': 5, # k 意味着每 k 次迭代执行bagging 'verbose': 1 # <0 显示致命的, =0 显示错误 (警告), >0 显示信息 } # 模型训练 gbm = lgb.train(params, lgb_train, num_boost_round=500, valid_sets=lgb_eval, early_stopping_rounds=50) # 模型保存 # gbm.save_model('model.txt') # 模型加载 # gbm = lgb.Booster(model_file='model.txt') # 模型预测 res = gbm.predict(X_test, num_iteration=gbm.best_iteration) return res
统计图
- 特征(列)数据分布情况
import seaborn as sns import numpy as np import pandas as pd import matplotlib.pyplot as plt '''特征分布图''' for column in trains.columns[1:-1]:# 遍历trains中的所有行 g = sns.kdeplot(trains[column][(trains["fake"] == 1)], color="Red", shade = True)# label为1的 g = sns.kdeplot(trains[column][(trains["fake"] == 0)], color="Green", shade=True)# label为0的 # g = sns.kdeplot(trains[column], ax=g, color="Green", shade=True)# trains中所有 # g = sns.kdeplot(tests[column], ax =g, color="Blue", shade= True)# test中所有 g.set_xlabel(column) g.set_ylabel("Frequency") g = g.legend(["train_fake", "train_normal", "test"]) plt.show() print("finish")
- 探索性分析
import pandas_profiling def pd_profiling(df,path):# df为dataframe,path为文件保存路径 # 用pandas_profiling进行EDA profile = pandas_profiling.ProfileReport(df) profile.to_file(output_file=path)# 也可直接写"filename.html"
数据处理
- 分箱操作
def pandas_qcut(col, type, n): ''' type分箱类型cut,qcut col是准备分箱的列 n是组数 返回值是列,需要再赋值给数据集 ''' if type=='q': col_cut=pd.qcut(col, n, labels=[i for i in range(1, n+1)]) else: col_cut = pd.cut(col, n, labels=[i for i in range(1, n+1)]) return col_cut
def pct_rank_qcut(series, n): ''' 在python 较新的版本中,pandas.qcut()这个函数中是有duplicates这个参数的, 它能解决在等频分箱中遇到的重复值过多引起报错的问题 series:要分箱的列 n:箱子数 ''' edages = pd.Series([i/n for i in range(n)]) # 转换成百分比 func = lambda x: (edages >= x).argmax() #函数:(edages >= x)返回fasle/true列表中第一次出现true的索引值 return series.rank(pct=1).astype(float).apply(func) #series.rank(pct=1)每个值对应的百分位数,最终返回对应的组数;rank()函数传入的数据类型若为object,结果会有问题,因此进行了astype
- 对所有列做与标准差的差和其结果绝对值
def std_abs(data,col_n): # 传入合并后的数据集,返回一个增加了每列与本列标准差的差,绝对值的列 data = data.fillna(data.mean())# 不能有空值和字符类型 for i in col_n: data[i + 'std'] = data[i] - data[i].std() data[i + 'std_abs'] = data[i + 'std'].abs() print('std_abs finished') return data
损失函数
- focal_loss
def focal_loss(predictions, labels, alpha = 0.25, gamma = 2): zeros = np.zeros_like(predictions, dtype=predictions.dtype) pos_corr = np.where(labels > zeros, labels - predictions, zeros) neg_corr = np.where(labels > zeros, zeros, predictions) fl_loss = - alpha*(pos_corr ** gamma)*np.log(predictions)-(1.0 - alpha)*(neg_corr ** gamma)*np.log(1-predictions) return np.sum(fl_loss)