文章目錄

.

一 特徵工程介紹(Feature Engineering)


什麼是特徵工程?
特徵工程解決了什麼問題?
為什麼特徵工程對機器學習很重要?
怎麼做特徵工程?
怎麼做好特徵工程?
集眾多博友智慧,一文全面瞭解並應用特徵工程。

1 定義及意義

(1)定義

  • 特徵工程(Feature Engineering)特徵工程是將原始資料轉化成更好的表達問題本質的特徵的過程,使得將這些特徵運用到預測模型中能提高對不可見資料的模型預測精度。
  • 特徵工程簡單講就是發現對因變數y有明顯影響作用的特徵,通常稱自變數x為特徵,特徵工程的目的是發現重要特徵。
  • 如何能夠分解和聚合原始資料,以更好的表達問題的本質?這是做特徵工程的目的。

“feature engineering is manually designing what the input x’s should be.”
“you have to turn your inputs into things the algorithm can understand.”

  • 特徵工程是資料探勘模型開發中最耗時、最重要的一步。

(2)意義

  • 特徵工程是一個包含內容很多的主題,也被認為是成功應用機器學習的一個很重要的環節。如何充分利用資料進行預測建模就是特徵工程要解決的問題!

“實際上,所有機器學習演算法的成功取決於如何呈現資料。”
“特徵工程是一個看起來不值得在任何論文或者書籍中被探討的一個主題。但是他卻對機器學習的成功與否起著至關重要的作用。機器學習演算法很多都是由於建立一個學習器能夠理解的工程化特徵而獲得成功的。”——ScottLocklin,in “Neglected machine learning ideas”

  • 資料中的特徵對預測的模型和獲得的結果有著直接的影響。可以這樣認為,特徵選擇和準備越好,獲得的結果也就越好。這是正確的,但也存在誤導。預測的結果其實取決於許多相關的屬性:比如說能獲得的資料、準備好的特徵以及模型的選擇。
    在這裡插入圖片描述

(3)相關概念

Feature:An attribute useful for your modeling task.
Feature Selection:From many features to a few that are useful
Feature Extraction:The automatic construction of new features from raw data.
Feature Construction:The manual construction of new features from raw data.
Feature Importance:An estimate of the usefulness of a feature.

1)特徵與屬性的區別?

並不是所有的屬性都可以看做特徵,區分它們的關鍵在於看這個屬性對解決這個問題有沒有影響!可以認為特徵是對於建模任務有用的屬性。
表格式的資料是用行來表示一個例項,列來表示屬性和變數。每一個屬性可以是一個特徵。特徵與屬性的不同之處在於,特徵可以表達更多的跟問題上下文有關的內容。特徵是一個對於問題建模有意義的屬性。我們使用有意義(有用的)來區別特徵和屬性,認為如果一個特徵沒有意義是不會被認為是特徵的,如果一個特徵對問題沒有影響,那就不是這個問題的一部分。在計算機視覺領域,一幅影象是一個物件,但是一個特徵可能是影象中的一行;在自然語言處理中每一個文件或者一條微博是一個物件,一個短語或者單詞的計數可以作為特徵;在語音識別中,一段聲音是一個例項,一個特徵可能是單個詞或者發音。

2)什麼是特徵重要性?

特徵重要性,可以被認為是一個選擇特徵重要的評價方法。特徵可以被分配一個分值,然後按照這個分值排序,那些具有較高得分的特徵可以被選出來包含在訓練集中,同時剩餘的就可以被忽略。特徵重要性得分可以幫助我們抽取或者構建新的特徵。挑選那些相似但是不同的特徵作為有用的特徵。
如果一個特徵與因變數(被預測的事物)高度相關,那麼這個特徵可能很重要。相關係數和其他單變數的方法(每一個變數被認為是相互獨立的)是比較通用的評估方法。
更復雜的方法是通過預測模型演算法來對特徵進行評分。這些預測模型內部有這樣的特徵選擇機制,比如MARS,隨機森林,梯度提升機。這些模型也可以得出變數的重要性。

2 流程及方法

特徵工程的定義形形色色,筆者同樣對特徵工程的全流程有著自己的理解。下面三幅圖是比較常見的特徵工程流程,可以參考,便於理解。跟深入瞭解特徵工程,還是需要在廣泛學習的基礎上對其有充分的自我理解。

  • 1.圖一是基本的資料探勘場景

在這裡插入圖片描述

  • 2.圖二是特徵工程的迭代過程
    在這裡插入圖片描述
  • 3.圖三是特徵工程的常見方法和步驟 在這裡插入圖片描述

二 資料獲取


要實現特徵工程目標,要用到什麼資料?需要結合特定業務,具體情況具體分析。
重點考慮如下三方面:
①資料獲取途徑

  • 如何獲取特徵(介面呼叫or自己清洗or/github資源下載等)
  • 如何儲存?(/data/csv/txt/array/Dataframe//其他常用分散式)

②資料可用性評估

  • 獲取難度
  • 覆蓋率
  • 準確率

③特徵維度

三 資料描述(Feature Describe)


通過資料獲取,我們得到未經處理的特徵,這時的特徵可能有以下問題:

  • 存在缺失值:缺失值需要補充。
  • 不屬於同一量綱:即特徵的規格不一樣,不能夠放在一起比較。
  • 資訊冗餘:對於某些定量特徵,其包含的有效資訊為區間劃分,例如學習成績,假若只關心“及格”或不“及格”,那麼需要將定量的考分,轉換成“1”和“0”表示及格和未及格。
  • 定性特徵不能直接使用:某些機器學習演算法和模型只能接受定量特徵的輸入,那麼需要將定性特徵轉換為定量特徵。
  • 資訊利用率低:不同的機器學習演算法和模型對資料中資訊的利用是不同的。

那麼最好先對資料的整體情況做一個描述、統計、分析,並且可以嘗試相關的視覺化操作。主要可分為以下幾方面:

1 資料結構

2 質量檢驗

標準性、唯一性、有效性、正確性、一致性、缺失值、異常值、重複值

3 分佈情況

統計值

包括max, min, mean, std等。python中用pandas庫序列化資料後,可以得到資料的統計值。

探索性資料分析(EDA,Exploratory Data Analysis)

集中趨勢、離中趨勢、分佈形狀

四 特徵處理(Feature Processing)


對資料的整體性有一個巨集觀的瞭解之後,即需要進入特徵工程第一個重要的環節——特徵處理,特徵處理會消耗大量時間,並且直接影響特徵選擇的結果。
特徵處理主要包括:
①資料預處理。即資料的清洗工作,主要為缺失值、異常值、錯誤值、資料格式、取樣度等問題的處理。
②特徵轉換。即連續變數、離散變數、時間序列等的轉換,便於入模。

1 資料預處理

【特徵工程】python特徵預處理大全

(1)缺失值處理

有些特徵可能因為無法取樣或者沒有觀測值而缺失.例如距離特徵,使用者可能禁止獲取地理位置或者獲取地理位置失敗,此時需要對這些特徵做特殊的處理,賦予一個缺失值。我們在進行模型訓練時,不可避免的會遇到類似缺失值的情況,下面整理了幾種填充空值的方法

1)缺失值刪除(dropna)

①刪除例項
②刪除特徵

2)缺失值填充(fillna)

①用固定值填充

對於特徵值缺失的一種常見的方法就是可以用固定值來填充,例如0,9999, -9999, 例如下面對灰度分這個特徵缺失值全部填充為-99

data['灰度分'] = data['灰度分'].fillna('-99')
②用均值填充

對於數值型的特徵,其缺失值也可以用未缺失資料的均值填充,下面對灰度分這個特徵缺失值進行均值填充

data['灰度分'] = data['灰度分'].fillna(data['灰度分'].mean()))
③用眾數填充

與均值類似,可以用未缺失資料的眾數來填充缺失值

data['灰度分'] = data['灰度分'].fillna(data['灰度分'].mode()))
④用上下資料進行填充
  • 用前一個數據進行填充
data['灰度分'] = data['灰度分'].fillna(method='pad')
  • 用後一個數據進行填充
data['灰度分'] = data['灰度分'].fillna(method='bfill')
⑤用插值法填充
data['灰度分'] = data['灰度分'].interpolate()
⑥用KNN進行填充
from fancyimpute import BiScaler, KNN, NuclearNormMinimization, SoftImpute
dataset = KNN(k=3).complete(dataset)
⑦random forest進行填充
from sklearn.ensemble import RandomForestRegressor
zero_columns_2 = ['機構查詢數量', '直接聯絡人數量', '直接聯絡人在黑名單數量', '間接聯絡人在黑名單數量',
                '引起黑名單的直接聯絡人數量', '引起黑名單的直接聯絡人佔比']
#將出現空值的除了預測的列全部取出來,不用於訓練                
dataset_list2 = [x for x in dataset if x not in zero_columns_2]
dataset_2 = dataset[dataset_list2]
# 取出灰度分不為空的全部樣本進行訓練
know = dataset_2[dataset_2['灰度分'].notnull()]
print(know.shape) #26417, 54
# 取出灰度分為空的樣本用於填充空值
unknow = dataset_2[dataset_2['灰度分'].isnull()]
print(unknow.shape) #2078, 54
y = ['灰度分']
x = [1]
know_x2 = know.copy()
know_y2 = know.copy()
print(know_y2.shape)
#
know_x2.drop(know_x2.columns[x], axis=1, inplace=True)
print(know_y2.shape)
print(know_x2.shape)
#
know_y2 = know[y]
# RandomForestRegressor
rfr = RandomForestRegressor(random_state=666, n_estimators=2000, n_jobs=-1)
rfr.fit(know_x2, know_y2)
# 填充為空的樣本
unknow_x2 = unknow.copy()
unknow_x2.drop(unknow_x2.columns[x], axis=1, inplace=True)
print(unknow_x2.shape) #(2078, 53)
unknow_y2 = rfr.predict(unknow_x2)
unknow_y2 = pd.DataFrame(unknow_y2, columns=['灰度分'])                
⑧使用fancyimpute包中的其他方法
# matrix completion using convex optimization to find low-rank solution
# that still matches observed values. Slow!
X_filled_nnm = NuclearNormMinimization().complete(X_incomplete)
# Instead of solving the nuclear norm objective directly, instead
# induce sparsity using singular value thresholding
X_filled_softimpute = SoftImpute().complete(X_incomplete_normalized)
# print mean squared error for the three imputation methods above
nnm_mse = ((X_filled_nnm[missing_mask] - X[missing_mask]) ** 2).mean()
# print mean squared error for the three imputation methods above
nnm_mse = ((X_filled_nnm[missing_mask] - X[missing_mask]) ** 2).mean()
print("Nuclear norm minimization MSE: %f" % nnm_mse)
softImpute_mse = ((X_filled_softimpute[missing_mask] - X[missing_mask]) ** 2).mean()
print("SoftImpute MSE: %f" % softImpute_mse)
knn_mse = ((X_filled_knn[missing_mask] - X[missing_mask]) ** 2).mean()
print("knnImpute MSE: %f" % knn_mse)
⑨缺失值作為資料的一部分不填充

LightGBM和XGBoost都能將NaN作為資料的一部分進行學習,所以不需要處理缺失值。

(2)異常值處理

1)特徵異常平滑

  • 基於統計的異常點檢測演算法
    例如極差,四分位數間距,均差,標準差等,這種方法適合於挖掘單變數的數值型資料。
  • 基於距離的異常點檢測演算法
    主要通過距離方法來檢測異常點,將資料集中與大多數點之間距離大於某個閾值的點視為異常點,主要使用的距離度量方法有絕對距離(曼哈頓距離)、歐氏距離和馬氏距離等方法。
  • 基於密度的異常點檢測演算法
    考察當前點周圍密度,可以發現區域性異常點。

(3)重複值處理

根據需求判斷是否需要去重操作

(4)資料格式處理

  • 數字型別的轉換
  • 數字單位的調整
  • 時間格式的處理

(5)資料取樣

多的類別過取樣/少的類別欠取樣來平衡分佈欠取樣(undersampling)和過取樣(oversampling)會對模型帶來不一樣的影響。

2 特徵轉換

特徵也就是我們常常說的變數/自變數,一般分為三類:

  • 連續型
  • 無序類別(離散)型
  • 有序類別(離散)型

主要轉換方式有以下幾種:
在這裡插入圖片描述

(1)連續型特徵處理

1)函式轉換

有時我們的模型的假設條件是要求自變數或因變數服從某特殊分佈(如正太分佈),或者說自變數或因變數服從該分佈時,模型的表現較好。這個時候我們就需要對特徵或因變數進行非線性函式轉換。這個方法操作起來很簡單,但記得對新加入的特徵做歸一化。對於特徵的轉換,需要將轉換之後的特徵和原特徵一起加入訓練模型進行訓練。

2)特徵縮放

某些特徵比其他特徵具有較大的跨度值。舉個例子,將一個人的收入和他的年齡進行比較,更具體的例子,如某些模型(像嶺迴歸)要求你必須將特徵值縮放到相同的範圍值內。通過縮放可以避免某些特徵比其他特徵獲得大小非常懸殊的權重值。

3)無量綱化

無量綱化使不同規格的資料轉換到同一規格。常見的無量綱化方法有標準化、歸一化、區間縮放法。標準化的前提是特徵值服從正態分佈,標準化後,其轉換成標準正態分佈。區間縮放法利用了邊界值資訊,將特徵的取值區間縮放到某個特點的範圍,例如[0, 1]等。
把資料放縮到同樣的範圍 SVM/NN影響很大 樹模型影響小。不是什麼時候都需要標準化,比如物理意義非常明確的經緯度,如果標準化,其本身的意義就會丟失。

①標準化
· 均值方差法
· z-score標準化
· StandardScaler標準化

標準化是依照特徵矩陣的列處理資料,其通過求z-score的方法,將樣本的特徵值轉換到同一量綱下。標準化需要計算特徵的均值和標準差,公式表達為:
在這裡插入圖片描述
使用preproccessing庫的StandardScaler類對資料進行標準化的程式碼如下:

from sklearn.preprocessing import StandardScaler
#標準化,返回值為標準化後的資料
StandardScaler().fit_transform(iris.data)
②歸一化
· 最大最小歸一化(最常用)
· 對數函式轉換(log)
· 反餘切轉換

歸一化是依照特徵矩陣的行處理資料,其目的在於樣本向量在點乘運算或其他核函式計算相似性時,擁有統一的標準,也就是說都轉化為“單位向量”。規則為l2的歸一化公式如下:
在這裡插入圖片描述
使用preproccessing庫的Normalizer類對資料進行歸一化的程式碼如下:

from sklearn.preprocessing import Normalizer
#歸一化,返回值為歸一化後的資料
Normalizer().fit_transform(iris.data)
③區間縮放法

區間縮放法的思路有多種,常見的一種為利用兩個最值進行縮放,公式表達為:
在這裡插入圖片描述
使用preproccessing庫的MinMaxScaler類對資料進行區間縮放的程式碼如下:

from sklearn.preprocessing import MinMaxScaler
#區間縮放,返回值為縮放到[0, 1]區間的資料
MinMaxScaler().fit_transform(iris.data)
壓縮範圍
有些分類變數的少部分取值可能佔據了90%的case,這種情況下可以採用預測模型、領域專家、或者簡單的頻率分佈統計。具體問題具體分析,高頻和低頻都是需要特別處理的地方,拋棄效果不好時,可以考慮取樣(高頻)或上取樣(低頻),加權等等方法。

4)二值化(定量特徵)

特徵的二值化處理是將數值型資料輸出為布林型別。其核心在於設定一個閾值,當樣本書籍大於該閾值時,輸出為1,小於等於該閾值時輸出為0。我們通常使用preproccessing庫的Binarizer類對資料進行二值化處理。
定量特徵二值化的核心在於設定一個閾值,大於閾值的賦值為1,小於等於閾值的賦值為0,公式表達如下:
在這裡插入圖片描述
使用preproccessing庫的Binarizer類對資料進行二值化的程式碼如下:

from sklearn.preprocessing import Binarizer
 #二值化,閾值設定為3,返回值為二值化後的資料
Binarizer(threshold=3).fit_transform(iris.data)

5)離散化分箱處理(數值型轉類別型)

有時候,將數值型屬性轉換成類別型更有意義,同時將一定範圍內的數值劃分成確定的塊,使演算法減少噪聲的干擾。
在實際應用中,當你不想讓你的模型總是嘗試區分值之間是否太近時,分割槽能夠避免過擬合。例如,如果你所感興趣的是將一個城市作為整體,這時你可以將所有落入該城市的維度值進行整合成一個整體。
分箱也能減小錯誤的影響,通過將一個給定值劃入到最近的塊中。
對於一些特殊的模型(信用評分卡)開發,有時候我們需要對連續型的特徵(年齡、收入)進行離散化。
常用的離散化方法包括等值劃分和等量劃分。例如某個特徵的取值範圍為[0,10],我們可以將其劃分為10段,[0,1),[1,2),⋯,[9,10)

  • 離散特徵的增加和減少都很容易,易於模型的快速迭代;
  • 稀疏向量內積乘法運算速度快,計算結果方便儲存,容易擴充套件;
  • 離散化後的特徵對異常資料有很強的魯棒性模型也會更穩定;
  • 離散化後可以進行特徵交叉,由M+N個變數變為M*N個變數,進一步引入非線性 提 升表達能力;
  • 特徵離散化以後,起到了簡化了邏輯迴歸模型的作用,降低了模型過擬合的風險

離散化方法的關鍵是怎麼確定分段中的離散點,下面介紹幾種常用的離散化方法:

  • 等距離離散(等距分組)
    顧名思義,就是離散點選取等距點。
  • 等樣本點離散(等深分組)
    選取的離散點保證落在每段裡的樣本點數量大致相同
  • 決策樹離散化(最優分組)
    決策樹離散化方法通常也是每次離散化一個連續特徵,原理如下:
    單獨用此特徵和目標值y訓練一個決策樹模型,然後把訓練獲得的模型內的特徵分割點作為離散化的離散點。
  • 其他離散化方法
    其中,最優分組除決策樹方法以外,還可以使用卡方分箱的方法,這種方法在評分卡開發中比較常見。

6)不處理

除了歸一化(去中心,方差歸一),不用做太多特殊處理,可以直接把連續特徵扔到模型裡使用。根據模型型別而定。

(2)離散型特徵處理

1)數值化處理

二分類問題:能夠將類別屬性轉換成一個標量,最有效的場景應該就是二分類的情況。即{0,1}對應{類別1,類別2}。這種情況下,並不需要排序,並且你可以將屬性的值理解成屬於類別1或類別2的概率。
多分類問題:選取多分類,編碼到[0,classnum)。
類別不平衡問題:樣本層面可以採用oversampling/undersampling. 演算法層面可以採用代價敏感方法/樣本設定權重
也不是所有的無序變數都需要做數值化處理,決策樹、隨機森林等樹模型可能不需要處理,視情況而定。

例:label encoder
一個變數的k個值,按序轉換成k個數字(1,2,3…k)。例如一個人的狀態status有三種取值:bad, normal, good,顯然bad < normal < good。這個時候bad, normal, good就可以分別轉換成 1、2、3。該方法侷限性較大:

  • 不適用於建立預測具體數值的模型,比如線性迴歸,只能用於分類,
  • 即使用於分類,也有一些模型不適合,
  • 可能結果的精度不如one-hot編碼。

2)啞編碼

①獨熱編碼(one-hot)

例:
再次舉一個簡單的例子,由{紅,綠、藍}組成的顏色屬性,最常用的方式是把每個類別屬性轉換成二元屬性,即從{0,1}取一個值。因此基本上增加的屬性等於相應數目的類別。對於資料集中的每個例項,只有一個是1(其他的為0),這也就是獨熱(one-hot)編碼方式(類似於轉換成啞變數)。
如果你不瞭解這個編碼的話,你可能會覺得分解會增加沒必要的麻煩(因為編碼大量的增加了資料集的維度)。相反,你可能會嘗試將類別屬性轉換成一個標量值,例如顏色屬性可能會用{1,2,3}表示{紅,綠,藍}。這裡存在兩個問題,首先,對於一個數學模型,這意味著某種意義上紅色和綠色比和藍色更“相似”(因為|1-3| > |1-2|)。除非你的類別擁有排序的屬性(比如鐵路線上的站),這樣可能會誤導你的模型。然後,可能會導致統計指標(比如均值)無意義,更糟糕的情況是,會誤導你的模型。還是顏色的例子,假如你的資料集包含相同數量的紅色和藍色的例項,但是沒有綠色的,那麼顏色的均值可能還是得到2,也就是綠色的意思。

啞編碼主要是採用N位狀態暫存器來對N個狀態進行編碼,一個變數N個值就轉換成N個虛擬變數,每個狀態都由他獨立的暫存器位,並且在任意時候只有一位有效。
使用one-hot編碼,將離散特徵的取值擴充套件到了歐式空間,離散特徵的某個取值就對 應歐式空間的某個點。
在迴歸,分類,聚類等機器等學習演算法中,特徵之間距離的計算或相似度的計算是 非常重要的,而我們常用的距離或相似度的計算都是在歐式空間的相似度計算,計算 餘弦相似性,基於的就是歐式空間。

優點:
簡單,且保證無共線性。
將離散型特徵使用one-hot編碼,確實會讓特徵之間的距離計算更加合理。
對離散型特徵進行one-hot編碼可以加快計算速度。
缺點:太稀(稀疏矩陣)
避免產生稀疏矩陣的常見方法是降維,將變數值較多的分類維度,儘可能降到最少,能降則降,不能降的,別勉強。

②順序性啞變數

與one-hot編碼一樣,都是將一個變數的k個值生成k個啞變數,但同時保護了特徵的順序關係。一般的表達方式如下:
在這裡插入圖片描述
(上面這種表達方式很巧妙地利用遞進表達了值之間的順序關係。)

(3)時間序列處理

1)時間戳處理

時間戳屬性通常需要分離成多個維度比如年、月、日、小時、分鐘、秒鐘。但是在很多的應用中,大量的資訊是不需要的。比如在一個監督系統中,嘗試利用一個’位置+時間‘的函式預測一個城市的交通故障程度,這個例項中,大部分會受到誤導只通過不同的秒數去學習趨勢,其實是不合理的。並且維度’年’也不能很好的給模型增加值的變化,我們可能僅僅需要小時、日、月等維度。因此在呈現時間的時候,試著保證你所提供的所有資料是你的模型所需要的。並且別忘了時區,假如你的資料來源來自不同的地理資料來源,別忘了利用時區將資料標準化。

五 特徵選擇(Feature Selection)


1 特徵檢驗

(1)單變數

1)正態性檢驗

2)顯著性分析

(2)多變數

1)一致性檢驗

2)多重共線性

2 特徵選擇

(1)定義

從大量的特徵中選擇少量的有用特徵。
不是所有的特徵都是平等的。那些與問題不相關的屬性需要被刪除;還有一些特徵可以比其他特徵更重要;也有的特徵跟其他的特徵是冗餘的。特徵選擇就是自動地選擇對於問題最重要的特徵的一個子集。
在這裡插入圖片描述

(2)作用

  • 簡化模型,增加模型的可解釋性
  • 縮短訓練時間
  • 避免維度災難
  • 改善模型通用性、降低過擬合

(3)方法

判斷特徵是否發散:如果一個特徵不發散,就是說這個特徵大家都有或者非常相似,說明這個特徵不需要。
判斷特徵和目標是否相關:與目標的相關性越高,越應該優先選擇。
按照特徵評價標準分類:
選擇使分類器的錯誤概率最小的特徵或者特徵組合。
利用距離來度量樣本之間相似度。
利用具有最小不確定性(Shannon熵、Renyi熵和條件熵)的那些特徵來分類。
利用相關係數, 找出特徵和類之間存在的相互關係;
利用特徵之間的依賴關係, 來表示特徵的冗餘性加以去除。

  • 特徵選擇演算法可以利用得分排序的方法選擇特徵,如相關性和其他特徵重要性手段;
  • 更高階的方法通過試錯來搜尋特徵子集。這些方法通過建立模型,評價模型,然後自動的獲得對於目標最具預測能力的特徵子集。
  • 還有一些演算法能得到特徵選擇的副產品。比如說逐步迴歸就是能夠自動的選擇特徵來構建模型。
  • 正則化的方法比如lasso和嶺迴歸可以作為特徵選擇的演算法。他們在構建模型的過程中刪去或者減小不重要特徵的貢獻。(An Introduction to feature selection)

在這裡插入圖片描述

根據特徵選擇的形式可以將特徵選擇方法分為3種:

  • Filter:過濾法,按照發散性或者相關性對各個特徵進行評分,設定閾值或者待選擇閾值的個數,選擇特徵。
  • Wrapper:包裝法,根據目標函式(通常是預測效果評分),每次選擇若干特徵,或者排除若干特徵。
  • Embedded:嵌入法,先使用某些機器學習的演算法和模型進行訓練,得到各個特徵的權值係數,根據係數從大到小選擇特徵。類似於Filter方法,但是是通過訓練來確定特徵的優劣。
    在這裡插入圖片描述

1)過濾式(Filter)

過濾式特徵選擇的評價標準從資料集本身的內在性質獲得,與特定的學習演算法無關,因此具有較好的通用性。通常選擇和類別相關度大的特徵或者特徵子集。過濾式特徵選擇的研究者認為,相關度較大的特徵或者特徵子集會在分類器上獲得較高的準確率。過濾式特徵選擇的評價標準分為四種,即距離度量、資訊度量、關聯度度量以及一致性度量。
優點:演算法的通用性強;省去了分類器的訓練步驟,演算法複雜性低,因而適用於大規模資料集;可以快速去除大量不相關的特徵,作為特徵的預篩選器非常合適。
缺點:由於演算法的評價標準獨立於特定的學習演算法,所選的特徵子集在分類準確率方面通常低於Wrapper方法。

①方差選擇法

使用方差選擇法,先要計算各個特徵的方差,選擇方差大於閾值的特徵 (Analysis of Variance:ANOVA,方差分析,通過分析研究不同來源的變異對總變異的貢獻大小,從而確定可控因素對研究結果影響力的大小)。

 from sklearn.feature_selection import VarianceThreshold
#方差選擇法,返回值為特徵選擇後的資料
#引數threshold為方差的閾值
VarianceThreshold(threshold=3).fit_transform(iris.data)

在這裡插入圖片描述

②相關係數法

使用相關係數法,先要計算各個特徵對目標值的相關係數以及相關係數的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)

皮爾遜係數只能衡量線性相關性而互資訊係數能夠很好地度量各種相關性,但是計算相對複雜一些,好在很多toolkit裡邊都包含了這個工具(如sklearn的MINE),得到相關性之後就可以排序選擇特徵了 (皮爾遜相關係數,更多反應兩個服從正態分佈的隨機變數的相關性,取值範圍在 [-1,+1] 之間。)

③互資訊法

計算各個特徵的資訊增益
Linear Discriminant Analysis(LDA,線性判別分析):更 像一種特徵抽取方式,基本思想是將高維的特徵影到最佳鑑別向量空間,這樣就可以抽取分類資訊和達到壓縮特徵空間維數的效果。投影后的樣本在子空間有最大可分離性。
經典的互資訊也是評價定性自變數對定性因變數的相關性的,互資訊計算公式如下:
在這裡插入圖片描述
為了處理定量資料,最大資訊係數法被提出,使用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)
④卡方檢驗(Chi-Square)

就是統計樣本的實際觀測值與理論推斷值之間的偏離程度,實際觀測值與理論推斷值之間的偏離程度就決定卡方值的大小,卡方值越大,越不符合;卡方值越小,偏差越小,越趨於符合。
優點: 快速, 只需要基礎統計知識。
缺點:特徵之間的組合效應難以挖掘。
經典的卡方檢驗是檢驗定性自變數對定性因變數的相關性。假設自變數有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)

在這裡插入圖片描述

特點:
執行時間短(+):一般不會在資料集上進行迭代計算,且是分類器無關的,相比於訓練分類器要快。
一般性(+):評價資料中屬性的本身的性質,而不是屬性與特定分類器的關聯關係(適合程度),所以得到的結果更具有一般性,而且對於很多分類器都能表現“良好”。
選擇大規模子集(-):傾向於選擇全部最優的特徵子集,導致決定停止的條件決定權交給了使用者,具有較強的主觀性

2)封裝式(Wrapper)

Wrapper:封裝式特徵選擇是利用學習演算法的效能評價特徵子集的優劣。因此,對於一個待評價的特徵子集,Wrapper方法需要訓練一個分類器,根據分類器的效能對該特徵子集進行評價。Wrapper方法中用以評價特徵的學習演算法是多種多樣的,例如決策樹、神經網路、貝葉斯分類器、近鄰法、支援向量機等等。
優點:相對於Filter方法,Wrapper方法找到的特徵子集分類效能通常更好。缺點:Wrapper方法選出的特徵通用性不強,當改變學習演算法時,需要針對該學習演算法重新進行特徵選擇;由於每次對子集的評價都要進行分類器的訓練和測試,所以演算法計算複雜度很高,尤其對於大規模資料集來說,演算法的執行時間很長。
在這裡插入圖片描述
基於目標函式
在這裡插入圖片描述

①完全搜尋[窮舉]
· 遞迴特徵消除法

遞迴消除特徵法使用一個基模型來進行多輪訓練,每輪訓練後,消除若干權值係數的特徵,再基於新的特徵集進行下一輪訓練。使用feature_selection庫的RFE類來選擇特徵的程式碼如下:

· 遞迴特徵消除法遞迴消除法

使用基模型(如LR)在訓練中進行迭代,選擇不同 特徵
構建單個特徵的模型,通過模型的準確性為特徵排序,藉此來選擇特徵

②啟發式搜尋[貪心]
· 前向選擇法

從0開始不斷向模型加能最大限度提升模型效果的特徵資料用以訓練,直到任何訓練資料都無法提升模型表現。

· 後向剃除法

先用所有特徵資料進行建模,再逐一丟棄貢獻最低的特徵來提升模型效果,直到模型效果收斂。
優點: 直接面向演算法優化, 不需要太多知識。缺點: 龐大的搜尋空間, 需要定義啟發式策略。

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)
③隨機搜尋[策略+好運氣]

Wrapper特點:
準確性(+):由於特徵子集是針對特定的分類器調準,能獲得較好的識別率。
泛化能力(+):有很多機制可以防止過擬合,例如在分類器中可以使用交叉驗證等技術。
執行速度(-):對於每個候選的特徵子集,必須重新訓練一個分類器甚至多個分類器(交叉驗證),所以對於計算密集型非常不適合。
一般性(-):由於此種方法對分類器敏感,而不同的分類器具有不同原理的評價函式(損失函式),只能說最終選擇特徵子集是對當前分類器“最好”的。

3)嵌入式(Embedded)

在嵌入式特徵選擇中,特徵選擇演算法本身作為組成部分嵌入到學習演算法裡。最典型的即決策樹演算法,如ID3、C4.5以及CART演算法等,決策樹演算法在樹增長過程的每個遞迴步都必須選擇一個特徵,將樣本集劃分成較小的子集,選擇特徵的依據通常是劃分後子節點的純度,劃分後子節點越純,則說明劃分效果越好,可見決策樹生成的過程也就是特徵選擇的過程。
嵌入法Embedded(效果最好速度最快,模式單調,快速並且效果明顯, 但是如何引數設定, 需要深厚的背景知識。)
在模型既定的條件下,尋找最優特徵子集

  • 正則化項( L1、L2 )
  • LASSO迴歸
  • 嶺迴歸(RidgeRegression)
  • 決策樹
  • ID3、C4.5、CART
  • 深度學習
    在這裡插入圖片描述
①基於懲罰項

使用帶懲罰項的基模型,除了篩選出特徵外,同時也進行了降維。
使用帶懲罰項的基模型進行特徵選擇
比如LR加入正則。通過L1正則項來選擇特徵:L1正則方法具有稀疏解的特性,因此天然具備特徵選擇的特性,但是要注意,L1沒有選到的特徵不代表不重要,原因是兩個具有高相關性的特徵可能只保留了一個,如果要確定哪個特徵重要應再通過L2正則方法交叉檢驗
使用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)
②基於樹模型

基於樹模型的特徵選擇法
樹模型中GBDT也可用來作為基模型進行特徵選擇,使用feature_selection庫的SelectFromModel類結合GBDT模型,來選擇特徵的程式碼如下:訓練能夠對特徵打分的預選模型:RandomForest和Logistic Regression等都能對模型的特徵打分,通過打分獲得相關性後再訓練最終模型;

  • Lasso
  • Elastic Net
  • Ridge Regression
    優點: 快速, 並且面向演算法。缺點: 需要調整結構和引數配置, 而這需要深入的知識和經驗。
 from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import GradientBoostingClassifier
#GBDT作為基模型的特徵選擇
SelectFromModel(GradientBoostingClassifier()).fit_transform(iris.data, iris.target)
③深度學習

目前這種手段正在隨著深度學習的流行而成為一種手段,尤其是在計算機視覺領域,原因是深度學習具有自動學習特徵的能力,這也是深度學習又叫unsupervised feature learning的原因。從深度學習模型中選擇某一神經層的特徵後就可以用來進行最終目標模型的訓練了。
在特徵學習中,K-means演算法可以將一些沒有標籤的輸入資料進行聚類,然後使用每個類別的質心來生成新的特徵。

3 特徵構造

(1)定義

從原始資料中構造新特徵
在機器學習或者統計學中,又稱為變數選擇、屬性選擇或者變數子集選擇,是在模型構建中,選擇相關特徵並構成特徵子集的過程。
根據已有特徵生成新特徵,增加特徵的非線性。常見的資料變換有基於多項式的、基於指數函式的、基於對數函式的。
特徵工程中引入的新特徵,需要驗證它確實能提高預測得準確度,而不是加入一個無用的特徵增加演算法運算的複雜度。
特徵重要性和特徵選擇可以告訴你特徵的效用。你需要構造新的特徵出來。這要求你在樣本資料上花費大量的時間並且思考問題的本質,資料的結構,以及怎麼最好的在預測模型中利用他們。

(2)作用

對於表格型資料,通常對特徵進行混合聚集,組合或者分解分割來創造新的特徵;
對於文字資料通常需要設計特定的與問題相關的文件指標;
對於影象資料通常需要花費大量時間指示過濾器發現相關的特徵。
這部分就是人們通常認為的特徵工程最具藝術性的部分。這是一個漫長的部分,需要耗費大量的腦力和時間,並可以產生巨大的不同。

(3)方法

1)簡單構造

①四則運算

比如原來的特徵是x1和x2,那麼x1+x2就是一個新的特徵,或者當x1大於某個數c的時候,就產生一個新的變數x3,並且x3=1,當x1小於c的時候,x3=0,所以這樣看來呢,可以按照這種方法構造出很多特徵,這個就是構造。

②特徵交叉(組合分類特徵)

交叉特徵算是特徵工程中非常重要的方法之一了,它是將兩個或更多的類別屬性組合成一個。當組合的特徵要比單個特徵更好時,這是一項非常有用的技術。數學上來說,是對類別特徵的所有可能值進行交叉相乘。假如擁有一個特徵A,A有兩個可能值{A1,A2}。擁有一個特徵B,存在{B1,B2}等可能值。然後,A&B之間的交叉特徵如下:{(A1,B1),(A1,B2),(A2,B1),(A2,B2)},並且你可以給這些組合特徵取任何名字,但是需要明白每個組合特徵其實代表著A和B各自資訊協同作用。一個更好地詮釋好的交叉特徵的例項是類似於(經度,緯度)。一個相同的經度對應了地圖上很多的地方,緯度也是一樣。但是一旦你將經度和緯度組合到一起,它們就代表了地理上特定的一塊區域,區域中每一部分是擁有著類似的特性。

③分解類別特徵

對於一個特徵item_color有‘red’、‘green’、‘unknown’三個取值,那麼可以創造一些新的特徵例如:

  • 二值特徵has_color: 1知道具體顏色,0表示不知道。這個可以替換item_color特徵用到更簡單的線性模型中。
  • 三個二值特徵is_red、is_green和is_unknown。這個可以新增到原有特徵中用到決策樹模型中。
④重構數值量

單位轉換
整數部分與小數部分分離
構造範圍二值特徵
構造階段性的統計特徵
構造其他二值特徵

⑤分解Datatime
⑥視窗變數統計

2)機器學習

①監督式學習
②非監督式學習

4 特徵提取

(1)定義

可能由於特徵矩陣過大,一些樣本如果直接使用預測模型演算法可能在原始資料中有太多的列被建模,導致計算量大,訓練時間長的問題,因此降低特徵矩陣維度也是必不可少的。特徵提取是一個自動化的降維過程。使得特徵太多的樣本被建模的維數降低。

(2)作用

最大限度地降低資料的維度的前提下能夠同時保證保留目標的重要的資訊,特徵提取涉及到從原始屬性中自動生成一些新的特徵集的一系列演算法,降維演算法就屬於這一類。特徵提取是一個自動將觀測值降維到一個足夠建模的小資料集的過程。
​ 資料降維有以下幾點好處:
​ 1、避免維度災難,導致演算法失效,或者時間複雜度高
​ 2、避免高維資料中引入的噪聲,防止過擬合
​ 3、壓縮儲存,視覺化分析

(3)方法

對於列表資料,可使用的方法包括一些投影方法,像主成分分析和無監督聚類演算法。
對於圖形資料,可能包括一些直線檢測和邊緣檢測,對於不同領域有各自的方法。
特徵提取的關鍵點在於這些方法是自動的(只需要從簡單方法中設計和構建得到),還能夠解決不受控制的高維資料的問題。大部分的情況下,是將這些不同型別資料(如圖,語言,視訊等)存成數字格式來進行模擬觀察。
​ 不同的資料降維方法除了實現降維目標的作用,同時具有各自的特點,比如