在機器學習中,特徵選擇是選擇對您的預測最有用的特徵的過程。儘管聽起來很簡單,但這是創建新的機器學習模型時最複雜的問題之一。
在本文中,我將與您分享我在Fiverr領導的上一個項目期間研究的一些方法。
您將獲得有關我嘗試的基本方法以及更複雜的方法的一些想法,該方法獲得了最佳效果-刪除了60%以上的功能,同時保持了準確性並為我們的模型實現了更高的穩定性。我還將分享我們對該演算法的改進。
為什麼進行特徵選擇如此重要?
如果您構建了機器學習模型,您就會知道識別哪些功能很重要而哪些僅僅是噪音是多麼困難。
刪除嘈雜的功能將有助於內存,計算成本和模型準確性。
此外,通過刪除功能部件,將有助於避免模型的過擬合。
有時,您具有一項具有業務意義的功能,但這並不意味著此功能將幫助您進行預測。
您需要記住,功能在一種演算法(例如決策樹)中可能有用,而在另一種演算法中的代表性可能不足(例如回歸模型),並非所有功能都是一樣的:)
不相關或部分相關的特徵可能會對模型性能產生負面影響。功能選擇和數據清理應該是設計模型的第一步,也是最重要的一步。
特徵選擇方法:
儘管有很多用於特徵選擇的技術,例如向後消除,套索回歸。在本文中,我將分享3種方法,這些方法被發現對完成更好的特徵選擇最有用,每種方法都有其自身的優勢。
「除了X」
在Fiverr中,將這種技術命名為「 All But X」。此技術很簡單,但很有用。
- 您可以反覆訓練和評估
- 在每次迭代中,都將刪除一個功能。
如果您有大量功能,則可以刪除功能的「系列」,在Fiverr,我們通常會匯總不同時間,30天點擊次數,60天點擊次數等功能。這是一系列功能。 - 根據基準檢查評估指標。
該技術的目標是查看功能族中的哪些不影響評估,或者甚至刪除它也可以改善評估。
這種方法的問題在於,一次刪除一個要素,不會使要素彼此產生效果(非線性效果)。也許特徵X和特徵Y的組合正在產生雜訊,而不僅僅是特徵X。
特徵重要性+隨機特徵
我們嘗試的另一種方法是使用大多數機器學習模型API具有的功能重要性。
我們所做的不僅僅是從功能重要性中獲取前N個功能。我們向數據添加了3個隨機特徵:
- 二進位隨機特徵(0或1)
- 在0至1個隨機特徵之間均勻
- 整數隨機特徵
在重要功能列表之後,我們僅選擇了高於隨機特徵的功能。
重要的是採用隨機特徵的不同分布,因為每種分布都會產生不同的影響。
在樹木中,模型「喜歡」連續要素(由於分割),因此這些要素將位於層次結構中的較高位置。因此,您需要將每個功能與其均布的隨機功能進行比較。
Boruta
Boruta是一種由華沙大學開發的功能分級和選擇演算法。該演算法基於隨機森林,但也可以用於XGBoost和不同的樹演算法。
在Fiverr,我使用了該演算法,並對XGBoost排名和分類器模型進行了一些改進,我將對此進行簡要介紹。
該演算法是我上面提到的兩種方法的一種組合。
- 為數據集中的每個要素創建一個「陰影」要素,具有相同的要素值,但僅在各行之間隨機排列
- 循環運行,直到停止條件之一:
2.1。我們不會刪除任何其他功能
2.2。我們刪除了足夠的功能-可以說我們要刪除60%的功能
2.3。我們進行了N次迭代-我們限制了迭代次數以免陷入無限循環 - 運行X次迭代-我們使用5來消除模式
3.1 的隨機性。使用常規特徵和陰影特徵訓練模型
3.2。保存每個特徵的平均特徵重要性得分
3.3刪除所有低於其陰影特徵的特徵
def _create_shadow(x):
"""
Take all X variables, creating copies and randomly shuffling them
:param x: the dataframe to create shadow features on
:return: dataframe 2x width and the names of the shadows for removing later
"""
x_shadow = x.copy()
for c in x_shadow.columns:
np.random.shuffle(x_shadow[c].values) # shuffle the values of each feature to all the features
# rename the shadow
shadow_names = ["shadow_feature_" + str(i + 1) for i in range(x.shape[1])]
x_shadow.columns = shadow_names
# Combine to make one new dataframe
x_new = pd.concat([x, x_shadow], axis=1)
return x_new, shadow_names
# Set up the parameters for running the model in XGBoost
param = booster_params
df = pd.DataFrame() # initial empty dataframe
for i in range(1, n_iterations + 1):
# Create the shadow variables and run the model to obtain importances
new_x, shadow_names = _create_shadow(x)
bst, df = _run_model(new_x, y, group, weights, param, num_boost_round, early_stopping_rounds, i == 1, df)
df = _check_feature_importance(bst, df, i, importance_type)
df[MEAN_COLUMN] = df.mean(axis=1)
# Split them back out
real_vars = df[~df['feature'].isin(shadow_names)]
shadow_vars = df[df['feature'].isin(
)]
# Get mean value from the shadows
mean_shadow = shadow_vars[MEAN_COLUMN].mean() * (perc / 100)
real_vars = real_vars[(real_vars[MEAN_COLUMN] > mean_shadow)]
criteria = _check_stopping_crietria(delta, real_vars, x)
return criteria, real_vars['feature']
Boruta 2.0
這是本文的最佳部分,是對Boruta的改進。
我們使用原始模型的「簡短版本」運行了Boruta。通過獲取數據樣本和較少數量的樹(我們使用XGBoost),我們在不降低準確性的情況下改善了原始Boruta的運行時間。
另一個改進是,我們使用前面提到的隨機特徵運行了該演算法。可以看出我們已經從數據集中刪除了所有隨機特徵,這是一個很好的條件。
有了改進,我們看不到模型準確性的任何變化,但是看到了運行時的改進。通過刪除,我們能夠將200多個要素轉換為少於70個要素。我們看到了該模型在樹木數量和訓練的不同階段的穩定性。
我們還看到訓練損失與驗證集之間的距離有所改善。
改進和Boruta的優勢在於您正在運行模型。在這種情況下,發現的有問題的特徵對您的模型有問題,而不是不同的演算法。
總結
在本文中,您了解了3種不同的技術,這些技術如何對數據集進行特徵選擇以及如何建立有效的預測模型。您看到了我們對Boruta的實現,運行時的改進以及添加了隨機功能以幫助進行健全性檢查。
通過這些改進,我們的模型僅以原始功能的35%就能運行得更快,更穩定並保持了一定的準確性。
選擇最適合您的技術。請記住,功能選擇可以幫助提高準確性,穩定性和運行時間,並避免過度擬合。更重要的是,更少的功能使調試和解釋性變得更加容易。
本文轉自 medium,原文地址
Comments