本文记录了尝试该比赛的全过程,感谢Coggle数据科学 7月的活动!! ——30天入门数据竞赛
任务1:比赛报名赛事地址:http://challenge.xfyun.cn/topic/info?type=diabetes
- 步骤1:报名比赛http://challenge.xfyun.cn/topic/info?type=diabetes&ch=ds22-dw-zmt05
- 步骤2:下载比赛数据(点击比赛页面的赛题数据)
下载到本地
- 步骤3:解压比赛数据,并使用pandas进行读取;
解压得到:
用pandas开始读取,我们使用基础的read_csv方法来读取数据集
import pandas as pd
train_df = pd.read_csv('F:ProgramsPycharmProjectOHSSdiabetesPractice糖尿病遗传风险预测挑战赛公开数据比赛训练集.csv')
test_df = pd.read_csv('F:ProgramsPycharmProjectOHSSdiabetesPractice糖尿病遗传风险预测挑战赛公开数据比赛测试集.csv')
结果报错:
报错是说解码错误 “utf-8”编解码器无法解码位置0中的字节0xb1:起始字节无效。
为什么呢,可能因为该csv文件是中文操作系统下制作的,而编码规则一般由操作系统的语言区域设置决定,在中文操作系统下默认的是GBK。在当今UTF-8编码一统天下的年代,pd.read_csv方法默认按照UTF-8编码解析,所以报错了。
怎么解决:我们用pd.read_csv解码文件的时候,指定为GBK编码,理论上就不会报错了,接下来我们指定编码格式为GBK,调整一下代码,并用pd.head() 粗略看一看数据 试试
import pandas as pd
train_df = pd.read_csv('F:ProgramsPycharmProjectOHSSdiabetesPractice糖尿病遗传风险预测挑战赛公开数据比赛训练集.csv', encoding='gbk')
test_df = pd.read_csv('F:ProgramsPycharmProjectOHSSdiabetesPractice糖尿病遗传风险预测挑战赛公开数据比赛测试集.csv', encoding='gbk')
print(train_df.head())
print(test_df.head())
我们看到,可以正常显示了
- 步骤4:查看训练集和测试集字段类型,并将数据读取代码写到博客
按照Coggle的指导,我们使用df.shape查看数据集的大小,使用df.dtypes查看一下字段类型
import pandas as pd
train_df = pd.read_csv('F:ProgramsPycharmProjectOHSSdiabetesPractice糖尿病遗传风险预测挑战赛公开数据比赛训练集.csv', encoding='gbk')
test_df = pd.read_csv('F:ProgramsPycharmProjectOHSSdiabetesPractice糖尿病遗传风险预测挑战赛公开数据比赛测试集.csv', encoding='gbk')
print(train_df.head())
print(test_df.head())
print(train_df.shape, test_df.shape) # 查看数据集的大小
print(train_df.dtypes, test_df.dtypes) # 查看一下字段类型
我们可以看到如官方所说:
训练集(比赛训练集.csv)一共有5070条数据,10个字段:5070×10。数据的字段有编号、性别、出生年份、体重指数、糖尿病家族史、舒张压、口服耐糖量测试、胰岛素释放实验、肱三头肌皮褶厚度、患有糖尿病标识(最后一列)。
测试集(比赛测试集.csv)一共有1000条数据,用于验证预测模型的性能。因为没有给你标注是否是患有糖尿病,所以少了最后一个字段。shape是1000×9。数据的字段有编号、性别、出生年份、体重指数、糖尿病家族史、舒张压、口服耐糖量测试、胰岛素释放实验、肱三头肌皮褶厚度。
任务2:比赛数据分析另外我们还需要注意到:数据集在int类型和float类型中,混入了一个object类型,这可能会影响我们后续的模型选择。
- 步骤1:统计字段的缺失值,计算缺失比例;
我们做机器学习任务的时候,通常情况下,拿到的数据都会存在缺失值,而数据预处理首先需要做的就是对存在的缺失值进行处理。我们首先调用df.isnull()通过缺失值统计,训练集和测试集的缺失值分布是否一致?
我们可以通过df.isnull.sum()来查看各个缺失值的数量,也可以通过df.isnull.mean()来查看缺失值的比例
print(train_df.isnull().sum()) print(train_df.isnull().mean())
我们可以看到,在train_df这个数据集中,舒张压有247个缺失值,占比达 0.048718
我们再来看看test_df
print(test_df.isnull().sum()) print(test_df.isnull().mean())
我们可以看到验证集也是只有舒张压这个指标又缺失值,而且和训练集分布差不多一致,也是占到4%左右
通过缺失值统计,有没有缺失比例很高的列?
一般来说,如果我们的特征非常多,比如高达260个特征,但是其中有些列的缺失值比例很大,有99%,那么这些特征一般很难被我们利用起来,预处理的时候,我们可以对这些字段进行舍弃。我们这次的数据集还没有缺失得很厉害,数据集都比较完备。
步骤2:分析字段的类型;
首先我们看一下官方对数据集的描述
数据集字段说明
编号:标识个体身份的数字;
性别:1表示男性,0表示女性;
出生年份:出生的年份;
体重指数:体重除以身高的平方,单位kg/m2;
糖尿病家族史:标识糖尿病的遗传特性,记录家族里面患有糖尿病的家属,分成三种标识,分别是父母有一方患有糖尿病、叔叔或者姑姑有一方患有糖尿病、无记录;
舒张压:心脏舒张时,动脉血管弹性回缩时,产生的压力称为舒张压,单位mmHg;
口服耐糖量测试:诊断糖尿病的一种实验室检查方法。比赛数据采用120分钟耐糖测试后的血糖值,单位mmol/L;
胰岛素释放实验:空腹时定量口服葡萄糖刺激胰岛β细胞释放胰岛素。比赛数据采用服糖后120分钟的血浆胰岛素水平,单位pmol/L;
肱三头肌皮褶厚度:在右上臂后面肩峰与鹰嘴连线的重点处,夹取与上肢长轴平行的皮褶,纵向测量,单位cm;
患有糖尿病标识:数据标签,1表示患有糖尿病,0表示未患有糖尿病。
通过官方对数据集的说明,我们可以知道,在训练集上,数据类型主要分为两类,类别型 4个,数值型 6个。
类别型:编号、性别、糖尿病家族史、患有糖尿病标识、
数值型:出生年份、体重指数、舒张压、口服耐糖量测试、胰岛素释放实验、肱三头肌皮褶厚度、
- 步骤3:计算字段相关性;
print(train_df.corr().iloc[:,-1]) # 计算df的相关系数,只返回最后一列结果
我们可以看到 体重指数,肱三头肌皮褶厚度和标签的相关性最高,分别是0.377919和0.410667,看来糖尿病和肥胖非常相关。
尝试使用一些可视化方法将字段 与 标签的分布差异进行可视化;
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
train_df = pd.read_csv('F:ProgramsPycharmProjectOHSSdiabetesPractice糖尿病遗传风险预测挑战赛公开数据比赛训练集.csv', encoding='gbk')
test_df = pd.read_csv('F:ProgramsPycharmProjectOHSSdiabetesPractice糖尿病遗传风险预测挑战赛公开数据比赛测试集.csv', encoding='gbk')
print(train_df.head())
print(test_df.head())
# print(train_df.shape, test_df.shape)
# print(train_df.dtypes, test_df.dtypes)
print(train_df.isnull().sum())
print(train_df.isnull().mean())
print(test_df.isnull().sum())
print(test_df.isnull().mean())
print(train_df.corr().iloc[:,-1])
plt.rcParams['font.sans-serif'] = ['SimHei'] # 因为用的seaborn画图,所以我们需要设置sns的
sns.set(style="darkgrid") # 基本设置,默认是白板
sns.set(font='SimHei') # 用的seaborn 这个生效了
g = sns.FacetGrid(train_df,col="患有糖尿病标识")
g.map(sns.histplot,'体重指数')
plt.show()
结合之前的代码,我们用sns.FacetGrid来绘图看看效果
好像不够直观,再尝试一下,用sns.scatterplot看一下肱三头肌皮褶厚度、体重指数 这两个指标对糖尿病的影响
sns.scatterplot(x='肱三头肌皮褶厚度',y='体重指数',hue='患有糖尿病标识', data=train_df) plt.show()
这下比较直观了,肱三头肌皮褶厚度、体重指数 这两个指标很重要,我们可以看到肱三头肌皮褶厚度>40的基本都是糖尿病患者,而体重指数 超过50的,基本都是糖尿病患者。
还记得之前我们有一个特殊的特征吗,做逻辑回归前,我们需要先对它进行处理。
我们先来看看这个字段有哪些值,以及分布情况。
print(train_df["糖尿病家族史"].value_counts())
看来这个字段也有缺失值,经验上来说,父母一方患有糖尿病,应该影响因子更大。所以我们这里把值做一下映射,
{‘无记录’: 0, ‘叔叔或者姑姑有一方患有糖尿病’: 2, ‘叔叔或姑姑有一方患有糖尿病’: 2, ‘父母有一方患有糖尿病’: 4}替换这些字符型数据为数值。
print(pd.unique(train_df["糖尿病家族史"])) # 看有哪些值 condition_history=['无记录','叔叔或者姑姑有一方患有糖尿病','叔叔或姑姑有一方患有糖尿病','父母有一方患有糖尿病'] # 把print出来的值做成列表 condition_history_value=[0,2,2,4] # 写好想映射的值 _ =dict(zip(condition_history,condition_history_value)) # 生成字典 print(_) # 检查是否有误 train_df["糖尿病家族史"]=train_df["糖尿病家族史"].replace(_) print(train_df["糖尿病家族史"].head())
我们看到已经替换好了,然后在之间缺失值的检查中,还有舒张压这个字段也是需要我们处理的,
我们按标签分组求均值
print(train_df.groupby('患有糖尿病标识')['舒张压'].mean())
我们可以看到还是很不一样的,我们按糖尿病标识分组取均值进行填充。测试集就用均值填充
train_df["舒张压"] = train_df.groupby("患有糖尿病标识")["舒张压"].transform(lambda x: x.fillna(x.mean()))
test_df['舒张压'].fillna(test_df['舒张压'].mean(), inplace=True)
完成缺失值处理后,我们导入train_test_split进行训练集和验证集的划分,将训练集20%划分为验证集,在训练部分进行训练,在测试部分使用LogisticRegression进行逻辑回归,因为逻辑回归是一种最优化问题,我们可以选择不同的优化器,sklearn提供了五种方法,我们使用GridSearchCV找出效果最好的一个。
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
from pprint import pprint
from sklearn.metrics import make_scorer
from sklearn.metrics import f1_score
train_df_feature=train_df.iloc[:, 1:9]
train_df_label=train_df['患有糖尿病标识']
# 划分验证集
X_train, X_test, y_train, y_test = train_test_split(train_df_feature,train_df_label , stratify=train_df_label,
random_state=1117, test_size=0.2)
# 设置超参列表
param_grid = {
'solver': ["newton-cg", "lbfgs", "sag", "saga", "liblinear"]
}
# 设置评分标准
scoring = {'acc': 'accuracy', 'p': 'precision', 'r': 'recall', 'f1': make_scorer(f1_score)}
# 使用暴力搜索
clf = GridSearchCV(
estimator=LogisticRegression(random_state=0, max_iter=1000),
param_grid=param_grid,
scoring=scoring,
refit=False,
n_jobs=4, # 使用4核心,加速运算
)
clf.fit(X_train, y_train)
pprint(clf.cv_results_)
我们发现‘saga’这个算法在多个评分指标中均表现良好,接下来我们就设置solver为saga,跑一下逻辑回归并提交成绩
# 训练输出
lr=LogisticRegression(max_iter=1000, random_state=0, solver='saga')
lr.fit(X_train, y_train)
lr_y_predict = lr.predict(X_test)
# 生成提交
test_df['label'] = lr.predict(test_df.drop(['编号'], axis=1))
test_df.rename({'编号': 'uuid'}, axis=1)[['uuid', 'label']].to_csv('submit.csv', index=None)
然后查看我们生成的这个提交文件,和官网的实例一样,我们提交试试
提交结果:
0.72这和我们在验证集上0.74的结果还是差不多的。看来效果还是不够好,这让我们想起机器学习业界里的老话。数据和特征决定了机器学习的上限,接下来我们从特征工程入手,看能不能提高一下效果
步骤1:统计每个性别对应的【体重指数】、【舒张压】平均值
步骤2:计算每个患者与每个性别平均值的差异;
train_df["舒张压差异"] = train_df.groupby("性别")["舒张压"].transform(lambda x: x-x.mean())
test_df["舒张压差异"] = train_df.groupby("性别")["舒张压"].transform(lambda x: x-x.mean())
train_df["体重指数差异"] = train_df.groupby("性别")["体重指数"].apply(lambda x: x-x.mean())
test_df["体重指数差异"] = train_df.groupby("性别")["体重指数"].apply(lambda x: x-x.mean())
步骤3:在上述基础上将训练集20%划分为验证集,使用逻辑回归完成训练,精度是否有提高?
我们以这个为基准测试一下新的特征有没有效果
train_df_feature=pd.concat([train_df.iloc[:, 1:9], train_df.iloc[:, 10:]], axis=1)
train_df_label=train_df['患有糖尿病标识']
# 划分验证集
X_train, X_test, y_train, y_test = train_test_split(train_df_feature,train_df_label ,
random_state=1117, test_size=0.2)
lr=LogisticRegression(max_iter=400, random_state=0, solver='saga')
lr.fit(X_train, y_train)
lr_y_predict = lr.predict(X_test)
y_train_true = lr.predict(X_train)
y_test_true = lr.predict(X_test)
print("f1 on training set: {:.3f}".format(f1_score(y_train_true, y_train)))
print("f1 on test set: {:.3f}".format(f1_score(y_test_true, y_test)))
加入的"舒张压差异"反向提升了
再加入"体重指数差异"这个特征,再提点到
似乎都没有很好地work。
步骤4:思考字段含义,尝试新的特征
train_df["体重指数超重"] = train_df["体重指数"]-24 test_df["体重指数超重"] = train_df["体重指数"]-24 train_df["体重指数肥胖"] = train_df["体重指数"]-28 test_df["体重指数肥胖"] = train_df["体重指数"]-28
新加"体重指数超重"和"体重指数肥胖"这两个特征,也没有太大影响
我们把出生年份转换为年龄呢,看能不能让机器更好地学习到年龄这个特征
train_df["年龄"] = 2022-train_df["出生年份"] test_df["年龄"] = 2022-train_df["出生年份"]
效果也很有限
步骤1:使用树模型完成模型的训练,通过特征重要性筛选出Top5的特征;
接下来我们尝试一下决策树,并输树的判断逻辑
from sklearn.tree import DecisionTreeClassifier
from sklearn import tree
clf=DecisionTreeClassifier(criterion="gini", max_depth=10, min_samples_split=6,min_impurity_decrease=0.01, min_samples_leaf=1)
clf.fit(X_train,y_train)
y_train_true = clf.predict(X_train)
y_test_true = clf.predict(X_test)
#
print("f1 on training set: {:.3f}".format(f1_score(y_train_true, y_train)))
print("f1 on test set: {:.3f}".format(f1_score(y_test_true, y_test)))
# 生成提交
test_df['label'] = clf.predict(test_df.drop(['编号'], axis=1))
test_df.rename({'编号': 'uuid'}, axis=1)[['uuid', 'label']].to_csv('submit.csv', index=None)
fig = plt.figure(figsize=(25,20))
_ = tree.plot_tree(
clf,
feature_names=X_train.columns.tolist(),
class_names=['没有患有糖尿病','患有糖尿病'],
filled=True
)
fig.show()
fig.savefig("决策树分类.png",dpi=200)
我看到训练集上的F1分数,一下子就提到了0.9以上,效果非常显著,接下来我们看看该模型认为的最重要的几个特征
一个是我们手动的特征“体重指数超重”,然后是“肱三头肌皮褶厚度“,”口服耐糖量测试“,”舒张压“,以及”胰岛素释放实验“。
好像都有理有据,在训练集上达到0.9以上,而且似乎也没有过拟合,我们的模型真是太好啦!简单有效,肯定是大杀四方了。谁说基本算法日薄西山已经达不到比赛要求了,只要加一点点trick,效果还是很好的嘛。
看看我们的模型是否真的很好呢,让我们来满怀信心提交分数。
啊这,0.73,只是比之前好了一丢丢。
(好吧,看来是真的不行。。。)
步骤2:使用筛选出的特征和逻辑回归进行训练,在验证集精度是否有提高?
我们重新取特征并进行训练,看看这些特征能帮助逻辑回归更好地学习吗
X_train, X_test=X_train[["体重指数超重","肱三头肌皮褶厚度","口服耐糖量测试","舒张压","胰岛素释放实验"]], X_test[["体重指数超重","肱三头肌皮褶厚度","口服耐糖量测试","舒张压","胰岛素释放实验"]]
跑出来的结果如下
步骤3:如果有提高,为什么?如果没有提高,为什么?
我们发现虽然在训练集上只有0.731,比之前低了,但是在test set上的分数0.755比之前有提升,这说明,适当的做特征选取,可以帮助我们的模型更快,更好地学习。过多的不必要的特征,反而可能会误导我们的模型,相当于是增加了噪声,反而导致效果变差。
步骤1:安装LightGBM,并学习基础的使用方法;
在anaconda环境中安装LightGBM
步骤2:将训练集20%划分为验证集,使用LightGBM完成训练,精度是否有提高?
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.metrics import f1_score
from lightgbm import LGBMClassifier
train_df = pd.read_csv('F:ProgramsPycharmProjectOHSSdiabetesPractice糖尿病遗传风险预测挑战赛公开数据比赛训练集.csv', encoding='gbk')
test_df = pd.read_csv('F:ProgramsPycharmProjectOHSSdiabetesPractice糖尿病遗传风险预测挑战赛公开数据比赛测试集.csv', encoding='gbk')
condition_history=['无记录','叔叔或者姑姑有一方患有糖尿病','叔叔或姑姑有一方患有糖尿病','父母有一方患有糖尿病']
condition_history_value=[0,2,2,4]
_ =dict(zip(condition_history,condition_history_value))
print(_)
train_df["糖尿病家族史"]=train_df["糖尿病家族史"].replace(_)
test_df["糖尿病家族史"]=test_df["糖尿病家族史"].replace(_)
train_df["舒张压"] = train_df.groupby("患有糖尿病标识")["舒张压"].transform(lambda x: x.fillna(x.mean()))
test_df['舒张压'].fillna(test_df['舒张压'].mean(), inplace=True)
train_df["舒张压差异"] = train_df.groupby("性别")["舒张压"].transform(lambda x: x-x.mean())
test_df["舒张压差异"] = test_df.groupby("性别")["舒张压"].transform(lambda x: x-x.mean())
train_df["体重指数差异"] = train_df.groupby("性别")["体重指数"].apply(lambda x: x-x.mean())
test_df["体重指数差异"] = test_df.groupby("性别")["体重指数"].apply(lambda x: x-x.mean())
train_df["年龄"] = 2022-train_df["出生年份"]
test_df["年龄"] = 2022-train_df["出生年份"]
train_df['糖尿病家族史'] = train_df['糖尿病家族史'].astype('category')
test_df['糖尿病家族史'] = train_df['糖尿病家族史'].astype('category')
train_df['性别'] = train_df['性别'].astype('category')
test_df['性别'] = train_df['性别'].astype('category')
train_df['口服耐糖量测试_diff'] = train_df.groupby("糖尿病家族史")["口服耐糖量测试"].transform(lambda x: x-x.mean())
test_df['口服耐糖量测试_diff'] = test_df.groupby("糖尿病家族史")["口服耐糖量测试"].transform(lambda x: x-x.mean())
train_df_feature=train_df.drop("患有糖尿病标识",axis=1)
train_df_label=train_df['患有糖尿病标识']
X_train, X_test, y_train, y_test = train_test_split(train_df_feature,train_df_label ,
random_state=420, test_size=0.2)
clf=LGBMClassifier(
# 引用官网推荐参数
max_depth=3,
n_estimators=4000,
n_jobs=-1,
verbose=-1,
verbosity=-1,
learning_rate=0.1,
)
clf.fit(X_train, y_train)
y_train_predict = clf.predict(X_train)
y_test_predict = clf.predict(X_test)
print("f1 on training set: {:.3f}".format(f1_score(predict, y_train)))
print("f1 on test set: {:.3f}".format(f1_score(predict, y_test)))
步骤3:将步骤2预测的结果文件提交到比赛,截图分数;
我们运行代码后得到如下结果, 确实是比赛利器啊,效果比之前的几个模型好多了,但是在training set上的分数是100%, 这有可能出现了过拟合.
步骤4:尝试调节搜索LightGBM的参数;
我们尝试调整一下参数,看能不能再提高一下LightGBM的模型效果,官方给出的深度只有3,显然太低了,我们调高一点试试.
clf=LGBMClassifier(
n_estimators=100,
learning_rate=0.09,
subsample_for_bin=10000,
max_depth=8
)
得分有所提升!
步骤5:将步骤4调参之后的模型从新训练,将最新预测的结果文件提交到比赛,截图分数;
经过搜参以后,我们提交一下分数.
- 步骤1:使用KFold完成数据划分;
在我们之前的训练中,我们为了好复现,设置了随机数种子来划分我们的数据集,这导致了我们的数据集划分是有偏差的,我们应该使用多折训练来减少在数据集划分中导致的误差. KFold它将原始数据分成K组,将每个子集数据分别划1组为验证集,其余的K-1组子集数据作为训练.比如在默认的五折交叉检验中.会被这样划分:
我们现在使用KFold来划分数据
from sklearn.model_selection import KFold
train_df_feature,train_df_label
kf = KFold(n_splits=10)
for train_index, test_index in kf.split(train_df_feature):
print("TRAIN:", train_index, "TEST:", test_index)
X_train, X_test = train_df_feature.iloc[train_index], train_df_feature.iloc[test_index]
y_train, y_test = train_df_label.iloc[train_index], train_df_label.iloc[test_index]
类似之前的train_test_split返回的四个变量,在每轮循环中,我们都可以完成一轮测试.
- 步骤2:使用StratifiedKFold完成数据划分;
进一步的,人们发现KFold的取值太随机了,破坏了数据集中的分布.StratifiedKFold用法类似Kfold,但是他是分层采样,确保训练集,测试集中各类别样本的比例与原始数据集中相同.这使得我们每轮训练的数据更接近真实情况.
StratifiedKFold用法类似Kfold, 我们来划分一下数据集,实际上就多了一个参数,其他完全相同.
from sklearn.model_selection import StratifiedKFold
train_df_feature,train_df_label
# kf = KFold(n_splits=10)
kf = StratifiedKFold(n_splits=10)
for train_index, test_index in kf.split(train_df_feature,train_df_label):
print("TRAIN:", train_index, "TEST:", test_index)
X_train, X_test = train_df_feature.iloc[train_index], train_df_feature.iloc[test_index]
y_train, y_test = train_df_label.iloc[train_index], train_df_label.iloc[test_index]
- 步骤3:使用StratifiedKFold配合LightGBM完成模型的训练和预测
from sklearn.model_selection import StratifiedKFold train_df_feature,train_df_label kf = StratifiedKFold(n_splits=10) f1_ = cross_val_score(clf, train_df_feature, train_df_label, scoring='f1',cv=kf) print(f1_) print(f1_.mean())
- 步骤4:在步骤3训练得到了多少个模型,对测试集多次预测,将最新预测的结果文件提交到比赛,截图分数;
因为是十折交叉验证,所以我们获得了10个模型,在10折交叉验证下,得到了我们目前最好的超参数.
clf=LGBMClassifier( n_estimators=300, learning_rate=0.02810101, max_depth=8 )
提交到比赛看看结果.确实比之前有了更好的提升.
- 步骤5:使用交叉验证训练5个机器学习模型(svm、lr等),使用stacking完成集成,将最新预测的结果文件提交到比赛,截图分数;
from lightgbm import LGBMClassifier
from sklearn.ensemble import RandomForestClassifier, ExtraTreesClassifier, GradientBoostingClassifier,AdaBoostClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from mlxtend.classifier import StackingClassifier
rf=RandomForestClassifier(n_estimators=352, n_jobs=-1, criterion='gini')
et=ExtraTreesClassifier()
gbdt=GradientBoostingClassifier()
adb=AdaBoostClassifier()
lgb=LGBMClassifier(n_estimators=300, learning_rate=0.02810101,max_depth=8)
lr=LogisticRegression()
clfs=[rf,et,gbdt,adb,lgb]
sclf=StackingClassifier(classifiers=clfs, meta_classifier=lr,use_probas=True,)
print("+++++++++++++++++++++++华丽分割线+++++++++++++++++")
for clf, label in zip([rf,et,gbdt,adb,lgb,sclf],
['rf',
'et',
'gbdt',
'adb',
'lgb',
'sclf']):
scores = cross_val_score(clf, train_df_feature, train_df_label, cv=10, scoring='f1')
print("F1: %0.2f (+/- %0.2f) [%s]" % (scores.mean(), scores.std(), label))
sclf.fit(train_df_feature,train_df_label)
test_df['label'] = sclf.predict(test_df.drop(['编号'], axis=1))
test_df.rename({'编号': 'uuid'}, axis=1)[['uuid', 'label']].to_csv('submit.csv', index=None)
我们可以看到不同模型在十折交叉验证下的平均分数,以及最后stacking后的表现.
不过,我们提交成绩后发现比之前lgb的单模型还低了一点点,
暂时就到这里啦,后续还要更多地学习



