概述
1、赛题理解
赛题以心电图心跳信号数据为背景,要求根据心电图感应数据预测心跳信号所属类别,其中心跳信号对应正常病例以及受不同心律不齐和心肌梗塞影响的病例,这是一个多分类的问题。
2、赛题数据
数据来自某平台心电图数据记录,总数据量超过20万,主要为1列心跳信号序列数据,其中每个样本的信号序列采样频次一致,长度相等。为了保证比赛的公平性,将会从中抽取10万条作为训练集,2万条作为测试集A,2万条作为测试集B,同时会对心跳信号类别(label)信息进行脱敏。
给出的数据格式如下:
- train.csv
id: 为心跳信号分配的唯一标识
heartbeat_signals: 心跳信号序列(数据之间采用“,”进行分隔)
label: 心跳信号类别(0、1、2、3) - testA.csv
id :心跳信号分配的唯一标识
heartbeat_signals: 心跳信号序列(数据之间采用“,”进行分隔)
给出的标签有四类,直观看是个多分类项目。数据特征特征是个字符串,需要预处理成多列特征。
3、评价指标
赛事给出了模型评价算法,选手需提交4种不同心跳信号预测的概率,选手提交结果与实际心跳类型结果进行对比,求预测的概率与真实值差值的绝对值。
其实多分类的评价指标的计算方式与二分类是一样的,只不过我们计算的是针对于每一类来说的召回率、精确度、准确率和 F1分数,然后对多类别的得分求平均,得到针对多分类的得分。
分类评价指标有如下几种:
- 混淆矩阵(Confuse Matrix);
- 准确率(Accuracy):准确率是常用的一个评价指标,但是不适合样本不均衡的情况,医疗数据大部分都是样本不均衡数据;
- 精确率(Precision)也叫查准率简写为P:精确率(Precision)是针对预测结果而言的,其含义是在被所有预测为正的样本中实际为正样本的概率在被所有预测为正的样本中实际为正样本的概率,精确率和准确率看上去有些类似,但是是两个完全不同的概念。精确率代表对正样本结果中的预测准确程度,准确率则代表整体的预测准确程度,包括正样本和负样本;
- 召回率(Recall) 也叫查全率 简写为R:召回率(Recall)是针对原样本而言的,其含义是在实际为正的样本中被预测为正样本的概率;
- 宏查准率(macro-P):计算每个样本的精确率然后求平均值;
- 宏查全率(macro-R):计算每个样本的召回率然后求平均值;
- 宏F1(macro-F1):是统计学中用来衡量二分类模型精确度的一种指标。它同时兼顾了分类模型的精确率和召回率。F1分数可以看作是模型精确率和召回率的一种加权平均,它的最大值是1,最小值是0。
与上面的宏不同,微查准查全,先将多个混淆矩阵的TP,FP,TN,FN对应位置求平均,然后按照P和R的公式求得micro-P和micro-R,最后根据micro-P和micro-R求得micro-F1; - 微查准率(micro-P):同准确率类似,但是采用的TP,FP是多个类别均值后得到;
- 微查全率(micro-R):同上;
- 微F1(micro-F1):同上;
4、赛题思路
- 本题为传统的数据挖掘问题,通过数据科学以及机器学习深度学习的办法来进行建模得到结果;
- 本题为典型的多分类问题,心跳信号一共有4个不同的类别;
- 主要应用xgb、lgb、catboost,以及pandas、numpy、matplotlib、seabon、sklearn、keras等等数据挖掘常用库或者框架来进行数据挖掘任务。
5、BaseLine代码理解
1、导入需要用的第三方包,读入数据
import os
import gc
import math
import pandas as pd
import numpy as np
import lightgbm as lgb
import xgboost as xgb
from catboost import CatBoostRegressor
from sklearn.linear_model import SGDRegressor, LinearRegression, Ridge
from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import StratifiedKFold, KFold
from sklearn.metrics import log_loss
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import OneHotEncoder
from tqdm import tqdm
import matplotlib.pyplot as plt
import time
import warnings
warnings.filterwarnings('ignore')
# 读取数据,采用pandas读入csv文件数据
train = pd.read_csv('train.csv')
test=pd.read_csv('testA.csv')
train.head()
2、数据查看
train.head() # 查看训练集数据结构
test.head() # 测试集数据结构
train.groupby('label').count() # 训练集类别分布
3、数据预处理
上文查看了数据结构可得,心跳数据是以字符串的形式提供的,采用逗号分割,预处理主要切分心跳数据,并做格式化,怎对不同大小的数据采用对应精度的数据类型,节省内存占用。
def reduce_mem_usage(df):
start_mem = df.memory_usage().sum() / 1024**2
print('Memory usage of dataframe is {:.2f} MB'.format(start_mem))
for col in df.columns:
col_type = df[col].dtype
if col_type != object:
c_min = df[col].min()
c_max = df[col].max()
if str(col_type)[:3] == 'int': # 针对不同数据采用不同的数据类型
if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max:
df[col] = df[col].astype(np.int8)
elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:
df[col] = df[col].astype(np.int16)
elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:
df[col] = df[col].astype(np.int32)
elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max:
df[col] = df[col].astype(np.int64)
else:
if c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max:
df[col] = df[col].astype(np.float16)
elif c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max:
df[col] = df[col].astype(np.float32)
else:
df[col] = df[col].astype(np.float64)
else:
df[col] = df[col].astype('category')
end_mem = df.memory_usage().sum() / 1024**2
print('Memory usage after optimization is: {:.2f} MB'.format(end_mem))
print('Decreased by {:.1f}%'.format(100 * (start_mem - end_mem) / start_mem))
return df
# 简单预处理
train_list = []
for items in train.values:
train_list.append([items[0]] + [float(i) for i in items[1].split(',')] + [items[2]]) # 切割字符串
train = pd.DataFrame(np.array(train_list))
train.columns = ['id'] + ['s_'+str(i) for i in range(len(train_list[0])-2)] + ['label']
train = reduce_mem_usage(train) # 降低内存占用
test_list=[]
for items in test.values:
test_list.append([items[0]] + [float(i) for i in items[1].split(',')])
test = pd.DataFrame(np.array(test_list))
test.columns = ['id'] + ['s_'+str(i) for i in range(len(test_list[0])-1)]
test = reduce_mem_usage(test)
3、获取训练集和测试集
训练集和测试集
x_train = train.drop(['id','label'], axis=1)
y_train = train['label']
x_test=test.drop(['id'], axis=1)
4、模型配置
def cv_model(clf, train_x, train_y, test_x, clf_name):
folds = 5 # 采用五折交叉验证
seed = 2021
kf = KFold(n_splits=folds, shuffle=True, random_state=seed)
test = np.zeros((test_x.shape[0],4))
cv_scores = []
onehot_encoder = OneHotEncoder(sparse=False)
for i, (train_index, valid_index) in enumerate(kf.split(train_x, train_y)):
print('************************************ {} ************************************'.format(str(i+1)))
trn_x, trn_y, val_x, val_y = train_x.iloc[train_index], train_y[train_index], train_x.iloc[valid_index], train_y[valid_index]
if clf_name == "lgb": # light
train_matrix = clf.Dataset(trn_x, label=trn_y)
valid_matrix = clf.Dataset(val_x, label=val_y)
params = {
'boosting_type': 'gbdt', # 基模型
'objective': 'multiclass', # 多分类
'num_class': 4, # 类别数
'num_leaves': 2 ** 5,
'feature_fraction': 0.8,
'bagging_fraction': 0.8,
'bagging_freq': 4,
'learning_rate': 0.1,
'seed': seed,
'nthread': 28,
'n_jobs':24,
'verbose': -1,
}
model = clf.train(params,
train_set=train_matrix,
valid_sets=valid_matrix,
num_boost_round=2000,
verbose_eval=100,
early_stopping_rounds=200)
val_pred = model.predict(val_x, num_iteration=model.best_iteration)
test_pred = model.predict(test_x, num_iteration=model.best_iteration)
val_y=np.array(val_y).reshape(-1, 1)
val_y = onehot_encoder.fit_transform(val_y)
print('预测的概率矩阵为:')
print(test_pred)
test += test_pred
score=abs_sum(val_y, val_pred)
cv_scores.append(score)
print(cv_scores)
print("%s_scotrainre_list:" % clf_name, cv_scores)
print("%s_score_mean:" % clf_name, np.mean(cv_scores))
print("%s_score_std:" % clf_name, np.std(cv_scores))
test=test/kf.n_splits
return test
5、测试集测试
def lgb_model(x_train, y_train, x_test):
lgb_test = cv_model(lgb, x_train, y_train, x_test, "lgb")
return lgb_test
# 训练模型,返回测试集结果
lgb_test = lgb_model(x_train, y_train, x_test)
6、输出结果到提交文件
result=pd.read_csv('sample_submit.csv')
result['label_0']=temp[0]
result['label_1']=temp[1]
result['label_2']=temp[2]
result['label_3']=temp[3]
result.to_csv('submit.csv',index=False)
6、总结
1、本赛题是多分类,训练样本类别不均衡,针对样本不均衡需要调整损失函数;
2、模型选择需要多尝试几种,基础的逻辑回归也需要尝试,作为最基础的模型,后续xgb、catboot也需要调测;
3、目前的特征中存在大量为0特征列,后续需要进行特征工程。
最后
以上就是拉长中心为你收集整理的零基础入门数据挖掘-心跳信号分类预测TASK01的全部内容,希望文章能够帮你解决零基础入门数据挖掘-心跳信号分类预测TASK01所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复