TensorFlow是我們機器學習領域很是經常使用的一個組件,它在數據處理,模型創建,模型驗證等等關於機器學習方面的領域都有很好的表現,前面的一節我已經簡單介紹了一下TensorFlow裏面基礎的數據結構即:Tensor和Dataset; 這裏我們開始介紹TensorFlow的建模過程以及驗證模型的一些簡單方法。其實不管是sklearn仍是TensorFlow,他們的模型創建過程都是類似的,都是經歷columns類型聲明,模型定義,數據訓練,validation等等幾個步驟。前面的幾節內容我已經簡單的介紹瞭如何用sklearn創建tree_based模型,這裏我主要是想演示TensorFlow的應用,因此我就用linear regressor來當作例子來演示TensorFlow是如何從數據加載一直到數據驗證的階段。至於線性擬合的實現的具體細節,我在下一節的內容會從數學的角度具體解釋的。本節內容所使用的數據都是來自於網絡中,你們能夠忽略具體的數據的意思,主要的瞭解TensorFlow的應用過程,沒必要過於糾結於模型的細節部分,模型的細節我會在隨後的章節解釋。好了,那麼我們如今開始吧python
第一步:數據準備api
顧名思義,就是我們準備數據的過程,這裏包括有missing value handling, categorical data encoding,data split, data permutation等等內容,這一步我們要將我們未來模型訓練所用到的數據都能準備好。這個準備過程無非也就是上面的這些步驟,我們能夠看下面的代碼演示網絡
cali_housing_dataset_original = pd.read_csv("https://download.mlcc.google.com/mledu-datasets/california_housing_train.csv") cali_housing_dataset_original["median_house_value"] /= 1000.0 #create a random generator generator = np.random.Generator(np.random.PCG64()) #permutate the data frame cali_housing_dataset_permutation = cali_housing_dataset_original.reindex( generator.permutation(cali_housing_dataset_original.index) ) cali_housing_dataset_permutation.describe() #select the features that we will use in the model trainning process my_feature = cali_housing_dataset_permutation[["total_rooms"]] #select the targets of the dataset targets = cali_housing_dataset_permutation[["median_house_value"]]
這裏我就不演示那些feature engineering的過程,那些內容太多,你們能夠看我以前的博客,這裏主要是想向你們演示一下permutation的過程。由於最新的numpy對於randomize的過程已經有更新了,再也不使用的那些老的API了,numpy中最新的randomize的過程是經過建立2個generator來實現隨機過程和隨機數的生成了,這兩個generator一個個是bit generator, 就如我們上面代碼中的PCG64(), 它能產生一個隨機的bit stream, 根據numpy的官方文檔,雖然有不少種bit generator,可是PCG64是最穩定的一種;另一個就是Generator, 它是經過np.random.Generator()函數來實例化一個對象的,它能將bit generator產生的bit stream轉化成數字。這裏的數據我們就選擇一個最最簡單的linear regression的方式,那就是隻選擇一個feature,那就是total_rooms; 我們的target是median_house_value。數據結構
第二步:定義feature 類型 和 optimizerapp
既然我們的數據都準備好了,那麼以後那麼得定義一下我們數據的類型(每個column的類型都得定義),未來在我們定義模型的時候我們也得將columns的信息傳遞給我們的模型對象;以及用什麼optimizer未來來訓練我們的模型,這個optimizer未來也得傳遞給我們的模型對象。 具體optimizer是什麼我下面會慢慢講的。爲了方便演示,仍是先上代碼給你們看dom
#indicates what is the data type of the feature to tensorflow feature_columns = [tf.feature_column.numeric_column("total_rooms")]
#using stochastic gradient descent as the optimizer for our model #to ensure the magtitute of gradient do not become too large, we apply clipping_norm to our optimizer my_optimizer = tf.optimizers.SGD(learning_rate = 0.0000001, clipnorm=5.0)
從上面的代碼能夠看出,第一句是聲明我們feature_columns裏面只有一個numeric_column,記住每個column都有一個feature_column對象,這裏由於我們只選取了一個feature是total_rooms,因此我們這裏就一個tf.feature_column對象。這裏的第二行代碼是我們的重點,也是之後優化模型中常常要調整的部分,這裏我們能夠看出,這裏的optimizer是一個SGD, SGD是stochastic gradient descent的縮寫,就是每一次計算我們的gradient descent的時候,我們只選取一組數據進行計算,若是每一次計算gradient descent的時候我們都用整個數據進行計算,那麼我們的計算機是負擔不起的,消耗的存儲空間和計算能力都太大了,由於在實際中我們的數據集的數量常常都是以萬爲單位的。具體計算gradient descent的過程我會在下一節中講述模型訓練過程當中演示的。我們能夠看出來,SGD中還有兩個參數,分別是learning_rate和clipnorm, 我們知道,當咱們在訓練咱們的模型的時候,咱們須要逐步的訓練不少次,知道我們的gradient descent趨於0是才中止,我們的每一步的大小都要合理,若是learning_rate過小,我們訓練的步數就會太多,影響我們的效率;若是learning_rate太大,則可能致使我們訓練模型的過程不能converge,就是永遠找不到那個最小值,從而致使訓練的模型失敗;爲了防止我們我們的gradient太大,咱們這裏不僅僅用learning_rate來限制,我們還加了一個clipnorm來限制我們的gradient magtitute大小,防止我們fail to converge, 這至關於一個雙重保險。機器學習
第三步:定義一個模型model函數
將上面的參數都定義完成後,我們就得定義一下我們的模型啦,TensorFlow提供了大量的模型可供使用,幾乎全部主流的機器學習的模型和深度學習相關的模型,TensorFlow幾乎實現全覆蓋了,具體我們能夠去他的官網查詢, 他的官網地址是:https://www.tensorflow.org/api_docs/python/tf ,記住在TensorFlow中,他的模型都在tf.estimator這個模塊中。由於這裏是我們講述用TensorFlow開發機器學習應用的入門,我們就選一個最簡單的模型linear regressor模型來演示學習
linear_regressor = tf.estimator.LinearRegressor( feature_columns = feature_columns, optimizer = my_optimizer )
這裏我們能夠看出是如何初始化一個LinearRegressor對象的,一樣的,我們能夠看出來它初始化的時候也是須要傳遞feature_columns和optimizer這2個參數的,而這兩個參數正是我們第二步中所初始化的,能夠說是環環相扣啊,哈哈,也能夠看出我們前面定義初始化的一個對象都是沒有多餘的,都是要用到的。這兩個參數分別告訴了我們的模型我們數據columns的類型以及用什麼optimizer來訓練這2個信息。優化
第四步:數據源input_fn
既然我們的原始數據準備好了,模型也都定義好了,若是須要訓練我們的模型,我們還差什麼呢?對了就是將我們的原始數據(這裏的例子是dataframe)轉化成TensorFlow中的dataset,並將轉化後的data傳遞給我們的模型,讓我們以前定義的模型用這些數據去訓練。這裏應該也是我們用TensorFlow來建模的一個核心部分了,我們先看代碼演示,而後我會逐個詳細解釋的
def my_input(features, targets, batch_size=500, shuffle=True, num_epochs=None): """ epochs: while trainning, in the case of steps is larger than the length of dataset, we set the epochs to None, which means repeat forever. However, in trainning process, we have the steps to control the total number of iterations. While in the case of making predictions of a given dataset, we must set epochs to 1 and shuffle to False. Because we only want the input function return the dataset once, otherwise the function will keep returnning the results forvere once and once again. shuffle: in the trainning process, in order to balance the dataset, we set it to True. However while in prediction process, we have to set it to False, which could help us to evaluate the outputs. For example, if the outputs are shuffled, we have no way to compare the outputs to our original lables. """ #convert panda dataframe to a dict of Numpy array features = {key:tf.multiply(np.array(value),1) for key,value in dict(features).items()} #construct a dataset ds = tf.data.Dataset.from_tensor_slices((features,targets)) ds = ds.batch(batch_size).repeat(num_epochs) if shuffle: ds = ds.shuffle(buffer_size = 10000) return ds
這裏有幾個核心的參數我須要解釋一下,首先features和target兩個參數很明顯就是我們第一步中獲取的數據,分別是用來訓練這個模型的特徵變量和label;重點這裏解釋一下batch_size, shuffle 和 num_epochs這三個參數,這三個參數在我們TensorFlow的整個學習過程當中都得用到,絕對的重點,不容懷疑。首先我們來看batch_size, 由於SGD每一次都只會選用一條數據來計算我們的gradient(訓練模型),而我們的數據具備很強的隨機性,那麼就會致使我們的模型最後極可能不可用,可是若是我們每個step都選用整個dataset來訓練模型,又會致使我們的訓練過程很是漫長,那麼聰明的人類就天然而然的想到了我們能夠每一次選用必定數量的數據來訓練模型,通常的數據量我們大體的範圍都是在10-10000之間,這種方式就成爲mini-batch SGD, 在這裏我們就是採用了這種方式,我們每一次選用500條數據來訓練我們的模型,這是經過設置batch_size的值來實現的。對於shuffle這個參數呢,也是爲了打亂我們的數據來進行訓練,最終的目的也是爲了能幫助我們訓練出更加精確的模型,防止我們的數據分佈不合理致使模型有誤差,它裏面的buffer_size的意思是先從ds中選中buffer_size個數據(這些數據暫時仍是有序的,順序和ds中同樣),而後iterate的時候呢,就從這個buffer中隨機的選擇數據(這個選擇數據的過程就是無序的選擇了,實現了隨機的目的)。最後還有這個repeat(num_epochs)的函數,首先repeat函數在training的過程當中必定須要的,由於當我們設置steps步數參數的時候,若是steps的總數要多餘整個dataset的數據量的時候,那麼這時候我們必定得重複利用我們的dataset來達到訓練的目的,不然我們的數據源的數據量不夠了,會出錯的,這就是爲何須要repeat的緣由,至於num_epochs是來控制重複的次數的,通常在training階段我們將它設置成None, 意思就是無限循環,知道training中的steps所有走完位置,若是在predict階段,我們通常就設置成1,由於我們驗證階段不須要重複的,一樣的在predict的時候,數據源函數中的shuffle也要設置成False的,不然predict的結果都是亂序的,沒法跟原來的數據進行對比了。前面幾個參數在我們模型訓練過程當中能夠說是最重要的參數了,這裏說的也比較多,因此一點得用心搞明白。
第五步:訓練模型 training
既然上面我們把模型的參數都設置好了,數據源也定義好了,那麼接下來我們的任務就是訓練我們定義的模型了,這個過程在代碼中是很簡單的,但它內部作的工做是不少的,它須要計算在每一個維度(feature)上的gradient descent,知道它趨於0爲止,它的計算細節我會在接下來的一個章節中展現出來,我們先看代碼
linear_regressor.train( input_fn = lambda:my_input(my_feature, targets), steps = 1000 )
是否是很簡單,我們只須要將數據源函數做爲參數傳遞給他,而且設置一個steps就能夠了。這裏input_fn我就不解釋了,簡單說一下steps,steps指的是我們訓練的步數,我們每計算一次gradient descent,就算一步,這裏指我們最多計算1000次,即便1000的時候gradient descent不等於0咱也中止咱的訓練過程,而後我們能夠從新設置optimizer中的learning_rate來從新訓練。
第六步:predict和evaluate
通過前面五步後,我們已經訓練出來了一個模型,那麼接下來我們須要用這個模型來預測一下數據,而且看看它的效果,去evaluate一下這個模型。正常的狀況下我們會將數據split成training data 和 validation data,這裏我爲了方便,咱就直接用training data來演示如何predict還有如何evaluate我們的模型。簡單的代碼以下
#create a input function for prediction prediction_input_fn = lambda:my_input(my_feature,targets,shuffle=False,num_epochs=1) #prediction predictions = linear_regressor.predict(input_fn = prediction_input_fn) predictions = np.array([item["predictions"][0] for item in predictions]) #errors MSE mean_squared_error(targets,predictions)
在我們作prediction的時候,我們也是須要數據源input_fn的,在prediction的時候,shuffle=False, num_epochs=1; 而後調用這個模型linear_regressor的predict方法,將數據源函數傳遞給他, 它返回的結果是一個list,這個list裏面的element是一個dictionary,這個dictionary的key值「predictions」, value也是一個一個list,而且只有一個元素element,此element就是我們要的結果。最後我們要evaluate這個模型預測的結果,我們有不少種方式能夠驗證,這裏只展現了一個最簡單的方式,就是計算我們的target和prediction的方差,其實有不少不少種方式,在後面的章節我會慢慢介紹。
第七步:data visualization
好了,最後我們來看一下根據我們的學習的模型,我們想看看它的具體的擬合的效果,這裏就須要用一點以前我們學習的數據可視化的內容了,這裏比較簡單,我們經過模型學習到的參數,畫一條擬合線,而後在將數據畫到畫布上,座標分別是"total_rooms"和"house_median_price",而後經過scatter plot展現出來。代碼以下
sample = cali_housing_dataset_permutation.sample(n=300) x_0 = sample["total_rooms"].min() x_1 = sample["total_rooms"].max() linear_regressor.get_variable_names()#retrieve the name of the variable weights = linear_regressor.get_variable_value("linear/linear_model/total_rooms/weights")[0]#returns the value of variable given by name bias = linear_regressor.get_variable_value("linear/linear_model/bias_weights")#retruns the value of bias y_0 = weights*x_0+bias y_1 = weights*x_1+bias plt.plot([x_0,x_1],[y_0,y_1])#plot our regression line plt.ylabel("median_house_value")#label the y Axes plt.xlabel("total_rooms")#label the x Axes plt.scatter(sample["total_rooms"],sample["median_house_value"])#plot a scatter plot from the sample plt.show()
結果以下
能夠看得出來,擬合的還不錯。嘿嘿,關於模型訓練過程的可視化,後面還有不少種,之後我慢慢說,例如:x座標是steps, y座標是loss, 也是很是常見的一種方式。
總結
今天完整的展現了用TensorFlow建立模型的整個過程,一直從data preparation到最後的evaluation,能夠說貫穿了TensorFlow開發機器學習應用的整個過程。今天先用一個最簡單的線性擬合例子展現這個過程,後面我還會展現更多的更加複雜的模型,例如:Logistic Regression, DNN, LSTM,等等等等。可是萬變不離其宗,他們的基礎步驟都是上面的七個步驟。最後 ,祝武漢加油!!!!!!!!