【AI設計模式】01-資料表示-特徵雜湊(Feature Hashed)模式
摘要
資料是機器學習的生命線,對資料的有效管理是AI中重要的工程實踐。在《【AI設計模式】機器學習設計模式概述》中,我們介紹了機器學習領域設計模式的背景,以及設計模式解決的問題等。本篇文章將介紹AI設計模式中的一種資料表示模式 - 特徵雜湊(Feature Hashed)模式,並探討如何使用MindSpore實踐該模式。
模式定義
特徵雜湊是AI設計模式中的一種資料表示模式,能夠有效解決分類資料不完整、高基數(特徵類別不均)、以及冷啟動問題(推理時無法處理新出現的類別)。結合MindSpore提供的資料處理介面,開發者可以很容易的應用該實踐。
問題
機器學習在資料處理時,通常使用
獨熱編碼
(one-hot encoding)的方式將分類資料轉換為數值資料。獨熱編碼是用N個狀態對N個分類資料編碼,這樣在任意時刻,只有一位是有效的。比如,假設我們有6個郵政編碼[1,2,3,4,5,6],然後透過獨熱編碼對這些分類資料進行編碼:
import
numpy
as
np
import
mindspore。dataset。transforms。c_transforms
as
c_transforms
import
mindspore。dataset
as
ds
code
=
[
1
,
2
,
3
,
4
,
5
,
6
]
data
=
np
。
array
(
code
)
# 將結果列表轉為Numpy的陣列
dataset
=
ds
。
NumpySlicesDataset
(
data
,
column_names
=
[
“clz”
],
shuffle
=
False
)
# 基於MindSpore的Dataset介面把Numpy陣列轉為Dataset物件
onehot_op
=
c_transforms
。
OneHot
(
num_classes
=
7
)
# 定義操作,這裡num_class要大於code中最大數的值
dataset
=
dataset
。
map
(
operations
=
onehot_op
,
input_columns
=
[
“clz”
])
# 應用獨熱編碼
for
item
in
dataset
:
(
item
)
執行後可以看到編碼的結果:
[
Tensor
(
shape
=
[
7
],
dtype
=
Int32
,
value
=
[
0
,
1
,
0
,
0
,
0
,
0
,
0
])]
[
Tensor
(
shape
=
[
7
],
dtype
=
Int32
,
value
=
[
0
,
0
,
1
,
0
,
0
,
0
,
0
])]
[
Tensor
(
shape
=
[
7
],
dtype
=
Int32
,
value
=
[
0
,
0
,
0
,
1
,
0
,
0
,
0
])]
[
Tensor
(
shape
=
[
7
],
dtype
=
Int32
,
value
=
[
0
,
0
,
0
,
0
,
1
,
0
,
0
])]
[
Tensor
(
shape
=
[
7
],
dtype
=
Int32
,
value
=
[
0
,
0
,
0
,
0
,
0
,
1
,
0
])]
[
Tensor
(
shape
=
[
7
],
dtype
=
Int32
,
value
=
[
0
,
0
,
0
,
0
,
0
,
0
,
1
])]
這樣可以確保分類資料的輸入的唯一性。
處理分類輸入需要提前知道所有的類別,語言、日期等相對確定的資料很容易處理,而對於比較難預測的資料會存在一些問題:
1。
資料不完整
訓練資料中沒有包含所有的特徵類別。如果訓練資料不完整,可能無法提前獲得所有可能的單詞,導致編碼以後的資料也不完整。比如,針對醫療方面的一些模型,訓練資料的詞彙表中無法包含所有的醫院和醫生資訊。
2。
高基數(某個分類特徵的類別特別多)
單個分類特徵的不同值很多,可能需要長度數百萬的特徵向量, 如IP地址、家庭住址等,導致模型也需要很大空間,無法在小裝置上部署。
3。
冷啟動問題(推理時無法處理新出現的類別)
對於新的分類資料,生產環境中的模型無法正確的預測,會出現錯誤,需要專門的服務來處理這種冷啟動的問題。
解決方案
以參考圖書中預測航班的準點率模型場景為例,美國約有350個機場,機場間的差別會比較大,有些機場航班很多,有些機場航班很少,同時,每年會有新的機場出現。這個場景同時存在了獨熱編碼時的資料不完整、高基數和冷啟動問題。
透過特徵雜湊模式來解決分類資料在
獨熱編碼
存在的問題。具體的操作如下:
將機場的分類資料,把輸入轉化為唯一的字串,如把機場名稱資料改為縮寫並保證資料不重複;
對字串使用穩定可移植(訓練和推理場景都可用)的雜湊演算法進行雜湊;
對雜湊結果取餘數。
透過farmhash演算法,對於這些機場進行雜湊,然後分別放入10,1000個桶中,結果如下:
>>
airports
=
[
“DTW”
,
“LBB”
,
“SNA”
,
“MSO”
,
“ANC”
]
>>>
list
(
map
(
lambda
x
:
farmhash
。
hash64withseed
(
x
,
10
)
%
10
,
airports
))
[
9
,
9
,
4
,
0
,
1
]
>>>
list
(
map
(
lambda
x
:
farmhash
。
hash64withseed
(
x
,
1000
)
%
1000
,
airports
))
[
416
,
532
,
193
,
538
,
971
]
機場縮寫
hash 10
hash 1000
DTW
9
416
LBB
9
532
SNA
4
193
MSO
0
538
ANC
1
971
特徵雜湊如何解決分類資料的問題:
針對資料不完整問題
:即使有些機場資料不在訓練資料集中,但它透過特徵值雜湊後在桶的大小範圍內,不用擔心資料不完整的情況。
針對高基數問題
:透過雜湊的方式可以將資料的規模降低,減少了系統記憶體佔用和模型大小,即便有百萬的資料規模,雜湊後也只會落入到有限的桶中。
針對冷啟動問題
:如果新的分類資料新增到系統中,它在雜湊後落入和其它機場相同的桶,所以不用擔心在生產環境中預測時會出錯的情況。之後透過訓練更新的模型獲得更好的預測。比如,對於350個機場,雜湊桶設定為70,大約每個桶有5個機場,每個桶都有資料,生產環境預測就不會落空,只是預測的資料可能不會特別精確,需要後續訓練來最佳化模型。
案例
這裡沿用了上面提到的預測機場航班準點率的例子,首先對機場資料應用模式,而後透過MindSpore的獨熱編碼介面,完成資料的編碼準備。其中依賴雜湊演算法庫需要透過`pip install pyfarmhash`安裝。
import
farmhash
import
numpy
as
np
import
mindspore。dataset。transforms。c_transforms
as
c_transforms
import
mindspore。dataset
as
ds
airports
=
[
“DTW”
,
“LBB”
,
“SNA”
,
“MSO”
,
“ANC”
,
“ABC”
,
“CDE”
,
“FGH”
]
# 將機場名稱縮寫
hashed_data
=
list
(
map
(
lambda
x
:
farmhash
。
hash64withseed
(
x
,
1000
)
%
4
,
airports
))
# 對字串應用特徵雜湊模式
data
=
np
。
array
(
hashed_data
)
# 將結果列表轉為Numpy的陣列
dataset
=
ds
。
NumpySlicesDataset
(
data
,
column_names
=
[
“airport_name”
],
shuffle
=
False
)
# 基於MindSpore的Dataset介面把Numpy陣列轉為Dataset物件
onehot_op
=
c_transforms
。
OneHot
(
num_classes
=
4
)
# 定義獨熱編碼操作,這裡num_class的數量和桶的數量保持一致
dataset
=
dataset
。
map
(
operations
=
onehot_op
,
input_columns
=
[
“airport_name”
])
# 對機場資訊資料應用編碼
for
item
in
dataset
:
(
item
)
編碼的輸出結果如下:
[
Tensor
(
shape
=
[
4
],
dtype
=
Int32
,
value
=
[
1
,
0
,
0
,
0
])]
[
Tensor
(
shape
=
[
4
],
dtype
=
Int32
,
value
=
[
1
,
0
,
0
,
0
])]
[
Tensor
(
shape
=
[
4
],
dtype
=
Int32
,
value
=
[
0
,
1
,
0
,
0
])]
[
Tensor
(
shape
=
[
4
],
dtype
=
Int32
,
value
=
[
0
,
0
,
1
,
0
])]
[
Tensor
(
shape
=
[
4
],
dtype
=
Int32
,
value
=
[
0
,
0
,
0
,
1
])]
[
Tensor
(
shape
=
[
4
],
dtype
=
Int32
,
value
=
[
0
,
0
,
0
,
1
])]
[
Tensor
(
shape
=
[
4
],
dtype
=
Int32
,
value
=
[
0
,
0
,
1
,
0
])]
[
Tensor
(
shape
=
[
4
],
dtype
=
Int32
,
value
=
[
1
,
0
,
0
,
0
])]
總結
特徵雜湊模式在使用時有它適用的場景,它的主要問題是損失了模型精度。特徵雜湊模式不適合分類資料明確,詞彙表大小相對較小(1000量級),並且不存在冷啟動的場景。取模是有損操作,特徵雜湊模式將不同的分類放到了同一個桶中,損失了資料的準確性。在分類的資料特別不平衡時,會導致推理的誤差比較大。比如榆林機場的流量比較小,西安機場的流量比它大兩個量級,如果它們被放到同一個桶中,當成一種編碼處理。模型的結果將更偏向於西安的場景,導致對於起飛等待時間等預測出現偏差。
有兩種方式可以緩解模式造成的模型精度損失,可以在實踐時考慮應用:
新增聚合特徵
:如果分類變數的分佈偏斜,或者桶的數量少導致衝突多,可以透過新增聚合特徵作為模型的輸入來緩解。比如,對於每個機場,都可以在訓練資料集中找到準時航班的機率,並將其作為一個特徵新增到模型中。避免在雜湊機場程式碼時丟失與個別機場相關的資訊。在某些情況下,可以完全避免將機場名稱作為一個特徵,因為有航班準點的相對頻率資料可能就夠了。
把桶的數量作為超參來調整,以達到精度的平衡。
在下一篇,我們講介紹資料表示的嵌入模式(Embeddings)。
參考
1。 《Machine Learning Design Patterns》
上一篇:【AI設計模式】機器學習設計模式概述