AI机器学习时序序列特征提取实现分类预测实战

news/2024/11/23 0:53:03/

最近有位做医疗项目的同学咨询有一批人员的身高、体重、性别、年龄、心电图、是否有心脏病等数据是否可以根据这些数据预测某个人是否有心脏病的迹象。这当然是可以的,AI机器学习不就是干这事的吗?这是一个典型的分类算法。根据这些人体特征来判断是否存在潜在的疾病。问题是如何对心电图进行特征提取,提取出相关的特征,让模型进行学习和训练。

拿到数据后,第一步,我们首先来看一下数据。

一、数据探索

1、读入数据

导入numpy、pandas、matplotlib三大件,读入数据

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
df=pd.read_csv('data_csv.csv')
df

在这里插入图片描述

数据集中有age年龄、ismale性别、Weight身高、Height体重、HRTrend心电图、label是否有心脏病(1,是有心脏病、0是无心脏病)
这里看到主要的几个关键性的指标。HRTrend是csv中载入的时候数据是文本字符串格式,还有nan及\n等字符串,我们要将这些数据进行清洗规则化,将其转化为数组。

2、数据处理

先拿一个样本数据来看看数据的情况。对它进行相应的处理,包括去掉回车换行符、去多余空格、然后以空格作为分隔形成数组。

HRTrend_Data=df['HRTrend'][1][1:len(df['HRTrend'][1])-1]
HRTrend_Data=HRTrend_Data.replace('\n','') #替换掉换行符
HRTrend_Data=HRTrend_Data.replace('nan',str(0))   #将nan补0
HRTrend_Data=re.sub(' +', ' ', HRTrend_Data).strip() #去掉多余的空格
HRTrend_Data=np.asarray([float(s) for s in HRTrend_Data.split(' ')])  #将字符串通过空格分隔,转换成数组
pd.DataFrame(HRTrend_Data).plot()
HRTrend_Data

在这里插入图片描述

这个图形不是很规则不平滑,看数据是因为异常值太多,后面的数据都是0,这些0都是因为数据为Non补充进来的,有可能是应为数据采集的时候某个点位没有采集到。我们需要将这些异常值给处理掉。
对于中间为0的,我们可以通过采用前值填充或者后值填充(也就是用前面的值或后面的值来替代为0的值),后面全部为0的部分要去掉。应为会影响到一些关键性的特征,如均值、50%的值、70%的值等。

df_HRTrend1=pd.DataFrame(HRTrend_Data)
df_HRTrend1.describe()

在这里插入图片描述

可以看到,这些异常值将会很大程度的影响一些关键特征,所以我们要处理异常值。

HRTrend_Data=np.trim_zeros(HRTrend_Data)  #去掉首尾的0
df_data1=pd.DataFrame(HRTrend_Data)
df_data1.replace(to_replace=0, method='ffill',inplace=True)  #用前值替换掉中间的异常0
df_data1.plot()
df_data1.describe()

在这里插入图片描述

把刚对一个样本处理的过程写成一个函数,应用到所有的样本数据。

def procdata(df_dataclumn):ary_data=df_dataclumn[1:len(df_dataclumn)-1]ary_data=ary_data.replace('\n','')ary_data=ary_data.replace('nan',str(0))ary_data=re.sub(' +', ' ', ary_data).strip()ary_data=np.asarray([float(s) for s in ary_data.split(' ')])ary_data=np.trim_zeros(ary_data)df_data=pd.DataFrame(ary_data)df_data.replace(to_replace=0, method='ffill',inplace=True)ary_data=df_data.valuesreturn ary_datadf['HRTrend']=df['HRTrend'].map(procdata)
df['Weight'].replace(to_replace=0, method='ffill',inplace=True) #去异常值
df['Height'].replace(to_replace=0, method='ffill',inplace=True) #去异常值
df

找前六个样本看看效果

fig,axes = plt.subplots(2,3,figsize=(12,4))
i=0
for x in range(2):for y in range(3):i=i+1axes[x,y].plot(df['HRTrend'][i])

在这里插入图片描述

二、特征工程及模型训练

方法一:通过描叙统计提取时序特征并进行模型训练

  • 特征提取

有量纲时序特征提取包括以内容。
在这里插入图片描述

可以看到,大部分内容都可以通过describe()获取。可以写个函数方法来获取相关的特征值。

def getdescribefeatures(data):df_feature=pd.DataFrame(data)df_feature=df_feature.describe().Trange=df_feature['max'][0]-df_feature['min'][0]return range,df_feature['count'][0],df_feature['mean'][0],df_feature['std'][0],df_feature['min'][0],df_feature['25%'][0],df_feature['50%'][0],df_feature['75%'][0],df_feature['max'][0]HRTrend_np=np.array(df['HRTrend'])
HRTrend_features_ary=[getdescribefeatures(d) for d in HRTrend_np]
df_HRTrend_features=pd.DataFrame(HRTrend_features_ary,columns=['HRTrend'+str(i) for i in range(len(HRTrend_features_ary[0]))])
df_HRTrend_features

在这里插入图片描述

将心电图提出的统计信息特征与年龄、性别、身高、体重等特征合并,形成特征集。

df_data=df[['age','ismale','Weight','Height','label']].join(df_HRTrend_features)

预留15个样本做最后的预测看效果。

df_train_data=df_data[0:len(df_data)-15]    #训练数据
df_predict_data=df_data[len(df_data)-15:len(df_data)]  #用于预测的数据
  • 模型训练
from sklearn.metrics import f1_score
from sklearn.metrics import recall_score
from sklearn.metrics import accuracy_score
from sklearn.svm import SVC
from sklearn.neighbors import KNeighborsClassifierx_tt, x_validation, y_tt, y_validation = train_test_split(x, y, test_size=0.2)
# 将训练集再切分为训练集和测试集
x_train, x_test, y_train, y_test = train_test_split(x_tt, y_tt, test_size=0.25)#将模型的名字和模型函数作为元组添加到列表当中存储;
models = []
models.append(("KNN",KNeighborsClassifier(n_neighbors=3))) #指定邻居个数
models.append(("SVM Classifier",SVC(C=1000)))
#可以通过参数C来控制精度,C越大要求精度越高;  C——错分点的惩罚度#循环调用所有模型进行训练、预测
for clf_name, clf in models:clf.fit(x_train, y_train)xy_lst = [(x_train, y_train), (x_validation, y_validation), (x_test, y_test)]for i in range(len(xy_lst)):x_part = xy_lst[i][0]  # 为遍历中的第0部分y_part = xy_lst[i][1]  # 为遍历中的第1部分y_pred = clf.predict(x_part)print(i)  # i是下标,0表示训练集,1表示验证集,2表示测试集print(clf_name, "ACC:", accuracy_score(y_part, y_pred))print(clf_name, "REC:", recall_score(y_part, y_pred))print(clf_name, "F-score:", f1_score(y_part, y_pred))

结果如下:
在这里插入图片描述

SVM分类模型的效果要稍好于KNN的模型,但整体效果还不是很好。应该是提取的特征还是不够。我们来试下通过tsfresh提取时序特征并进行模型训练。

方法二:通过tsfresh提取时序特征并进行模型训练

  • 特征提取

tsfresh可以自动提取各种时间特征,可以参考官方文档,一般的取最大、最小、偏度、峰度等统计指标这些都自动化集成了。
https://tsfresh.readthedocs.io/en/latest/text/introduction.html
在这里插入图片描述

通过tsfresh提取时序特征代码如下:

from tsfresh import extract_features
from tsfresh import select_features
dfx_HRTrend=pd.DataFrame()
for i in df.index:df_i=pd.DataFrame(df['HRTrend'][i],columns=['HRTrend'])df_i['id']=idf_i['time']=np.array(range(1,len(df_i)+1))df_i['label']=df['label'][i]dfx_HRTrend=pd.concat(objs=[dfx_HRTrend,df_i])dfx_xtracted_features = extract_features(dfx_HRTrend,column_id="id", column_sort="time")
dfx_xtracted_features

在这里插入图片描述

可以看到tsfresh自动提取了1574colums的特征,但是我们要选取与标签有相关性的特征。tsfresh可以自动做到这一点,通过tsfresh的select_features传入特征和标签来选择与标签有相关性的特征,

from tsfresh.utilities.dataframe_functions import impute
impute(dfx_xtracted_features)
df_HRTrend_features = select_features(dfx_xtracted_features, df['label'])
df_HRTrend_features

在这里插入图片描述

通过特征选择自动选取了有相关性的143个特征,比前面缩减了很多,有利于提高模型训练的效率和精度。
我们再来看一下模型训练的效果。
同样将心电图通过tsfresh提出的时序特征与年龄、性别、身高、体重等特征合并,形成特征集。

df_data=df[['age','ismale','Weight','Height','label']].join(df_HRTrend_features)

预留15个样本做最后的预测看效果。

df_train_data=df_data[0:len(df_data)-15]    #训练数据
df_predict_data=df_data[len(df_data)-15:len(df_data)]  #用于预测的数据

模型训练

from sklearn.metrics import f1_score
from sklearn.metrics import recall_score
from sklearn.metrics import accuracy_score
from sklearn.svm import SVC
from sklearn.neighbors import KNeighborsClassifierx_tt, x_validation, y_tt, y_validation = train_test_split(x, y, test_size=0.2)
# 将训练集再切分为训练集和测试集
x_train, x_test, y_train, y_test = train_test_split(x_tt, y_tt, test_size=0.25)#将模型的名字和模型函数作为元组添加到列表当中存储;
models = []
models.append(("KNN",KNeighborsClassifier(n_neighbors=3))) #指定邻居个数
models.append(("SVM Classifier",SVC(C=1000)))
#可以通过参数C来控制精度,C越大要求精度越高;  C——错分点的惩罚度#循环调用所有模型进行训练、预测
for clf_name, clf in models:clf.fit(x_train, y_train)xy_lst = [(x_train, y_train), (x_validation, y_validation), (x_test, y_test)]for i in range(len(xy_lst)):x_part = xy_lst[i][0]  # 为遍历中的第0部分y_part = xy_lst[i][1]  # 为遍历中的第1部分y_pred = clf.predict(x_part)print(i)  # i是下标,0表示训练集,1表示验证集,2表示测试集print(clf_name, "ACC:", accuracy_score(y_part, y_pred))print(clf_name, "REC:", recall_score(y_part, y_pred))print(clf_name, "F-score:", f1_score(y_part, y_pred))

结果如下:
在这里插入图片描述

可以看到不管是KNN模型和SVM的模型都取得了不错的效果。

三、效果

最后我们来看一下,用预留的15个样本预测的效果。

pre_test_y=df_predict_data['label']
pre_test_x=df_predict_data.drop(columns='label')for clf_name, clf in models:for i in pre_test_x.index:y_predict=clf.predict(pre_test_x.loc[[i]])predict_result='预测错误!'if y_predict==pre_test_y.loc[[i]].values:predict_result='预测正确!'print('第'+str(i)+'个样本'+clf_name+' 预测y='+str(y_predict)+'--实际 y='+str(pre_test_y.loc[[i]].values)+' - '+predict_result)print('-'*10)

先是通过描叙统计提取时序特征并进行模型训练后模型预测的结果:
在这里插入图片描述

还是有不少预测错误了。
再来看通过tsfresh提取时序特征并进行模型训练后模型预测的结果:
在这里插入图片描述

可以看到预留的15个样本都预测正确,取得了不错的效果!

本文通过心电图分类模型介绍了从数据处理、时序特征提取、模型训练和效果评估。验证了对于小数据量,通过tsfresh提取时序特征,往往能够取得很好的效果。

全部源代码及数据集见:https://download.csdn.net/download/fullbug/87369380


博客地址:http://xiejava.ishareread.com/


http://www.ppmy.cn/news/9951.html

相关文章

Git的标签:tag

目录 1. 查看标签 1.1 简单查看 1.2 匹配筛选标签 2. 创建标签 2.1 附注标签 2.2 轻量标签 2.3 代码提交之后打标签 2.4 提交标签 3. 删除标签 4. 检出标签 Git 可以给仓库历史中的某一个提交打上标签,以示重要。 比较有代表性的是人们会使用这个功能来标记…

【Java语法】之String类练习2

目录 1.转换成小写字母 2.字符串中的单词数 3.交替合并字符串 转为数组 转为StringBuilder 4.字符串压缩 5.关于同构 有效的字母异位词 字符串的排列 6.长度最小的子数组 7.小结 1.转换成小写字母 709. 转换成小写字母 难度简单220 给你一个字符串 s ,将该字符串中…

基础算法[四]之图的那些事儿

文章目录前言图的表示邻接矩阵邻接表结构存储遍历路径搜索多源最短路问题问题描述Floyd实现模板单源最短路径问题Dijkstra算法朴素版本堆优化邻接表python实现Bellman-Ford 算法实现SPFA 算法实现python 版本判断负环小结最小生成树Prim算法Kruskra算法实现python版本二分图二分…

线段树讲解

0、引入 假设给定一个长度为 1001 的数组,即下标 0 到 1000。 现在需要完成 3 个功能: add(1, 200, 6); //给下标 1 到 200 的每个数都加 6; update(7, 375, 4); //下标 7 到 375 的数全部修改为 4 query(3, 999); //下标 3 到 999 所有数…

Python数据分析——pandas

1.pandas简介 pandas 是 Python 的核心数据分析支持库,提供了快速、灵活、明确的数据结构,旨在简单、直观地处理关系型、标记型数据。pandas 的目标是成为 Python 数据分析实践与实战的必备高级工具,其长远目标是成为最强大、最灵活、可以支持…

【小知识点】Python 随机生成一个汉字,提供了多种办法,目的竞然是用于创建头像

文章目录需求来源随机汉字随机生成常用汉字需求来源 在编写爬虫训练场 项目时,碰到一个随机头像的需求,这里用汉字去随机生成。 模拟的效果如下所示,输入一组汉字,然后返回一张图片。 接口地址如下所示: https://ui…

Struts2获取表单数据

Struts2获取表单数据Struts2获取表单数据1、原始Servlet方法2、属性封装3、表达式封装4、模型驱动封装Struts2获取表单数据 在Struts2中获取表单数据或提交路径的参数值的方式有4种。如下: 原始Servlet方法属性封装表达式封装模型驱动封装 1、原始Servlet方法 该…

FME对调查云平台完成变更调查照片的批量迁移

目录 前言 二、实际步骤 1.准备基础数据 2.模拟登录 3.获取图斑标识码 4.获取图形信息 5.通过空间位置关系过滤不合格照片 5.通过深度学习模型过滤照片特征错误图斑 6.照片迁移 总结 前言 又到了一年一度国土变更调查的苦日子,因为项目规则原因,…