1、概述
特徵列是原始數據與模型之間進行鏈接的橋樑。一般來說,人工智能的本質是要進行權重與偏置的運算用來確定模型的形態。
在使用之前的tensorflow版本時,都需要預先將數據進行類型、分佈的處理,才能被人工智能模型所使用。而特徵列的出現則使得數據處理的工作變得簡單的多。
2、特徵列的作用
特徵列主要解決對用戶數據進行預處理與特徵化的處理,這種技術的出現主要是原始輸入數據的多樣性。
如下圖所示,您可以通過 Estimator(鳶尾花的 DNNClassifier
)的 feature_columns
參數指定模型的輸入。特徵列在輸入數據(由 input_fn
返回)與模型之間架起了橋樑。
3、使用特徵列
在上面的例子中我們採用如下方式來定義特徵列。
my_feature_columns = []
for key in train_x.keys():
my_feature_columns.append(tf.feature_column.numeric_column(key=key))
print(my_feature_columns)
其中關鍵語句是
tf.feature_column.numeric_column(key=key)
要創建特徵列,請調用 tf.feature_column
模塊的函數。本文檔介紹了該模塊中的九個函數。如下圖所示,所有九個函數都會返回一個 Categorical-Column 或一個 Dense-Column 對象,但卻不會返回 bucketized_column
,後者繼承自這兩個類:
- 數值型的特徵列
tf.numeric_column
(如下所示)也是一種將具有默認數據類型 (tf.float32
) 的數值指定爲模型輸入的不錯方式:
numeric_feature_column = tf.feature_column.numeric_column(key="SepalLength")
要指定一個非默認的數值數據類型,請使用 dtype
參數。例如:
numeric_feature_column = tf.feature_column.numeric_column(key="SepalLength",
dtype=tf.float64)
默認情況下,數值列會創建單個值(標量)。使用 shape 參數指定另一種形狀。例如:
vector_feature_column = tf.feature_column.numeric_column(key="Bowling",shape=10)
matrix_feature_column = tf.feature_column.numeric_column(key="MyMatrix",shape=[10,5])
特徵列
本文檔詳細介紹了特徵列。您可以將特徵列視爲原始數據和 Estimator 之間的媒介。特徵列內容豐富,使您可以將各種原始數據轉換爲 Estimator 可以使用的格式,從而可以輕鬆地進行實驗。
在預創建的 Estimator 中,我們使用預創建的 Estimator (DNNClassifier
) 來訓練模型,根據四個輸入特徵預測不同類型的鳶尾花。該示例僅創建了數值特徵列(類型爲 tf.feature_column.numeric_column
)。雖然數值特徵列有效地對花瓣和花萼的長度進行了建模,但真實的數據集包含各種各樣的特徵,其中很多特徵並非數值。
深度神經網絡的輸入
深度神經網絡可以處理哪類數據?答案當然是數字(例如 tf.float32
)。畢竟,神經網絡中的每個神經元都會對權重和輸入數據執行乘法和加法運算。不過,實際輸入數據通常包含非數值(分類)數據。以一個可包含下列三個非數值的 product_class
特徵爲例:
kitchenware
electronics
sports
機器學習模型一般將分類值表示爲簡單的矢量,其中 1 表示存在某個值,0 表示不存在某個值。例如,如果將 product_class
設置爲 sports
,機器學習模型通常將 product_class
表示爲 [0, 0, 1]
,意即:
0
:kitchenware
不存在0
:electronics
不存在1
:sports
存在
因此,雖然原始數據可以是數值或分類值,但機器學習模型會將所有特徵表示爲數字。
特徵列
如下圖所示,您可以通過 Estimator(鳶尾花的 DNNClassifier
)的 feature_columns
參數指定模型的輸入。特徵列在輸入數據(由 input_fn
返回)與模型之間架起了橋樑。
要創建特徵列,請調用 tf.feature_column
模塊的函數。本文檔介紹了該模塊中的九個函數。如下圖所示,所有九個函數都會返回一個 Categorical-Column 或一個 Dense-Column 對象,但卻不會返回 bucketized_column
,後者繼承自這兩個類:
我們來更詳細地瞭解這些函數。
數值列
鳶尾花分類器會針對所有輸入特徵調用 tf.feature_column.numeric_column
函數:
SepalLength
SepalWidth
PetalLength
PetalWidth
雖然 tf.numeric_column
提供可選參數,但在沒有任何參數的情況下調用 tf.numeric_column
(如下所示)也是一種將具有默認數據類型 (tf.float32
) 的數值指定爲模型輸入的不錯方式:
# Defaults to a tf.float32 scalar.numeric_feature_column = tf.feature_column.numeric_column(key="SepalLength")
要指定一個非默認的數值數據類型,請使用 dtype
參數。例如:
# Represent a tf.float64 scalar.
numeric_feature_column = tf.feature_column.numeric_column(key="SepalLength",
dtype=tf.float64)
默認情況下,數值列會創建單個值(標量)。使用 shape 參數指定另一種形狀。例如:
# Represent a 10-element vector in which each cell contains a tf.float32.vector_feature_column = tf.feature_column.numeric_column(key="Bowling", shape=10)# Represent a 10x5 matrix in which each cell contains a tf.float32.matrix_feature_column = tf.feature_column.numeric_column(key="MyMatrix", shape=[10,5])
- 分桶列
通常,您不會直接向模型饋送數字,相反,您會根據數值範圍將其值分爲不同的類別。爲此,請創建一個分桶列。以表示房屋建造年份的原始數據爲例。我們並非以標量數值列表示年份,而是將年份分成下列四個分桶:
模型將按以下方式表示這些分桶:
爲什麼要將數字(一個完全有效的模型輸入)拆分爲分類值?請注意,該分類將單個輸入數字分成了一個四元素矢量。因此,模型現在可以學習四個單獨的權重,而非僅僅一個;相比一個權重,四個權重能夠創建一個內容更豐富的模型。更重要的是,藉助分桶,模型能夠清楚地區分不同年份類別,因爲僅設置了一個元素 (1),其他三個元素則被清除 (0)。當我們僅將單個數字(年份)用作輸入時,模型只能學習線性關係。因此,分桶爲模型提供了可用於學習的額外靈活性。
以下代碼演示瞭如何創建分桶特徵:
# 首先創建一個原始的數值形式的特徵列 numeric_feature_column = tf.feature_column.numeric_column("Year") # 使用 年份 作爲邊界對數據進行分桶處理 bucketized_feature_column = tf.feature_column.bucketized_column( source_column = numeric_feature_column, boundaries = [1960, 1980, 2000])
- 分類標識列
可將分類標識列視爲分桶列的一種特殊情況。在傳統的分桶列中,每個分桶表示一系列值(例如,從 1960 年到 1979 年)。在分類標識列中,每個分桶表示一個唯一整數。例如,假設您想要表示整數範圍 [0, 4)
。也就是說,您想要表示整數 0、1、2 或 3。在這種情況下,分類標識映射如下所示:
調用 tf.feature_column.categorical_column_with_identity
以實現分類標識列。例如:
identity_feature_column = tf.feature_column.categorical_column_with_identity(
key='my_feature_b',num_buckets=4)
- 分類詞彙列
我們不能直接向模型中輸入字符串。相反,我們必須首先將字符串映射到數值或分類值。分類詞彙列提供了一種將字符串表示爲獨熱矢量的好方法。例如:
您可以看到,分類詞彙列就像是分類標識列的枚舉版本。TensorFlow 提供了兩種不同的函數來創建分類詞彙列:
tf.feature_column.categorical_column_with_vocabulary_list
tf.feature_column.categorical_column_with_vocabulary_file
categorical_column_with_vocabulary_list
根據明確的詞彙表將每個字符串映射到一個整數。例如:
vocabulary_feature_column =
tf.feature_column.categorical_column_with_vocabulary_list(
key="a feature returned by input_fn()",
vocabulary_list=["kitchenware", "electronics", "sports"])
上面的函數非常簡單,但它有一個明顯的缺點。那就是,當詞彙表很長時,需要輸入的內容太多了。對於此類情況,請改爲調用 tf.feature_column.categorical_column_with_vocabulary_file
,以便將各個詞彙放在單獨的文件中。例如:
vocabulary_feature_column =
tf.feature_column.categorical_column_with_vocabulary_file(
key="a feature returned by input_fn()",
vocabulary_file="product_class.txt",
vocabulary_size=3)
product_class.txt
應該讓每個詞彙元素各佔一行。在我們的示例中:
kitchenware
electronics
sports
- 經過哈希處理的列
到目前爲止,我們處理的示例都包含很少的類別。例如,我們的 product_class 示例只有 3 個類別。但是通常,類別的數量非常大,以至於無法爲每個詞彙或整數設置單獨的類別,因爲這會消耗太多內存。對於此類情況,我們可以反問自己:“我願意爲我的輸入設置多少類別?”實際上,
tf.feature_column.categorical_column_with_hash_bucket
函數使您能夠指定類別的數量。對於這種類型的特徵列,模型會計算輸入的哈希值,然後使用模運算符將其置於其中一個 hash_bucket_size
類別中
另外還有其他幾種比較複雜的特徵列,使用場景相對較少