【机器学习】基于LightGBM算法实现数据挖掘!
?作者:黃雨龍,中國科學(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)信息進(jìn)行脫敏。
字段描述
id:為心跳信號分配的唯一標(biāo)識
heartbeat_signals:心跳信號序列數(shù)據(jù),其中每個樣本的信號序列采樣頻次一致,長度相等(每個樣本有205條記錄)。
label:心跳信號類別(0、1、2、3)
評測標(biāo)準(zhǔn)
選手需提交4種不同心跳信號預(yù)測的概率,選手提交結(jié)果與實際心跳類型結(jié)果進(jìn)行對比,求預(yù)測的概率與真實值差值的絕對值(越小越好)。
總共有n個病例,針對某一個信號,若真實值為[y1,y2,y3,y4],模型預(yù)測概率值為[a1,a2,a3,a4],那么該模型的評價指標(biāo)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ù)評測標(biāo)準(zhǔn),每一個心跳樣本都要輸出4個類別下的概率值,所以可以用「邏輯回歸LR」or 「貝葉斯分類」實現(xiàn)?
由于心跳信號自帶明顯的「時序特征」(心跳參數(shù)隨時間變化),在后續(xù)的數(shù)據(jù)處理過程中要考慮「時序特征」所來來的影響?
根據(jù)評測公式,更關(guān)注的是「查準(zhǔn)率」,即預(yù)測準(zhǔn)確率越高,值就越小(模型得分目標(biāo))
根據(jù)初步理解,我會初步使用「邏輯回歸LR算法」,給出每個分類下的概率值。
二、數(shù)據(jù)讀取
Baseline文檔可以粗略的劃分以下幾個部分:
工具包準(zhǔn)備
import?os import?gc import?mathimport?pandas?as?pd import?numpy?as?npimport?lightgbm?as?lgb #?import?xgboost?as?xgb from?catboost?import?CatBoostRegressor from?sklearn.linear_model?import?SGDRegressor,?LinearRegression,?Ridge from?sklearn.preprocessing?import?MinMaxScalerfrom?sklearn.model_selection?import?StratifiedKFold,?KFold from?sklearn.metrics?import?log_loss from?sklearn.model_selection?import?train_test_split from?sklearn.preprocessing?import?OneHotEncoderfrom?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)計信息:均值、標(biāo)準(zhǔn)差、中位數(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ù)值類型」:由每列的最大值和最小值來確定。
轉(zhuǎn)換數(shù)據(jù)格式
將「字符串」轉(zhuǎn)為「浮點數(shù)」
數(shù)據(jù)樣本處理
訓(xùn)練數(shù)據(jù)樣本與測試數(shù)據(jù)樣本
四、模型訓(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?loss2、模型參數(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?=?100seed?=?2021kf?=?KFold(n_splits=folds,?shuffle=True,?random_state=seed)#設(shè)置測試集,輸出矩陣。每一組數(shù)據(jù)輸出:[0,0,0,0]以概率值填入test?=?np.zeros((test_x.shape[0],4))#交叉驗證分?jǐn)?shù)cv_scores?=?[]onehot_encoder?=?OneHotEncoder(sparse=False)#將訓(xùn)練集「K折」操作,i值代表第(i+1)折。每一個K折都進(jìn)行「數(shù)據(jù)混亂:隨機(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次迭代,進(jìn)行一次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ù),原來為2000verbose_eval=100,???????????#early_stopping_rounds=500)??#如果數(shù)據(jù)在500次內(nèi)沒有提高,停止計算,原來為200val_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?/?7return?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í)賽分?jǐn)?shù)
將最終的預(yù)測結(jié)果上傳到學(xué)習(xí)賽,給出結(jié)果值!
五、思考
1、Baseline代碼是基于LGBM算法實現(xiàn)的,其中一些參數(shù)具體含義需要后續(xù)學(xué)習(xí)。
2、在原始代碼上,我修改了一下學(xué)習(xí)率,增加了迭代次數(shù),嘗試配置了約束項。輸出的訓(xùn)練誤差很小(score25左右),但是在測試集上的誤差就很大,說明模型過擬合了,需要后續(xù)研究是哪些參數(shù)的作用。
3、Baseline里面只是對原始數(shù)據(jù)做了學(xué)習(xí),根據(jù)4中心跳信號分類圖可以知道,不同類型的信號「時序特征」有著明顯的區(qū)別,如何在模型中體現(xiàn)?
4、是否需要考慮類別數(shù)量不均衡的問題?
往期精彩回顧適合初學(xué)者入門人工智能的路線及資料下載機(jī)器學(xué)習(xí)及深度學(xué)習(xí)筆記等資料打印機(jī)器學(xué)習(xí)在線手冊深度學(xué)習(xí)筆記專輯《統(tǒng)計學(xué)習(xí)方法》的代碼復(fù)現(xiàn)專輯 AI基礎(chǔ)下載機(jī)器學(xué)習(xí)的數(shù)學(xué)基礎(chǔ)專輯 本站qq群851320808,加入微信群請掃碼:總結(jié)
以上是生活随笔為你收集整理的【机器学习】基于LightGBM算法实现数据挖掘!的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Win7旗舰版系统hosts文件位置在哪
- 下一篇: win7系统设置开机自动联网的方法