• 【心跳信号分类预测】Datawhale打卡- Task03 特征工程


    请勿推荐,谢谢!

    比赛地址
    https://tianchi.aliyun.com/competition/entrance/531883/information

    3.1 学习目标

    • 学习时间序列数据的特征预处理方法
    • 学习时间序列特征处理工具 Tsfresh(TimeSeries Fresh)的使用

    3.2 内容介绍

    • 数据预处理
      • 时间序列数据格式处理
      • 加入时间步特征time
    • 特征工程
      • 时间序列特征构造
      • 特征筛选
      • 使用 tsfresh 进行时间序列特征处理
    
    

    baseline

    1.导入第三方包

    import time
    import warnings
    import lightgbm as lgb
    import matplotlib.pyplot as plt
    import numpy as np
    import pandas as pd
    from sklearn.model_selection import KFold
    from sklearn.preprocessing import OneHotEncoder
    warnings.filterwarnings('ignore')
    """
    sns 相关设置
    @return:
    """
    import datetime
    import seaborn as sns
    sns.set()
    sns.set_style("whitegrid")
    sns.set_context('talk')
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False
    sns.set(font='SimHei')
    
    t0 = time.time()
    print('import done, sns & plt preset done, clock() start', datetime.datetime.now())
    
    import done, sns & plt preset done, clock() start 2021-03-16 18:00:24.924459
    
    #### 1.1 公共变量
    win_file_path = 'E:\competition-data\016_heartbeat_signals\'
    
    now = datetime.datetime.now().strftime('%Y-%m-%d_%H_%M_%S')
    
    out_path = 'E:\PycharmProjects\TianChiProject\00_hardworker\competitions\016_heartbeat_signals\predict_result\'+ 'dw_baseline_predict_{}.csv'.format(now)
    print('out_path: ', out_path)
    
    out_path:  E:PycharmProjectsTianChiProject0_hardworkercompetitions16_heartbeat_signalspredict_resultdw_baseline_predict_2021-03-16_18_00_24.csv
    

    2.读取数据

    data_train = pd.read_csv(win_file_path+'train.csv')
    data_test_A=pd.read_csv(win_file_path+'testA.csv')
    data_train.head()
    
    id heartbeat_signals label
    0 0 0.9912297987616655,0.9435330436439665,0.764677... 0.0
    1 1 0.9714822034884503,0.9289687459588268,0.572932... 0.0
    2 2 1.0,0.9591487564065292,0.7013782792997189,0.23... 2.0
    3 3 0.9757952826275774,0.9340884687738161,0.659636... 0.0
    4 4 0.0,0.055816398940721094,0.26129357194994196,0... 2.0
    data_test_A.head()
    
    id heartbeat_signals
    0 100000 0.9915713654170097,1.0,0.6318163407681274,0.13...
    1 100001 0.6075533139615096,0.5417083883163654,0.340694...
    2 100002 0.9752726292239277,0.6710965234906665,0.686758...
    3 100003 0.9956348033996116,0.9170249621481004,0.521096...
    4 100004 1.0,0.8879490481178918,0.745564725322326,0.531...

    3.数据预处理

    对心电特征进行行转列处理,同时为每个心电信号加入时间步特征time

    train_heartbeat_df = data_train["heartbeat_signals"].str.split(",", expand=True).stack()
    train_heartbeat_df = train_heartbeat_df.reset_index()
    train_heartbeat_df = train_heartbeat_df.set_index("level_0")
    train_heartbeat_df.index.name = None
    train_heartbeat_df.rename(columns={"level_1":"time", 0:"heartbeat_signals"}, inplace=True)
    train_heartbeat_df["heartbeat_signals"] = train_heartbeat_df["heartbeat_signals"].astype(float)
    
    train_heartbeat_df
    
    time heartbeat_signals
    0 0 0.991230
    0 1 0.943533
    0 2 0.764677
    0 3 0.618571
    0 4 0.379632
    ... ... ...
    99999 200 0.000000
    99999 201 0.000000
    99999 202 0.000000
    99999 203 0.000000
    99999 204 0.000000

    20500000 rows × 2 columns

    将处理后的心电特征加入到训练数据中,同时将训练数据label列单独存储

    data_train_label = data_train["label"]
    data_train = data_train.drop("label", axis=1)
    data_train = data_train.drop("heartbeat_signals", axis=1)
    data_train = data_train.join(train_heartbeat_df)
    
    data_train
    
    id time heartbeat_signals
    0 0 0 0.991230
    0 0 1 0.943533
    0 0 2 0.764677
    0 0 3 0.618571
    0 0 4 0.379632
    ... ... ... ...
    99999 99999 200 0.000000
    99999 99999 201 0.000000
    99999 99999 202 0.000000
    99999 99999 203 0.000000
    99999 99999 204 0.000000

    20500000 rows × 3 columns

    可以看到,每个样本的心电特征都由205个时间步的心电信号组成。

    3 使用 tsfresh 进行时间序列特征处理

    1. 使用tsfresh特征抽取

    Tsfresh(TimeSeries Fresh)是一个Python第三方工具包。 它可以自动计算大量的时间序列数据的特征。此外,该包还包含了特征重要性评估、特征选择的方法,因此,不管是基于时序数据的分类问题还是回归问题,tsfresh都会是特征提取一个不错的选择。官方文档:Introduction — tsfresh 0.17.1.dev24+g860c4e1 documentation

    from tsfresh import extract_features
    
    # 特征提取
    train_features = extract_features(data_train, column_id='id', column_sort='time', n_jobs=6)
    train_features
    
    Feature Extraction:  100%|███████████████████████████████                           
    
    
    
    import pickle
    import pandas as pd
    
    # train_features_filtered = pd.DataFrame({'Gender':['F','F','M','M'], 'Height':[163, 160, 175, 180]})
    
    pickle_file_path = 'E:\competition-data\016_heartbeat_signals\pickle_model\'+ 'train_features.csv'
    train_features.to_csv(pickle_file_path, index=False)
    #
    # train_features_filtered = pd.read_csv(pickle_file_path)
    # train_features_filtered.head()
    
    

    2. 特征选择

    train_features中包含了heartbeat_signals的779种常见的时间序列特征(所有这些特征的解释可以去看官方文档),这其中有的特征可能为NaN值(产生原因为当前数据不支持此类特征的计算),使用以下方式去除NaN值:

    from tsfresh.utilities.dataframe_functions import impute
    
    # 去除抽取特征中的NaN值
    impute(train_features)
    

    接下来,按照特征和响应变量之间的相关性进行特征选择,这一过程包含两步:首先单独计算每个特征和响应变量之间的相关性,然后利用Benjamini-Yekutieli procedure [1] 进行特征选择,决定哪些特征可以被保留。

    from tsfresh import select_features
    
    # 按照特征和数据label之间的相关性进行特征选择
    train_features_filtered = select_features(train_features, data_train_label, multiclass=True, n_jobs=6)
    
    pickle_file_path = 'E:\competition-data\016_heartbeat_signals\pickle_model\'+ 'train_features_filtered.csv'
    train_features_filtered.to_csv(pickle_file_path, index=False)
    
    # train_features_filtered = pd.read_csv(pickle_file_path)
    # train_features_filtered.head()
    
    print(train_features_filtered.columns)
    print(type(train_features_filtered))
    
    print('id' in np.array(train_features_filtered.columns))
    print('label' in np.array(train_features_filtered.columns))
    

    4.训练数据/测试数据准备

    x_train = train_features_filtered.drop(['id','label'], axis=1)
    y_train = train_features_filtered['label']
    x_test=data_test_A.drop(['id'], axis=1)
    

    5.模型训练

    from tsfresh import extract_features
    
    # 特征提取
    train_features = extract_features(data_train, column_id='id', column_sort='time')
    train_features
    

    2. 特征选择

    train_features中包含了heartbeat_signals的779种常见的时间序列特征(所有这些特征的解释可以去看官方文档),这其中有的特征可能为NaN值(产生原因为当前数据不支持此类特征的计算),使用以下方式去除NaN值:

    from tsfresh.utilities.dataframe_functions import impute
    
    # 去除抽取特征中的NaN值
    impute(train_features)
    

    接下来,按照特征和响应变量之间的相关性进行特征选择,这一过程包含两步:首先单独计算每个特征和响应变量之间的相关性,然后利用Benjamini-Yekutieli procedure [1] 进行特征选择,决定哪些特征可以被保留。

    from tsfresh import select_features
    
    # 按照特征和数据label之间的相关性进行特征选择
    train_features_filtered = select_features(train_features, data_train_label)
    
    print(train_features_filtered.columns)
    print(type(train_features_filtered))
    
    print('id' in np.array(train_features_filtered.columns))
    print('label' in np.array(train_features_filtered.columns))
    

    5. 补充之前记过的笔记,做一下更多的特征选择

    3.3.7 特征选择/特征筛选/特征精简

    • 1.1 Filter
      • a. 方差选择法
      • b. 相关系数法(pearson 相关系数)
      • c. 卡方检验
      • d. 互信息法
    • 2.2 Wrapper (RFE)
      • a. 递归特征消除法
    • 3.3 Embedded
      • a. 基于惩罚项的特征选择法
      • b. 基于树模型的特征选择

    3.3.7.1 Fi特征重要性评估后,可以获得更好的数据拟合效果,更低的方差和偏差,实际rank上提分80+。 筛选特征列 : 相关系数法/卡方检验/互信息法

    # 基于特征间的关系进行筛选  方差选择法
    #  方差选择法中,先要计算各个特征的方差,然后根据设定的阈值,选择方差大于阈值的特征
    from sklearn.feature_selection import VarianceThreshold
    #其中参数threshold为方差的阈值
    VarianceThreshold(threshold=3).fit_transform(train, target_train)
    
    # 相关系数法
    # Pearson 相关系数
    # 皮尔森相关系数是一种最简单的,可以帮助理解特征和响应变量之间关系的方法,该方法衡量的是变量之间的线性相关性。
    # 结果的取值区间为 [-1,1] , -1 表示完全的负相关, +1表示完全的正相关,0 表示没有线性相关。
    from sklearn.feature_selection import SelectKBest
    from scipy.stats import pearsonr
    #选择K个最好的特征,返回选择特征后的数据
    # #第一个参数为计算评估特征是否好的函数,该函数输入特征矩阵和目标向量,
    # #输出二元组(评分,P值)的数组,数组第i项为第i个特征的评分和P值。在此定义为计算相关系数
    # #参数k为选择的特征个数
    SelectKBest(k=5).fit_transform(train, target_train)
    
    # 卡方检验
    # 1. 经典的卡方检验是用于检验自变量对因变量的相关性。 假设自变量有N种取值,因变量有M种取值,考虑自变
    # 量等于i且因变量等于j的样本频数的观察值与期望的差距。 其统计量如下: χ2=∑(A−T)2T,其中A为实际值,
    # T为理论值
    # 2. (注:卡方只能运用在正定矩阵上,否则会报错Input X must be non-negative)
    from sklearn.feature_selection import SelectKBest
    from sklearn.feature_selection import chi2 #参数k为选择的特征个数
    SelectKBest(chi2, k=5).fit_transform(train, target_train)
    
    # 互信息法
    #  经典的互信息也是评价自变量对因变量的相关性的。 在feature_selection库的SelectKBest类结合最大信息系数
    #   法可以用于选择特征,
    from sklearn.feature_selection import SelectKBest
    from minepy import MINE
    #由于MINE的设计不是函数式的,定义mic方法将其为函数式的,
    # #返回一个二元组,二元组的第2项设置成固定的P值0.5
    def mic(x, y):
        m = MINE()
        m.compute_score(x, y)
        return (m.mic(), 0.5) #参数k为选择的特征个数
        SelectKBest(lambda X, Y: np.array(map(lambda x:mic(x, Y), X.T)).T, k=2).fit_transform(train,target_train)
    
    

    3.3.7.2 Wrapper (Recursive feature elimination,RFE)递归特征消除法

    递归消除特征法
    
    #  递归消除特征法使用一个基模型来进行多轮训练,每轮训练后,消除若干权值系数的特征,
    # 再基于新的特征集进行下一轮训练。 在feature_selection库的RFE类可以用于选择特征,相关代码如下(以逻辑
    # 回归为例):
    
    # from sklearn.feature_selection import RFE
    # from sklearn.linear_model import LogisticRegression #递归特征消除法,返回特征选择后的数据 #参数estimator为基模型 #参数
    # # n_features_to_select为选择的特征个数
    # RFE(estimator=LogisticRegression(), n_features_to_select=2).fit_transform(train, target_train)
    

    3.3.7.3 Embedded (汉译:嵌入式的/基模型)

    # # 基于惩罚项的特征选择法 使用带惩罚项的基模型,除了筛选出特征外,同时也进行了降维。 在
    # # feature_selection库的SelectFromModel类结合逻辑回归模型可以用于选择特征,相关代码如下:
    # from sklearn.feature_selection import SelectFromModel
    # from sklearn.linear_model import LogisticRegression #带L1惩罚项的逻辑回归作为基模型的特征选择
    # SelectFromModel(LogisticRegression(penalty="l1", C=0.1)).fit_transform(train, target_train)
    
    # # 基于树模型的特征选择 树模型中GBDT也可用来作为基模型进行特征选择。 在feature_selection库的
    # #   SelectFromModel类结合GBDT模型可以用于选择特征,相关代码如下:
    # from sklearn.feature_selection import SelectFromModel
    # from sklearn.ensemble import GradientBoostingClassifier #GBDT作为基模型的特征选择
    # SelectFromModel(GradientBoostingClassifier()).fit_transform(train, target_train)
    

    6. 小结

    • tsfresh后,可以获得更多特征, 707列特征,直接训练会导致过拟合——泛化能力大幅降低。
    • 通过多轮特征重要性评估后,可以获得更好的数据拟合效果,更低的方差和偏差,实际rank上提分80+。
    你不逼自己一把,你永远都不知道自己有多优秀!只有经历了一些事,你才会懂得好好珍惜眼前的时光!
  • 相关阅读:
    [bxd学习java基本点]4.List,与角标有关的均来自此,及其独有的方式
    Android APK加壳技术方案代码实现
    如何在图片上加入QQ链接窗口
    商店管理系统源代码(一)
    百度推荐与个性化部架构组二面
    商店管理系统源代码(三)
    在HTML中使用WCF RESTful上传文件
    sharepoint 2010 扩展富文本框上传图片功能extend InputFormTextBox for uploading image
    Linux中gmtime和localtime的区别
    NDK下 将Platinum SDK 编译成so库 (android upnp)
  • 原文地址:https://www.cnblogs.com/zhazhaacmer/p/14687530.html
Copyright © 2020-2023  润新知