data_train = pd.read_csv('./比赛训练集.csv',encoding='gbk')
data_test = pd.read_csv('./比赛测试集.csv',encoding='gbk')
print('训练集',data_train.shape)
print('测试集',data_test.shape)
训练集 (5070, 10) 测试集 (1000, 9)
data_train.describe()任务2:比赛数据分析 2.1缺失值
训练集和测试集都只有【舒张压】有缺失,训练集和测试集缺失比例差别不大
fea_lst = []
num_lst = []
num_rate_lst = []
for i in list(data_train.columns):
num = data_train[i].isnull().sum()
num_rate = num/len(data_train)
fea_lst.append(i)
num_lst.append(num)
num_rate_lst.append(num_rate)
df_null_ana_train = pd.DataFrame({'fea_训练集':fea_lst,'缺失值个数':num_lst,'缺失率':num_rate_lst})
2.2 数据类型
data_train.dtypes
编号 int64 性别 int64 出生年份 int64 体重指数 float64 糖尿病家族史 object 舒张压 float64 口服耐糖量测试 float64 胰岛素释放实验 float64 肱三头肌皮褶厚度 float64 患有糖尿病标识 int64
连续型变量:出生年份、体重指数、舒张压、口服耐糖量测试、胰岛素释放实验、肱三头肌皮褶厚度
类别型变量:【性别】【糖尿病家族史】,分布如下:
从相关性系数可以看出,肱三头肌皮褶厚度和标签的相关性最高
使用其他可视化方法将字段 与 标签的分布差异进行可视化
sns.pairplot(data_train,diag_kind='hist',hue='患有糖尿病标识') plt.show()任务3:逻辑回归尝试
from sklearn.metrics import confusion_matrix
from sklearn.linear_model import LogisticRegression as LR
lr = LR(C=1e2,random_state=2020)
train_x = df_train[col].drop('患有糖尿病标识',axis=1).values
train_y = df_train['患有糖尿病标识'].values
lr.fit(train_x,train_y)
result = confusion_matrix(train_y, lr.predict(train_x))
sns.heatmap(result, annot=True, cmap='Blues')
plt.xlabel('PredictedLabels')
plt.ylabel('TrueLabels')
plt.show()
提交结果
data['舒张压'] = data['舒张压'].fillna(0)
data['体重指数_round'] = data['体重指数'] // 10
data['年龄'] = 2022 - data['出生年份']
data['口服耐糖量测试'] = data['口服耐糖量测试'].replace(-1, np.nan)
for col in ['糖尿病家族史','性别']:
data[col] = data[col].astype('category')
dict_糖尿病家族史 = {
'无记录': 0,
'叔叔或姑姑有一方患有糖尿病': 1,
'叔叔或者姑姑有一方患有糖尿病': 1,
'父母有一方患有糖尿病': 2
}
data['糖尿病家族史'] = data['糖尿病家族史'].map(dict_糖尿病家族史)
print(data.shape)
任务5:特征筛选
importance = clf.feature_importances_
feature_name = clf.feature_name_
feature_importance = pd.DataFrame({'feature_name':feature_name,'importance':importance} )
feature_importance = feature_importance.sort_values(by=['importance'],ascending=False)
feature_importance.to_csv('feature_importance.csv',index=False)
import matplotlib.pyplot as plt
plt.figure(figsize=(24,12))
lgb.plot_importance(clf, max_num_features=15)
plt.title("Featurertances")
plt.show()
任务6:高阶树模型
# 模型交叉验证
def run_model_cv(model, kf, X_tr, y, X_te, cate_col=None):
train_pred = np.zeros( (len(X_tr), len(np.unique(y))) )
test_pred = np.zeros( (len(X_te), len(np.unique(y))) )
cv_clf = []
for tr_idx, val_idx in kf.split(X_tr, y):
x_tr = X_tr.iloc[tr_idx]; y_tr = y.iloc[tr_idx]
x_val = X_tr.iloc[val_idx]; y_val = y.iloc[val_idx]
call_back = [
lgb.early_stopping(50),
]
eval_set = [(x_val, y_val)]
model.fit(x_tr, y_tr, eval_set=eval_set, callbacks=call_back, verbose=-1)
cv_clf.append(model)
train_pred[val_idx] = model.predict_proba(x_val)
test_pred += model.predict_proba(X_te)
test_pred /= kf.n_splits
return train_pred, test_pred, cv_clf
clf = lgb.LGBMClassifier(
max_depth=3,
n_estimators=4000,
n_jobs=-1,
verbose=-1,
verbosity=-1,
learning_rate=0.1,
)
train_pred, test_pred, cv_clf = run_model_cv(
clf, KFold(n_splits=5),
df_train.drop(['编号', '患有糖尿病标识'], axis=1),
df_train['患有糖尿病标识'],
df_test.drop(['编号', '患有糖尿病标识'], axis=1),
)
print((train_pred.argmax(1) == df_test['患有糖尿病标识']).mean())
df_test['label'] = test_pred.argmax(1)
df_test.rename({'编号': 'uuid'}, axis=1)[['uuid', 'label']].to_csv('submit_lgb_0628.csv', index=None)
任务7:多折训练与集成
params = {
'num_leaves': 31, #叶子节点数,默认31,树模型复杂度 num_leaves<2^max_depth
'min_data_in_leaf': 15, # 也叫min_child_samples,将其设置的较大可以避免生成一个过深的树, 但有可能导致欠拟合。
'objective': 'binary', # 目标函数,可选 ‘regression’ binary 二分类(二进制) multiclass: 多分类
'learning_rate': 0.03, # 学习率 默认 0.1 取值范围:0.01-0.3 学习率越小越好
"boosting": "gbdt", # 提升类型,默认 gbdt
"feature_fraction": 0.78, # 建树的特征选择比例 ,boosting为 rf 时用 在不进行重采样的情况下随机选择部分数据
"bagging_fraction": 0.85, # 建树的样本采样比例,用于加快训练速度、防止过拟合
'bagging_freq':3, # 3或5 表示bagging的频率,每 k 次迭代执行bagging ( bagging_fraction + bagging_freq 必须同时设置)
"bagging_seed": 1017,
"metric": 'auc', # 评估函数 可选 'auc','mae','mse','rmse','binary_logloss','multi_logloss','l2'
"lambda_l1": 0.1, # L1正则化,默认为0
"nthread": -1, # lgb线程数,一般设置为 CPU的内核数, -1 是自动匹配
'is_unbalance':True, # 用于 binary 分类 ,如果培训数据不平衡 设置为 true
# 'device ': 'gpu',
# 'gpu_platform_id ': 0,
# 'gpu_device_id' : 0
}
print('Start training...')
for i, (train_index, test_index) in enumerate(skf.split(X_train, y), start=1):
print(i)
trn_data = lgb.Dataset(X_train[feature_name].iloc[train_index], label=y.iloc[train_index])
# 加载验证集
val_data = lgb.Dataset(X_train[feature_name].iloc[test_index], label=y.iloc[test_index])
# 迭代次数
num_round = 10000
clf = lgb.train(params, trn_data, num_round, feval=f1_score_vail,valid_sets = [trn_data, val_data],
verbose_eval= 100, early_stopping_rounds = 200)
cv_model.append(clf)
clf.save_model('lgb_model.txt')
y_test = clf.predict(X_test[feature_name])
y_val = clf.predict(X_train[feature_name].iloc[test_index], num_iteration=clf.best_iteration)
oof_lgb[test_index] = y_val
cv_score.append(f1_score(y.iloc[test_index],(y_val >=0.5).astype(int)))
Start training... 1 [LightGBM] [Info] Number of positive: 1549, number of negative: 2507 [LightGBM] [Warning] Auto-choosing col-wise multi-threading, the overhead of testing was 0.000687 seconds. You can set `force_col_wise=true` to remove the overhead. [LightGBM] [Info] Total Bins 1091 [LightGBM] [Info] Number of data points in the train set: 4056, number of used features: 10 [LightGBM] [Info] [binary:BoostFromScore]: pavg=0.381903 -> initscore=-0.481477 [LightGBM] [Info] Start training from score -0.481477 Training until validation scores don't improve for 200 rounds [100] training's auc: 0.997866 training's f1_score: 0.966921 valid_1's auc: 0.989895 valid_1's f1_score: 0.926209 [200] training's auc: 0.999613 training's f1_score: 0.982748 valid_1's auc: 0.990942 valid_1's f1_score: 0.927757 Early stopping, best iteration is: [49] training's auc: 0.996568 training's f1_score: 0.962584 valid_1's auc: 0.988172 valid_1's f1_score: 0.932312 2 [LightGBM] [Info] Number of positive: 1549, number of negative: 2507 [LightGBM] [Warning] Auto-choosing row-wise multi-threading, the overhead of testing was 0.000262 seconds. You can set `force_row_wise=true` to remove the overhead. And if memory is not enough, you can set `force_col_wise=true`. [LightGBM] [Info] Total Bins 1103 [LightGBM] [Info] Number of data points in the train set: 4056, number of used features: 10 [LightGBM] [Info] [binary:BoostFromScore]: pavg=0.381903 -> initscore=-0.481477 [LightGBM] [Info] Start training from score -0.481477 Training until validation scores don't improve for 200 rounds [100] training's auc: 0.997904 training's f1_score: 0.96927 valid_1's auc: 0.993126 valid_1's f1_score: 0.949285 [200] training's auc: 0.999592 training's f1_score: 0.986872 valid_1's auc: 0.991918 valid_1's f1_score: 0.947781 Early stopping, best iteration is: [90] training's auc: 0.997623 training's f1_score: 0.96737 valid_1's auc: 0.993567 valid_1's f1_score: 0.947781 3 [LightGBM] [Info] Number of positive: 1549, number of negative: 2507 [LightGBM] [Warning] Auto-choosing col-wise multi-threading, the overhead of testing was 0.000516 seconds. You can set `force_col_wise=true` to remove the overhead. [LightGBM] [Info] Total Bins 1094 [LightGBM] [Info] Number of data points in the train set: 4056, number of used features: 10 [LightGBM] [Info] [binary:BoostFromScore]: pavg=0.381903 -> initscore=-0.481477 [LightGBM] [Info] Start training from score -0.481477 Training until validation scores don't improve for 200 rounds [100] training's auc: 0.997832 training's f1_score: 0.966667 valid_1's auc: 0.993447 valid_1's f1_score: 0.942821 [200] training's auc: 0.999566 training's f1_score: 0.98431 valid_1's auc: 0.993736 valid_1's f1_score: 0.941327 [300] training's auc: 0.999991 training's f1_score: 0.998065 valid_1's auc: 0.99341 valid_1's f1_score: 0.943445 Early stopping, best iteration is: [152] training's auc: 0.9989 training's f1_score: 0.97728 valid_1's auc: 0.993794 valid_1's f1_score: 0.941327 4 [LightGBM] [Info] Number of positive: 1549, number of negative: 2507 [LightGBM] [Warning] Auto-choosing col-wise multi-threading, the overhead of testing was 0.000544 seconds. You can set `force_col_wise=true` to remove the overhead. [LightGBM] [Info] Total Bins 1097 [LightGBM] [Info] Number of data points in the train set: 4056, number of used features: 10 [LightGBM] [Info] [binary:BoostFromScore]: pavg=0.381903 -> initscore=-0.481477 [LightGBM] [Info] Start training from score -0.481477 Training until validation scores don't improve for 200 rounds [100] training's auc: 0.998376 training's f1_score: 0.96836 valid_1's auc: 0.988011 valid_1's f1_score: 0.930946 [200] training's auc: 0.999756 training's f1_score: 0.987472 valid_1's auc: 0.988304 valid_1's f1_score: 0.924262 Early stopping, best iteration is: [19] training's auc: 0.995624 training's f1_score: 0.956607 valid_1's auc: 0.983099 valid_1's f1_score: 0.932292 5 [LightGBM] [Info] Number of positive: 1548, number of negative: 2508 [LightGBM] [Warning] Auto-choosing row-wise multi-threading, the overhead of testing was 0.000219 seconds. You can set `force_row_wise=true` to remove the overhead. And if memory is not enough, you can set `force_col_wise=true`. [LightGBM] [Info] Total Bins 1096 [LightGBM] [Info] Number of data points in the train set: 4056, number of used features: 10 [LightGBM] [Info] [binary:BoostFromScore]: pavg=0.381657 -> initscore=-0.482522 [LightGBM] [Info] Start training from score -0.482522 Training until validation scores don't improve for 200 rounds [100] training's auc: 0.997908 training's f1_score: 0.967329 valid_1's auc: 0.991967 valid_1's f1_score: 0.950695 [200] training's auc: 0.999629 training's f1_score: 0.986231 valid_1's auc: 0.992375 valid_1's f1_score: 0.946835 Early stopping, best iteration is: [5] training's auc: 0.993822 training's f1_score: 0 valid_1's auc: 0.994075 valid_1's f1_score: 0



