- 完成coggle任务
- 任务1:报名比赛
- 步骤1:报名比赛http://challenge.xfyun.cn/topic/info?type=diabetes&ch=ds22-dw-zmt05
- 赛事
- 提交说明
- 步骤2:下载比赛数据(点击比赛页面的赛题数据)
- 字段说明
- 步骤3:解压比赛数据,并使用pandas进行读取;
- 步骤4:查看训练集和测试集字段类型,并将数据读取代码写到博客;
- 任务2:比赛数据分析
- 步骤1:统计字段的缺失值,计算缺失比例;
- 步骤2:分析字段的类型;
- 步骤3:计算字段相关性;
- 通过.corr()计算字段之间的相关性;
- 可视化
- 补充学习 b站7.1录播
- groupby
- apply
- agg
- map、transform
- 可视化
- 特征工程
- onehot
- labelEncoder
- 有序变量
- 任务3:逻辑回归尝试
- 步骤1:导入sklearn中的逻辑回归;
- 步骤1.5 数据预处理
- 步骤2:使用训练集和逻辑回归进行训练,并在测试集上进行预测;
- 步骤3:将步骤2预测的结果文件提交到比赛,截图分数;
- 步骤4:将训练集20%划分为验证集,在训练部分进行训练,在测试部分进行预测,调节逻辑回归的超参数;
- 任务4:特征工程(使用pandas完成)
- 步骤1:统计每个性别对应的【体重指数】、【舒张压】平均值
- 步骤2:计算每个患者与每个性别平均值的差异;
- 步骤3:在上述基础上将训练集20%划分为验证集,使用逻辑回归完成训练,精度是否有提高?
- 步骤4:思考字段含义,尝试新的特征,将你的尝试写入博客;
- 任务5:特征筛选
- 步骤1:使用树模型完成模型的训练,通过特征重要性筛选出Top5的特征;
- 步骤2:使用筛选出的特征和逻辑回归进行训练,在验证集精度是否有提高?
- 步骤3:如果有提高,为什么?如果没有提高,为什么?
- 步骤4:将你的尝试写入博客;
- 任务6:高阶树模型
- 步骤1:安装LightGBM,并学习基础的使用方法;
- 步骤2:将训练集20%划分为验证集,使用LightGBM完成训练,精度是否有提高?
- 步骤3:将步骤2预测的结果文件提交到比赛,截图分数;
- 步骤4:尝试调节搜索LightGBM的参数;
- 步骤5:将步骤4调参之后的模型从新训练,将最新预测的结果文件提交到比赛,截图分数;
- 任务7:多折训练与集成
- 步骤1:使用KFold完成数据划分;
- 步骤2:使用StratifiedKFold完成数据划分;
- 步骤3:使用StratifiedKFold配合LightGBM完成模型的训练和预测
- 步骤4:在步骤3训练得到了多少个模型,对测试集多次预测,将最新预测的结果文件提交到比赛,截图分数;
- 步骤4:使用交叉验证训练5个机器学习模型(svm、lr等),使用stacking完成集成,将最新预测的结果文件提交到比赛,截图分数;
在这次比赛中,您需要通过训练数据集构建糖尿病遗传风险预测模型,然后预测出测试数据集中个体是否患有糖尿病。对于测试数据集当中的个体,您必须预测其是否患有糖尿病(患有糖尿病:1,未患有糖尿病:0),预测值只能是整数1或者0。
训练集(比赛训练集.csv)一共有5070条数据,用于构建您的预测模型(您可能需要先进行数据分析)。数据的字段有编号、性别、出生年份、体重指数、糖尿病家族史、舒张压、口服耐糖量测试、胰岛素释放实验、肱三头肌皮褶厚度、患有糖尿病标识(最后一列),您也可以通过特征工程技术构建新的特征。
测试集(比赛测试集.csv)一共有1000条数据,用于验证预测模型的性能。数据的字段有编号、性别、出生年份、体重指数、糖尿病家族史、舒张压、口服耐糖量测试、胰岛素释放实验、肱三头肌皮褶厚度。
提交说明对于测试数据集当中的个体,您必须预测其是否患有糖尿病(患有糖尿病:1,未患有糖尿病:0),预测值只能是整数1或者0。提交的数据应该具有如下格式:
uuid,label
1,0
2,1
3,1
…
本次比赛中,预测模型的结果文件需要命名成:预测结果.csv,然后提交。请确保您提交的文件格式规范。
编号:标识个体身份的数字;
性别:1表示男性,0表示女性;
出生年份:出生的年份;
体重指数:体重除以身高的平方,单位kg/m2;
糖尿病家族史:标识糖尿病的遗传特性,记录家族里面患有糖尿病的家属,分成三种标识,分别是父母有一方患有糖尿病、叔叔或者姑姑有一方患有糖尿病、无记录;
舒张压:心脏舒张时,动脉血管弹性回缩时,产生的压力称为舒张压,单位mmHg;
口服耐糖量测试:诊断糖尿病的一种实验室检查方法。比赛数据采用120分钟耐糖测试后的血糖值,单位mmol/L;
胰岛素释放实验:空腹时定量口服葡萄糖刺激胰岛β细胞释放胰岛素。比赛数据采用服糖后120分钟的血浆胰岛素水平,单位pmol/L;
肱三头肌皮褶厚度:在右上臂后面肩峰与鹰嘴连线的重点处,夹取与上肢长轴平行的皮褶,纵向测量,单位cm;
患有糖尿病标识:数据标签,1表示患有糖尿病,0表示未患有糖尿病。
import pandas as pd
train_df = pd.read_csv("./比赛训练集.csv", encoding='gbk')
test_df = pd.read_csv("./比赛测试集.csv", encoding='gbk')
print(train_df.shape, test_df.shape)
print(train_df.dtypes, test_df.dtypes)
步骤4:查看训练集和测试集字段类型,并将数据读取代码写到博客;
任务2:比赛数据分析
步骤1:统计字段的缺失值,计算缺失比例;
通过缺失值统计,训练集和测试集的缺失值分布是否一致?
通过缺失值统计,有没有缺失比例很高的列?
#缺失值计算 train_df.isnull().mean(0) test_df.isnull().mean(0)
可以看出舒张压这个字段缺失了 4.9%。测试集和训练集比例差不多的。
从info和head(查看前5行的数据)可以看出,体重,舒张压,口服耐糖量测试 ,胰岛素释放实验,肱三头肌皮褶厚度是连续型,其余都是整型(糖尿病标识是0 1)。家族史那一列是备注(后期这个特征应该要由字符型可以处理为整型加入模型的使用)。
# 相关性计算 train_df.corr()
哪些字段与标签的相关性最高
- 可以看出 肱三头肌皮褶厚度和体重系数和糖尿病关系比较大。
尝试使用其他可视化方法将字段 与 标签的分布差异进行可视化;
以下也是用图表看一下糖尿病之间的分布。
之前没用过seaborn,boxplot应该是箱式图,countplot,和violinplot就不知道了
查了一下,countplot就是直方图,violinplot是小提琴样式的箱线图。
出现上图的原因是1.seaborn的几个图都叠在一起了,2.我语言设置没有切换为中文也没用(之后加入设置代码,这样中文和负坐标轴的符号才能正常显示),从老师那里偷的图片设置svg语句,更清楚一些
import seaborn as sns
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = ['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False #用来正常显示负号
from IPython.display import set_matplotlib_formats
set_matplotlib_formats('svg')#展示图片格式
# train_df['性别'].value_counts().plot(kind='barh')# barh水平的,kind类型
# sns.countplot(x='患有糖尿病标识', hue='性别', data=train_df)#hue分列 value_counts和 countplot其实是一样的
# sns.boxplot(y='出生年份', x='患有糖尿病标识', hue='性别', data=train_df)
sns.violinplot(y="体重指数", x="患有糖尿病标识", hue="性别", data=train_df)
依次注释图像语句,得到下列图片
1是男性,0是女性。女性数据多一些
barh 水平的
横坐标轴0是没得糖尿病的,蓝色竖条0是女性。反正都是女性多一些,这也看不出糖尿病和性别的相关关系。
男性黄条的都算正态分布吧,女性蓝条的有点上移,不怎么正态。没得糖尿病的男的,有几个很长寿的点(离群点)。
糖尿病人的体重分布比正常的要偏上一些。
小提琴图其实就是测过来的密度直方图,对称的,看一半就好了.
scatterplot 散点图,xy都是数值型
然后 每个图都有一些 属性,像什么填充fill 还有 alpha透明度,自己可以去官网学。
tips:根据xy轴的数据类型来定用什么图
根据这些来判断能不能 做交叉特征(两列的加减乘除),能不能分离
apply用 lambda 可以自定义许多
- groupby 和 agg 可以实现优雅的聚合效果
map可以映射改变 键值
groupby 一系列操作又是得到键值关系
所以 map里面写个groupby 自然而然就可以映射替换了
实例
可以这样产生一列维度合适的新的特征
见上面步骤三的
特征工程 onehot labelEncoder通常的类别变量用labelEncoder即可
需要保留顺序的 有序变量 用map
import pandas as pd from sklearn.linear_model import LogisticRegression from sklearn.preprocessing import MinMaxScaler from sklearn.pipeline import make_pipeline
导入对应的包
步骤1.5 数据预处理我觉得因为家族史根据常识可以当成有序变量,而且‘叔叔或者姑姑有一方患有糖尿病’和‘叔叔或姑姑有一方患有糖尿病’其实(含义一样)是一类,如果直接用labelEncoder就会变成两类,是不对的,所以用map处理。
train_df = pd.read_csv('./糖尿病遗传风险预测挑战赛公开数据/比赛训练集.csv', encoding='gbk')
test_df = pd.read_csv('./糖尿病遗传风险预测挑战赛公开数据/比赛测试集.csv', encoding='gbk')
dict_糖尿病家族史 = {
'无记录': 0,
'叔叔或姑姑有一方患有糖尿病': 1,
'叔叔或者姑姑有一方患有糖尿病': 1,
'父母有一方患有糖尿病': 2
}
train_df['糖尿病家族史'] = train_df['糖尿病家族史'].map(dict_糖尿病家族史)
test_df['糖尿病家族史'] = test_df['糖尿病家族史'].map(dict_糖尿病家族史)
train_df['舒张压'].fillna(89, inplace=True)
test_df['舒张压'].fillna(89, inplace=True)
舒张压用平均值或者中位数都是89这个值这里,而且观察原来数据都是整数,所以就用89了。
补全之后,没有缺失值了。
家族史和糖尿病标识之间的相关性,这么低吗。(意外,明明地球OL里面,遗传是导致糖尿病的重要因素)
读数据-》将有序变量转换为数值变量(利用map)
根据前面数据分析,(4.9%的缺失不至于删除),所以补全缺失值
from sklearn.linear_model import LogisticRegression as LR
from sklearn.model_selection import cross_val_score
from sklearn.feature_selection import SelectFromModel
import numpy as np
import pandas as pd
from sklearn.metrics import accuracy_score
from sklearn.preprocessing import MinMaxScaler
from sklearn.pipeline import make_pipeline
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import cross_val_score
features=[f for f in train_df.columns if f not in ['编号','患有糖尿病标识','出生年份']]
X=train_df[features]
y=train_df['患有糖尿病标识']
Xtrain, Xtest, Ytrain, Ytest = train_test_split(X,y,test_size=0.2,random_state=2022)
#修正索引
for i in [Xtrain, Xtest, Ytrain, Ytest]:
i.index=range(i.shape[0])
l1 = []
l2 = []
l1test = []
l2test = []
for i in np.linspace(0.05,1,19):
lrl1 = LR(penalty="l1",solver="liblinear",C=i,max_iter=1000)
lrl2 = LR(penalty="l2",solver="liblinear",C=i,max_iter=1000)
lrl1 = lrl1.fit(Xtrain,Ytrain)
l1.append(accuracy_score(lrl1.predict(Xtrain),Ytrain))
l1test.append(accuracy_score(lrl1.predict(Xtest),Ytest))
lrl2 = lrl2.fit(Xtrain,Ytrain)
l2.append(accuracy_score(lrl2.predict(Xtrain),Ytrain))
l2test.append(accuracy_score(lrl2.predict(Xtest),Ytest))
graph = [l1,l2,l1test,l2test]
color = ["green","black","lightgreen","gray"]
label = ["L1","L2","L1test","L2test"]
plt.figure(figsize=(6,6))
for i in range(len(graph)):
plt.plot(np.linspace(0.05,1,19),graph[i],color[i],label=label[i])
plt.legend(loc=4)
plt.show()
# 构建树模型
model = make_pipeline(
MinMaxScaler(),
DecisionTreeClassifier()
)
步骤3:将步骤2预测的结果文件提交到比赛,截图分数;
lrl2 = LR(penalty="l2",solver="liblinear",C=0.395,max_iter=1000)
lrl2 = lrl2.fit(Xtrain,Ytrain)
test_df['label'] = lrl2.predict(test_df.drop(['编号','出生年份'], axis=1))
test_df.rename({'编号': 'uuid'}, axis=1)[['uuid', 'label']].to_csv('submit.csv', index=None)
步骤4:将训练集20%划分为验证集,在训练部分进行训练,在测试部分进行预测,调节逻辑回归的超参数;
步骤4:如果精度有提高,则重复步骤2和步骤3;如果没有提高,可以尝试树模型,重复步骤2、3;
在这里插入代码片任务4:特征工程(使用pandas完成) 步骤1:统计每个性别对应的【体重指数】、【舒张压】平均值 步骤2:计算每个患者与每个性别平均值的差异; 步骤3:在上述基础上将训练集20%划分为验证集,使用逻辑回归完成训练,精度是否有提高? 步骤4:思考字段含义,尝试新的特征,将你的尝试写入博客; 任务5:特征筛选 步骤1:使用树模型完成模型的训练,通过特征重要性筛选出Top5的特征; 步骤2:使用筛选出的特征和逻辑回归进行训练,在验证集精度是否有提高? 步骤3:如果有提高,为什么?如果没有提高,为什么? 步骤4:将你的尝试写入博客; 任务6:高阶树模型 步骤1:安装LightGBM,并学习基础的使用方法; 步骤2:将训练集20%划分为验证集,使用LightGBM完成训练,精度是否有提高? 步骤3:将步骤2预测的结果文件提交到比赛,截图分数; 步骤4:尝试调节搜索LightGBM的参数; 步骤5:将步骤4调参之后的模型从新训练,将最新预测的结果文件提交到比赛,截图分数; 任务7:多折训练与集成 步骤1:使用KFold完成数据划分; 步骤2:使用StratifiedKFold完成数据划分; 步骤3:使用StratifiedKFold配合LightGBM完成模型的训练和预测 步骤4:在步骤3训练得到了多少个模型,对测试集多次预测,将最新预测的结果文件提交到比赛,截图分数; 步骤4:使用交叉验证训练5个机器学习模型(svm、lr等),使用stacking完成集成,将最新预测的结果文件提交到比赛,截图分数;



