AWS機器學習 — 特徵工程
在機器學習(以下簡稱ML)的各階段中,其中一個最重要的就是特徵工程(Feature Engineering)。在本文中,我們將介紹不同類型資料集的特徵功能的一些關鍵概念,並描述一些主要在幫助產生特徵(feature)和AWS 工具。
特徵工程概念
我們在之前的AWS機器學習的其他文章中有討論到針對ML的資料的收集與準備階段。這通常會伴隨著資料轉換(data transformation)作業,像是轉變資料型態或格式(Apache Parquet to CSV)或使用SQL query來執行data aggregation,例如 merge/join dataset或 grouping有相關columns的data。以上這些步驟都完成後,這個dataset中相關的row/columns就可以使用在我們的ML模型中。
不過,資料仍然可能不是完全準備好用於ML演算法中。ML演算法的input是數字或數字向量,我們準備的資料集可能仍包含categorical values 或missing values,例如missing row。它也許包含離群值,這很有可能會扭曲我們的模型,特別是離群值沒有很多的狀況下。本文中,我們將會討論如何轉換我們的資料,或結合多個columns的資料變成是一個特徵,而這個特徵是可以讓ML演算法使用的。
特徵工程是一門藝術,資料科學家採用的許多常見特徵工程策略通常來自經驗,而不是精確的數學方法。 我們將在本文中討論使用不同資料集進行特徵工程的最常見策略。
資料類型決定了我們將如何設計特徵。 大多數特徵工程工具和技術都適用於表格資料。 我們還將簡要介紹可用於Text和Image資料以及時間序列(time series)資料的策略。
表格資料的特徵工程
以下是一些表格資料集所需的最常見的特徵工程類型:
(1)Duplicate Data
作為最佳實踐,刪除我們資料集中可能存在的任何重複data/row。 稍後,我們將討論training dataset和testing dataset之間的data leakage,以及duplicates資料如何增加資料集中data leakage的風險。
(2)Normalization
Normalization應用於我們資料集中的columns,這些columns是數字。 想像我們有一個資料集,我們試圖在其中預測房價,我們有一個column表示臥室總數,另一columns表示平均坪數。 雖然臥室的總數大多在 2到8間之間,但坪數可以在幾十到幾百之間。 然而,對於ML演算法來說,都是簡單的數字,對於使用gradient descent的演算法,數字的大小會影響梯度的step size。 這可能會導致covergence issues,最終生成精確度較低的模型。 Normalization只是將所有特徵縮放到 [0, 1] 之間。
(3)Standardization
Normalization的一個相關技術是Standardization,我們不是將所有特徵限制在 [0, 1] 之間,而是將所有值集中在具有unit standard deviation column的平均值周圍。 當我們的資料具有常態分佈或接近常態分佈時,Standardization是有效的。
小提示:
不是所有的演算法都對standardization/normalization是靈敏的。線性與邏輯回歸演算法的正確性與收斂(convergence)是可以用這兩種方法強化的,然而tree-based演算法就不哪麼具靈敏性了。這是因為tree-based演算法是根據每一個feature分配到每一個node的。因此,每一個node之間都不受彼此影響。
(4)Outlier Detection
離群值是一個data point,而這一個data point是超出一定數量個標準差(通常大概是2或3個)。離群值的挑戰在於我們通常在資料集中沒有足夠多的離群值來讓ML模型達到有意義的學習,這反過來意味著 ML 模型不能很好地概括(generalize)離群值。
或者,在我們的資料集中保留離群值也會扭曲我們的模型,因為模型可能會調整其權重以更好地預測離群值,這反過來又會降低模型在大多數data point 上的整體效能。
以下是一些通常我們會用來應對離群值的策略:
1.Outlier Removal
這是最簡單的方式,消除掉有著一定數量的標準差的data point。
2.Log Transformation
假如我們的資料分布是高度偏斜的並且有很多的離群值,我們可以考慮使用log transformation來轉換我們的資料分布更加像常態分佈並且在哪之後使用standardization。常一般常用的Python Library或 NumPy, 我們可以使用 log1p 函數來達成,如下圖。
(5).Label Encoding
在處理分類變量(categorical variables)時,我們可以考慮兩種策略。 Label encoding是指簡單地用整數標記categorical column中的唯一值。 例如,如果我們有一個分類特徵,例如 Day_of_Week ,我們可以做 {“Monday”: 1, “Tuesday”: 2, “Wednesday”:3 等等}。 Label encoding的主要優點是它的簡單性,特別是當我們有大量唯一的分類值時。 主要的缺點是演算法可能會錯誤地解釋Label encoding,以表示一個值顯示出另一個值的好壞。 例如,3 大於 2,但星期三並不“大於”星期二。
(6).One-Hot encoding
而為了避免Label encoding的問題,一個比較好的方式是使用one-hot encoding categorical values。在這個狀況下,我們可以將每一個value轉換為它自己的column並根據該 row是否具有這個value來給予 1 或 0的值。one-hot encoding的主要效益是它可以避免像label encoding的錯誤性的解釋。然而,假如我們有很多的categroical value(在整個美國有很多的郵遞區號或很多顏色的型態)在我們的資料集,這樣one-hot encoding會產生一個非常大的feature matrix。這樣我們就需要提高我們電腦運算能力來達成在一個有著大量columns的模型訓練。
(7) Binary Encoding
另一個常見的encoding策略,特別是我們分類式的columns的值只有”yes” or “No”,這時經常會用這種binary encoding。這種方式很像label encoding,而encode會像是這樣 {“value_1”:0, “value_2”:1}
(8)處理缺失值
一個我們在dataset常處理的狀況是缺失值,它可能在一個或多個columns中的row是沒資料的。根據缺失值的數量,我們有以下一些對應策略:
- 收集更多的資料 — 最好的方法是收集更多的資料。然而現實中這可能是代價很高或是很耗時。在這種狀況下就要使用別的方法。
- Drop Column — 如果有columns的缺失值已占了資料的大部分,移掉這個columns可能最簡單的方法。
- Constant Imputation — 如果缺失值是很小量的,一個好的應對方式是執行替換,其中我們的“替換”用column 整個value的平均值或中位數甚至是出現最多的值替換缺失值。對於具有常態分佈的columns,我們也許可以考慮使用平均值替換。中位數是比較適合已經偏斜的column分布。這種方式不適合我們的資料中有大量的缺失值,因為這樣做會對整體資料產生偏差。
- 監督式學習 — 我們也可以根據資料集中的其他row value來訓練一個ML模型預測其他的value。這個方式可以消除因為我們使用替換的方式(不論是平均值或中位數)所可能帶來的資料偏差並保有這一個column。但代價是我們要花額外的運算能力,因為我們等於又要訓練一個模型來做這件事。
(9).Label Sampling
在一些比較特定的問題上,label value本身可能存在很大的不平衡。一個普遍的例子是詐欺偵測,這是因為詐欺的資料遠遠少於非詐欺的資料,在這樣的狀況下我們有以下五種方式可以對應:
- 收集更多的資料 — 這是比較好對應我們只有少量的label data的方法。然而這樣的方法很多時候是代價高昂或是耗時的。所以通常會用一些替代方法。
- Downsampling — 我們可以通過簡單地刪除具有多數標籤的row的一小部分來對多數類別進行downsample以嘗試產生更平衡的資料集。這裡的多數類別是指具有最多value的標籤。 當我們有大量資料時,downsampling是一個很好的策略,因此我們可以減少多數example的數量。
- Upsampling — 這是上一個做法的相反,這個方法是針對少量類別的資料去增加data point(replicate row),藉此平衡整個資料集。這個方式的好處是當我們的資料不夠大到可以做downsampling,不過這樣做通常會帶出其他的問題,因為我們只是簡單的copy同樣的資料在同一個資料集中。
- SMOTE(Synthetic Minority Oversampling Technique) — 這是使用非監督式學習來產生少量類別的資料。SMOTE 適用於特徵數量遠遠超過樣本數量的情況。 SMOTE 取少數標籤類別中的一個data point,並首先提取 k-nearest neighbors。 然後它通過在其中一個neighbor和data point之間取一個向量並將其乘以一個隨機數來產生一個新的data point。
- Weighting — 這是另一種對不平衡的資料集進行加權技術修改loss function,對錯誤分類少數標籤的演算法進行更多一種懲罰方式。這個方式避免了對資料進行donwsampling 或upsampling。
(10) Data Splitting
最後,要訓練一個ML模型,我們需要將資料分割成training, validation, and testing data或者training , testing data兩種。通常來說,資料科學家會將資料分類的比例分成80–10–10(training-validation-testing)或 80–20(training-testing)。在訓練階段我們也常用到像是 k-fold cross-validation,我們通過將資料分成 k 個偶數分割(稱為folds)來訓練 k 個模型。 然後我們在folds1 到folds k-1 上訓練模型 1,並在折folds k 上驗證模型; folds 2到 folds k 上的模型 2 並在 fold1 上驗證,模型 3 在folds 1、3到 k 上並在folds 2 上測試,依此類推。k-fold cross-validation 方式在小型的資料集使用很普遍,但是卻不適合在大型資料集上這麼做,因為這等於我們對資料集訓練 k次,因此會有k 次的代價產生,而這通常花費很高。
不管如何,我們是至少要將dataset分成 train 與 test sets。一個好的作法是,test set應該保留原始的label distribution(要進行資料加工前)以便它模仿我們的真實生產數據。通常使用在訓練時提供給我們的演算法的第三個validation dataset來評估我們的模型在訓練期間的效能是很常見的。 作為一般規則,除非我們已經完成訓練,否則不要在我們的模型上使用我們的測試資料集。
小提示:
一種常見的錯誤是data leakage,這是將某些 test data 洩漏到training dataset。作為最佳實踐,我們希望不惜一切代價避免這種情況,因為為了評估我們的模型,我們需要確保它從未看過test data。 只有這樣,我們才能真正確定模型的效能。一種常見會發生這種狀況是在 normalization/standardization 時期。
正確的作法是,先把資料分成train/test data然後再normalize/standardize。 normalize training data之後,使用這些normalization score(像是平均值或標準差)去normalize測試資料。
非結構化與time series資料的特徵工程
我們將簡介這兩種類型資料的特徵工程:
Data Augmentation
通常,在處理image data時,我們可能希望擴充資料以為我們的模型提供更多example。 有許多不同的增強image data的方法,例如旋轉image、翻轉image、向image添加更多random noise。 改變亮度,垂直或水平移動image,或放大或縮小等。 流行的 ML library Keras 提供了一個方便的data preprocessing class(詳情可參考此篇文件),我們可以使用它來預處理我們的image。 對於 image labeling 問題,由於這些轉換都不會改變資料的標籤,我們可以在為我們的模型提供更多特定標籤的example的同時增加我們的資料。
Windowed Splitting of Time Series Data
針對時間序列問題,我們經常需要在具有真實標籤的歷史資料上測試我們的模型。 例如,假設我們正在建立一個模型來預測股票價格。 一旦我們的模型經過訓練,我們就可以在歷史股票價格上對其進行測試,我們知道股票是上漲還是下跌。這種方式通常被稱為 回測(backtesting)。
為了正確回測 time series資料,我們不能使用簡單的k-fols cross validation 方式,原因是我們不能隨機分割一個單一的time series,因為每一個time series的資料的 time intervals是不同的。在這個情況下,我們應該使用一種策略,首先選擇一個prediction windows(下圖中的四條bar的斜線部分)。 然後我們取time series的一個windows(實心部分)並在prediction windows上進行預測。 我們延伸我們的prediction windows以包括前一個prediction windows,再次訓練模型,並預測下一個prediction。
NLP(Natural Language Processing)的預處理 — NLP 模型在輸入模型之前通常需要大量的預處理。 Word2Vec 或 BERT 等模型依賴於token,因此首先需要對資料進行tokenization。Tokenization是指將dataset拆分為構成 vocabulary一部分的單個單詞或label。 然後在 vocabulary中為每個單詞分配一個數值,這個 vocabulary通常被分類為key value pairs字典。 根據每個token的value將句子轉換為數字序列。
其他常見的text preprocessing技術包括去除停用詞,例如“is”、“and”和“the”; 去除頻繁或極其罕見的詞; 將所有text更改為小寫; 詞幹(stemming); 和詞形還原(lemmatization)。 詞幹是指將派生詞轉換為其詞根形式或詞幹。 例如,單詞“organize”、“oreganizes”都可以轉換為“organize”。 詞形還原是一種將單詞轉換為其詞元的相關技術。 詞形還原具有依賴於上下文的好處; 例如,“better”這個詞的引理是 “good”。 我們在應用詞幹提取或詞形還原時應該小心,因為它們往往會影響模型的效能。 根據Standford NLP 小組的說法。 詞幹提取可以提高模型recall,但會損害precision(更多stemming與lemmatization資訊可參考此篇文件)。
AWS Feature Engineering工具
我們在AWS機器學習 — 資料準備階段這一篇介紹了兩個針對特徵工程的big data tool: AWS EMR 與AWS Glue。Glue是一個Serverless ETL 工具。我們只要把我們的 Python, Scala或PySpark的代碼放上去執行就可以,並且將執行結果放到S3 bucket中。而使用EMR,我們則可以spin up我們的EMR cluster並submit Spark jobs到cluster來處理大規模運算的資料。
在2020年時,AWS釋出了新的feature engineering的工具,叫做 Glue Data Brew(幾乎不用寫代碼)。Glue Data Brew是一款視覺化的資料準備工具,我們在這一款工具中可以視覺化/清理/normalize我們的資料,還可以使用超過250個transformation來執行特徵工程轉換作業而不必寫任何的代碼。我們還可以組合這一些transformation成為一個菜單,並且之後可以根據這一個菜單定期或按需求來執行成為單一作業。因為Glue Data Brew只接與Glue Data Catalog整合,它支援數種資料來源,包括如S3、Redshift、RDS、Aurora並提供第三方Data warehouse(如Snowflake) 連接器。
同年,SageMaker在SageMaker Studio中也推出一個新服務稱為Data Wrangler,這可以從S3或Redshift拉資料。Data Wrangler提供類似的 UI 功能和 300 個以上的transforms,以及使用我們自己的代碼編寫自定義transforms的能力。Data Wrangler 還允許我們在沒有代碼的資料子集上快速構建 ML 模型以獲得baseline model。 與 Data Wrangler類似,一旦我們對我們的特徵工程覺得ok了,我們就可以建立一個流水線(pipeline)並將engineering steps作為對整個dataset的處理作業來運行。
總結
在本文中,我們討論到不同的特徵工程技術,是一般的資料孤城都會使用到的。我們還討論了如何插補(impute)資料,處理缺失值,與處理 categorical features跟imbalanced data。另外最重要的如何分割我們的dataset在training, validuation與test sets。我們簡略的提到AWS哪一些tool可以幫助我們執行特徵工程作業。