<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          基于LightGBM算法實現(xiàn)數(shù)據(jù)挖掘!

          共 20939字,需瀏覽 42分鐘

           ·

          2021-03-26 21:22

          ↑↑↑關(guān)注后"星標"Datawhale
          每日干貨 & 每月組隊學(xué)習(xí),不錯過
           Datawhale干貨 
          作者:黃雨龍,中國科學(xué)技術(shù)大學(xué)

          對于回歸問題,Datawhale已經(jīng)梳理過完整的實踐方案(可點擊),本文對多分類的數(shù)據(jù)挖掘問題做了完整的方案總結(jié)。

          一、賽題數(shù)據(jù)

          賽題背景

          本賽題是一個多分類的數(shù)據(jù)挖掘問題。賽題以醫(yī)療數(shù)據(jù)挖掘為背景,要求選手使用提供的心跳信號傳感器數(shù)據(jù)訓(xùn)練模型并完成不同心跳信號的分類的任務(wù)。

          實踐地址:https://tianchi.aliyun.com/competition/entrance/531883/information

          賽題介紹

          • 任務(wù):賽題以預(yù)測心電圖心跳信號類別為任務(wù)
          • 數(shù)據(jù)集:
            • 10萬條作為訓(xùn)練集;
            • 2萬條作為測試集A;
            • 2萬條作為測試集B;
            • 對心跳信號類別(label)信息進行脫敏。

          字段描述

          • id:為心跳信號分配的唯一標識
          • heartbeat_signals:心跳信號序列數(shù)據(jù),其中每個樣本的信號序列采樣頻次一致,長度相等(每個樣本有205條記錄)。
          • label:心跳信號類別(0、1、2、3)

          評測標準

          選手需提交4種不同心跳信號預(yù)測的概率,選手提交結(jié)果與實際心跳類型結(jié)果進行對比,求預(yù)測的概率與真實值差值的絕對值(越小越好)。

          總共有n個病例,針對某一個信號,若真實值為[y1,y2,y3,y4],模型預(yù)測概率值為[a1,a2,a3,a4],那么該模型的評價指標abs-sum為 :

          例如,某心跳信號類別為1,通過編碼轉(zhuǎn)成[0,1,0,0],預(yù)測不同心跳信號概率為[0.1,0.7,0.1,0.1],那么這個信號預(yù)測結(jié)果的abs-sum為 :

          簡單小結(jié)

          • 根據(jù)賽題數(shù)據(jù)可以知道,此問題為「分類問題」,且為「多分類問題」,分類算法可以考慮,如「LR」、「貝葉斯分類」、「決策樹」等等。
          • 根據(jù)評測標準,每一個心跳樣本都要輸出4個類別下的概率值,所以可以用「邏輯回歸LR」or 「貝葉斯分類」實現(xiàn)?
          • 由于心跳信號自帶明顯的「時序特征」(心跳參數(shù)隨時間變化),在后續(xù)的數(shù)據(jù)處理過程中要考慮「時序特征」所來來的影響?
          • 根據(jù)評測公式,更關(guān)注的是「查準率」,即預(yù)測準確率越高,值就越?。P偷梅帜繕耍?/span>

          根據(jù)初步理解,我會初步使用「邏輯回歸LR算法」,給出每個分類下的概率值。

          二、數(shù)據(jù)讀取

          Baseline文檔可以粗略的劃分以下幾個部分:

          工具包準備

          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')

          工具包導(dǎo)入:pandas、numpy、sklearn、lightgbm等。

          數(shù)據(jù)讀取

          path = '/Users/huangyulong/Desktop/心跳信號分類預(yù)測'

          train_csv = '/train.csv' 
          testA_csv = '/testA.csv'

          train = pd.read_csv(path + train_csv)
          test = pd.read_csv(path + testA_csv)

          查看數(shù)據(jù)集與測試集

          train.head()

          test.head()

          4種心跳信號特征:

          signal_values = []
          for i in range(4):
              temp = train[train['label']==i].iloc[0, 1].split(',')
              temp = list(map(float, temp))
              signal_values.append(temp)
              
          signal_values = np.array(signal_values)

          color = ['red''green''yellow''blue']
          label = ['label_0''label_1' ,'label_2' ,'label_3']

          plt.figure(figsize=(8, 4))

          for i in range(4):
              plt.plot(signal_values[i], color=color[i], label=label[i])
              plt.legend() 
              
          plt.show()

          數(shù)據(jù)整體信息:數(shù)據(jù)類型、是否有缺失值等

          train.info()

          <class 'pandas.core.frame.DataFrame'>
          RangeIndex: 100000 entries, 0 to 99999
          Data columns (total 3 columns):
           #   Column             Non-Null Count   Dtype  
          ---  ------             --------------   -----  
           0   id                 100000 non-null  int64  
           1   heartbeat_signals  100000 non-null  object 
           2   label              100000 non-null  float64
          dtypes: float64(1), int64(1), object(1)
          memory usage: 2.3+ MB

          數(shù)據(jù)統(tǒng)計信息:均值、標準差、中位數(shù)等等。

          注:這里面只能統(tǒng)計ID、label列;因為heartbeat_signals數(shù)據(jù)不符合格式。

          train.describe()

          4種心跳信號類別在數(shù)據(jù)集中占比情況:

          train['label'].value_counts()

          0.0    64327
          3.0    17912
          2.0    14199
          1.0     3562
          Name: label, dtype: int64

          三、數(shù)據(jù)預(yù)處理

          由于原始數(shù)據(jù)中,heartbeat_signals 列存儲了205條信息,所以要把這一列數(shù)據(jù)轉(zhuǎn)化成方便讀取、易于使用的格式:比如構(gòu)建205列。

          train_list = []

          for items in train.values:
              train_list.append([items[0]] + [float(i) for i in items[1].split(',')] + [items[2]])

          train1 = pd.DataFrame(np.array(train_list))
          train1.columns = ['id'] + ['s_'+str(i) for i in range(len(train_list[0])-2)] + ['label']

          train1

          設(shè)置數(shù)值類型

          設(shè)置每列數(shù)值的「數(shù)值類型」:由每列的最大值和最小值來確定。

          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

          轉(zhuǎn)換數(shù)據(jù)格式

          將「字符串」轉(zhuǎn)為「浮點數(shù)」

          train_list = []

          for items in train.values:
          train_list.append([items[0]] + [float(i) for i in items[1].split(',')] + [items[2]])

          train2 = pd.DataFrame(np.array(train_list))
          train2.columns = ['id'] + ['s_'+str(i) for i in range(len(train_list[0])-2)] + ['label']
          train2 = reduce_mem_usage(train2)

          test_list=[]
          for items in test.values:
          test_list.append([items[0]] + [float(i) for i in items[1].split(',')])

          test2 = pd.DataFrame(np.array(test_list))
          test2.columns = ['id'] + ['s_'+str(i) for i in range(len(test_list[0])-1)]
          test2 = reduce_mem_usage(test2)

          數(shù)據(jù)樣本處理

          訓(xùn)練數(shù)據(jù)樣本與測試數(shù)據(jù)樣本

          #訓(xùn)練樣本
          x_train = train2.drop(['id','label'], axis=1)
          y_train = train2['label']

          #測試樣本
          x_test = test2.drop(['id'], axis=1)

          四、模型訓(xùn)練

          1、評估函數(shù)

          評測公式(損失函數(shù)):

          def abs_sum(y_pre,y_tru):
              y_pre=np.array(y_pre)
              y_tru=np.array(y_tru)
              loss=sum(sum(abs(y_pre-y_tru)))
              return loss

          2、模型參數(shù)設(shè)置

          • n_splits : int, default=3
          • shuffle : Whether to shuffle the data before splitting into batches.
          • random_state : When shuffle=True, pseudo-random number generator state used for shuffling. If None, use default numpy RNG for shuffling.

          3、one-hot編碼

          而我們的分類結(jié)果是為了得到隸屬于某個類別的概率,所以這里采用「one-hot編碼」。

          • sparse : Will return sparse matrix if set True else will return an array.(為True時返回稀疏矩陣)

          模型參數(shù)設(shè)置

          def cv_model(clf, train_x, train_y, test_x, clf_name):
              folds = 100
              seed = 2021
              kf = KFold(n_splits=folds, shuffle=True, random_state=seed)
              
              #設(shè)置測試集,輸出矩陣。每一組數(shù)據(jù)輸出:[0,0,0,0]以概率值填入
              test = np.zeros((test_x.shape[0],4))
              
              #交叉驗證分數(shù)
              cv_scores = []
              onehot_encoder = OneHotEncoder(sparse=False)
              
              #將訓(xùn)練集「K折」操作,i值代表第(i+1)折。每一個K折都進行「數(shù)據(jù)混亂:隨機」操作
              #train_index:用于訓(xùn)練的(K-1)的樣本索引值
              #valid_index:剩下1折樣本索引值,用于給出「訓(xùn)練誤差」
              for i, (train_index, valid_index) in enumerate(kf.split(train_x, train_y)):
                  if i < 7:
                      #打印第(i+1)個模型結(jié)果
                      print('************************************ {} ************************************'.format(str(i+1)))
                      
                      #將訓(xùn)練集分為:真正訓(xùn)練的數(shù)據(jù)(K-1折),和 訓(xùn)練集中的測試數(shù)據(jù)(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]
                      
                      
                      #LGB模型
                      if clf_name == "lgb":
                          
                          #訓(xùn)練樣本
                          train_matrix = clf.Dataset(trn_x, label=trn_y)
                          #訓(xùn)練集中測試樣本
                          valid_matrix = clf.Dataset(val_x, label=val_y)
                          
                          #參數(shù)設(shè)置
                          params = {
                              'boosting_type''gbdt',          #boosting方式
                              'objective''multiclass',        #任務(wù)類型為「多分類」
                              'num_class': 4,                   #類別個數(shù)
                              'num_leaves': 2 ** 5,             #最大的葉子數(shù)
                              'feature_fraction': 0.9,          #原來是0.8
                              'bagging_fraction': 0.9,          #原來是0.8
                              'bagging_freq': 5,                #每5次迭代,進行一次bagging
                              'learning_rate': 0.05,            #學(xué)習(xí)效率:原來是0.1
                              'seed': seed,                     #seed值,保證模型復(fù)現(xiàn)
                              'nthread': 28,                    #
                              'n_jobs':24,                      #多線程
                              'verbose': 1,
                              'lambda_l1': 0.4,                 #新添加 L1
                              'lambda_l2': 0.5,                 #新添加 L2
                              'min_data_in_leaf':100,           #葉子可能具有的最小記錄數(shù)
                          }
                          
                          #模型
                          model = clf.train(params, 
                                    train_set=train_matrix,     #訓(xùn)練樣本
                                    valid_sets=valid_matrix,    #測試樣本 
                                    num_boost_round=10000,      #迭代次數(shù),原來為2000
                                    verbose_eval=100,           #
                                    early_stopping_rounds=500)  #如果數(shù)據(jù)在500次內(nèi)沒有提高,停止計算,原來為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('預(yù)測的概率矩陣為:')
                      print(test_pred)
                      
                      #將預(yù)測結(jié)果填入到test里面,這是一個「i個模型結(jié)果累加過程」
                      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))
              
              #下面公式是什么含義呢?為啥要除以「K折數(shù)」?:i個模型輸出結(jié)果的平均值。
              test = test / 7

              return test

          調(diào)用模型

          def lgb_model(x_train, y_train, x_test):
              lgb_test = cv_model(lgb, x_train, y_train, x_test, "lgb")
              return lgb_test

          訓(xùn)練模型

          lgb_test = lgb_model(x_train, y_train, x_test)

          預(yù)測結(jié)果

          temp = pd.DataFrame(lgb_test)

          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('submit1.csv',index=False)

          第一次天池學(xué)習(xí)賽分數(shù)

          將最終的預(yù)測結(jié)果上傳到學(xué)習(xí)賽,給出結(jié)果值!

          五、思考

          1、Baseline代碼是基于LGBM算法實現(xiàn)的,其中一些參數(shù)具體含義需要后續(xù)學(xué)習(xí)。
          2、在原始代碼上,我修改了一下學(xué)習(xí)率,增加了迭代次數(shù),嘗試配置了約束項。輸出的訓(xùn)練誤差很?。╯core25左右),但是在測試集上的誤差就很大,說明模型過擬合了,需要后續(xù)研究是哪些參數(shù)的作用。
          3、Baseline里面只是對原始數(shù)據(jù)做了學(xué)習(xí),根據(jù)4中心跳信號分類圖可以知道,不同類型的信號「時序特征」有著明顯的區(qū)別,如何在模型中體現(xiàn)?
          4、是否需要考慮類別數(shù)量不均衡的問題?
          “整理不易,三連
          瀏覽 59
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  99免费观看视频 | 亚洲不卡顿一区二区 | 五月丁香六月婷婷免费视频 | 国产真空露出福利视频 | 亚洲三级视频在线 |