0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

以KaggleDays數(shù)據(jù)集為例,編碼方法介紹

zhKF_jqr_AI ? 來源:未知 ? 作者:李倩 ? 2018-11-22 09:10 ? 次閱讀

編者按:華沙大學(xué)機(jī)器學(xué)習(xí)科學(xué)家Wojciech Rosinski介紹了類別編碼的主要方法。

介紹

這是特征工程方法系列的第一篇。在機(jī)器學(xué)習(xí)的實踐中,特征工程是最重要而定義最松散的方面之一。它可以被視為藝術(shù),沒有嚴(yán)格的規(guī)則,創(chuàng)造性是其關(guān)鍵。

特征工程是要為機(jī)器學(xué)習(xí)模型創(chuàng)建更好的信息表示。即便使用非線性算法,如果使用原始數(shù)據(jù),我們也無法建模數(shù)據(jù)集的變量之間的所有交互(關(guān)系)。因此,我們需要手工探查、處理數(shù)據(jù)。

這就帶來了一個問題——深度學(xué)習(xí)怎么講?深度學(xué)習(xí)是為了最小化手工處理數(shù)據(jù)的需求,使模型能夠自行學(xué)習(xí)恰當(dāng)?shù)臄?shù)據(jù)表示。在圖像、語音、文本之類沒有給定其他“元數(shù)據(jù)”的數(shù)據(jù)上,深度學(xué)習(xí)會表現(xiàn)得更好。而在表格式數(shù)據(jù)上,沒有什么可以戰(zhàn)勝梯度提升樹方法,例如XGBoost或LightGBM。機(jī)器學(xué)習(xí)競賽證明了這一點——幾乎所有表格式數(shù)據(jù)的獲勝方案中,基于決策樹的模型是最佳的,而深度學(xué)習(xí)模型通常沒法達(dá)到這么好的結(jié)果(但混合基于決策樹的模型時效果非常好 ;-) )

特征工程的偏差是領(lǐng)域知識。取決于需要解決的問題,每個數(shù)據(jù)集應(yīng)該使用不同的特征工程方法,原因正在于此。不過,仍有一些廣泛使用的方法,至少值得嘗試下能否提升模型表現(xiàn)。HJ vav Veen的講演中提到了大量的實用信息。下面的一些方法正是根據(jù)講演的描述實現(xiàn)的。

本文以KaggleDays數(shù)據(jù)集為例,編碼方法介紹參考了上面的講演。

數(shù)據(jù)集

數(shù)據(jù)來自reddit,包含問題和回答。目標(biāo)是預(yù)測回答的贊數(shù)。之所以用這個數(shù)據(jù)集為例,是因為它包含文本和標(biāo)準(zhǔn)特征。

引入需要用到的庫:

import gc

import numpy as np

import pandas as pd

加載數(shù)據(jù):

X = pd.read_csv('../input/train.csv', sep="\t", index_col='id')

列:

['question_id',

'subreddit',

'question_utc',

'question_text',

'question_score',

'answer_utc',

'answer_text',

'answer_score']

每個question_id對應(yīng)一個具體問題(見question_text)。每個question_id可能出現(xiàn)多次,因為每一行包含對這一問題的一個不同回答(見answer_text)。問題和回答的時間日期由_utc列提供。另外還包括問題發(fā)布的subreddit(版塊)的信息。question_score是問題的贊數(shù),而answer_score是回答的贊數(shù)。answer_score是目標(biāo)變量。

數(shù)據(jù)需要根據(jù)question_id分為訓(xùn)練子集和驗證子集,仿效Kaggle分訓(xùn)練集和測試集的做法。

question_ids = X.question_id.unique()

question_ids_train = set(pd.Series(question_ids).sample(frac=0.8))

question_ids_valid = set(question_ids).difference(question_ids_train)

X_train = X[X.question_id.isin(question_ids_train)]

X_valid = X[X.question_id.isin(question_ids_valid)]

類別特征和數(shù)值特征

機(jī)器學(xué)習(xí)模型只能處理數(shù)字。數(shù)值(連續(xù)、定量)變量是可以在有限或無限區(qū)間內(nèi)取任何值的變量,它們可以很自然地用數(shù)字表示,所以可以在模型中直接使用。原始類別變量通常以字符串的形式存在,在傳入模型之前需要變換。

subreddit是類別變量的一個好例子,其中包含41個不同的類別,例如:

['AskReddit', 'Jokes', 'politics', 'explainlikeimfive', 'gaming']

讓我們看下最流行的類別(X.subreddit.value_counts()[:5]):

AskReddit 275667

politics 123003

news 42271

worldnews 40016

gaming 32117

Name: subreddit, dtype: int64

數(shù)值變量的一個例子是question_score,可以通過X.question_score.describe()瀏覽信息:

mean 770.891169

std 3094.752794

min 1.000000

25% 2.000000

50% 11.000000

75% 112.000000

max 48834.000000

Name: question_score, dtype: float64

類別特征編碼

類別編碼的兩個基本方法是獨熱編碼(onehot encoding)和標(biāo)簽編碼(label encoding)。獨熱編碼可以通過pandas.get_dummies完成。具備K個類別的變量的編碼結(jié)果是一個K列的二值矩陣,其中第i列的值為1意味著這項觀測屬于第i類。

標(biāo)簽編碼直接將類別轉(zhuǎn)換為數(shù)字。pandas.factorize提供了這一功能,或者,pandas中category類型的列提供了cat.codes。使用標(biāo)簽編碼能夠保持原本的維度。

還有一些不那么標(biāo)準(zhǔn)的編碼方法也值得一試,它們可能可以提升模型的表現(xiàn)。這里將介紹三種方法:

頻數(shù)編碼(count encoding)

labelcount編碼

目標(biāo)編碼(target encoding)

頻數(shù)編碼

頻數(shù)編碼使用頻次替換類別,頻次根據(jù)訓(xùn)練集計算。這個方法對離群值很敏感,所以結(jié)果可以歸一化或者轉(zhuǎn)換一下(例如使用對數(shù)變換)。未知類別可以替換為1。

盡管可能性不是非常大,有些變量的頻次可能是一樣的,這將導(dǎo)致碰撞——兩個類別編碼為相同的值。沒法說這是否會導(dǎo)致模型退化或者改善,不過原則上我們不希望出現(xiàn)這種情況。

def count_encode(X, categorical_features, normalize=False):

print('Count encoding: {}'.format(categorical_features))

X_ = pd.DataFrame()

for cat_feature in categorical_features:

X_[cat_feature] = X[cat_feature].astype(

'object').map(X[cat_feature].value_counts())

if normalize:

X_[cat_feature] = X_[cat_feature] / np.max(X_[cat_feature])

X_ = X_.add_suffix('_count_encoded')

if normalize:

X_ = X_.astype(np.float32)

X_ = X_.add_suffix('_normalized')

else:

X_ = X_.astype(np.uint32)

return X_

讓我們編碼下subreddit列:

train_count_subreddit = count_encode(X_train, ['subreddit'])

并查看結(jié)果。最流行的5個subreddit:

AskReddit 221941

politics 98233

news 33559

worldnews 32010

gaming 25567

Name: subreddit, dtype: int64

編碼為:

221941 221941

98233 98233

33559 33559

32010 32010

25567 25567

Name: subreddit_count_encoded, dtype: int64

基本上,這用頻次替換了subreddit類別。我們也可以除以最頻繁出現(xiàn)的類別的頻次,以得到歸一化的值:

1.000000 221941

0.442609 98233

0.151207 33559

0.144228 32010

0.115197 25567

Name: subreddit_count_encoded_normalized, dtype: int64

LabelCount編碼

我們下面將描述的方法稱為LabelCount編碼,它根據(jù)類別在訓(xùn)練集中的頻次排序類別(升序或降序)。相比標(biāo)準(zhǔn)的頻次編碼,LabelCount具有特定的優(yōu)勢——對離群值不敏感,也不會對不同的值給出同樣的編碼。

def labelcount_encode(X, categorical_features, ascending=False):

print('LabelCount encoding: {}'.format(categorical_features))

X_ = pd.DataFrame()

for cat_feature in categorical_features:

cat_feature_value_counts = X[cat_feature].value_counts()

value_counts_list = cat_feature_value_counts.index.tolist()

if ascending:

# 升序

value_counts_range = list(

reversed(range(len(cat_feature_value_counts))))

else:

# 降序

value_counts_range = list(range(len(cat_feature_value_counts)))

labelcount_dict = dict(zip(value_counts_list, value_counts_range))

X_[cat_feature] = X[cat_feature].map(

labelcount_dict)

X_ = X_.add_suffix('_labelcount_encoded')

if ascending:

X_ = X_.add_suffix('_ascending')

else:

X_ = X_.add_suffix('_descending')

X_ = X_.astype(np.uint32)

return X_

編碼:

train_lc_subreddit = labelcount_encode(X_train, ['subreddit'])

這里默認(rèn)使用降序,subreddit列最流行的5個類別是:

0 221941

1 98233

2 33559

3 32010

4 25567

Name: subreddit_labelcount_encoded_descending, dtype: int64

AskReddit是最頻繁的類別,因此被轉(zhuǎn)換為0,也就是第一位。

使用升序的話,同樣這5個類別編碼如下:

40 221941

39 98233

38 33559

37 32010

36 25567

Name: subreddit_labelcount_encoded_ascending, dtype: int64

目標(biāo)編碼

最后是最有技巧性的方法——目標(biāo)編碼。它使用目標(biāo)變量的均值編碼類別變量。我們?yōu)橛?xùn)練集中的每個分組計算目標(biāo)變量的統(tǒng)計量(這里是均值),之后會合并驗證集、測試集以捕捉分組和目標(biāo)之間的關(guān)系。

舉一個更明確的例子,我們可以在每個subreddit上計算answer_score的均值,這樣,在特定subreddit發(fā)帖可以期望得到多少贊,我們可以有個大概的估計。

使用目標(biāo)變量時,非常重要的一點是不要泄露任何驗證集的信息。所有基于目標(biāo)編碼的特征都應(yīng)該在訓(xùn)練集上計算,接著僅僅合并或連接驗證集和測試集。即使驗證集中有目標(biāo)變量,它不能用于任何編碼計算,否則會給出過于樂觀的驗證誤差估計。

如果使用K折交叉驗證,基于目標(biāo)的特征應(yīng)該在折內(nèi)計算。如果僅僅進(jìn)行單次分割,那么目標(biāo)編碼應(yīng)該在分開訓(xùn)練集和驗證集之后進(jìn)行。

此外,我們可以通過平滑避免將特定類別編碼為0. 另一種方法是通過增加隨機(jī)噪聲避免可能的過擬合。

處置妥當(dāng)?shù)那闆r下,無論是線性模型,還是非線性模型,目標(biāo)編碼都是最佳的編碼方式。

def target_encode(X, X_valid, categorical_features, X_test=None,

target_feature='target'):

print('Target Encoding: {}'.format(categorical_features))

X_ = pd.DataFrame()

X_valid_ = pd.DataFrame()

if X_test isnotNone:

X_test_ = pd.DataFrame()

for cat_feature in categorical_features:

group_target_mean = X.groupby([cat_feature])[target_feature].mean()

X_[cat_feature] = X[cat_feature].map(group_target_mean)

X_valid_[cat_feature] = X_valid[cat_feature].map(group_target_mean)

X_ = X_.astype(np.float32)

X_ = X_.add_suffix('_target_encoded')

X_valid_ = X_valid_.astype(np.float32)

X_valid_ = X_valid_.add_suffix('_target_encoded')

if X_test isnotNone:

X_test_[cat_feature] = X_test[cat_feature].map(group_target_mean)

X_test_ = X_test_.astype(np.float32)

X_test_ = X_test_.add_suffix('_target_encoded')

return X_, X_valid_, X_test_

return X_, X_valid_

編碼:

train_tm_subreddit, valid_tm_subreddit = target_encode(

X_train, X_valid, categorical_features=['subreddit'],

target_feature='answer_score')

如果我們查看下編碼后的值,就會發(fā)現(xiàn)不同reddit的平均贊數(shù)有明顯的差別:

23.406061 220014

13.082699 98176

19.020845 33916

17.521887 31869

18.235424 25520

21.535477 24692

18.640282 20416

23.688890 20009

3.159401 18695

Name: subreddit_target_encoded, dtype: int64

AskReddit 220014

politics 98176

news 33916

worldnews 31869

gaming 25520

todayilearned 24692

funny 20416

videos 20009

teenagers 18695

Name: subreddit, dtype: int64

AskReddit中的回答平均能有23.4個贊,而politics和teenagers中的回答分別只有13.1個贊。這樣的特征可能非常強(qiáng)大,因為它讓我們可以在特征集中明確編碼一些目標(biāo)信息。

獲取類別的編碼值

無需修改編碼函數(shù),我們可以通過如下方式在驗證集或測試集上合并取得的值:

encoded = train_lc_subreddit.subreddit_labelcount_encoded_descending.value_counts().index.values

raw = X_train.subreddit.value_counts().index.values

encoding_dict = dict(zip(raw, encoded))

X_valid['subreddit_labelcount_encoded_descending'] = X_valid.loc[:,

'subreddit'].map(

encoding_dict)

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 編碼
    +關(guān)注

    關(guān)注

    6

    文章

    915

    瀏覽量

    54651
  • 機(jī)器學(xué)習(xí)

    關(guān)注

    66

    文章

    8306

    瀏覽量

    131845
  • 數(shù)據(jù)集
    +關(guān)注

    關(guān)注

    4

    文章

    1197

    瀏覽量

    24538

原文標(biāo)題:特征工程方法:一、類別變量編碼

文章出處:【微信號:jqr_AI,微信公眾號:論智】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    存儲器的編碼方法

    ,上述編碼運(yùn)算包括相加或者相減運(yùn)算。圖2的示意圖為。假設(shè)第一存儲體中的數(shù)據(jù)“10110”,第二存儲體中的
    發(fā)表于 11-15 15:44

    求一種準(zhǔn)循環(huán)LDPC碼的快速編碼方法

    LDPC碼的通用編碼方法有哪些?準(zhǔn)循環(huán)LDPC碼的快速編碼方法是什么?
    發(fā)表于 04-25 07:16

    一種實用的混沌保密編碼方法

    基于實用符號動力學(xué)的基礎(chǔ)理論,提出了一種實用的混沌保密編碼方法,該方法借助于單峰的logistic映射處于混沌吸引子狀態(tài)時產(chǎn)生的符號序列作為密鑰,對信源編碼信號進(jìn)行加密
    發(fā)表于 11-18 00:17 ?12次下載

    一種宏塊分裂的多描述視頻編碼方法

    一種宏塊分裂的多描述視頻編碼方法:多描述編碼是近年來提出的用于不可靠網(wǎng)絡(luò)的視頻編碼方法。本文在塊基編碼的基礎(chǔ)上,提出了一種基于宏塊分裂的多描述編碼方
    發(fā)表于 08-08 08:29 ?19次下載

    一種實用的混沌保密編碼方法

    一種實用的混沌保密編碼方法 基于實用符號動力學(xué)的基礎(chǔ)理論,提出了一種實用的混沌保密編碼方法,該方法借助于單峰的logistic映射處于混沌吸引子狀態(tài)時產(chǎn)生的符號序列
    發(fā)表于 11-18 10:55 ?10次下載

    定點小數(shù)的編碼方法

    定點小數(shù)的編碼方法  用定點小數(shù)引出數(shù)值的三種編碼(原碼、補(bǔ)碼和反碼)方法是最方便的。   (1) 原碼表示法,是用機(jī)器數(shù)的最高一位代表符號,以下各位
    發(fā)表于 10-13 17:19 ?3237次閱讀
    定點小數(shù)的<b class='flag-5'>編碼方法</b>

    整數(shù)的編碼方法

    整數(shù)的編碼方法   與定點小數(shù)的三種編碼方法類似,整數(shù)也可以用原碼、補(bǔ)碼和反碼三種不同的編碼方法表示。區(qū)別主要表現(xiàn)在:
    發(fā)表于 10-13 17:19 ?5456次閱讀

    浮點數(shù)常用的編碼方法

    浮點數(shù)常用的編碼方法  前面已經(jīng)說到,在計算機(jī)內(nèi),浮點數(shù)被表示如下格式:    通常情況
    發(fā)表于 10-13 17:21 ?4363次閱讀
    浮點數(shù)常用的<b class='flag-5'>編碼方法</b>

    AVS立體視頻編碼方法

    提出一種基于AVS(audio video coding standard)的快速立體視頻編碼方法,對左路參考圖像使用AVS編碼編碼,對右路目標(biāo)圖像同時在時間域和空間域進(jìn)行預(yù)測. 使用兩級神經(jīng)分類器來快速確定預(yù)
    發(fā)表于 05-14 10:54 ?36次下載
    AVS立體視頻<b class='flag-5'>編碼方法</b>

    DNA計算中的單模板編碼方法改進(jìn)研究

    如何避免各種不期望的雜交是DNA 計算以及微陣列技術(shù)中的一個關(guān)鍵問題. 為了得到穩(wěn)定可靠的雜交,必須探索一種可靠的、魯棒性的編碼方法. 單模板編碼方法是Arita 提出的另一種模板編
    發(fā)表于 08-18 15:24 ?0次下載
    DNA計算中的單模板<b class='flag-5'>編碼方法</b>改進(jìn)研究

    一種低耦合翻轉(zhuǎn)的數(shù)據(jù)總線編碼方法

    一種低耦合翻轉(zhuǎn)的數(shù)據(jù)總線編碼方法
    發(fā)表于 01-07 20:32 ?2次下載

    一種新的基于素數(shù)的XML動態(tài)編碼方法_田帥

    一種新的基于素數(shù)的XML動態(tài)編碼方法_田帥
    發(fā)表于 03-19 11:45 ?0次下載

    基于引用圖片的信息編碼方法

    編碼方法。該方法中,每個字符都用一個RGB分量的相對位置和偏移量表示,編碼數(shù)據(jù)則通過激活擴(kuò)散的方法生成。同一個字符可以用不同的編碼表示,而相
    發(fā)表于 12-06 13:52 ?1次下載
    基于引用圖片的信息<b class='flag-5'>編碼方法</b>

    改進(jìn)的分形圖像編碼方法

    傳統(tǒng)圖像編碼方法一般已成定式,發(fā)展?jié)摿Σ淮?。分形圖像編碼方法思想新穎,是極具發(fā)展?jié)摿Φ膲嚎s方法,但分形編碼存在編碼耗時過長的缺點。本文基于分
    發(fā)表于 12-20 13:56 ?2次下載

    常見的11個分類變量編碼方法

    機(jī)器學(xué)習(xí)算法只接受數(shù)值輸入,所以如果我們遇到分類特征的時候都會對分類特征進(jìn)行編碼,本文總結(jié)了常見的11個分類變量編碼方法。
    的頭像 發(fā)表于 11-28 15:45 ?3153次閱讀