機器學習中,有哪些特徵選擇的工程方法?
本題已加入知乎圓桌 ?「機器學習 · 學以致用」,更多「機器學習」相關話題討論歡迎關注。
特徵選擇是特徵工程中的重要問題(另一個重要的問題是特徵提取),坊間常說:數據和特徵決定了機器學習的上限,而模型和演算法只是逼近這個上限而已。由此可見,特徵工程尤其是特徵選擇在機器學習中佔有相當重要的地位。
通常而言,特徵選擇是指選擇獲得相應模型和演算法最好性能的特徵集,工程上常用的方法有以下:
1. 計算每一個特徵與響應變數的相關性:工程上常用的手段有計算皮爾遜係數和互信息係數,皮爾遜係數只能衡量線性相關性而互信息係數能夠很好地度量各種相關性,但是計算相對複雜一些,好在很多toolkit裡邊都包含了這個工具(如sklearn的MINE),得到相關性之後就可以排序選擇特徵了;
2. 構建單個特徵的模型,通過模型的準確性為特徵排序,藉此來選擇特徵,另外,記得JMLR"03上有一篇論文介紹了一種基於決策樹的特徵選擇方法,本質上是等價的。當選擇到了目標特徵之後,再用來訓練最終的模型;
3. 通過L1正則項來選擇特徵:L1正則方法具有稀疏解的特性,因此天然具備特徵選擇的特性,但是要注意,L1沒有選到的特徵不代表不重要,原因是兩個具有高相關性的特徵可能只保留了一個,如果要確定哪個特徵重要應再通過L2正則方法交叉檢驗;
4. 訓練能夠對特徵打分的預選模型:RandomForest和Logistic Regression等都能對模型的特徵打分,通過打分獲得相關性後再訓練最終模型;
5. 通過特徵組合後再來選擇特徵:如對用戶id和用戶特徵最組合來獲得較大的特徵集再來選擇特徵,這種做法在推薦系統和廣告系統中比較常見,這也是所謂億級甚至十億級特徵的主要來源,原因是用戶數據比較稀疏,組合特徵能夠同時兼顧全局模型和個性化模型,這個問題有機會可以展開講。
6. 通過深度學習來進行特徵選擇:目前這種手段正在隨著深度學習的流行而成為一種手段,尤其是在計算機視覺領域,原因是深度學習具有自動學習特徵的能力,這也是深度學習又叫unsupervised feature learning的原因。從深度學習模型中選擇某一神經層的特徵後就可以用來進行最終目標模型的訓練了。
整體上來說,特徵選擇是一個既有學術價值又有工程價值的問題,目前在研究領域也比較熱,值得所有做機器學習的朋友重視。
我來寫一個入門級的實踐吧,為了保持連貫性,引用了全文:
作者:城東
鏈接:特徵工程到底是什麼? - 城東的回答
來源:知乎
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。
目錄
1 特徵工程是什麼?
2 數據預處理
2.1 無量綱化
2.1.1 標準化
2.1.2 區間縮放法
2.1.3 標準化與歸一化的區別
2.2 對定量特徵二值化
2.3 對定性特徵啞編碼
2.4 缺失值計算
2.5 數據變換
3 特徵選擇
3.1 Filter
3.1.1 方差選擇法
3.1.2 相關係數法
3.1.3 卡方檢驗
3.1.4 互信息法
3.2 Wrapper
3.2.1 遞歸特徵消除法
3.3 Embedded
3.3.1 基於懲罰項的特徵選擇法
3.3.2 基於樹模型的特徵選擇法
4 降維
4.1 主成分分析法(PCA)
4.2 線性判別分析法(LDA)
5 總結
6 參考資料
1 特徵工程是什麼?
有這麼一句話在業界廣泛流傳:數據和特徵決定了機器學習的上限,而模型和演算法只是逼近這個上限而已。那特徵工程到底是什麼呢?顧名思義,其本質是一項工程活動,目的是最大限度地從原始數據中提取特徵以供演算法和模型使用。通過總結和歸納,人們認為特徵工程包括以下方面:
特徵處理是特徵工程的核心部分,sklearn提供了較為完整的特徵處理方法,包括數據預處理,特徵選擇,降維等。首次接觸到sklearn,通常會被其豐富且方便的演算法模型庫吸引,但是這裡介紹的特徵處理庫也十分強大!
本文中使用sklearn中的IRIS(鳶尾花)數據集來對特徵處理功能進行說明。IRIS數據集由Fisher在1936年整理,包含4個特徵(Sepal.Length(花萼長度)、Sepal.Width(花萼寬度)、Petal.Length(花瓣長度)、Petal.Width(花瓣寬度)),特徵值都為正浮點數,單位為厘米。目標值為鳶尾花的分類(Iris Setosa(山鳶尾)、Iris Versicolour(雜色鳶尾),Iris Virginica(維吉尼亞鳶尾))。導入IRIS數據集的代碼如下:
from sklearn.datasets import load_iris
#導入IRIS數據集
iris = load_iris()
#特徵矩陣
iris.data
#目標向量
iris.target
2 數據預處理
通過特徵提取,我們能得到未經處理的特徵,這時的特徵可能有以下問題:
- 不屬於同一量綱:即特徵的規格不一樣,不能夠放在一起比較。無量綱化可以解決這一問題。
- 信息冗餘:對於某些定量特徵,其包含的有效信息為區間劃分,例如學習成績,假若只關心「及格」或不「及格」,那麼需要將定量的考分,轉換成「1」和「0」表示及格和未及格。二值化可以解決這一問題。
- 定性特徵不能直接使用:某些機器學習演算法和模型只能接受定量特徵的輸入,那麼需要將定性特徵轉換為定量特徵。最簡單的方式是為每一種定性值指定一個定量值,但是這種方式過於靈活,增加了調參的工作。通常使用啞編碼的方式將定性特徵轉換為定量特徵:假設有N種定性值,則將這一個特徵擴展為N種特徵,當原始特徵值為第i種定性值時,第i個擴展特徵賦值為1,其他擴展特徵賦值為0。啞編碼的方式相比直接指定的方式,不用增加調參的工作,對於線性模型來說,使用啞編碼後的特徵可達到非線性的效果。
- 存在缺失值:缺失值需要補充。
- 信息利用率低:不同的機器學習演算法和模型對數據中信息的利用是不同的,之前提到在線性模型中,使用對定性特徵啞編碼可以達到非線性的效果。類似地,對定量變數多項式化,或者進行其他的轉換,都能達到非線性的效果。
我們使用sklearn中的preproccessing庫來進行數據預處理,可以覆蓋以上問題的解決方案。
2.1 無量綱化無量綱化使不同規格的數據轉換到同一規格。常見的無量綱化方法有標準化和區間縮放法。標準化的前提是特徵值服從正態分布,標準化後,其轉換成標準正態分布。區間縮放法利用了邊界值信息,將特徵的取值區間縮放到某個特點的範圍,例如[0, 1]等。
2.1.1 標準化標準化需要計算特徵的均值和標準差,公式表達為:
使用preproccessing庫的StandardScaler類對數據進行標準化的代碼如下:
from sklearn.preprocessing import StandardScaler
#標準化,返回值為標準化後的數據
StandardScaler().fit_transform(iris.data)
2.1.2 區間縮放法
區間縮放法的思路有多種,常見的一種為利用兩個最值進行縮放,公式表達為:
使用preproccessing庫的MinMaxScaler類對數據進行區間縮放的代碼如下:
from sklearn.preprocessing import MinMaxScaler
#區間縮放,返回值為縮放到[0, 1]區間的數據
MinMaxScaler().fit_transform(iris.data)
2.1.3 標準化與歸一化的區別
簡單來說,標準化是依照特徵矩陣的列處理數據,其通過求z-score的方法,將樣本的特徵值轉換到同一量綱下。歸一化是依照特徵矩陣的行處理數據,其目的在於樣本向量在點乘運算或其他核函數計算相似性時,擁有統一的標準,也就是說都轉化為「單位向量」。規則為l2的歸一化公式如下:
使用preproccessing庫的Normalizer類對數據進行歸一化的代碼如下:
from sklearn.preprocessing import Normalizer
#歸一化,返回值為歸一化後的數據
Normalizer().fit_transform(iris.data)
2.2 對定量特徵二值化
定量特徵二值化的核心在於設定一個閾值,大於閾值的賦值為1,小於等於閾值的賦值為0,公式表達如下:
使用preproccessing庫的Binarizer類對數據進行二值化的代碼如下:
from sklearn.preprocessing import Binarizer
#二值化,閾值設置為3,返回值為二值化後的數據
Binarizer(threshold=3).fit_transform(iris.data)
2.3 對定性特徵啞編碼
由於IRIS數據集的特徵皆為定量特徵,故使用其目標值進行啞編碼(實際上是不需要的)。使用preproccessing庫的OneHotEncoder類對數據進行啞編碼的代碼如下:
from sklearn.preprocessing import OneHotEncoder
#啞編碼,對IRIS數據集的目標值,返回值為啞編碼後的數據
OneHotEncoder().fit_transform(iris.target.reshape((-1,1)))
2.4 缺失值計算
由於IRIS數據集沒有缺失值,故對數據集新增一個樣本,4個特徵均賦值為NaN,表示數據缺失。使用preproccessing庫的Imputer類對數據進行缺失值計算的代碼如下:
from numpy import vstack, array, nan
from sklearn.preprocessing import Imputer
#缺失值計算,返回值為計算缺失值後的數據
#參數missing_value為缺失值的表示形式,默認為NaN
#參數strategy為缺失值填充方式,默認為mean(均值)
Imputer().fit_transform(vstack((array([nan, nan, nan, nan]), iris.data)))
2.5 數據變換
常見的數據變換有基於多項式的、基於指數函數的、基於對數函數的。4個特徵,度為2的多項式轉換公式如下:
使用preproccessing庫的PolynomialFeatures類對數據進行多項式轉換的代碼如下:
from sklearn.preprocessing import PolynomialFeatures
#多項式轉換
#參數degree為度,默認值為2
PolynomialFeatures().fit_transform(iris.data)
基於單變元函數的數據變換可以使用一個統一的方式完成,使用preproccessing庫的FunctionTransformer對數據進行對數函數轉換的代碼如下:
from numpy import log1p
from sklearn.preprocessing import FunctionTransformer
#自定義轉換函數為對數函數的數據變換
#第一個參數是單變元函數
FunctionTransformer(log1p).fit_transform(iris.data)
3 特徵選擇
當數據預處理完成後,我們需要選擇有意義的特徵輸入機器學習的演算法和模型進行訓練。通常來說,從兩個方面考慮來選擇特徵:
- 特徵是否發散:如果一個特徵不發散,例如方差接近於0,也就是說樣本在這個特徵上基本上沒有差異,這個特徵對於樣本的區分並沒有什麼用。
- 特徵與目標的相關性:這點比較顯見,與目標相關性高的特徵,應當優選選擇。除方差法外,本文介紹的其他方法均從相關性考慮。
根據特徵選擇的形式又可以將特徵選擇方法分為3種:
- Filter:過濾法,按照發散性或者相關性對各個特徵進行評分,設定閾值或者待選擇閾值的個數,選擇特徵。
- Wrapper:包裝法,根據目標函數(通常是預測效果評分),每次選擇若干特徵,或者排除若干特徵。
- Embedded:嵌入法,先使用某些機器學習的演算法和模型進行訓練,得到各個特徵的權值係數,根據係數從大到小選擇特徵。類似於Filter方法,但是是通過訓練來確定特徵的優劣。
我們使用sklearn中的feature_selection庫來進行特徵選擇。
3.1 Filter3.1.1 方差選擇法
使用方差選擇法,先要計算各個特徵的方差,然後根據閾值,選擇方差大於閾值的特徵。使用feature_selection庫的VarianceThreshold類來選擇特徵的代碼如下:
from sklearn.feature_selection import VarianceThreshold
#方差選擇法,返回值為特徵選擇後的數據
#參數threshold為方差的閾值
VarianceThreshold(threshold=3).fit_transform(iris.data)
3.1.2 相關係數法
使用相關係數法,先要計算各個特徵對目標值的相關係數以及相關係數的P值。用feature_selection庫的SelectKBest類結合相關係數來選擇特徵的代碼如下:
from sklearn.feature_selection import SelectKBest
from scipy.stats import pearsonr
#選擇K個最好的特徵,返回選擇特徵後的數據
#第一個參數為計算評估特徵是否好的函數,該函數輸入特徵矩陣和目標向量,輸出二元組(評分,P值)的數組,數組第i項為第i個特徵的評分和P值。在此定義為計算相關係數
#參數k為選擇的特徵個數
SelectKBest(lambda X, Y: array(map(lambda x:pearsonr(x, Y), X.T)).T, k=2).fit_transform(iris.data, iris.target)
3.1.3 卡方檢驗
經典的卡方檢驗是檢驗定性自變數對定性因變數的相關性。假設自變數有N種取值,因變數有M種取值,考慮自變數等於i且因變數等於j的樣本頻數的觀察值與期望的差距,構建統計量:
不難發現,這個統計量的含義簡而言之就是自變數對因變數的相關性。用feature_selection庫的SelectKBest類結合卡方檢驗來選擇特徵的代碼如下:
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
#選擇K個最好的特徵,返回選擇特徵後的數據
SelectKBest(chi2, k=2).fit_transform(iris.data, iris.target)
3.1.4 互信息法
經典的互信息也是評價定性自變數對定性因變數的相關性的,互信息計算公式如下:
為了處理定量數據,最大信息係數法被提出,使用feature_selection庫的SelectKBest類結合最大信息係數法來選擇特徵的代碼如下:
from sklearn.feature_selection import SelectKBest
from minepy import MINE
#由於MINE的設計不是函數式的,定義mic方法將其為函數式的,返回一個二元組,二元組的第2項設置成固定的P值0.5
def mic(x, y):
m = MINE()
m.compute_score(x, y)
return (m.mic(), 0.5)
#選擇K個最好的特徵,返回特徵選擇後的數據
SelectKBest(lambda X, Y: array(map(lambda x:mic(x, Y), X.T)).T, k=2).fit_transform(iris.data, iris.target)
3.2 Wrapper
3.2.1 遞歸特徵消除法
遞歸消除特徵法使用一個基模型來進行多輪訓練,每輪訓練後,消除若干權值係數的特徵,再基於新的特徵集進行下一輪訓練。使用feature_selection庫的RFE類來選擇特徵的代碼如下:
from sklearn.feature_selection import RFE
from sklearn.linear_model import LogisticRegression
#遞歸特徵消除法,返回特徵選擇後的數據
#參數estimator為基模型
#參數n_features_to_select為選擇的特徵個數
RFE(estimator=LogisticRegression(), n_features_to_select=2).fit_transform(iris.data, iris.target)
3.3 Embedded
3.3.1 基於懲罰項的特徵選擇法
使用帶懲罰項的基模型,除了篩選出特徵外,同時也進行了降維。使用feature_selection庫的SelectFromModel類結合帶L1懲罰項的邏輯回歸模型,來選擇特徵的代碼如下:
from sklearn.feature_selection import SelectFromModel
from sklearn.linear_model import LogisticRegression
#帶L1懲罰項的邏輯回歸作為基模型的特徵選擇
SelectFromModel(LogisticRegression(penalty="l1", C=0.1)).fit_transform(iris.data, iris.target)
實際上,L1懲罰項降維的原理在於保留多個對目標值具有同等相關性的特徵中的一個,所以沒選到的特徵不代表不重要。故,可結合L2懲罰項來優化。具體操作為:若一個特徵在L1中的權值為1,選擇在L2中權值差別不大且在L1中權值為0的特徵構成同類集合,將這一集合中的特徵平分L1中的權值,故需要構建一個新的邏輯回歸模型:
from sklearn.linear_model import LogisticRegression
class LR(LogisticRegression):
def __init__(self, threshold=0.01, dual=False, tol=1e-4, C=1.0,
fit_intercept=True, intercept_scaling=1, class_weight=None,
random_state=None, solver="liblinear", max_iter=100,
multi_class="ovr", verbose=0, warm_start=False, n_jobs=1):
#權值相近的閾值
self.threshold = threshold
LogisticRegression.__init__(self, penalty="l1", dual=dual, tol=tol, C=C,
fit_intercept=fit_intercept, intercept_scaling=intercept_scaling, class_weight=class_weight,
random_state=random_state, solver=solver, max_iter=max_iter,
multi_class=multi_class, verbose=verbose, warm_start=warm_start, n_jobs=n_jobs)
#使用同樣的參數創建L2邏輯回歸
self.l2 = LogisticRegression(penalty="l2", dual=dual, tol=tol, C=C, fit_intercept=fit_intercept, intercept_scaling=intercept_scaling, class_weight = class_weight, random_state=random_state, solver=solver, max_iter=max_iter, multi_class=multi_class, verbose=verbose, warm_start=warm_start, n_jobs=n_jobs)
def fit(self, X, y, sample_weight=None):
#訓練L1邏輯回歸
super(LR, self).fit(X, y, sample_weight=sample_weight)
self.coef_old_ = self.coef_.copy()
#訓練L2邏輯回歸
self.l2.fit(X, y, sample_weight=sample_weight)
cntOfRow, cntOfCol = self.coef_.shape
#權值係數矩陣的行數對應目標值的種類數目
for i in range(cntOfRow):
for j in range(cntOfCol):
coef = self.coef_[i][j]
#L1邏輯回歸的權值係數不為0
if coef != 0:
idx = [j]
#對應在L2邏輯回歸中的權值係數
coef1 = self.l2.coef_[i][j]
for k in range(cntOfCol):
coef2 = self.l2.coef_[i][k]
#在L2邏輯回歸中,權值係數之差小於設定的閾值,且在L1中對應的權值為0
if abs(coef1-coef2) &< self.threshold and j != k and self.coef_[i][k] == 0:
idx.append(k)
#計算這一類特徵的權值係數均值
mean = coef / len(idx)
self.coef_[i][idx] = mean
return self
使用feature_selection庫的SelectFromModel類結合帶L1以及L2懲罰項的邏輯回歸模型,來選擇特徵的代碼如下:
from sklearn.feature_selection import SelectFromModel
#帶L1和L2懲罰項的邏輯回歸作為基模型的特徵選擇
#參數threshold為權值係數之差的閾值
SelectFromModel(LR(threshold=0.5, C=0.1)).fit_transform(iris.data, iris.target)
3.3.2 基於樹模型的特徵選擇法
樹模型中GBDT也可用來作為基模型進行特徵選擇,使用feature_selection庫的SelectFromModel類結合GBDT模型,來選擇特徵的代碼如下:
from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import GradientBoostingClassifier
#GBDT作為基模型的特徵選擇
SelectFromModel(GradientBoostingClassifier()).fit_transform(iris.data, iris.target)
4 降維
當特徵選擇完成後,可以直接訓練模型了,但是可能由於特徵矩陣過大,導致計算量大,訓練時間長的問題,因此降低特徵矩陣維度也是必不可少的。常見的降維方法除了以上提到的基於L1懲罰項的模型以外,另外還有主成分分析法(PCA)和線性判別分析(LDA),線性判別分析本身也是一個分類模型。PCA和LDA有很多的相似點,其本質是要將原始的樣本映射到維度更低的樣本空間中,但是PCA和LDA的映射目標不一樣:PCA是為了讓映射後的樣本具有最大的發散性;而LDA是為了讓映射後的樣本有最好的分類性能。所以說PCA是一種無監督的降維方法,而LDA是一種有監督的降維方法。
4.1 主成分分析法(PCA)使用decomposition庫的PCA類選擇特徵的代碼如下:
from sklearn.decomposition import PCA
#主成分分析法,返回降維後的數據
#參數n_components為主成分數目
PCA(n_components=2).fit_transform(iris.data)
4.2 線性判別分析法(LDA)
使用lda庫的LDA類選擇特徵的代碼如下:
from sklearn.lda import LDA
#線性判別分析法,返回降維後的數據
#參數n_components為降維後的維數
LDA(n_components=2).fit_transform(iris.data, iris.target)
5 總結
再讓我們回歸一下本文開始的特徵工程的思維導圖,我們可以使用sklearn完成幾乎所有特徵處理的工作,而且不管是數據預處理,還是特徵選擇,抑或降維,它們都是通過某個類的方法fit_transform完成的,fit_transform要不只帶一個參數:特徵矩陣,要不帶兩個參數:特徵矩陣加目標向量。這些難道都是巧合嗎?還是故意設計成這樣?方法fit_transform中有fit這一單詞,它和訓練模型的fit方法有關聯嗎?接下來,我將在《使用sklearn優雅地進行數據挖掘》中闡述其中的奧妙!
6 參考資料
- FAQ: What is dummy coding?
- IRIS(鳶尾花)數據集
- 卡方檢驗
- 乾貨:結合Scikit-learn介紹幾種常用的特徵選擇方法
- 機器學習中,有哪些特徵選擇的工程方法?
- 機器學習中的數學(4)-線性判別分析(LDA), 主成分分析(PCA)
最近一段時間,我們米筐科技量化策略研究團隊在自己的策略研究平台上,做了一些量化分析方面的特徵工程和特徵選擇研究。關於它們在量化交易中的應用,我可以分享一下我們團隊的經驗。
首先,追本溯源,為什麼特徵工程和特徵選擇值得討論?在實際的數據分析和建模中,我們通常要面對兩種情況:1 數據集中已有的特徵變數不夠多,或者已有的特徵變數不足以充分表徵數據的特點;2 我們擁有大量的特徵,需要判斷出哪些是相關特徵,哪些是不相關特徵。特徵工程解決的是第一個問題,而特徵選擇解決的是第二個問題。
對於特徵工程來說,它的的難點在於找到好的思路,來產生能夠表徵數據特點的新特徵變數;而特徵選擇的難點則在於,其本質是一個複雜的組合優化問題(combinatorial optimization)。例如,如果有 30 個特徵變數,當我們進行建模的時候,每個特徵變數有兩種可能的狀態:「保留」和「被剔除」。那麼,這組特徵維度的狀態集合中的元素個數就是。更一般地,如果我們有 N 個特徵變數,則特徵變數的狀態集合中的元素個數就是。因此,從演算法角度講,通過窮舉的方式進行求解的時間複雜度是指數級的(O())。當 N 足夠大時,特徵篩選將會耗費大量的時間和計算資源(圖1)。在實際應用中,為了減少運算量,目前特徵子集的搜索策略大都採用貪心演算法(greedy
algorithm),其核心思想是在每一步選擇中,都採納當前條件下最好的選擇,從而獲得組合優化問題的近似最優解。
圖1:通過窮舉法求解特徵選擇問題的二叉樹表示。狀態集合中元素的個數隨特徵變數數目增加而呈現指數增長。
目前很多流行的機器學習的材料,都未能給出特徵工程和特徵選擇的詳細論述。其主要原因是,大部分機器學習演算法有標準的推導過程,因而易於講解。但是在很多實際問題中,尋找和篩選特徵變數並沒有普適的方法。 然而,特徵工程和特徵選擇對於分析結果的影響,往往比之後的機器學習模型的選擇更為重要。斯坦福大學教授,Coursera 上著名的機器學習課程主講老師 Andrew Ng 就曾經表示:「基本上,所謂機器學習應用,就是進行特徵工程。」
在特徵工程和特徵選擇的在量化交易的應用方面,我們試圖回答以下兩個問題:
1 如何對滬深300指數進行特徵工程?
2 如何儘可能減少數據,以及演算法本身的局限性給特徵選擇帶來的負面影響?
接下來,就以上兩個問題,不揣淺陋,我分享一些我們團隊的經驗和思考。
1 滬深300指數的特徵工程
在量化分析中,常見的因子大致可以分為四類:
(1)
量價因子,例如成交量,收盤價等;
(2)
基本面因子,例如市盈率,所屬行業等;
(3)
技術分析因子,例如MACD, DIF等;
(4)
宏觀經濟因子(或稱外部響應因子),例如利率,各個季度的經濟數據等。
1970年,尤金法馬(Eugene Fama)提出了有效市場理論,認為證券資產價格包含一切的市場信息。這就是量價因子能夠反映市場特徵的根本依據。對於一個非有效市場而言,我們認為,量價因子甚至可能更為重要:任何人根據非公開信息進行交易,其交易信息仍然會反映在量價因子中。類似的觀點更接近於有效市場理論的強假設版本:市場上一切公開或非公開的信息,都會反映在資產的價格中。
基於這個思路,在四類因子中,我們首先嘗試對量價因子實現特徵工程。2015年,在一篇名為《WorldQuant Formulaic 101 Alphas》的研究報告中,以數據挖掘能力而聞名業界的對沖基金
WorldQuant LLC 給出了他們的 101 個阿爾法的數學表達式。在報告中,這些阿爾法表達式被分為了趨勢追隨,均值回歸和混合型三種。既然這 101 個阿爾法表達式在實踐中被證明行之有效,且對應明確的市場意義(趨勢,反轉和混合),在特徵工程研究中,我們使用報告中的變換方法和阿爾法表達式為基礎,構造了
60 個特徵變數,用於下一步的機器學習建模。這 60 個特徵變數的構建過程,可參看我們第二份報告的附錄2。
2 集成特徵打分器 (Ensemble Feature Grader, EFG)
如上所述,特徵選擇的本質上是求解一個計算量隨特徵變數個數呈指數增長的組合優化問題。基於不同的子集搜索和評價標準,不同的方法給出的都只是一個近似最優解,而解的合理性也將受方法本身的局限性所影響。因此,為了系統化地進行特徵選擇,獲得更為合理的相關特徵變數子集,在這裡我們借鑒機器學習裡面的集成學習(ensemble learning)的思想,提出一個集成特徵打分器(以下稱EFG)。在這個打分器中,我們使用了八種方法(Pearson 相關係數,距離相關係數,簡單線性回歸,基於AIC的Lasso回歸,基於BIC的Lasso回歸,隨機森林,循環特徵剔除和嶺回歸)對特徵變數分別進行打分,並進而計算其總得分,以盡量減少數據和單一特徵選擇方法引起的問題,進而改善特徵選擇的效果。
我們進一步使用了 Frideman 訓練集對 EFG 進行測試。這個訓練集中包含非線性相關項,噪音項,權重不同的線性相關項和引起多重共線性的項,基本上囊括了實際數據處理中可能出現的主要問題,而 EFG 的測試表現令人滿意。有興趣的朋友,可以參看我們第二份研究報告附錄1,了解詳細的測試過程和結果。
在實際建模中,我們使用 EFG 對上一步獲得的 60 個特徵變數進行打分,篩選出 14 個得分較高的特徵變數,並以此進行了聚類分析。我們發現兩個聚類所對應的不同收益率分布,其中第一個聚類所包含的交易日,其下一個交易日的收益率的均值明顯高於第二個聚類所對應的均值。基於這個結果,我們實現了一個基準擇時策略。其思路是,如果一個交易日和聚類1的距離較近,我們就進行買入;離聚類2較近,則不進行交易。下午為該策略的累計收益率(圖2),其表現明顯好於長期持有滬深300指數相關的資產。
圖2:使用 EFG 進行特徵選擇後累積收益率曲線計算:(a)滬深300指數;(b) 在聚類1包含的交易日進行交易;(c) 在聚類2包含的交易日進行交易
以上就是我們在利用機器學習演算法進行金融量化分析中的經驗和嘗試。關於下筆為文,古人有一句真知灼見:「結字因時而變,運筆千秋不易。」 對於數據分析和建模來說,道理也不外如是。計算機理論和機器學習演算法的發展,使得數據分析和建模成為了這個時代的顯學。目前,用
R 或者 Python 等高級編程語言實現一個複雜的模型,所需的可能就是區區幾十行代碼。但是自問自心,我們是否能夠真的對於數據和模型做得了如指掌?是否能保證當模型出現問題時,我們能知其所以然?在一個足夠長的時間維度內,我們認為,在數據建模和量化交易中能夠出類拔萃的人,始終應該保持著對數據和演算法全面,準確,深刻的理解和思考。
概而言之,撥開數據的重重迷霧,理解和預測複雜多變的金融市場,即使不考慮其物質回報,其過程本身也令人著迷。我們走上了這條荊棘叢生,又有壯麗風光的旅途,樂於體認這個過程中一切的艱辛和甘甜。希望我們這裡所敘述的經驗和思考,也對你有所啟發。
研究報告鏈接:
com/p/21337419
com/p/21406355
枕書達旦,以爭朝夕,與君共勉。
附上整理的筆記,歡迎交流
參考資料:
【1】機器學習中的數據清洗與特徵處理綜述
http://tech.meituan.com/machinelearning-data-feature-process.html
【2】《Applied Predictive Modeling》
看kaggle獲勝者源碼。
http://www.chioka.in/kaggle-competition-solutions/
特別的,kaggle排名第一的owen zhang,他的github有幾個源碼。
https://github.com/owenzhang
手機發的沒有超鏈接 T0T在有時候不僅僅是需要從100個columns里選出十個來作為x variable (feature selection)。更重要的是從raw data里自己create出來一些列,create這些列的方法基本上是trial and error。就是先根據你對問題的 domain knowledge,覺得什麼feature 跟 y variable可能相關,再去產生這些列,然後在訓練個model看效果。然後根據預測結果,再重複上一個過程。說得有點亂,見諒,改天有空了我試著舉個例子。
實際工程不是做kaggle那種感覺,為了提高百分之幾,拼的你死我活。關鍵還是怎麼create feature。
回答問題:
我簡單說下我的經驗。找feature要結合問題的domain knowledge,比如我要定位潛在的客戶,有一些已知的客戶的數據,也有些已知的非客戶的用戶在前一年的消費記錄。憑直覺,我可以列出如下feature:用戶前三個月購買某類商品的總和,單次消費的最大額,消費記錄的中位數,等等都是要從raw data里總結出來的。然後跑model,比如random forest,跑完了你可能發現預測的並不理想,那就要再回頭去試別的feature。過程是trial and error的循環模式。
再舉個例子,聽羅振宇節目講的,說英國人想找出恐怖分子,他們總結出來,恐怖分子不買人身保險,而普通人有基本上都會買。那買不買人身保險就是一個非常好的feature。
總結一下,做feature要有domain knowledge,還要比較懂統計。
特徵工程是一個非常重要的課題,是機器學習中不可缺少的一部分,但是它幾乎很少出現於機器學習書本裡面的某一章。在機器學習方面的成功很大程度上在於如果使用特徵工程。
(I)特徵工程可以解決什麼樣的問題?
在機器學習中,經常是用一個預測模型(線性回歸,邏輯回歸,SVD等)和一堆原始數據來得到一些預測的結果,人們需要做的是從這堆原始數據中去提煉較優的結果,然後做到最優的預測。這個就包括兩個方面,第一就是如何選擇和使用各種模型,第二就是怎麼樣去使用這些原始的數據才能達到最優的效果。那麼怎麼樣才能夠獲得最優的結果呢?貼上一句經典的話就是:
Actually the sucess of all Machine Learning algorithms depends on how you present the data.
------ Mohammad Pezeshki
直接翻譯過來便是:事實上所有機器學習演算法上面的成功都在於你怎麼樣去展示這些數據。由此可見特徵工程在實際的機器學習中的重要性,從數據裡面提取出來的特徵好壞與否就會直接影響模型的效果。從某些層面上來說,所使用的特徵越好,得到的效果就會越好。所需要的特徵就是可以藉此來描述已知數據的內在關係。總結一下就是:
Better feature means flexibility. Better feature means simpler models. Better feature means better results.
有的時候,可以使用一些不是最優的模型來訓練數據,如果特徵選擇得好的話,依然可以得到一個不錯的結果。很多機器學習的模型都能夠從數據中選擇出不錯的結構,從而進行良好的預測。一個優秀的特徵具有極強的靈活性,可以使用不那麼複雜的,運算速度快,容易理解和維護的模型來得到不錯的結果。
(II)什麼才是特徵工程?
Feature Engineering is the process of transforming raw data into features that better represent the underlying problem to the predictive models, resulting in improved model accuracy on unseen data.
------ Jason Brownlee
Feature Engineering is manually designing what the input x"s should be.
------ Tomasz Malisiewicz
從這個概念可以看出,特徵工程其實是一個如何展示和表現數據的問題,在實際工作中需要把數據以一種「良好」的方式展示出來,使得能夠使用各種各樣的機器學習模型來得到更好的效果。如何從原始數據中去除不佳的數據,展示合適的數據就成為了特徵工程的關鍵問題。
(III)特徵有用性的預估
每次構造了一個特徵,都需要從各個方面去證明該特徵的有效性。一個特徵是否重要主要在於該特徵與要預測的東西是否是高度相關的,如果是高度相關,那麼該特徵就是十分重要的。比如常用的工具就是統計學裡面的相關係數。
(IV)特徵的構造過程
在實際工作中首先肯定要確定具體的問題,然後就是數據的選擇和準備過程,再就是模型的準備和計算工作,最後才是展示數據的預測結果。構造特徵的一般步驟:
[1]任務的確定:根據具體的業務確定需要解決的問題;
[2]數據的選擇:整合數據,收集數據;
[3]預處理數據:設計數據展現的格式,清洗數據,選擇合適的樣本使得機器學習模型能夠使用它。比方說一些年齡特徵是空值或者負數或者大於200等,或者說某個頁面的播放數據大於曝光數據,這些就是數據的不合理,需要在使用之前把這一批數據排除掉。
[4]特徵的構造:轉化數據,使之成為有效的特徵。常用的方法是標準化,歸一化,特徵的離散化等。
(4.1)標準化(Standardization):比方說有一些數字的單位是千克,有一些數字的單位是克,這個時候需要統一單位。如果沒有標準化,兩個變數混在一起搞,那麼肯定就會不合適。
(4.2)歸一化(Normalization):歸一化是因為在特徵會在不同的尺度下有不同的表現形式,歸一化會使得各個特徵能夠同時以恰當的方式表現。比方說某個專輯的點擊播放率一般不會超過0.2,但是專輯的播放次數可能會達到幾千次,所以說為了能夠在模型裡面得到更合適結果,需要先把一些特徵在尺度上進行歸一化,然後進行模型訓練。
(4.3)特徵的離散化(Discretization):離散化是指把特徵進行必要的離散處理,比方說年齡特徵是一個連續的特徵,但是把年齡層分成5-18歲(中小學生),19-23歲(大學生),24-29歲(工作前幾年),30-40歲(成家立業),40-60歲(中年人)從某些層面來說比連續的年齡數據(比如說某人年齡是20歲1月3日之類的)更容易理解不同年齡層人的特性。典型的離散化步驟:對特徵做排序-&> 選擇合適的分割點-&> 作出區間的分割 -&> 作出區間分割-&> 查看是否能夠達到停止條件。
[5]模型的使用:創造模型,選擇合適的模型,用合適的模型來進行預測,用各種統計指標來判斷該特徵是否合適;
[6]上線的效果:通過在線測試來看效果。
數據的轉換(Transforming Data)就是把數據從原始的數據狀態轉換成適合模型計算的狀態,從某些層面上來說,「數據轉換「和」特徵構造「的過程幾乎是一致的。
(V)特徵工程的迭代過程
特徵工程的迭代步驟:[1]選擇特徵:需要進行頭腦風暴(brainstorm)。通過具體的問題分析,查看大量的數據,從數據中查看出可以提取出數據的關鍵;
[2]設計特徵:這個需要具體問題具體分析,可以自動進行特徵提取工作,也可以進行手工進行特徵的構造工作,甚至混合兩種方法;
[3]選擇特徵:使用不同的特徵構造方法,來從多個層面來判斷這個特徵的選擇是否合適;
[4]計算模型:通過模型計算得到模型在該特徵上所提升的準確率。
[5]上線測試:通過在線測試的效果來判斷特徵是否有效。
有人不想做特徵工程,於是有了深度學習
目前的實際工作中,對特徵選擇沒有這麼重視,我們目前常用的方式是:
1、選擇N多變數;
2、然後扔到xgboost和Randomforest模型去跑一邊,然後查看一下變數重要性排序;一般性選擇用gini增益查看變數重要性排序;
3、如果是數值型預測,也可以用xgboost加入lamda來進行變數的篩選;
4、根據這個重要性變數的排序,我們可以剔除掉那些不重要的變數,然後再重新預測一下模型,根據模型評估EvaluateMetric,看一下AUC等指標下降了多少;一般性都不是很重要的;
---------------------------------------------------------------------------------------------------------------
以上方法是最快速有效的方法,其他的方法,REF,LASSO等方法都比價耗時耗力。因為很多的特徵選擇的目的是為了規避特徵之間的多重共線性,導致模型效果欠擬合或者過擬合。而上述提供的方法能夠很好的對抗特徵之間的交互性,模型整體來說比較穩健。
看這裡
https://www.zhihu.com/lives/819543866939174912
一般簡單且常見的都是卡方檢驗,互信息和信息增益這三種。往深了說估計就數不清了
就沒有人回答業務理解和經驗嗎?
【Machine Learning】機器學習の特徵
(放大即可看到內容)
導圖下載:地址
[機器學習] 特徵選擇簡明指南
知乎專欄
介紹
數據工程項目往往嚴格遵循著riro (rubbish in, rubbish out) 的原則,所以我們經常說數據預處理是數據工程師或者數據科學家80%的工作,它保證了數據原材料的質量。而特徵工程又至少佔據了數據預處理的半壁江山,在實際的數據工程工作中,無論是出於解釋數據或是防止過擬合的目的,特徵選擇都是很常見的工作。如何從成百上千個特徵中發現其中哪些對結果最具影響,進而利用它們構建可靠的機器學習演算法是特徵選擇工作的中心內容。在多次反覆的工作後,結合書本,kaggle等線上資源以及與其他數據工程師的討論,我決定寫一篇簡明的總結梳理特徵選擇工作的常見方法以及python實現。
總的來說,特徵選擇可以走兩條路:
特徵過濾(Filter methods): 不需要結合特定的演算法,簡單快速,常用於預處理
包裝篩選(Wrapper methods): 將特徵選擇包裝在某個演算法內,常用於學習階段
在scikit-learn環境中,特徵選擇擁有獨立的包sklearn.feature_selection, 包含了在預處理和學習階段不同層級的特徵選擇演算法。
A. 特徵過濾(Filter methods)
(1) 方差閾(Variance Treshhold)
最為簡單的特徵選擇方式之一,去除掉所有方差小於設定值的特徵。
在sklearn中實現:
from sklearn.feature_selection import VarianceThreshold
VarianceThreshold is a simple baseline approach to feature selection. It removes all features whose variance doesn』t meet some threshold. By default, it removes all zero-variance features, i.e. features that have the same value in all samples.
(2) 單變數特徵選擇 (Univariate feature selection)
基於單變數假設檢驗的特徵選擇,比如卡方檢驗(這裡有一篇很好的博文用於回顧)是檢測兩變數是否相關的常用手段,那麼就可以很自然的利用chi-square值來做降維,保留相關程度大的變數。
Univariate feature selection works by selecting the best features based on univariate statistical tests. It can be seen as a preprocessing step to an estimator.
X_new = SelectKBest(chi2, k=2).fit_transform(X, y)
B. 包裝篩選(Wrapper methods)
包裝篩選往往利用一些在訓練過程中可以計算各個特徵對應權重的演算法來達到選擇特徵的目的。在sklearn中有一個專門的模塊 SelectFromModel 來幫助我們實現這個過程。
SelectFromModel is a meta-transformer that can be used along with any estimator that has a coef_ or feature_importances_ attribute after fitting. The features are considered unimportant and removed, if the corresponding coef_ or feature_importances_ values are below the provided threshold parameter. Apart from specifying the threshold numerically, there are build-in heuristics for finding a threshold using a string argument. Available heuristics are 「mean」, 「median」 and float multiples of these like 「0.1*mean」.
(1)利用Lasso進行特徵選擇
在介紹利用Lasso進行特徵選擇之前,簡要介紹一下什麼是Lasso:
對於一個線性回歸問題
基本的任務是估計參數,使得
最小,這就是經典的 Ordinary Linear Square (OLS) 問題。
但在實際的工作中,僅僅使用OLS進行回歸計算很容易造成過擬合,雜訊得到了過分的關注,訓練數據的微小差異可能帶來巨大的模型差異(主要是樣本的共線性容易使矩陣成為對擾動敏感的病態陣,從而造成回歸係數解析解的不穩定,要更詳細的探究可以參考這裡)。
為了矯正過擬合,我們常使用帶有正則項的cost function,其中使用L1正則的表達式則為Lasso方法:
Lasso方法下解出的參數常常具有稀疏的特徵,即很多特徵對應的參數會為零,這就使得特徵選擇成為可能:我們可以訓練一個Lasso模型,然後將係數為零的特徵去除。
在實際的工作中,Lasso的參數lambda越大,參數的解越稀疏,選出的特徵越少。那麼如何確定使用多大的lambda?一個比較穩妥地方案是對於一系列lambda,用交叉驗證計算模型的rmse,然後選擇rmse的極小值點 (Kaggle上有一個很好的例子)。
Linear models penalized with the L1 norm have sparse solutions: many of their estimated coefficients are zero. When the goal is to reduce the dimensionality of the data to use with another classifier, they can be used along with feature_selection.SelectFromModel to select the non-zero coefficients. With Lasso, the higher the alpha parameter, the fewer features selected.
在sk-learn中的實現參看這裡。
(2)基於決策樹的特徵選擇
利用決策樹中深度較淺的節點對應的特徵提供信息較多(可以直觀的理解為這個特徵將更多的樣本區分開)這一特性,許多基於決策樹的演算法,如隨機森林也可以在結果中直接給出feature_importances屬性。其主要思想是訓練一系列不同的決策樹模型,在每一棵樹中使用特徵集的某一個隨機的子集(使用bootstrap等方法抽樣),最後統計每個特徵出現的次數,深度,分離的樣本量以及模型的準確率等給出特徵的權重值。設定一個閾值,我們便可以使用這類基於決策樹的演算法進行特徵選擇。
Tree-based estimators (see the sklearn.tree module and forest of trees in the sklearn.ensemble module) can be used to compute feature importances, which in turn can be used to discard irrelevant features (when coupled with the sklearn.feature_selection.SelectFromModel meta-transformer).
在sk-learn中的實現參看這裡。
小結
這篇短文簡明的介紹了部分常用的特徵處理方法,應該提出的是,除了feature selection,feature transformation,包括PCA等降維方法也可以達到減少特徵數量,抑制過擬合的目的。
其他參考資料:
scikit-learn feature selection documentation
修正的LARS演算法和lasso
個人了解的方法是:
單個特徵選擇,可以用決策樹的split 的方法:gini index,信息增益等。
組合特徵選擇,決策樹的整個路徑。
sklearn的文檔有相關的章節:1.13. Feature selection
看完後分分鐘就可以用了。
你好,L1正則化的邏輯回歸模型,有沒有可能選出一些起返作用的特徵。
特徵選擇主要分為兩大類:
- 特徵過濾
- 包裝選擇
- 特徵選擇:主要通過卡方檢驗,相關係數判定等方式
特徵選擇過程中,可以求出每個特徵與 Label 的相關係數,然後排序進行選擇。常見的相關係數有: Pearson皮爾森相關係數(積矩相關係數)和Spearman相關係數(秩相關係數)。
區別是: Pearson相關係數只能捕獲線性關係。
Spearman 可以捕獲單調線性關係(包括非線性關係)取值範圍是[-1,1]
包
2. 包裝選擇:主要有Lasso回歸進行特徵選擇,或者使用基於決策樹的特徵選擇,比如隨機森林,GBDT
數據挖掘導論Pang Ning Tan版里有說特徵選擇(中文版2.3 P33)
1.特徵提取
各個領域有高度針對的提取方法,不同領域的方法之間局限性很大,所以新領域需要重新開發。
2.映射數據到空間
使用一種完全不同的視角挖掘數據可能揭示出重要和有趣的特徵。
如時間序列數據,可以用傅里葉變換,小波變化 構造更好的特徵。
現在都深度學習了,特徵提取基本上不怎麼重要了,扔進去自動訓練出有效特徵。
推薦閱讀: