目录
任务
.corr()计算字段之间的相关性;任务3:逻辑回归尝试
任务6:高阶树模型
Just Do It!
- import pandas as pd
- import seaborn as sns
- from lightgbm import LGBMClassifier
- from sklearn.pipeline import make_pipeline
- from sklearn.metrics import f1_score
- from sklearn.linear_model import LogisticRegression
- from sklearn.model_selection import train_test_split
- from sklearn.metrics import accuracy_score
查看训练集和测试集的形状和类型
- train_df = pd.read_csv('../data/糖尿病遗传风险预测挑战赛公开数据/比赛训练集.csv', encoding='gbk')
- test_df = pd.read_csv('../data/糖尿病遗传风险预测挑战赛公开数据/比赛测试集.csv', encoding='gbk')
-
- print(train_df.shape, test_df.shape)
- print(train_df.dtypes, test_df.dtypes)

查看训练集和测试集的缺失值
- # 缺失值计算
- print(train_df.isnull().mean(0))
- print(test_df.isnull().mean(0))
-
- # 相关性计算
- train_df.corr()

可以看到,训练集和测试集中只有舒张压是有空值的。

再画一下热度图
- # 绘制热度图
- plot = sns.heatmap(train_df.corr())

根据相关性和热度图可以看出,肱三头肌皮褶厚度 和 体重指数 这两个特征对label的贡献是比较大的。
使用df.map功能(类似于df.apply功能)将包含 非数值型 的列对应的 非数值类型 转换成相应的数值类型,这样才能丢到模型去训练(模型只能理解数值型的数据)。
同时,要对包含空值的列进行填充。
- dict_糖尿病家族史 = {
- '无记录': 0,
- '叔叔或姑姑有一方患有糖尿病': 1,
- '叔叔或者姑姑有一方患有糖尿病': 1,
- '父母有一方患有糖尿病': 2
- }
-
- train_df['糖尿病家族史'] = train_df['糖尿病家族史'].map(dict_糖尿病家族史)
- test_df['糖尿病家族史'] = test_df['糖尿病家族史'].map(dict_糖尿病家族史)
- train_df['舒张压'].fillna(train_df['舒张压'].mean().round(2), inplace=True)
- test_df['舒张压'].fillna(train_df['舒张压'].mean().round(2), inplace=True)
- train_df
转换前
转换后

将训练集划分为训练集和验证集,方便本地进行测试,不然每天就三次提交机会,总不能每次调参都用平台的机会吧。
- # 把训练集划分为训练集和验证集,方便测试当前模型的好坏,并进行适当的调参
- train_df2,val_df,y_train,y_val = train_test_split(train_df.drop('患有糖尿病标识',axis=1),train_df['患有糖尿病标识'],test_size=0.3)
- train_df2
划分后的训练集和验证集数量为
- print('train2 length:',len(train_df2),' ',len(y_train))
- print('val length:',len(val_df),' ',len(y_val))

- # 选择模型
- #
- # 使用逻辑回归进行训练
- # model = LogisticRegression()
- # model.fit(train_df.drop('编号',axis=1),y_train)
-
- # 构建模型
- # model = make_pipeline(
- # MinMaxScaler(),
- # DecisionTreeClassifier()
- # )
- # model.fit(train_df.drop('编号',axis=1),y_train)
-
- model = LGBMClassifier(
- objective='binary',
- max_depth=3,
- n_estimators=4000,
- n_jobs=-1,
- verbose=-1,
- verbosity=-1,
- learning_rate=0.1,
- )
- model.fit(train_df2.drop('编号',axis=1),y_train,eval_set=[(val_df.drop('编号',axis=1),y_val)])
统一命名为model了,这样后面的代码都直接调用model就可以了,而用不同的模型只需要改一下model后面的就行了。目前写了逻辑回归、决策树、LGBM三种方法,后续可能会更新新的模型。目前榜上大佬们已经达到100%准确率了,太吊了。不知道他们用的什么模型。
- # 预测训练集
- train_df2['label'] = model.predict(train_df2.drop('编号',axis=1))
- # 预测训练集
- train_df2['label'] = model.predict(train_df2.drop('编号',axis=1))
平台使用F1评估,我本地测试的时候加了个accuracy,F1采用了macro方式计算。
- # 评估模型指标
- def eval(y_true,y_pred):
- lr_acc = accuracy_score(y_true,y_pred)
- lr_f1 = f1_score(y_true,y_pred,average='macro')
- print(f"lr_acc:{lr_acc},lr_f1:{lr_f1}")
- print('训练集指标:')
- eval(y_train,train_df2['label'])
- print('验证集指标:')
- eval(y_val,val_df['label'])
- # 预测测试集
- test_df['label'] = model.predict(test_df.drop('编号',axis=1))
- test_df
为了防止提交文件被新的输出覆盖,特地给输出文件加了个时间标注。
test_df.rename({'编号':'uuid'},axis=1)[['uuid','label']].to_csv('submit'+str(datetime.now().strftime('%m_%d_%H_%M_%S'))+'.csv',index=None)

OK,Fine!