日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【特征工程】17种将离散特征转化为数字特征的方法

發布時間:2025/3/12 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【特征工程】17种将离散特征转化为数字特征的方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

作者 | Samuele Mazzanti?

編譯 | VK?

來源 | Towards Data Science

“你知道哪種梯度提升算法?”

“Xgboost,LightGBM,Catboost,HistGradient。”

“你知道哪些離散變量的編碼?”

“one-hot”

在一次數據科學面試中聽到這樣的對話我不會感到驚訝。不過,這將是相當驚人的,「因為只有一小部分數據科學項目涉及機器學習,而實際上所有這些項目都涉及一些離散數據」

?

離散變量的編碼是將一個離散列轉換為一個(或多個)數字列的過程。

?

這是必要的,因為計算機處理數字比處理字符串更容易。為什么?因為用數字很容易找到關系(比如“大”、“小”、“雙”、“半”)。然而,當給定字符串時,計算機只能說出它們是“相等”還是“不同”。

然而,盡管離散變量的編碼有影響,但它很容易被數據科學從業者忽視。

?

離散變量的編碼是一個令人驚訝的被低估的話題。

?

這就是為什么我決定深化編碼算法的知識。我從一個名為“category_encoders”的Python庫開始(這是Github鏈接:https://github.com/scikit-learn-contrib/category_encoders)。使用它非常簡單:

!pip?install?category_encodersimport?category_encoders?as?cece.OrdinalEncoder().fit_transform(x)

這篇文章是對庫中包含的17種編碼算法的演練。對于每種算法,我用幾行代碼提供了簡短的解釋和Python實現。其目的不是要重新發明輪子,而是要認識到算法是如何工作的。畢竟,

?

“除非你能寫代碼,否則你不懂”。

?

并非所有編碼都是相同的

我根據17種編碼算法的一些特點對它們進行了分類。類似決策樹:

分割點為:

  • 「監督/無監督」:當編碼完全基于離散列時,它是無監督的。如果編碼是基于原始列和第二列(數字)的某個函數,則它是監督的。

  • 「輸出維度」:分類列的編碼可能產生一個數值列(輸出維度=1)或多個數值列(輸出維度>1)。

  • 「映射」:如果每個等級都有相同的輸出-無論是標量(例如OrdinalEncoder)還是數組(例如onehotcoder),那么映射是唯一的。相反,如果允許同一等級具有不同的可能輸出,則映射不是唯一的。

17種離散編碼算法

1.「OrdinalEncoder」

每個等級都映射到一個整數,從1到L(其中L是等級數)。在這種情況下,我們使用了字母順序,但任何其他自定義順序都是可以接受的。

sorted_x?=?sorted(set(x)) ordinal_encoding?=?x.replace(dict(zip(sorted_x,?range(1,?len(sorted_x)?+?1))))

你可能認為該編碼是沒有意義的,尤其是當等級沒有內在順序的時候。你是對的!實際上,它只是一種方便的表示,通常用于節省內存,或作為其他類型編碼的中間步驟。

2.CountEncoder

每個等級都映射到該級別的觀察數。

count_encoding?=?x.replace(x.value_counts().to_dict())

這種編碼可以作為每個級別的“可信度”的指標。例如,一個機器學習算法可能會自動決定只考慮其計數高于某個閾值的級別所帶來的信息。

3.OneHotEncoder

編碼算法中最常用的。每個級別映射到一個偽列(即0/1的列),指示該行是否攜帶屬于該級別。

one_hot_encoding?=?ordinal_encoding.apply(lambda?oe:?pd.Series(np.diag(np.ones(len(set(x))))[oe?-?1].astype(int)))

這意味著,雖然你的輸入是一個單獨的列,但是你的輸出由L列組成(原始列的每個級別對應一個列)。這就是為什么OneHot編碼應該小心處理:你最終得到的數據幀可能比原來的大得多。

一旦數據是OneHot編碼,它就可以用于任何預測算法。為了使事情一目了然,讓我們對每一個等級進行一次觀察。

假設我們觀察到一個目標變量,叫做y,包含每個人的收入(以千美元計)。讓我們用線性回歸(OLS)來擬合數據。

為了使結果易于閱讀,我在表的側面附加了OLS系數。

在OneHot編碼的情況下,截距沒有特定的意義。在這種情況下,由于我們每層只有一個觀測值,通過加上截距和乘上系數,我們得到y的精確值(沒有誤差)。

4.SumEncoder

下面的代碼一開始可能有點晦澀難懂。但是不要擔心:在這種情況下,理解如何獲得編碼并不重要,而是如何使用它。

sum_encoding?=?one_hot_encoding.iloc[:,?:-1].apply(lambda?row:?row?if?row.sum()?==?1?else?row.replace(0,?-1),?axis?=?1)

SumEncoder屬于一個名為“對比度編碼”的類。這些編碼被設計成在回歸問題中使用時具有特定的行為。換句話說,如果你想讓回歸系數有一些特定的屬性,你可以使用其中的一種編碼。

特別是,當你希望回歸系數加起來為0時,使用SumEncoder。如果我們采用之前的相同數據并擬合OLS,我們得到的結果是:

這一次,截距對應于y的平均值。此外,通過取最后一級的y并從截距(68-50)中減去它,我們得到18,這與剩余系數之和(-15-5+2=-18)正好相反。這正是我前面提到的SumEncoder的屬性。

5.BackwardDifferenceEncoder

另一種對比度編碼。

這個編碼器對序數變量很有用,也就是說,可以用有意義的方式對其等級進行排序的變量。BackwardDifferenceEncoder設計用于比較相鄰的等級。

backward_difference_encoding?=?ordinal_encoding.apply(lambda?oe:?pd.Series([i?/?len(set(x))?for?i?in?range(1,?oe)]?+?[-?i?/?len(set(x))?for?i?in?range(len(set(x))?-?oe,?0,?-1)]))

假設你有一個有序變量(例如教育水平),你想知道它與一個數字變量(例如收入)之間的關系。比較每一個連續的水平(例如學士與高中,碩士與學士)與目標變量的關系可能很有趣。這就是BackwardDifferenceEncoder的設計目的。讓我們看一個例子,使用相同的數據。

截距與y的平均值一致。學士的系數為10,因為學士的y比高中高10,碩士的系數等于7,因為碩士的y比單身漢高7,依此類推。

6.HelmertEncoder

HelmertEncoder與BackwardDifferenceEncoder非常相似,但不是只與前一個進行比較,而是將每個級別與之前的所有級別進行比較。

helmert_encoding?=?ordinal_encoding.apply(lambda?oe:?pd.Series([0]?*?(oe?-?2)?+?([oe?-?1]?if?oe?>?1?else?[])?+?[-1]?*?(len(set(x))?-?oe)) ).div(pd.Series(range(2,len(set(x))?+?1)))

]

讓我們看看OLS模型能給我們帶來什么:

PhD的系數是24,因為PhD比之前水平的平均值高24-((35+45+52)/3)=24。同樣的道理適用于所有的等級。

7.PolynomialEncoder

另一種對比編碼。

顧名思義,PolynomialEncoder被設計用來量化目標變量相對于離散變量的線性、二次和三次行為。

def?do_polynomial_encoding(order):#?代碼來自https://github.com/pydata/patsy/blob/master/patsy/contrasts.pyn?=?len(set(x))scores?=?np.arange(n)scores?=?np.asarray(scores,?dtype=float)scores?-=?scores.mean()raw_poly?=?scores.reshape((-1,?1))?**?np.arange(n).reshape((1,?-1))q,?r?=?np.linalg.qr(raw_poly)q?*=?np.sign(np.diag(r))q?/=?np.sqrt(np.sum(q?**?2,?axis=1))q?=?q[:,?1:]return?q[order?-?1]polynomial_encoding?=?ordinal_encoding.apply(lambda?oe:?pd.Series(do_polynomial_encoding(oe)))

我知道你在想什么。一個數值變量如何與一個非數值變量有線性(或二次或三次)關系?這是基于這樣一個假設,即潛在的離散變量不僅具有順序性,而且具有等間距。

基于這個原因,我建議謹慎使用它,只有當你確信這個假設是合理的。

8.BinaryEncoder

BinaryEncoder 與OrdinalEncoder基本相同,唯一的區別是將整數轉換成二進制數,然后每個位置數字都是one-hot編碼。

binary_base?=?ordinal_encoding.apply(lambda?oe:?str(bin(oe))[2:].zfill(len(bin(len(set(x))))?-?2)) binary_encoding?=?binary_base.apply(lambda?bb:?pd.Series(list(bb))).astype(int)

輸出由偽列組成,就像OneHotEncoder的情況一樣,但是它會導致相對于one-hot的維數降低。

老實說,我不知道這種編碼有什么實際應用。

9.BaseNEncoder

BaseNEncoder只是BinaryEncoder的一個推廣。實際上,在BinaryEncoder中,數字以2為基數,而在BaseNEncoder中,數字以n為底,n大于1。

def?int2base(n,?base):out?=?''while?n:out?+=?str(int(n?%?base))n?//=?basereturn?out[::-1]base_n?=?ordinal_encoding.apply(lambda?oe:?int2base(n?=?oe,?base?=?base)) base_n_encoding?=?base_n.apply(lambda?bn:?pd.Series(list(bn.zfill(base_n.apply(len).max())))).astype(int)

讓我們看一個base=3的例子。

老實說,我不知道這種編碼有什么實際應用。

10.HashingEncoder

在HashingEncoder中,每個原始級別都使用一些哈希算法(如SHA-256)進行哈希處理。然后,將結果轉換為整數,并取該整數相對于某個(大)除數的模。通過這樣做,我們將每個原始字符串映射到一個某個范圍的整數。最后,這個過程得到的整數是one-hot編碼的。

def?do_hash(string,?output_dimension):hasher?=?hashlib.new('sha256')hasher.update(bytes(string,?'utf-8'))string_hashed?=?hasher.hexdigest()string_hashed_int?=?int(string_hashed,?16)string_hashed_int_remainder?=?string_hashed_int?%?output_dimensionreturn?string_hashed,?string_hashed_int,?string_hashed_int_remainderhashing?=?x.apply(lambda?string:?pd.Series(do_hash(string,?output_dimension),?index?=?['x_hashed',?'x_hashed_int',?'x_hashed_int_remainder'])) hashing_encoding?=?hashing['x_hashed_int_remainder'].apply(lambda?rem:?pd.Series(np.diag(np.ones(output_dimension))[rem])).astype(int)

讓我們看一個輸出維數為10的示例。

散列的基本特性是得到的整數是均勻分布的。所以,如果除數足夠大,兩個不同的字符串不太可能映射到同一個整數。那為什么有用呢?實際上,這有一個非常實際的應用叫做“哈希技巧”。

假設你希望使用邏輯回歸來生成電子郵件垃圾郵件分類器。你可以通過對數據集中包含的所有單詞進行ONE-HOT編碼來實現這一點。主要的缺點是你需要將映射存儲在單獨的字典中,并且你的模型維度將在新字符串出現時發生更改。

使用散列技巧可以很容易地克服這些問題,因為通過散列輸入,你不再需要字典,并且輸出維是固定的(它只取決于你最初選擇的除數)。此外,對于散列的屬性,你可以認為新字符串可能具有與現有字符串不同的編碼。

11.TargetEncoder

假設有兩個變量:一個是離散變量(x),一個是數值變量(y)。假設你想把x轉換成一個數值變量。你可能需要使用y“攜帶”的信息。一個明顯的想法是取x的每個級別的y的平均值。在公式中:

這是合理的,但是這種方法有一個很大的問題:有些群體可能太小或太不穩定而不可靠。許多有監督編碼通過在組平均值和y的全局平均值之間選擇一種中間方法來克服這個問題:

其中$w_i$在0和1之間,取決于組的“可信”程度。

接下來的三種算法(TargetEncoder、MEstimateEncoder和JamesSteinEncoder)根據它們定義$w_i$的方式而有所不同。

在TargetEncoder中,權重取決于組的數量和一個稱為“平滑”的參數。當“平滑”為0時,我們僅依賴組平均值。然后,隨著平滑度的增加,全局平均權值越來越多,導致正則化更強。

y_mean?=?y.mean() y_level_mean?=?x.replace(y.groupby(x).mean()) weight?=?1?/?(1?+?np.exp(-(count_encoding?-?1)?/?smoothing)) target_encoding?=?y_level_mean?*?weight?+?y_mean?*?(1?-?weight)

讓我們看看結果如何隨著一些不同的平滑值而變化。

12.MEstimateEncoder

MEstimateEncoder類似于TargetEncoder,但$w_i$取決于一個名為“m”的參數,該參數設置全局平均值的絕對權重。m很容易理解,因為它可以被視為若干個觀測值:如果等級正好有m個觀測值,那么等級平均值和總體平均權重是相同的。

y_mean?=?y.mean() y_level_mean?=?x.replace(y.groupby(x).mean()) weight?=?count_encoding?/?(count_encoding?+?m) m_estimate_encoding?=??y_level_mean?*?weight?+?y_grand_mean?*?(1?-?weight)

讓我們看看不同m值的結果是如何變化的:

13.「JamesSteinEncoder」

TargetEncoder和MEstimateEncoder既取決于組的數量,也取決于用戶設置的參數值(分別是smoothing和m)。這不方便,因為設置這些權重是一項手動任務。

一個自然的問題是:有沒有一種方法可以在不需要任何人為干預的情況下,設定一個最佳的工作環境?JamesSteinEncoder試圖以一種基于統計數據的方式來做到這一點。

y_mean?=?y.mean() y_var?=?y.var() y_level_mean?=?x.replace(y.groupby(x).mean()) y_level_var?=?x.replace(y.groupby(x).var())weight?=?1?-?(y_level_var?/?(y_var?+?y_level_var)?*?(len(set(x))?-?3)?/?(len(set(x))?-?1)) james_stein_encoding?=?y_level_mean?*?weight?+?y_mean?*?(1?-?weight)

直覺是,一個高方差的群體的平均值應該不那么可信。因此,群體方差越高,權重就越低(如果你想知道更多關于公式的知識,我建議克里斯?賽義德的這篇文章)。

讓我們看一個數值示例:

JamesSteinEncoder有兩個顯著的優點:它提供比最大似然估計更好的估計,并且不需要任何參數設置。

14.GLMMEncoder

GLMMEncoder采用一種完全不同的方法。

基本上,它擬合y上的線性混合效應模型。這種方法利用了一個事實,即線性混合效應模型是為處理同質觀察組而精心設計的。因此,我們的想法是擬合一個沒有回歸變量(只有截距)的模型,并使用層次作為組。

然后,輸出就是截距和隨機效應的總和。

model?=?smf.mixedlm(formula?=?'y?~?1',?data?=?y.to_frame(),?groups?=?x).fit() intercept?=?model.params['Intercept'] random_effect?=?x.replace({k:?float(v)?for?k,?v?in?model.random_effects.items()}) glmm_encoding?=?intercept?+?random_effect

15.WOEEncoder

WOEEncoder(代表“證據權重 Weight of Evidence”編碼器)只能用于二元變量,即級別為0/1的目標變量。

證據權重背后的想法是你有兩種分布:

  • 1的分布(每組1的個數/y中1的個數)

  • 0的分布(每組0的個數/y中0的個數)

該算法的核心是將1的分布除以0的分布(對于每個組)。當然,這個值越高,我們就越有信心認為這個基團“偏向”1,反之亦然。然后,取該值的對數。

y_level_ones?=?x.replace(y.groupby(x).apply(lambda?l:?(l?==?1).sum())) y_level_zeros?=?x.replace(y.groupby(x).apply(lambda?l:?(l?==?0).sum())) y_ones?=?(y?==?1).sum() y_zeros?=?(y?==?0).sum() nominator?=?y_level_ones?/?y_ones denominator?=?y_level_zeros?/?y_zeros woe_encoder?=?np.log(nominator?/?denominator)

如你所見,由于公式中存在對數,因此無法直接解釋輸出。然而,它作為機器學習的一個預處理步驟工作得很好。

16.LeaveOneOutEncoder

到目前為止,所有的15個編碼器都有一個唯一的映射。

但是,如果你計劃使用編碼作為預測模型的輸入(例如GB),這可能是一個問題。實際上,假設你使用TargetEncoder。這意味著你在X_train中引入了關于y_train的信息,這可能會導致嚴重的過擬合風險。

關鍵是:如何在限制過擬合的風險的同時保持有監督的編碼?LeaveOneOutEncoder提供了一個出色的解決方案。它執行普通的目標編碼,但是對于每一行,它不考慮該行觀察到的y值。這樣,就避免了行方向的泄漏。

y_level_except_self?=?x.to_frame().apply(lambda?row:?y[x?==?row['x']].drop(row.name).to_list(),?axis?=?1) leave_one_out_encoding?=?y_level_except_self.apply(np.mean)

17.CatBoostEncoder

CatBoost是一種梯度提升算法(如XGBoost或LightGBM),它在許多問題中都表現得非常好。

CatboostEncoder的工作原理基本上類似于LeaveOneOutEncoder,但是是一個在線方法。

但是如何模擬在線行為?想象一下你有一張桌子。然后,在桌子中間的某個地方劃一排。CatBoost所做的是假裝當前行上方的行已經被及時觀察到,而下面的行還沒有被觀察到(即將來會觀察到)。然后,該算法執行leave one out編碼,但僅基于已觀察到的行。

y_mean?=?y.mean() y_level_before_self?=?x.to_frame().apply(lambda?row:?y[(x?==?row['x'])?&?(y.index?<?row.name)].to_list(),?axis?=?1) catboost_encoding?=?y_level_before_self.apply(lambda?ylbs:?(sum(ylbs)?+?y_mean?*?a)?/?(len(ylbs)?+?a))

這似乎有些荒謬。為什么要拋棄一些可能有用的信息呢?你可以將其簡單地視為對輸出進行隨機化的更極端嘗試(例如,減少過擬合)。


謝謝你的閱讀!我希望你覺得這篇文章有用。

往期精彩回顧適合初學者入門人工智能的路線及資料下載機器學習及深度學習筆記等資料打印機器學習在線手冊深度學習筆記專輯《統計學習方法》的代碼復現專輯 AI基礎下載機器學習的數學基礎專輯 獲取本站知識星球優惠券,復制鏈接直接打開: https://t.zsxq.com/qFiUFMV 本站qq群704220115。加入微信群請掃碼:

總結

以上是生活随笔為你收集整理的【特征工程】17种将离散特征转化为数字特征的方法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 久久久久久久久久影院 | 闺蜜张开腿让我爽了一夜 | 精品久久久久久亚洲 | 亚洲在线观看av | 男女被到爽流尿 | 蜜臀在线一区二区三区 | 日韩精品久久久 | 亚洲AV无码久久精品国产一区 | 国产精品第6页 | 18禁网站免费无遮挡无码中文 | 男人的亚洲天堂 | 69福利社区 | 久久精品无码一区 | 性xxxx欧美老肥妇牲乱 | www.com欧美 | 蜜臀久久99精品久久久画质超高清 | 最好看的中文字幕国语电影mv | 在线观看免费人成视频 | 午夜精品一区二区三区在线观看 | 女同毛片一区二区三区 | 亚洲欧美精品aaaaaa片 | 中文字幕一级二级三级 | 久久av在线播放 | 欧美特级毛片 | 日本一区二区视频 | 五十路在线视频 | 免费观看黄色一级片 | 97免费在线 | 精品免费视频 | 国产精品自拍区 | 麻豆传媒网址 | 日本不卡高清视频 | 日韩欧美精品一区二区 | 日韩最新在线 | 国产精品一区2区 | 这里只有精品22 | 免费成人在线网站 | 91视频网址入口 | 亚洲三级视频 | 伊人久久久 | 爆乳熟妇一区二区三区 | 中文字幕亚洲精品在线 | 女同动漫免费观看高清完整版在线观看 | 狂野欧美性猛交blacked | www.激情网| 美国三级视频 | 妻色成人网 | 大伊人久久 | 欧美丰满老妇性猛交 | 欧美日韩激情在线 | 在线成人一区二区 | 两口子交换真实刺激高潮 | 亚洲成人网在线观看 | 久久99精品国产麻豆91樱花 | 岛国片在线播放 | 美女视屏 | 在线免费a视频 | 久久久久久久久免费 | 日日夜夜精品免费视频 | 可以免费看的黄色网址 | 999zyz玖玖资源站永久 | 麻豆精品在线观看 | 亚洲性综合 | 国产乱视频 | 日韩成人动漫在线观看 | 成年人免费网站在线观看 | 国产丝袜在线播放 | 午夜视频福利在线观看 | 欧洲人妻丰满av无码久久不卡 | 极品销魂美女一区二区三区 | 日韩和的一区二区 | 成人网在线视频 | 九热这里只有精品 | 亚洲卡一卡二 | 亚洲老女人 | 四季av一区二区三区免费观看 | 天天干天天爽 | av男人网 | 亚洲逼| 成人亚洲精品久久久久软件 | 亚洲国产婷婷香蕉久久久久久99 | 久久久91精品 | 亚洲在线资源 | 国产精品999在线观看 | av毛片在线免费看 | 五月天久久综合 | 国产区在线视频 | 久久9999久久免费精品国产 | 国产一区二区免费视频 | 777色婷婷 | 久久天堂精品 | 好看的毛片 | 国产国产国产 | 不卡中文字幕在线 | 91久久精品国产91久久 | 日韩 欧美 国产 综合 | 久久中文字幕一区二区 | 亚洲一区二区国产精品 | 午夜小视频网站 |