Tensorflow 利用tf.contrib.learn建立輸入函數(shù)的方法
在實際的業(yè)務(wù)中,可能會遇到很大量的特征,這些特征良莠不齊,層次不一,可能有缺失,可能有噪聲,可能規(guī)模不一致,可能類型不一樣,等等問題都需要我們在建模之前,先預(yù)處理特征或者叫清洗特征。那么這清洗特征的過程可能涉及多個步驟可能比較復(fù)雜,為了代碼的簡潔,我們可以將所有的預(yù)處理過程封裝成一個函數(shù),然后直接往模型中傳入這個函數(shù)就可以啦~~~
接下來我們看看究竟如何做呢?
1. 如何使用input_fn自定義輸入管道
當使用tf.contrib.learn來訓(xùn)練一個神經(jīng)網(wǎng)絡(luò)時,可以將特征,標簽數(shù)據(jù)直接輸入到.fit(),.evaluate(),.predict()操作中。比如在筆記04中就使用到了,復(fù)看一下代碼:
# 將特征與標簽數(shù)據(jù)載入 training_set = tf.contrib.learn.datasets.base.load_csv_with_header( filename=IRIS_TRAINING, target_dtype=np.int, features_dtype=np.float32) test_set = tf.contrib.learn.datasets.base.load_csv_with_header( filename=IRIS_TEST, target_dtype=np.int, features_dtype=np.float32) # 然后將兩個數(shù)據(jù)喂給.fit()函數(shù)去訓(xùn)練 classifier.fit(x=training_set.data, y=training_set.target, steps=2000)
當原始數(shù)據(jù)不需要或幾乎很少需要一些額外的預(yù)處理時,使用以上的方式到也不為過。然而在實際的業(yè)務(wù)中我們往往需要去做大量的特征工程,于是tf.contrib.learn支持使用一個用戶自定義的輸入函數(shù)input_fn來封裝數(shù)據(jù)預(yù)處理的邏輯,并且將數(shù)據(jù)通過管道輸送到模型中。
1.1 解剖input_fn函數(shù)的結(jié)構(gòu)
以下是一個input_fn函數(shù)的基本結(jié)構(gòu):
def my_input_fn(): # Preprocess your data here...(首先預(yù)處理你的數(shù)據(jù)) # ...then return 1) a mapping of feature columns to Tensors with # the corresponding feature data, and 2) a Tensor containing labels # 然后返回新的特征數(shù)據(jù)與標簽數(shù)據(jù)(都是以tensor的形式) return feature_cols, labels
輸入函數(shù)的主體包括一個特定的預(yù)處理輸入數(shù)據(jù)的邏輯,比如去除一些臟數(shù)據(jù),彌補缺失數(shù)據(jù),歸一化等等。
輸入函數(shù)的返回是兩個部分:
(1)處理后的特征:feature_cols,格式是一個map,key是特征的名稱,value是tensor形式的對應(yīng)的特征列數(shù)據(jù)
(2)標簽數(shù)據(jù):labels,一個包含標簽數(shù)據(jù)的tensor
1.2 如何將特征數(shù)據(jù)轉(zhuǎn)換成tensors形式
如果你的特征/標簽是存儲在pandas的dataframe中或者numpy的array中的話,你就需要在返回特征與標簽的時候?qū)⑺鼈冝D(zhuǎn)換成tensor形式哦~那么怎么轉(zhuǎn)換呢,來看一個小例子。
對于連續(xù)型數(shù)據(jù),你可以使用tf.constant創(chuàng)建一個tensor:
feature_column_data = [1, 2.4, 0, 9.9, 3, 120] feature_tensor = tf.constant(feature_column_data)
對于稀疏型數(shù)據(jù),類別下數(shù)據(jù),你可以使用tf.SparseTensor來創(chuàng)建tensor:
sparse_tensor = tf.SparseTensor(indices=[[0,1], [2,4]], values=[6, 0.5], dense_shape=[3, 5])
可見,tf.SparseTensor有3個參數(shù),分別是:
(1)dense_shape
這是tensor的shape,比如dense_shape=[3,6],表示tensor有3*6共2個維度;dense_shape=[2,3,4]表示tensor有2*3*4共3個維度;dense_shape=[9]表示tensor有1個維度,這個維度里有9個元素。
(2)indices
表示在這個tensor中indices索引所在的位置是非0值,其余都是0值。比如[0,0]表示在第1行第1列的值非0.
(3)values
value是一個1維的tensor, 其元素與indices中的索引一一對應(yīng),比如indices=[[1,3], [2,4]],values=[18, 3.6],表示在行索引為1列索引為3的位置值為18,在行索引為2列索引為4的位置值為3.6
因此上面的代碼意思一目了然了,創(chuàng)建一個稀疏tensor,大小是3*5,在行索引為0列索引為1的位置值為6,在行索引為2,列索引為4的位置值為0.5,其余位置值為0.
打印出來應(yīng)是:
[[0, 6, 0, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0.5]]
1.3 如何將input_fn數(shù)據(jù)傳給模型
在輸入函數(shù)input_fn中封裝好了特征預(yù)處理的邏輯,并且也返回了新的特征與標簽。那怎么把這個輸入函數(shù)或者說新的特征與標簽傳入模型中呢?
在.fit()操作中有一個參數(shù):input_fn,只要將我們定義好的輸入函數(shù)傳給這個參數(shù)即可:
classifier.fit(input_fn=my_input_fn, steps=2000)
但是,極其注意的是絕不能直接這樣做:
classifier.fit(input_fn=my_input_fn(training_set), steps=2000)
如果你想直接傳參數(shù)給輸入函數(shù),可以選擇令愛幾個方法:
(1)再寫一個封裝函數(shù)如下:
def my_input_function_training_set(): return my_input_function(training_set) classifier.fit(input_fn=my_input_fn_training_set, steps=2000)
(2)使用Python's functools.partial方法:
classifier.fit(input_fn=functools.partial(my_input_function, data_set=training_set), steps=2000)
(3)在lambda中調(diào)用輸入函數(shù),然后將參數(shù)傳入input_fn中
classifier.fit(input_fn=lambda: my_input_fn(training_set), steps=2000)
個人建議使用第三種方法。
2.案例實戰(zhàn)
2.1 數(shù)據(jù)介紹
數(shù)據(jù)集下載地址:https://archive.ics.uci.edu/ml/datasets/Housing
這是一份預(yù)測房價的數(shù)據(jù),我們用它去訓(xùn)練一個神經(jīng)網(wǎng)絡(luò)去預(yù)測房價,總共選取9個特征,數(shù)據(jù)的特征如下:
要預(yù)測的標簽數(shù)據(jù)是MEDV,是業(yè)主自用住宅的價格均值。
在開始建模之前,我們先去下載好 boston_train.csv(訓(xùn)練集), boston_test.csv(測試集), and boston_predict.csv(預(yù)測集)這份文件
2.2 加載數(shù)據(jù)
首先導(dǎo)入需要的庫(包括pandas, tensorflow),并且設(shè)置logging verbosity為INFO,這樣就可以獲取到更多的日志信息了。
from __future__ import absolute_import from __future__ import division from __future__ import print_function import itertools import pandas as pd import tensorflow as tf tf.logging.set_verbosity(tf.logging.INFO)
定義一個變量COLUMNS,將所有的特征名稱與類別標簽名稱存儲成list并賦值給他。
為了區(qū)分特征名稱與標簽名稱,同時也將它們分別春初一個變量
COLUMNS = ["crim", "zn", "indus", "nox", "rm", "age", "dis", "tax", "ptratio", "medv"] FEATURES = ["crim", "zn", "indus", "nox", "rm", "age", "dis", "tax", "ptratio"] LABEL = "medv"
然后,將三份數(shù)據(jù)文件都用pandas.read_csv載入:
第一個參數(shù)是數(shù)據(jù)文件的路徑,第二個參數(shù)是是否需要取出前后空值,第三個參數(shù)是去除的行數(shù),第四個參數(shù)是列名
training_set = pd.read_csv("boston_train.csv", skipinitialspace=True, skiprows=1, names=COLUMNS) test_set = pd.read_csv("boston_test.csv", skipinitialspace=True, skiprows=1, names=COLUMNS) prediction_set = pd.read_csv("boston_predict.csv", skipinitialspace=True, skiprows=1, names=COLUMNS)
2.3 定義特征列并且創(chuàng)建回歸模型
現(xiàn)在創(chuàng)建一組FeatureColumn作為輸入數(shù)據(jù),正式指定哪些特征需要被用來訓(xùn)練。在我們的房價預(yù)測特征中所有數(shù)據(jù)都是連續(xù)型的值,因此你可以直接使用tf.contrib.layers.real_valued_column()來創(chuàng)建FeatureColumn
feature_cols = [tf.contrib.layers.real_valued_column(k) for k in FEATURES]
接著我們來調(diào)用DNNRegressor函數(shù)實例化一個神經(jīng)網(wǎng)絡(luò)回歸模型。
這里需要提供3個參數(shù):
- feature_columns:一組剛剛定義的特征列
- hidden_units:每層隱藏層的神經(jīng)網(wǎng)絡(luò)個數(shù)
- model_dir:模型保存的路徑
regressor = tf.contrib.learn.DNNRegressor(feature_columns=feature_cols, hidden_units=[10, 10], model_dir="/tmp/boston_model")
2.4 構(gòu)建輸入函數(shù)input_fn
這里我們構(gòu)建一個輸入函數(shù)去預(yù)處理數(shù)據(jù),處理的內(nèi)容比較簡單,只是將用pandas讀進來的dataframe形式的數(shù)據(jù)轉(zhuǎn)換成tensor.
def input_fn(data_set): feature_cols = {k: tf.constant(data_set[k].values) for k in FEATURES} labels = tf.constant(data_set[LABEL].values) return feature_cols, labels
2.5 訓(xùn)練模型
訓(xùn)練模型,我們調(diào)用fit()函數(shù),并且將訓(xùn)練數(shù)據(jù)集training_set作為參數(shù)傳入
regressor.fit(input_fn=lambda: input_fn(training_set), steps=5000)
運行代碼,你會看到有如下日志打印:
INFO:tensorflow:Step 1: loss = 483.179
INFO:tensorflow:Step 101: loss = 81.2072
INFO:tensorflow:Step 201: loss = 72.4354
...
INFO:tensorflow:Step 1801: loss = 33.4454
INFO:tensorflow:Step 1901: loss = 32.3397
INFO:tensorflow:Step 2001: loss = 32.0053
INFO:tensorflow:Step 4801: loss = 27.2791
INFO:tensorflow:Step 4901: loss = 27.2251
INFO:tensorflow:Saving checkpoints for 5000 into /tmp/boston_model/model.ckpt.
INFO:tensorflow:Loss for final step: 27.1674.
2.6 評估模型
模型訓(xùn)練好,就到了評估的時刻了,還是用測試數(shù)據(jù)集test_set來評估
ev = regressor.evaluate(input_fn=lambda: input_fn(test_set), steps=1)
提取損失并打?。?/p>
loss_score = ev["loss"] print("Loss: {0:f}".format(loss_score))
打印結(jié)果應(yīng)如下:
INFO:tensorflow:Eval steps [0,1) for training step 5000.
INFO:tensorflow:Saving evaluation summary for 5000 step: loss = 11.9221
Loss: 11.922098
2.7 使用模型做預(yù)測
模型要是評估通過,就可以用來預(yù)測新的數(shù)據(jù)了呢,這里我們使用prediction_set這個數(shù)據(jù)集,數(shù)據(jù)中只包含了特征沒有標簽,需要我們?nèi)ヮA(yù)測。
y = regressor.predict(input_fn=lambda: input_fn(prediction_set)) # .predict() returns an iterator; convert to a list and print predictions predictions = list(itertools.islice(y, 6)) print ("Predictions: {}".format(str(predictions)))
打印結(jié)果如下:
Predictions: [ 33.30348587 17.04452896 22.56370163 34.74345398 14.55953979
19.58005714]
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
pandas 數(shù)據(jù)實現(xiàn)行間計算的方法
今天小編就為大家分享一篇pandas 數(shù)據(jù)實現(xiàn)行間計算的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-06-06Python?time時間格式化和設(shè)置時區(qū)實現(xiàn)代碼詳解
這篇文章主要介紹了Python?time時間格式化和設(shè)置時區(qū)實現(xiàn)代碼,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值2023-02-02