糖尿病康复,内容丰富有趣,生活中的好帮手!
糖尿病康复 > 讯飞-糖尿病遗传风险检测挑战赛

讯飞-糖尿病遗传风险检测挑战赛

时间:2020-06-15 23:10:45

相关推荐

讯飞-糖尿病遗传风险检测挑战赛

讯飞-糖尿病遗传风险检测挑战赛

前言相关库一、比赛报名1.1 赛事任务1.2 读取数据训练数据集测试数据集1.3 数据集基本信息数据集维度数据表基本信息二、比赛数据分析2.1 缺失值统计2.2 分析字段类型每一列数据的类型int 和 float 类型数据的描述性统计2.3 字段相关性2.4 小结三、逻辑回归尝试3.1 使用名义变量重构糖尿病家族史和性别3.2 处理缺失值3.3 网格搜索查找最佳超参数3.4 初步评分四、特征工程4.1 增加年龄特征4.2 增加个体与性别平均值之间的差值字段

前言

本文章是在Coggle 30 Days of ML(7月)活动中创作的

截至,中国糖尿病患者近1.3亿。中国糖尿病患病原因受生活方式、老龄化、城市化、家族遗传等多种因素影响。同时,糖尿病患者趋向年轻化。

糖尿病可导致心血管、肾脏、脑血管并发症的发生。因此,准确诊断出患有糖尿病个体具有非常重要的临床意义。糖尿病早期遗传风险预测将有助于预防糖尿病的发生。

根据《中国2型糖尿病防治指南(版)》,糖尿病的诊断标准是具有典型糖尿病症状(烦渴多饮、多尿、多食、不明原因的体重下降)且随机静脉血浆葡萄糖≥11.1mmol/L或空腹静脉血浆葡萄糖≥7.0mmol/L或口服葡萄糖耐量试验(OGTT)负荷后2h血浆葡萄糖≥11.1mmol/L。

在这次比赛中,需要通过训练数据集构建糖尿病遗传风险预测模型,然后预测出测试数据集中个体是否患有糖尿病,和我们一起帮助糖尿病患者解决这“甜蜜的烦恼”。

相关库

pandas(1.1.5)numpy(1.19.5)matplotlib(3.3.4)seaborn(0.11.2)scikit-learn(0.24.2)

%matplotlib inlineimport pandas as pdimport numpy as npimport matplotlib.pyplot as pltimport seaborn as snsfrom sklearn.linear_model import LogisticRegressionfrom sklearn.model_selection import train_test_split, GridSearchCVfrom sklearn.preprocessing import MinMaxScalerfrom sklearn.pipeline import make_pipelineplt.rcParams['font.sans-serif'] = ['FangSong'] # 用来正常显示中文标签plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号

一、比赛报名

1.1 赛事任务

以下介绍从官网上复制而来

数据集字段说明:

编号:标识个体身份的数字;性别:1 表示男性,0 表示女性;出生年份,出生的年份,XXXX 格式;体重指数:体重除以身高的平方,单位 kg/m2kg/m^2kg/m2;糖尿病家族史,标识糖尿病的遗传特征,记录家族里面患有糖尿病的家属;舒张压:心脏舒张时,动脉血管弹性回缩时,产生的压力成为舒张压,单位 mmHgmmHgmmHg;口服耐糖量测试:比赛数据采用 120 分钟耐糖测试后的血糖值,单位 mmol/Lmmol/Lmmol/L;胰岛素释放实验:空腹时定量口服葡萄糖刺激 β\betaβ 细胞释放胰岛素,比赛数据采用服糖后 120 分钟的血浆胰岛素水平,单位 pmol/L;肱三头肌皮褶厚度:在右上臂后面肩峰与鹰嘴连线的重点处,夹取与上肢衣袖平行的皮褶,纵向测量,单位 cm;患有糖尿病标识:数据标签,1 表示患有糖尿病,0 表示未患有糖尿病。

1.2 读取数据

训练数据集

df_train = pd.read_csv(filepath_or_buffer='../data/比赛训练集.csv', encoding='gbk', index_col='编号')df_train.head()

测试数据集

df_test = pd.read_csv(filepath_or_buffer='../data/比赛测试集.csv', encoding='gbk', index_col='编号')df_test.head()

1.3 数据集基本信息

数据集维度

print(df_train.shape)print(df_test.shape)

(5070, 9)(1000, 8)

数据表基本信息

print('训练集:')df_train.info()

训练集:<class 'pandas.core.frame.DataFrame'>Int64Index: 5070 entries, 1 to 5070Data columns (total 9 columns):# Column Non-Null Count Dtype --- ------ -------------- ----- 0 性别 5070 non-null int64 1 出生年份5070 non-null int64 2 体重指数5070 non-null float643 糖尿病家族史 5070 non-null object 4 舒张压 4823 non-null float645 口服耐糖量测试 5070 non-null float646 胰岛素释放实验 5070 non-null float647 肱三头肌皮褶厚度 5070 non-null float648 患有糖尿病标识 5070 non-null int64 dtypes: float64(5), int64(3), object(1)memory usage: 396.1+ KB

df_train['糖尿病家族史'].unique()

array(['无记录', '叔叔或者姑姑有一方患有糖尿病', '叔叔或姑姑有一方患有糖尿病', '父母有一方患有糖尿病'],dtype=object)

print('测试集:')df_test.info()

测试集:<class 'pandas.core.frame.DataFrame'>Int64Index: 1000 entries, 1 to 1000Data columns (total 8 columns):# Column Non-Null Count Dtype --- ------ -------------- ----- 0 性别 1000 non-null int64 1 出生年份1000 non-null int64 2 体重指数1000 non-null float643 糖尿病家族史 1000 non-null object 4 舒张压 951 non-null float645 口服耐糖量测试 1000 non-null float646 胰岛素释放实验 1000 non-null float647 肱三头肌皮褶厚度 1000 non-null float64dtypes: float64(5), int64(2), object(1)memory usage: 70.3+ KB

df_test['糖尿病家族史'].unique()

array(['无记录', '叔叔或者姑姑有一方患有糖尿病', '父母有一方患有糖尿病', '叔叔或姑姑有一方患有糖尿病'],dtype=object)

二、比赛数据分析

2.1 缺失值统计

分析 1.3 数据集基本信息和下面的统计,发现训练集一共有 5070 条数据,但舒张压字段却只有 4823 个非空数据,其他字段都有 5070 个非空数据;测试集一共有 1000 条数据,舒张压字段只有 951 个非空数据。因此,可以发现无论是训练集还是测试集,只有舒张压字段存在缺失值,其中训练集存在 247 条带缺失值的数据,测试集 存在 49 条带缺失值的数据。

print('训练集每一列缺失值统计个数:')df_train.isnull().sum()

训练集每一列缺失值统计个数:性别 0出生年份0体重指数0糖尿病家族史 0舒张压 247口服耐糖量测试 0胰岛素释放实验 0肱三头肌皮褶厚度0患有糖尿病标识 0dtype: int64

print('测试集每一列缺失值统计个数:')df_test.isnull().sum()

测试集每一列缺失值统计个数:性别 0出生年份 0体重指数 0糖尿病家族史 0舒张压 49口服耐糖量测试0胰岛素释放实验0肱三头肌皮褶厚度0dtype: int64

训练集和测试集各列缺失比例计算:

df_train.isnull().mean(0)

性别0.000000出生年份 0.000000体重指数 0.000000糖尿病家族史0.000000舒张压 0.048718口服耐糖量测试0.000000胰岛素释放实验0.000000肱三头肌皮褶厚度 0.000000患有糖尿病标识0.000000dtype: float64

df_test.isnull().mean(0)

性别0.000出生年份 0.000体重指数 0.000糖尿病家族史0.000舒张压 0.049口服耐糖量测试0.000胰岛素释放实验0.000肱三头肌皮褶厚度 0.000dtype: float64

从上面两处结果可以看出训练集和测试集的缺失值分布差异不大,唯一包含缺失值的是舒张压这一列,且缺失值占比不大。

2.2 分析字段类型

每一列数据的类型

训练集数据类型

df_train.dtypes

性别 int64出生年份int64体重指数 float64糖尿病家族史 object舒张压 float64口服耐糖量测试float64胰岛素释放实验float64肱三头肌皮褶厚度 float64患有糖尿病标识 int64dtype: object

测试集数据类型

df_test.dtypes

性别 int64出生年份int64体重指数 float64糖尿病家族史 object舒张压 float64口服耐糖量测试float64胰岛素释放实验float64肱三头肌皮褶厚度 float64dtype: object

int 和 float 类型数据的描述性统计

训练集描述性统计

df_train[['性别', '出生年份', '体重指数', '舒张压', '口服耐糖量测试', '胰岛素释放实验', '肱三头肌皮褶厚度']].describe()

测试集描述性统计

df_test[['性别', '出生年份', '体重指数', '舒张压', '口服耐糖量测试', '胰岛素释放实验', '肱三头肌皮褶厚度']].describe()

对训练集和测试集进行描述性统计,发现两个数据集在平均值、方差、四分位数、中位数等方面差异不大。

2.3 字段相关性

训练集各字段及标签之间的相关性

# 训练集相关性热力图矩阵plt.subplots(figsize=(10,10))sns.heatmap(df_train.corr(method='pearson'), annot=True, vmax=1, square=True, cmap='RdBu_r')plt.savefig('../images/train_pearson.jpg', dpi=800)

测试集各字段相关性

# 测试集相关性热力图矩阵plt.subplots(figsize=(10,10))sns.heatmap(df_test.corr(method='pearson'), annot=True, vmax=1, square=True, cmap='RdBu_r')plt.savefig('../images/test_pearson.jpg', dpi=800)

从 2.3 中的两个热力图可以看出,训练集中体重指数和肱三头肌皮褶厚度与标签的相关性相对较高,肱三头肌皮褶厚度与标签的相关性最高。各字段之间的相关性普遍不高。

2.4 小结

通过对训练集和测试集计算缺失值比例、分析字段类型、进行描述性统计、计算字段相关性,可以发现训练集和测试集各项指标间的差异很小,甚至几乎没有,实现控制异常数据对模型的干扰。

三、逻辑回归尝试

3.1 使用名义变量重构糖尿病家族史和性别

dict_糖尿病家族史 = {'无记录': 0,'叔叔或姑姑有一方患有糖尿病': 1,'叔叔或者姑姑有一方患有糖尿病': 1,'父母有一方患有糖尿病': 2}df_train['糖尿病家族史'] = df_train['糖尿病家族史'].map(dict_糖尿病家族史)df_train['糖尿病家族史'] = df_train['糖尿病家族史'].astype('category')df_test['糖尿病家族史'] = df_test['糖尿病家族史'].map(dict_糖尿病家族史)df_test['糖尿病家族史'] = df_test['糖尿病家族史'].astype('category')

# 查看重构后的结果print(df_train['糖尿病家族史'].unique())print(df_test['糖尿病家族史'].unique())

[0, 1, 2]Categories (3, int64): [0, 1, 2][0, 1, 2]Categories (3, int64): [0, 1, 2]

df_train['性别'] = df_train['性别'].astype('category')df_test['性别'] = df_test['性别'].astype('category')

print(df_train['性别'].unique())print(df_test['性别'].unique())

[0, 1]Categories (2, int64): [0, 1][0, 1]Categories (2, int64): [0, 1]

3.2 处理缺失值

这里要提一下,我是第一次做讯飞的数据挖掘题,所以对比赛数据格式不是很了解,最开始处理缺失值的时候采用的是dropna的方法,这样做会将部分编号的数据给删掉,但是这样做会导致评测失败,失败原因:输入格式错误。所以后来换了fillna的方法。

# 用前一个非空白值填补df_train['舒张压'].fillna(method='ffill', inplace=True)df_test['舒张压'].fillna(method='ffill', inplace=True)

print('训练集每一列缺失值统计个数:')print(df_train.isnull().sum())print('\n')print('测试集每一列缺失值统计个数:')print(df_test.isnull().sum())

训练集每一列缺失值统计个数:性别0出生年份 0体重指数 0糖尿病家族史0舒张压 0口服耐糖量测试0胰岛素释放实验0肱三头肌皮褶厚度 0患有糖尿病标识0dtype: int64测试集每一列缺失值统计个数:性别0出生年份 0体重指数 0糖尿病家族史0舒张压 0口服耐糖量测试0胰岛素释放实验0肱三头肌皮褶厚度 0dtype: int64

df_train.head()

df_test.head()

挑选出字段集和标签集

X = df_train.drop(columns='患有糖尿病标识', inplace=False)y = df_train['患有糖尿病标识']

3.3 网格搜索查找最佳超参数

使用 sklearn 库的 GridSearchCV 实现网格搜索,并在上面训练集 df_train 上划分出的数据集 X_train 和 y_train 上进行 5 折交叉验证,用 X_test 和 y_test 进行检测,查找最佳超参数。

model = make_pipeline(MinMaxScaler(), LogisticRegression(penalty='l2', multi_class='ovr',max_iter=10000))params = {'logisticregression__solver': ['liblinear', 'sag', 'saga', 'newton-cg', 'lbfgs'],'logisticregression__C': np.linspace(0.1, 1, 10)}

model.get_params().keys()

dict_keys(['memory', 'steps', 'verbose', 'minmaxscaler', 'logisticregression', 'minmaxscaler__clip', 'minmaxscaler__copy', 'minmaxscaler__feature_range', 'logisticregression__C', 'logisticregression__class_weight', 'logisticregression__dual', 'logisticregression__fit_intercept', 'logisticregression__intercept_scaling', 'logisticregression__l1_ratio', 'logisticregression__max_iter', 'logisticregression__multi_class', 'logisticregression__n_jobs', 'logisticregression__penalty', 'logisticregression__random_state', 'logisticregression__solver', 'logisticregression__tol', 'logisticregression__verbose', 'logisticregression__warm_start'])

grid = GridSearchCV(estimator=model, param_grid=params, cv=5, verbose=1)grid.fit(X=X, y=y)

Fitting 5 folds for each of 50 candidates, totalling 250 fitsGridSearchCV(cv=5,estimator=Pipeline(steps=[('minmaxscaler', MinMaxScaler()),('logisticregression',LogisticRegression(max_iter=10000,multi_class='ovr'))]),param_grid={'logisticregression__C': array([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. ]),'logisticregression__solver': ['liblinear', 'sag','saga', 'newton-cg','lbfgs']},verbose=1)

df_test['label'] = grid.predict(df_test)df_test.head()

df_test.index.name = 'uuid'df_test['label'].to_csv(path_or_buf='../data/submit.csv', index='uuid')

3.4 初步评分

这里的分数只有 0.7,可能是因为训练模型过拟合,也可能是模型原因,后续再加以改进

四、特征工程

4.1 增加年龄特征

df_train['年龄'] = - df_train['年龄']df_test['年龄'] = - df_test['年龄']

4.2 增加个体与性别平均值之间的差值字段

先到这,后面再补充

如果觉得《讯飞-糖尿病遗传风险检测挑战赛》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。