這一節主要介紹一下TensorFlow在應用的過程當中的幾個小的知識點,第一個是關於features的處理的,例如Bucketized (Binned) Features 和 Feature scalling。第二個是簡單的介紹一下經常使用的幾個Optimizer之間的區別,例如SGD, Adagrad, Adam等等。這裏主要是對前面一節的內容的一個小補充。其實關於feature的處理,我在前面已經用了很長一段時間在講了,可是基本都是基於sklearn的框架來處理的,雖然前面我們說了不少不少,可是總有漏網之魚嘛,那就是Binned features,我們這裏就用TensorFlow來解釋而且應用。還有一個部分就是optimizer,我們前面說了一個SGD的應用,這一節我準備簡單講述一下另外兩個經常使用的optimizer,他們分別是Adagrad, Adam,我會簡單說一下它們之間的優缺點以及應用場景。git
Features engineering我們在前面講述了不少不少,而且都用sklearn演示了他們的應用和實現過程。這裏補充一下Binned features的知識點,具體什麼是Binned features呢?它其實很簡單就是將我們的數據按大小順序分紅n 個bins, 或者這裏能夠理解成n個quantiles, 而後我們將每個bin的boundary記錄下來放到一個list裏面,最後將我們的數據在應用到這個bin裏面,看看我們的每個數據屬於哪個bin,咱的的結果是按照bin的大小從小到大一次是0,1,2,................這樣。我們能夠看一個簡單的實例算法
boundaries = [0, 10, 100] input tensor = [[-5, 10000] [150, 10] [5, 100]]
output以下框架
output = [[0, 3] [3, 2] [1, 3]]
從上面的一個簡單的實例我們看出,我們的原始數據的範圍很是大,我們能夠根據boundaries這個list來將他們分紅4個bins, 最後再來看我們的原始數據屬於哪個bin。上面的是一個簡單的例子,那麼接下來我們來看看具體的代碼實現過程。若是我們須要將一個seriesbucketized,那麼整個bucketized的過程其實分紅三個部分,即分別是建立boundary,將series轉成numerical_column,和最後的bucketized三個部分;我們看下面函數
def get_quantile_based_boundaries(series,num_bucket): quantiles = np.arange(1.0,num_bucket)/num_bucket boundaries = series.quantile(quantiles)#the index are the quantiles return [boundaries[key] for key in boundaries.keys()]
上面的這個函數的目的就是根據quantile來找到每個bin的boundary;而後我們須要將我們的series轉成一個numerical_column,以下所示優化
house_median_age_numeric_column = tf.feature_column.numeric_column("housing_median_age")
其實這一個就是聲明我們的這一個column的類型,既然是按照大小來分配到不一樣的bin, 那麼我們這一列的數據確定得是數字型的。既然我們有了boundary, 也有了numeric_column, 那麼接下來就是bucketized啦,以下所示spa
bucketized_house_median_age = tf.feature_column.bucketized_column(source_column=house_median_age_numeric_column, boundaries = get_quantile_based_boundaries(series=cali_housing_dataset_permutation["housing_median_age"],num_bucket=10)
)
這裏我們就聲明而且完成了一個column的bucketized的過程,而後我們就是能夠將這個bucketized_column傳遞給模型的feature_column參數。我們就完成了一個column的bucketized的整個過程。code
補充:在這裏我們在補充一個小知識點,那就是既然我們實例化了一個bucketized feature_column對象,而且告訴了我們的模型,那麼我們如何獲取我們的這個bucketized後的feature_column的值呢??簡單點就是,我們怎麼知道bucketized_house_median_age這個轉化後的值呢?其實很簡單,我直接上代碼,你們能夠直接拿出來用哈對象
def demo(feature_column): feature_layer = tf.keras.layers.DenseFeatures(feature_column) print(feature_layer(dict(cali_housing_dataset_permutation)).numpy())
我們直接調用上面的函數就能打印出我們想要的值了,以下blog
[[0. 0. 0. ... 0. 1. 0.] [0. 0. 0. ... 0. 0. 0.] [0. 0. 0. ... 1. 0. 0.] ... [0. 0. 0. ... 0. 0. 0.] [0. 0. 1. ... 0. 0. 0.] [0. 0. 0. ... 1. 0. 0.]]
這裏我們也能夠看出來bucketized事後,我們的feature會轉成one-hot encoding的方式。element
在我們的sklearn中的feature generation中已經介紹了cross_features的相關信息,在sklearn中我們能夠直接將categorical data或者numerical data進行cross操做而且生成一個新的feature, 而且將它進行一個新的feature進行一些feature engineering中的相應的操做。其實在TensorFlow中我們也有相應的方法進行操做,TensorFlow中有專門的cross_feature來進行操做,而且將返回的cross_feature告訴我們的模型,這是一個cross feature;在這裏我們也能夠看出來TensorFlow的牛逼之處,那就是他只須要告訴我們的模型我們的如何操做每一列的數據,而不像在sklearn中的那樣,須要我們本身去label encoding 等一些列複雜的feature engineering的操做。可是凡事都是有好有壞的,TensorFlow中隱藏了不少feature engineering中的不少細節部分也致使我們不能理解一些操做的底層原理,不利於我們優化我們的feature engineering的過程。其實總結起來就是說TensorFlow在cross_feature方面只須要我們聲明一下某幾個features須要cross而且告訴一下模型就能夠了,而不須要我們真的去一步步的cross我們的數據生成一個新的feature從而改變了我們的原始的dataframe。具體在我們的TensorFlow中,feature cross有多簡單呢,我們看下面的就能夠了
lon_x_lat = tf.feature_column.crossed_column(keys=[bucketized_longitude, bucketized_latitude],
hash_bucket_size = 1000)
注意上面的keys是一個list,這個list裏面的元素只能夠是string或者是categorical feature type的feature_column, 這裏的element若是是string的話,咱們就會用這些string相對應的feature來cross(一樣的,這些feature的data type也必需要是string);若是是categorical feature type的話,我們就會直接用這些數據進行cross。這裏有個小細節哈就是feature type和data type的區別,初學者常常會混淆,feature type只有2中categorical和numerical, 而data type則有多是int float string等等,當data type是int 或者 float的時候,那麼它的feature type則不必定是numerical,也有多是categorical,例如我們上面的bucketized columns雖然data type是int,可是它仍是categorical data type。
在我們訓練模型的過程當中,常常會碰到選擇optimizer的狀況,實際中這一塊沒有最好只有更好。通常狀況下每一種optimizer都有本身的優缺點,適合不一樣的應用場景。我今天主要講一下三個經常使用的optimizer,分別是SGD, Adagrad和Adam。首先SDG是我們最傳統的一種計算梯度降低的算法, 它除了消耗的資源有點大外,沒啥大毛病,幾乎適用於全部的convex 的場景;Adagrad是一種改進的算法,它的learning rate並非固定的,它的learning rate可以根據我們數據的大小來改變的,它在convex problem中的表現很是好,可是在non-convex的場景中,表現的很差;Adam經常使用於non-convex的場景,它在non-convex中的表現要好於SGD和Adagrad。