catalogue
1. 特征工程是什么?有什么作用? 2. 特征獲取方案 - 如何獲取這些特征? 3. 特征觀察 - 運用各種統計工具、圖標等工具幫助我們從直觀和精確層面認識特征中的概率分布 4. 特征處理 - 特征清洗 5. 特征護理 - 特征預處理 6. 特征處理 - 特征選擇 7. 特征監控
1. 特征工程是什么?有什么作用?
從某種程度上來說,數據和特征決定了機器學習的上限,而模型和算法能做的只是逼近這個上限。特征工程本質上是一項工程活動,目的是最大限度地從原始數據中提取特征以供算法和模型使用
我們本章圍繞該xmin思維導圖展開討論
Relevant Link:
http://www.cnblogs.com/jasonfreak/p/5448385.html http://weibo.com/ttarticle/p/show?id=2309403973170330790744
2. 特征獲取方案 - 如何獲取這些特征?
0x1: 結合具體業務場景從原始日志中提取特征 - 結合業務!業務!業務!
在大部分時候我們從產品中得到的原始日志都不能直接進行數據挖掘,我們需要進行特征提取,但特征提取也不能簡單的直接就粗暴地分為數字型/文本型/序列型等等,這一步的思考非常重要,我們需要明確我們的業務場景細節,以及業務目標
以暴力破解識別為具體場景我們展開討論:
1. 我們的日志從哪里來?是什么形式的?
對於網絡層面的數據,我們的原始日志常常是Gateway網絡采集的原始五元組數據,包含
session_time: '會話發生時間' src_ip: '源IP' src_port: '源端口' dst_ip: '目的IP' dst_port: '目的端口'
樣本的形式是字符串型的,但是要注意到的五元組單條日志本身是不包含"異常特征"規律的,也即規律不在原始日志本身,而在於多條原始日志內的統計分布規律,只有將原始日志進行良好的聚合才能將包含爆破特征的規律暴露出來
2. 從攻防業務角度初步觀測暴力破解的規律特征是怎樣的?
我們將發起暴力破解的機器設定為攻擊者(不管是主動行為還是被入侵后淪為肉雞的情況),從攻擊者角度看暴力破解有2種方式:
1. 針對單點目標的深度破解; 2. 針對大范圍(常常是B/C段)目標的廣度破解;
思考清楚了這2點,可以指導我們在觀測樣本數據的時候抓住哪些重點,即觀察發生爆破安全事件的時候,有哪些樣本日志含有廣度特征,有哪些樣本日志含有深度特征。特征提取分析的第一步是要在了解業務場景的前提下觀察樣本數據的特征分布,這一步前期調研很重要,它可以幫助我們判斷后續用什么模型進行抽象建模,用什么算法進行計算
我們以暴力破解廣度掃描為例觀測一組存在異常事件的服務器和一台不存在安全事件的服務器,在一天中按照30min為原子時間窗口進行切分, 在初始階段,我們還不能非常好的定義我們的特征提取范圍,根據業務的理解直覺,我們先嘗試用最簡單的【src_ip;dst_port;protocal(協議)】三元組進行時間窗口區間內的發包頻率和攻擊目標dst_ip的廣度統計,來獲取樣本數據整體上的特征分布判斷
src_ip,proto,dst_port,dst_ip_cn,send_cn,timeindex 106.14.xxx.xx,tcp,22,7012,7012,3 106.14.xxx.xx,udp,65500,8,8,3 106.14.xxx.xx,udp,65500,4,4,4 106.14.xxx.xx,tcp,80,1,1,0 106.14.xxx.xx,tcp,80,6,6,3 106.14.xxx.xx,tcp,80,82,82,4 106.14.xxx.xx,tcp,80,1,1,10 106.14.xxx.xx,tcp,80,1,1,14 106.14.xxx.xx,tcp,80,2,2,16 106.14.xxx.xx,tcp,80,1,1,18 106.14.xxx.xx,tcp,80,1,1,19 106.14.xxx.xx,tcp,80,1,1,31 106.14.xxx.xx,tcp,80,1,1,33 106.14.xxx.xx,tcp,80,1,1,34 106.14.xxx.xx,tcp,9183,1,1,42
這該ip的全天五元組日志中,我們已知該機器當前發生了:22端口暴力掃描行為,可以看到存在異常的樣本聚合后,特征比較明顯,即在較短的時間窗口內產生大量對外發包頻率,以及對較多的dst_ip發起發包行為。而該服務器其他的正常通信行為則呈現出少且均勻的對外發包曲線
我們挑選一個不存在異常行為的服務器進行頻次聚合統計
src_ip,proto,dst_port,dst_ip_cn,send_cn,timeindex 114.215.175.203,tcp,22,1,1,29 114.215.175.203,tcp,443,2,2,0
由此證實了我們的猜想,暴力破解的特征提取要從發包頻次和攻擊目標dst_ip廣度重點入手
0x2: 定義特征模型,我們該從原始日志樣本中抽取哪些特征?
對於這個問題,有一個專門的研究分支叫"feature selection(特征選擇)",似乎可以先將所有能想到的特征都抽出來,然后用例如相關性分析、信息增益、互信息這些評價指標來選擇對算法模型分類效果最好的一系列特征。但我個人認為,特征選擇和提取的最好人選還是熟悉業務的人來完成,這個過程可以說是非常依賴經驗的參與,我們要在理解業務背景的基礎上,將人的判別經驗沉淀為需要提取的特征
以暴力破解為例,我們來嘗試定義出一組樣本特征(對每30min時間區間內的所有原始日志按照不同的維度進行聚合)
廣度暴力破解特征
1. proto:協議類型(tcp、udp):不同的網絡協議可能導致我們之后要為每個協議單獨建模,但是也有可能在一個模型中同學擬合2個協議樣本集的特征 2. dst_port:目標端口,代表了目標主機的網絡服務類型,從業務經驗上看,對22這種sshd服務端口發起的密集發包行為比對一個非常用端口發起的密集發包更傾向於在暴力破解,我們抽取這個特征的目的是需要模型盡量學習到不同的dst_port目的端口(代表了不同的服務)對判斷結果的權重是不一樣的 3. count(相同 dst_port):在一個時間統計窗口內和當前連接具有相同服務(不管dst_ip是否相同)的發包頻數,這個特征體現了暴力破解攻擊的強度 4. count(distinct dst_ip 去重):在一個時間統計窗口內攻擊的目標主機的個數,這個特征體現了廣度暴力破解攻擊的范圍廣度 5. max(session_time) - min(session_time):在一個時間統計窗口內和當前連接具有相同服務的攻擊包,第一個發包時間和最后一個發包時間的間隔,該特征越接近於時間窗口大小,表明攻擊的持續性越強
深度暴力破解特征
1. proto:協議類型(tcp、udp):不同的網絡協議可能導致我們之后要為每個協議單獨建模,但是也有可能在一個模型中同學擬合2個協議樣本集的特征 2. count(相同 dst_ip):在一個時間統計窗口內和當前連接具有相同目標主機(不論dst_port是否相同)的發包頻數,這個特征體現了暴力破解攻擊的強度 3. count(distinct dst_port 去重):在一個時間統計窗口內攻擊同一個目標主機的服務端口的個數,這個特征體現了深度暴力破解攻擊的范圍 4. max(session_time) - min(session_time):在一個時間統計窗口內和當前連接具有相同目標主機的攻擊包,第一個發包時間和最后一個發包時間的間隔,該特征越接近於時間窗口大小,表明攻擊的持續性越強
關於聚合的time windows的長度,讀者也需要根據具體的業務場景仔細思考,對於暴力破解來說,爆破事件的特征規律是包含在一個時間窗口內的頻率統計特征,但是對每個安全事件而言,攻擊的持續時間是不同的,這就導致每個樣本的length是變長的,我們需要對日級別的時間區間統計特征進行定長的切分,例如:按照30min為一個原子時間窗口,將樣本集中在這個time windows內的所有原始日志聚合成單條特征向量(具體情況視原始數據采樣能力和算法模型而定)
Relevant Link:
https://mp.weixin.qq.com/s?__biz=MzA5NzkxMzg1Nw==&mid=2653159305&idx=1&sn=077410cb7d95af0c343a13dbbd4e53fc&mpshare=1&scene=1&srcid=0510gYeDGwNdlniGYhamMGjn#wechat_redirect
3. 特征觀察 - 運用各種統計工具、圖標等工具幫助我們從直觀和精確層面認識特征中的概率分布
拿到樣本特征之后,我們可能需要做的是觀察樣本的特征概率分布、是否包含異常/離群點、空間分布上大致分為幾個族群等
0x1: 直方圖統計法
直方圖是在圖像處理上很常見也很有效的方法,它可以認為是圖像灰度密度函數的近似。直方圖雖然不能直接反映出圖像內容,但對它進行分析可以得出圖像的一些有用特征,這些特征能反映出圖像的特點。例如:當圖像對比度較小時,它的灰度直方圖只在灰度軸上較小的一段區間上非零
1. 較暗的圖像由於較多的像素灰度值低,因此它的直方圖的主體出現在低值灰度區間上,其在高值灰度區間上的幅度較小或為零 2. 而較亮的圖像情況正好相反
為使圖像變清晰,可以通過變換使圖像的灰度動態范圍變大,並且讓灰度頻率較小的灰度級經變換后,其頻率變得大一些,使變換后的圖像灰度直方圖在較大的動態范圍內趨於均化。同樣,區分度(對比度)這個概念也同樣適用於非圖像分類領域,在直方圖上低頻區間和高頻區間的間隔越大,對於分類器的訓練越容易
下面是kdd99的特征直方圖
從直方圖上我們可以得出一個大致的判斷,特征選取(feature selection)要盡量選擇在直方圖區間上分布較離散的特征(在分類問題場景中)
0x2: 經驗概率密度圖
經典統計推斷主要的思想就是用樣本來推斷總體的狀態,因為總體是未知的(即真實的規律是未知的),我們只能通過多次試驗的樣本(即實際值)來推斷總體。經驗分布函數是在這一思想下的一種方法,通過樣本分布函數來估計總體的分布函數。
為了解決這個問題,依泛函空間的大數定律得出:可通過該未知分布函數下的樣本集{xi}構造的經驗分布函數


需要特別注意的,該積分方程的求解是一個不適定計算問題,需使用正則化技術才能較好處理。也就是最大似然估計中的 經驗風險和 結構化風險

可以看到,在這個特征的經驗分布中,不同類型的樣本集還是大致可分的,同時,在左邊的mascan和netpture存在一個混淆區,在個該維度上基本不可分了,這會帶來一定誤報;同時在右邊guess_passwd出現了一個小的波峰(peak mode),它可能代表了一些異常點樣本點,可能暗示我們在進行后續的特征處理環節需要進行離群點過濾
gini指數、信息增益都來自於香濃信息論中的混亂度的概念,值越大,體現當前樣本的混亂度越大(區分度也越大)
從圖上可以看到,該特征離散值從0到100區間,gini指數逐漸下降,即指示如果用決策樹或者其他分類器,分界線設定在這個區間內才能獲得有效的信息增益
同時在100到109區間中,樣本在這個區間內只有一個單一的類別,分界線不應該選取在這個區間中,因為不能進行任何有效分類
在109到101區間,樣本在這個區間有有了不同的類別,即有一定的混亂度,特征分界面可以考慮在這個區間選取
0x4: Measures of Shape: Skewness and Kurtosis
Skewness 是描述數據分布是否對稱的指標。越對稱的分布,skewness越小。該指標可以暗示我們是否要進行特征標准化處理
Kurtosis 是用來描述數據是否heavy tail,如果一個分布異常點很多或者很長尾,那么其kurtosis也越大。該指標可以用於評估在該特征維度上離群樣本的密度 結合直方圖,可以很好解釋這兩個指標的意義
Relevant Link:
https://brownmath.com/stat/shape.htm
4. 特征處理 - 特征清洗
通過理解業務場景,深入觀察樣本數據后,我們建立了初步的特征模型,並據此抽取出了一些訓練樣本,但此時還不能盲目直接進入算法建模,我們還需要繼續深入觀察樣本,思考其中是否包含了異常離群數據、是否需要進行無量綱化處理?
0x1: 清洗異常樣本
日志數據中可能存在對挖掘無用的噪音數據或者由於系統異常出現的異常樣本數據,這需要我們結合業務情況和專家領域知識進行清洗過濾
除了結合業務經驗之外,還可以采用異常點檢測算法對樣本進行分析,常用的異常點檢測算法包括
1. 偏差檢測:例如 1) 聚類 2) 最近鄰等 2. 基於統計的異常點檢測算法:這種方法適合於挖掘單變量的數值型數據,常用的方法有 1) 極差(又稱全距(Range)):是用來表示統計資料中的變異量數(measures of variation) ,其最大值與最小值之間的差距 2) 四分位數間距:四分位距通常是用來構建箱形圖,以及對概率分布的簡要圖表概述 3) 均差 4) 標准差等 3. 基於距離的異常點檢測算法,主要通過距離方法來檢測異常點,將數據集中與大多數點之間距離大於某個閾值的點視為異常點,主要使用的距離度量方法有 1) 絕對距離(曼哈頓距離) 2) 歐氏距離 3) 馬氏距離等方法。 4. 基於密度的異常點檢測算法,考察當前點周圍密度,可以發現局部異常點,例如LOF算法
暴力破解場景中不存在本身是正常程序卻發起對外密集發包的情況,所以不需要進行異常樣本清洗
0x2: 特征采樣
機器學習模型要求正負樣本數量相差不多,而安全事件場景中發生暴力破解的情況畢竟是極少的幾個,所以還要對負樣本進行采樣。不然會導致負樣本(正常情況樣本)主導了參數調優過程,而忽略核心的正樣本的判別效果。
當正樣本數量遠少於負樣本的時候,即使訓練和測試精確率到了99.99%,也可能是因為正樣本被分錯了正好在那0.01%內,而導致整個模型面對真實線上樣本的時候表現非常差
Relevant Link:
https://www.zhihu.com/question/28641663
5. 特征護理 - 特征預處理
通過特征提取,我們能得到未經處理的特征,這時的特征可能有以下問題:
1. 不屬於同一量綱:即特征的取值范圍不一樣,不能夠放在一起比較。無量綱化可以解決這一問題 2. 信息冗余:對於某些定量特征,其包含的有效信息為區間划分,例如學習成績,假若只關心“及格”或不“及格”,那么需要將定量的考分,轉換成“1”和“0”表示及格和未及格。二值化可以解決這一問題 3. 定性特征不能直接使用:某些機器學習算法和模型只能接受定量特征的輸入,那么需要將定性特征轉換為定量特征。最簡單的方式是為每一種定性值指定一個定量值,但是這種方式過於靈活,增加了調參的工作。通常使用啞編碼的方式(即one-hot編碼思路)將定性特征轉換為定量特征 1) 假設有N種定性值,則將這一個特征擴展為N種特征,當原始特征值為第i種定性值時,第i個擴展特征賦值為1,其他擴展特征賦值為0 2) 啞編碼的方式相比直接指定的方式,不用增加調參的工作,對於線性模型來說,使用啞編碼后的特征可達到非線性的效果 4. 存在缺失值:缺失值需要補充 5. 信息利用率低:不同的機器學習算法和模型對數據中信息的利用是不同的,例如在線性模型中,使用對定性特征啞編碼可以達到非線性的效果。類似地,對定量變量多項式化,或者進行其他的轉換,都能達到非線性的效果
我們使用sklearn中的preproccessing庫來進行數據預處理,可以覆蓋以上問題的解決方案。我們來逐一討論下,然后再討論本例中的暴力破解要如何進行特征預處理
進行無量鋼化處理有一點要特別注意,一定要仔細區分“異常點”和“無量鋼化”問題,如果是因為觀測采樣造成的異常點,是不能簡單地進行無量鋼化處理的,否則會影響到樣本本身的概率分布
0x1: sklearn進行特征預處理的編程方法
1. 無量綱化
對於量綱不一致會影響模型訓練效率和效果的問題,可以參閱這篇文章的第一章
無量綱化使不同規格的數據轉換到同一規格,下面我們逐一介紹常用的無量綱化方法
標准化(z-score 標准化(zero-mean normalization))
標准化的前提是特征值服從正態分布,標准化后,其轉換成標准正態分布。標准化需要計算特征的均值和標准差,公式表達為:
使用preproccessing庫的StandardScaler類對數據進行標准化的代碼如下:
from sklearn.preprocessing import StandardScaler #標准化,返回值為標准化后的數據 StandardScaler().fit_transform(iris.data)
z-score標准化方法適用於屬性A的最大值和最小值未知的情況,或有超出取值范圍的離群數據的情況
我們的目的是根據樣本訓練分類器,並不是具體關心樣本內某一個屬性的絕對值,而是關注不同樣本之間的相對值區別,因此z-score標准化不會影響到最后分類器的效果
區間縮放法(歸一化)(min-max標准化(Min-max normalization))
區間縮放法利用了邊界值信息,將特征的取值區間縮放到某個特點的范圍,例如[0, 1]等。區間縮放法的思路有多種,常見的一種為利用兩個最值進行縮放,公式表達為:
使用preproccessing庫的MinMaxScaler類對數據進行區間縮放的代碼如下:
from sklearn.preprocessing import MinMaxScaler #區間縮放,返回值為縮放到[0, 1]區間的數據 MinMaxScaler().fit_transform(iris.data)
正則化(Normalization)
正則化的過程是將每個樣本縮放到單位范數(每個樣本的范數為1),如果后面要使用如二次型(點積)或者其它核方法計算兩個樣本之間的相似性這個方法會很有用。Normalization主要思想是對每個樣本計算其p-范數,然后對該樣本中每個元素除以該范數,這樣處理的結果是使得每個處理后樣本的p-范數等於1。
p-范數的計算公式:||X||p=(|x1|^p+|x2|^p+...+|xn|^p)^1/p
該方法主要應用於文本分類和聚類中。例如,對於兩個TF-IDF向量的l2-norm進行點積,就可以得到這兩個向量的余弦相似性
>>> X = [[ 1., -1., 2.], ... [ 2., 0., 0.], ... [ 0., 1., -1.]] >>> X_normalized = preprocessing.normalize(X, norm='l2') >>> X_normalized array([[ 0.40..., -0.40..., 0.81...], [ 1. ..., 0. ..., 0. ...], [ 0. ..., 0.70..., -0.70...]])
2. 數據變換
常見的數據變換有基於多項式的、基於指數函數的、基於對數函數的
Logistic/Softmax變換(尺度變化函數)
常用於邏輯斯蒂回歸和深度神經網絡中,用於將輸出層結果壓縮到[0,1]的概率區間范圍內。這本質上是一種特征數值壓縮方法
3. 連續特征離散化
對定量特征二值化
定量特征二值化的核心在於設定一個閾值,大於閾值的賦值為1,小於等於閾值的賦值為0,公式表達如下:
使用preproccessing庫的Binarizer類對數據進行二值化的代碼如下:
from sklearn.preprocessing import Binarizer #二值化,閾值設置為3,返回值為二值化后的數據 Binarizer(threshold=3).fit_transform(iris.data)
4. 缺失值處理
缺失值計算
在一般情況下,在一個采集機制良好的系統中,樣本集中不會存在缺失值,缺失值的發生可能在於我們對原始數據進行了一些聚合的join處理后,左/右表出現的缺失值;或者是在cnn圖像處理時在邊緣出現缺失值。這個時候我們需要根據業務場景具體需求補充缺失值,或者采集通用做法補零
0x2: 對於暴力破解識別場景來說需要做哪些特征處理?
對暴力破解場景來說,需要進行特征的問題可能有如下幾個
1. 問題3,在廣播破解模型中,dst_port目標端口這個特征是一個數字,也許需要通過one-hot的思路將其擴展成一定數量的特征,每個特征代表了一個服務類型,例如如果dst_port = 22,即在ssh特征置一,其他置零。但這里問題是目標端口服務可能不可枚舉,會有越來越多的服務加入進來,對建模來說存在困難。這步可以放到模型調優階段去考慮 2. 在一個時間區間內的頻數從十幾到幾千不等,這里需要進行z-score標准化處理,將頻數壓縮到標准正態分布 3. 用於標識使用協議的"tcp"、"udp"需要數值化為1(tcp)和2(udp)
Relevant Link:
http://blog.csdn.net/pipisorry/article/details/52247379 http://www.cnblogs.com/chaosimple/p/4153167.html
6. 特征處理 - 特征選擇
數據預處理完后第一步為分析數據,對數據整體結構有一個大致的把握,每種類型數據有自己特定的分析方式,這里我們將數據分為:
1. 類別型:輸出餅圖,觀察樣本數據分布,做頻繁項分析 2. 連續型(暴力破解頻數也屬於連續型,離散頻數也屬於連續的一種特例):輸出直方圖、KDE圖、CDF圖,做回歸分析 3. 日期型 4. 單詞型:輸出詞頻 5. 文本型
這里以暴力破解為例,打印頻數特征的散點分布圖來觀察樣本特征的空間距離分布,重點考察標准化后樣本數據是否含有一定的正態分布特性
z-score標准化前:
z-score標准化后:
當對數據有一個大致理解后,我們需要選擇有意義的特征輸入機器學習的算法和模型進行訓練。通常來說,從兩個方面考慮來選擇特征:
1. 特征是否發散:如果一個特征不發散,例如方差接近於0,也就是說樣本在這個特征上基本上沒有差異,這個特征對於樣本的區分並沒有什么貢獻 2. 特征與目標的相關性:這點比較顯見,與目標相關性高的特征,應當優選選擇
特征選擇的目標是尋找最優特征子集。特征選擇能剔除不相關(irrelevant)或冗余(redundant )的特征,從而達到減少特征個數,提高模型精確度,減少運行時間的目的。另一方面,選取出真正相關的特征簡化模型,協助理解數據產生的過程。特征選擇的一般過程如下圖所示:
下面討論特征選擇-產生過程和生成特征子集方法
0x1: Filter過濾法 - 與具體模型無關,而只關注自變量和因變量之間的關聯
按照發散性或者相關性對各個特征進行評分,設定閾值或者待選擇閾值的個數,選擇特征
1. 方差/標准差 - 體現發散性的數學評價標准
我們知道,如果一個特征對應的樣本取值發散度越大,說明這個特征在不同樣本間的差異性越明顯,根據該特征訓練得到的分類器效果也越好
使用方差選擇法,先要計算各個特征的方差,然后根據閾值,選擇方差大於閾值的特征。使用feature_selection庫的VarianceThreshold類來選擇特征的代碼如下
# -*- coding: utf-8 -*- from sklearn.feature_selection import VarianceThreshold from sklearn.datasets import load_iris if __name__ == '__main__': iris = load_iris() print "iris.data: ", iris.data[:5] # 方差選擇法,返回值為特征選擇后的數據 # 參數threshold為方差的閾值 res = VarianceThreshold(threshold=3).fit_transform(iris.data) print "VarianceThreshold: ", res[:5] iris.data: [[ 5.1 3.5 1.4 0.2] [ 4.9 3. 1.4 0.2] [ 4.7 3.2 1.3 0.2] [ 4.6 3.1 1.5 0.2] [ 5. 3.6 1.4 0.2]] VarianceThreshold: [[ 1.4] [ 1.4] [ 1.3] [ 1.5] [ 1.4]]
可以看到,設定了方差為3后,鳶尾花的樣本特征中的第三個特征被filter出來,表明第三列這個特征的離散方差最大
2. 相關系數法
使用相關系數法,先要計算各個特征對目標值的相關系數以及相關系數的P值。用feature_selection庫的SelectKBest類結合相關系數來選擇特征的代碼如下
# -*- coding: utf-8 -*- from sklearn.datasets import load_iris from sklearn.feature_selection import SelectKBest from scipy.stats import pearsonr from numpy import * if __name__ == '__main__': iris = load_iris() print "iris.data: ", iris.data[:5] # 選擇K個最好的特征,返回選擇特征后的數據 # 第一個參數為計算評估特征是否好的函數,該函數輸入特征矩陣和目標向量,輸出二元組(評分,P值)的數組,數組第i項為第i個特征的評分和P值。在此定義為計算相關系數 # 參數k為選擇的特征個數 res = SelectKBest(lambda X, Y: tuple(map(tuple,array(list(map(lambda x:pearsonr(x, Y), X.T))).T)), k=2).fit_transform(iris.data, iris.target) print res[:5] iris.data: [[ 5.1 3.5 1.4 0.2] [ 4.9 3. 1.4 0.2] [ 4.7 3.2 1.3 0.2] [ 4.6 3.1 1.5 0.2] [ 5. 3.6 1.4 0.2]] [[ 1.4 0.2] [ 1.4 0.2] [ 1.3 0.2] [ 1.5 0.2] [ 1.4 0.2]]
3. 卡方檢驗
經典的卡方檢驗是檢驗定性自變量對定性因變量的相關性。假設自變量有N種取值,因變量有M種取值,考慮自變量等於i且因變量等於j的樣本頻數的觀察值與期望的差距,構建統計量:
這個統計量的含義簡而言之就是自變量對因變量的相關性。用feature_selection庫的SelectKBest類結合卡方檢驗來選擇特征的代碼如下:
# -*- coding: utf-8 -*- from sklearn.datasets import load_iris from sklearn.feature_selection import SelectKBest from sklearn.feature_selection import chi2 from numpy import * if __name__ == '__main__': iris = load_iris() print "iris.data: ", iris.data[:5] # 選擇K個最好的特征,返回選擇特征后的數據 res = SelectKBest(chi2, k=2).fit_transform(iris.data, iris.target) print "SelectKBest: ", res[:5] iris.data: [[ 5.1 3.5 1.4 0.2] [ 4.9 3. 1.4 0.2] [ 4.7 3.2 1.3 0.2] [ 4.6 3.1 1.5 0.2] [ 5. 3.6 1.4 0.2]] SelectKBest: [[ 1.4 0.2] [ 1.4 0.2] [ 1.3 0.2] [ 1.5 0.2] [ 1.4 0.2]]
可以看到,卡方檢驗得出特征3、4的相關性最大,這和我們用線性模型分析相關R指數的結果一致
4. 互信息法(信息增益)- 信息熵原理
經典的互信息也是評價定性自變量對定性因變量的相關性的,互信息計算公式如下:
為了處理定量數據,最大信息系數法被提出,使用feature_selection庫的SelectKBest類結合最大信息系數法來選擇特征的代碼如下
# -*- coding: utf-8 -*- from sklearn.datasets import load_iris from sklearn.feature_selection import SelectKBest from minepy import MINE from numpy import * #由於MINE的設計不是函數式的,定義mic方法將其為函數式的,返回一個二元組,二元組的第2項設置成固定的P值0.5 def mic(x, y): m = MINE() m.compute_score(x, y) return (m.mic(), 0.5) if __name__ == '__main__': iris = load_iris() print "iris.data: ", iris.data[:5] # 選擇K個最好的特征,返回特征選擇后的數據 res = SelectKBest(lambda X, Y: array(map(lambda x: mic(x, Y), X.T)).T, k=2).fit_transform(iris.data, iris.target) print "SelectKBest: ", res[:5]
0x2: Wrapper包裝法 - 依賴具體模型,通過目標函數來決定是否加入一個特征
根據目標函數(通常是預測效果評分),每次選擇若干特征,或者排除若干特征,即
1. 序列前向選擇( SFS , Sequential Forward Selection ) 從空集開始,每次加入一個選最優。 2. 序列后向選擇( SBS , Sequential Backward Selection ) 從全集開始,每次減少一個選最優。 3. 增L去R選擇算法 ( LRS , Plus-L Minus-R Selection ) 從空集開始,每次加入L個,減去R個,選最優(L>R)或者從全集開始,每次減去R個,增加L個,選最優(L<R)。
關於特征的選取可以參閱這篇文章的回歸變量的選擇與逐步回歸 - 建立多元線性回歸模型前怎么去做特征工程部分的討論
0x3: Embedded集成法 - 學習器自身自動選擇特征
集成法,先使用某些機器學習的算法和模型進行訓練,得到各個特征的權值系數,根據系數從大到小選擇特征。類似於Filter方法,但是是通過訓練模型之后來確定特征的優劣。深度神經網絡的一個很重要的優勢就是算法能在訓練過程中自動選擇特征
1. 基於L1/L2懲罰項的特征選擇法
2. 基於樹模型的特征選擇法
樹模型中GBDT也可用來作為基模型進行特征選擇,使用feature_selection庫的SelectFromModel類結合GBDT模型,來選擇特征的代碼如下:
# -*- coding: utf-8 -*- from sklearn.datasets import load_iris from sklearn.feature_selection import SelectFromModel from sklearn.ensemble import GradientBoostingClassifier from numpy import * if __name__ == '__main__': iris = load_iris() print "iris.data: ", iris.data[:5] # GBDT作為基模型的特征選擇 res = SelectFromModel(GradientBoostingClassifier()).fit_transform(iris.data, iris.target) print "RFE: ", res[:5] iris.data: [[ 5.1 3.5 1.4 0.2] [ 4.9 3. 1.4 0.2] [ 4.7 3.2 1.3 0.2] [ 4.6 3.1 1.5 0.2] [ 5. 3.6 1.4 0.2]] RFE: [[ 1.4 0.2] [ 1.4 0.2] [ 1.3 0.2] [ 1.5 0.2] [ 1.4 0.2]]
0x4: 降維 - 獲取一個和原始特征空間分類效果等價的子特征空間
在一些情況下,可能會出現由於特征矩陣過大,導致計算量大,訓練時間長的問題,因此降低特征矩陣維度也是必不可少的。常見的降維方法有
1. 基於L1懲罰項的模型 2. 主成分分析法(PCA):PCA和LDA有很多的相似點,其本質是要將原始的樣本映射到維度更低的樣本空間中,但是PCA和LDA的映射目標不一樣:PCA是為了讓映射后的樣本具有最大的發散性;而LDA是為了讓映射后的樣本有最好的分類性能。所以說PCA是一種無監督的降維方法,而LDA是一種有監督的降維方法 3. 線性判別分析(LDA):線性判別分析本身也是一個分類模型。
PCA和LDA有很多的相似點,其本質是要將原始的樣本映射到維度更低的樣本空間中,但是PCA和LDA的映射目標不一樣:PCA是為了讓映射后的樣本具有最大的發散性;而LDA是為了讓映射后的樣本有最好的分類性能。所以說PCA是一種無監督的降維方法,而LDA是一種有監督的降維方法。
1. 主成分分析法(PCA)
使用decomposition庫的PCA類選擇特征的代碼如下
# -*- coding: utf-8 -*- from sklearn.datasets import load_iris from sklearn.decomposition import PCA from numpy import * if __name__ == '__main__': iris = load_iris() print "iris.data: ", iris.data[:5] # 主成分分析法,返回降維后的數據 # 參數n_components為主成分數目 res = PCA(n_components=2).fit_transform(iris.data) print res[:5] iris.data: [[ 5.1 3.5 1.4 0.2] [ 4.9 3. 1.4 0.2] [ 4.7 3.2 1.3 0.2] [ 4.6 3.1 1.5 0.2] [ 5. 3.6 1.4 0.2]] PCA: [[-2.68420713 0.32660731] [-2.71539062 -0.16955685] [-2.88981954 -0.13734561] [-2.7464372 -0.31112432] [-2.72859298 0.33392456]]
2. 線性判別分析法(LDA)
使用lda庫的LDA類選擇特征的代碼如下:
# -*- coding: utf-8 -*- from sklearn.datasets import load_iris from sklearn.lda import LDA from numpy import * if __name__ == '__main__': iris = load_iris() print "iris.data: ", iris.data[:5] # 線性判別分析法,返回降維后的數據 # 參數n_components為降維后的維數 res = LDA(n_components=2).fit_transform(iris.data, iris.target) print "PCA: ", res[:5] iris.data: [[ 5.1 3.5 1.4 0.2] [ 4.9 3. 1.4 0.2] [ 4.7 3.2 1.3 0.2] [ 4.6 3.1 1.5 0.2] [ 5. 3.6 1.4 0.2]] PCA: [[-8.0849532 0.32845422] [-7.1471629 -0.75547326] [-7.51137789 -0.23807832] [-6.83767561 -0.64288476] [-8.15781367 0.54063935]]
對於暴力破解這個場景來說,我們提取出的特征數量較少,同時從業務理解上看都和判別有較好的因果關系,因此不需要進行特征選擇步驟
Relevant Link:
https://www.zhihu.com/question/29316149 https://zhuanlan.zhihu.com/p/27076389 http://blog.csdn.net/onlyqi/article/details/50843541 http://blog.csdn.net/onlyqi/article/details/50844826 http://www.cnblogs.com/jasonfreak/p/5448385.html
7. 特征監控
在機器學習任務中,特征非常重要。對於重要的特征進行監控與有效性分析,了解模型所用的特征是否存在問題,當某個特別重要的特征出問題時,需要做好備案,防止災難性結果。需要建立特征有效性的長效監控機制
Relevant Link:
https://tech.meituan.com/machinelearning-data-feature-process.html
Copyright (c) 2017 LittleHann All rights reserved