使用TensorFlow的基本步驟

學習任務

學習使用TensorFlow,並以california的1990年的人口普查中的城市街區的房屋價值中位數做爲預測目標,使用均方根偏差(RMSE)評估模型的準確率,並經過調整超參數提升模型的準確率python

設置

加載必要的庫+數據導入以及一些簡單的處理git

加載必要庫算法

import math
# display模塊能夠決定顯示的內容以何種格式顯示
from IPython import display
# matplotlib爲python的2D繪圖庫
# cm爲顏色映射表
from matplotlib import cm  
# 使用 GridSpec 自定義子圖位置
from matplotlib import gridspec
# pyplot提供了和matlab相似的繪圖API,方便用戶快速繪製2D圖表
from matplotlib import pyplot as plt
# numpy爲python的科學計算包,提供了許多高級的數值編程工具
import numpy as np    
# pandas是基於numpy的數據分析包,是爲了解決數據分析任務而建立的    
import pandas as pd     
# sklearn(scikit-_learn_)是一個機器學習算法庫,包含了許多種機器學習得方式
# *   Classification 分類
# *   Regression 迴歸
# *   Clustering 非監督分類
# *   Dimensionality reduction 數據降維
# *   Model Selection 模型選擇
# *   Preprocessing 數據預處理 
# metrics:度量(字面意思),它提供了不少模塊能夠爲第三方庫或者應用提供輔助統計信息
from sklearn import metrics
# tensorflow是谷歌的機器學習框架
import tensorflow as tf   
# Dataset無比強大得數據集
from tensorflow.python.data import Dataset

tf.logging.set_verbosity(tf.logging.ERROR)
# 爲了觀察數據方便,最多隻顯示10行數據
pd.options.display.max_rows = 10
pd.options.display.float_format = '{:.1f}'.format

加載數據集編程

california_housing_dataframe = pd.read_csv("https://storage.googleapis.com/mledu-datasets/california_housing_train.csv", sep=",")

爲了防止數據集中出現病態排序,先對數據進行隨機化處理,此外並將median_house_value 調整爲以千爲單位,這樣更符合現實生活中的習慣,而且模型就可以以經常使用範圍內的學習速率較爲輕鬆地學習這些數據。api

//california_housing_dataframe.index原始序列集索引
//np.random.permutation()隨機打亂原索引順序
//california_housing_dataframe.reindex()以新的索引順序從新分配索引
california_housing_dataframe=california_housing_dataframe.reindex(np.random.permutation(california_housing_dataframe.index))
california_housing_dataframe["median_house_value"] /= 1000.0
california_housing_dataframe
longitude latitude housing_median_age total_rooms total_bedrooms population households median_income median_house_value
14836 -122.2 37.5 26.0 1777.0 555.0 1966.0 497.0 3.0 211.0
13475 -122.0 37.1 21.0 2387.0 357.0 913.0 341.0 7.7 397.7
3391 -117.9 33.7 27.0 1596.0 297.0 1703.0 289.0 4.1 184.9
4108 -118.0 33.8 34.0 1038.0 175.0 578.0 174.0 4.9 200.0
1901 -117.3 32.7 44.0 1934.0 325.0 783.0 316.0 4.9 358.6
... ... ... ... ... ... ... ... ... ...
7731 -118.4 34.0 44.0 1913.0 441.0 1295.0 432.0 4.0 266.4
4008 -118.0 34.1 20.0 2063.0 496.0 1573.0 468.0 3.2 157.1
1612 -117.2 33.6 6.0 13724.0 2269.0 5860.0 1986.0 4.0 183.0
6593 -118.3 34.0 46.0 1098.0 426.0 1510.0 374.0 2.1 156.3
9219 -119.1 34.4 52.0 1409.0 359.0 981.0 304.0 2.8 199.3

17000 rows × 9 columns數組

檢查數據

目的是爲了在使用以前對數據有一個初步的告終安全

california_housing_dataframe.describe()//輸出關於各列的一些實用統計信息快速摘要:樣本數、均值、標準誤差、最大值、最小值和各類分位數
longitude latitude housing_median_age total_rooms total_bedrooms population households median_income median_house_value
count 17000.0 17000.0 17000.0 17000.0 17000.0 17000.0 17000.0 17000.0 17000.0
mean -119.6 35.6 28.6 2643.7 539.4 1429.6 501.2 3.9 207.3
std 2.0 2.1 12.6 2179.9 421.5 1147.9 384.5 1.9 116.0
min -124.3 32.5 1.0 2.0 1.0 3.0 1.0 0.5 15.0
25% -121.8 33.9 18.0 1462.0 297.0 790.0 282.0 2.6 119.4
50% -118.5 34.2 29.0 2127.0 434.0 1167.0 409.0 3.5 180.4
75% -118.0 37.7 37.0 3151.2 648.2 1721.0 605.2 4.8 265.0
max -114.3 42.0 52.0 37937.0 6445.0 35682.0 6082.0 15.0 500.0

構建第一個模型

本次練習,咱們將嘗試預測 median_house_value(每一個街區的房屋價值的中位數),它將是咱們的標籤(有時也稱爲目標target)。咱們將使用 total_rooms (每一個街區的房間總數)做爲輸入特徵。網絡

爲了訓練模型,咱們將使用 TensorFlow Estimator(一種評估器) API 提供的 LinearRegressor 接口。此 API 負責處理大量低級別模型搭建工做,並會提供執行模型訓練、評估和推理的便利方法。app

estimator(估計量) 統計學中estimator是基於觀測數據計算給定量的估計值的規則,即經過給定的一些example,經過必定的規則,計算給出預測值。
在tensoflow中其是 tf.Estimator 類的一個實例,用於封裝負責構建 TensorFlow 圖並運行 TensorFlow 會話的邏輯,是處於最頂層的面向對象的高級api

LinearRegressor 線性迴歸,能夠理解爲 經過訓練得出一條逼近example的線框架

工具包 說明
Estimator (tf.estimator) 高級 OOP API。
tf.layers/tf.losses/tf.metrics 用於常見模型組件的庫。
TensorFlow 低級 API

如下是構建模型的步驟

第 1 步:定義特徵並配置特徵列


爲了將咱們的訓練數據導入 TensorFlow,咱們須要指定每一個特徵包含的數據類型。在本練習及從此的練習中,咱們主要會使用如下兩類數據:

  • 分類數據:一種文字數據。在本練習中,咱們的住房數據集不包含任何分類特徵,但您可能會看到的示例包括家居風格以及房地產廣告詞。
  • 數值數據:一種數字(整數或浮點數)數據以及您但願視爲數字的數據。有時您可能會但願將數值數據(例如郵政編碼)視爲分類數據(咱們將在稍後的部分對此進行詳細說明)。
當咱們有了example之後,其一般包含許多特徵,好比本次例子中的housing_median_age , total_rooms等,在以後爲了更好的處理對應特徵的對應數據,咱們選擇先給這些特徵分個類,而通過前輩的驗證發現主要是使用 分類數據數值數據,好比人的性別這個特徵能夠當作分類數據,男女在對槍戰遊戲的喜好程度上,就得分開站隊了,因此這時候,這樣得分類數據頗有意義,而像考試某門考試分數這個特徵仍是數值數據更合理啦

在 TensorFlow 中,咱們使用一種稱爲「特徵列」的結構來表示特徵的數據類型。特徵列僅存儲對特徵數據的描述;不包含特徵數據自己。

意義以及解釋在代碼註釋中

一開始,咱們只使用一個數值輸入特徵 total_rooms。如下代碼會從 california_housing_dataframe 中提取 total_rooms 數據,並使用 numeric_column 定義特徵列,這樣會將其數據指定爲數值:


# Define the input feature: total_rooms.
# 取數據集中得'total_rooms'這一列做爲輸入特徵
my_feature = california_housing_dataframe[["total_rooms"]]

# Configure a numeric feature column for total_rooms.
# 將一個名叫"total_rooms"的特徵列定義爲**數值數據** ,這樣的定義結果存在feature_columns中
# 即上文所說得**特徵列**中,這時候特徵列其實只是一個存儲了分類信息的集合,具體使用的時候須要
# 特徵集合和特徵列結合起來,分類器才能識別的呢
feature_columns = [tf.feature_column.numeric_column("total_rooms")]

注意total_rooms 數據的形狀是一維數組(每一個街區的房間總數列表)。這是 numeric_column 的默認形狀,所以咱們沒必要將其做爲參數傳遞。


第 2 步:定義目標


接下來,咱們將定義目標,也就是 median_house_value。一樣,咱們能夠從 california_housing_dataframe 中提取它:


# Define the label.
# 將"median_house_value"列的數據從數據集中取出做爲target,這就是咱們搭建的模型所要學習的東# 西
targets  =  california_housing_dataframe["median_house_value"]

第 3 步:配置 LinearRegressor


接下來,咱們將使用 LinearRegressor 配置線性迴歸模型,並使用 GradientDescentOptimizer(它會實現小批量隨機梯度降低法 (SGD))訓練該模型。learning_rate參數可控制梯度步長的大小。


  • 梯度 (gradient):偏導數相對於全部自變量的向量。在機器學習中,梯度是模型函數偏導數的向量。梯度指向最速上升的方向。
  • 梯度降低法 (gradient descent):一種經過計算而且減少梯度將損失降至最低的技術,它以訓練數據爲條件,來計算損失相對於模型參數的梯度。通俗來講,梯度降低法以迭代方式調整參數,逐漸找到權重和誤差的最佳組合,從而將損失降至最低。

上面的術語解釋讀起來比較抽象,而且爲了防止文章篇幅過長,看了上面忘了下面,因此模型的實現過程放在遇到問題在下面解釋

  • 下圖顯示了機器學習算法用於訓練模型的迭代試錯過程

圖片

輸入特徵=>模型預測=>根據結果計算一下損失(損失就是距離target的差距),而後將參數更新,再放回模型中預測,直至收斂,使得損失變得最小,這時候的參數就是咱們想要的參數

  • 下圖是上圖中"計算參數更新"的綠框中的內容

圖片

假設咱們可以將全部種可能狀況全都計算一遍,那麼獲得的必定是一個相似於這樣的碗狀圖,在其中一定有一點是損失最低的點,可是現實種咱們確定不會有那麼大的計算能力和時間去計算出每一個結果,咱們一般採用一種叫作梯度降低法的方式來"快速"的找到損失最低的點(梯度降低法屬於一種優化算法,雖然並非最好的優化算法,可是其方式簡單,應用也不少)。

  • 起點是隨意選定的,由於在預測的開始時,沒有人知道權重(w1,w2,w3..b)該是什麼,能夠設置爲0,也能夠設置爲1,無所謂。經過模型一次計算,計算得出損失(這時候損失並不重要,確定極大,沒有參考意義),而後計算起點處的偏導數(若是隻有一個權重那就是導數了),得出起點處的偏導數,而梯度是偏導數的矢量(即包含了此處偏導數的方向大小),能夠想象一下拋物線y=ax²+bx+c 在x0處的導數,其大小的絕對值是隨着x0的值而變化的,而且有正負之分,絕對值大小表明大小,正負表明方向,因此依據梯度就能夠肯定權重值調節的方向。
  • 至此,調節的基本原理說的就差很少了,那麼剩下的問題就是如何更好的優化,以便用最少的計算量最快的速度去達到目的。

  • 學習速率(也稱爲步長)

1.學習速率過慢

2.學習速率過快

3.學習速率比較好的

若是讓其按照每一個點自己的梯度大小來調節權值,那實在是太慢了,因此咱們能夠爲其乘上一個學習速率,意如其名,這樣能夠人手動的調節學習速率(或許有的人會擔憂,立即將逼近損失最小的點時,這樣會不會不太準確了,放心好了,咱們並不須要那麼的準確的權值,99%和98%的區別不是太大,可是所要付出的計算量倒是超大的)

附上谷歌提供的:優化學習速率體驗

下面是兩種個效果更好的梯度降低算法方案,第二種更優
隨機梯度降低法 (SGD) :它每次迭代只使用一個樣本(批量大小爲 1)。「隨機」這一術語表示構成各個批量的一個樣本都是隨機選擇的。(假設有10000個樣本,每次從中隨機選一個來執行梯度降低)

小批量隨機梯度降低法小批量 SGD)是介於全批量迭代與 SGD 之間的折衷方案。小批量一般包含 10-1000 個隨機選擇的樣本。小批量 SGD 能夠減小 SGD 中的雜亂樣本數量,但仍然比全批量更高效。(每次隨機選一批)

注意:爲了安全起見,咱們還會經過 clip_gradients_by_norm梯度裁剪應用到咱們的優化器。梯度裁剪可確保梯度大小在訓練期間不會變得過大,梯度過大會致使梯度降低法失敗。

解釋完畢,以上


華麗分割線


# Use gradient descent as the optimizer for training the model.
my_optimizer=tf.train.GradientDescentOptimizer(learning_rate=0.0000001)
# 這裏的clip_by_norm是指對梯度進行裁剪,經過控制梯度的最大範式,防止梯度爆炸的問題,是一種
# 比較經常使用的梯度規約的方式,解釋起來太費事啦。。。。略略
my_optimizer = tf.contrib.estimator.clip_gradients_by_norm(my_optimizer, 5.0)
# Configure the linear regression model with our feature columns and optimizer
# Set a learning rate of 0.0000001 for Gradient Descent.
# 線性迴歸模型,tf.estimator.LinearRegressor是tf.estimator.Estimator的子類
# 傳入參數爲**特徵**列和剛纔配置的**優化器**,至此線性迴歸模型就配置的差很少啦
# 前期須要配置模型,因此是與具體數據(特徵值,目標值是無關的)
linear_regressor = tf.estimator.LinearRegressor(
 feature_columns=feature_columns,
 optimizer=my_optimizer
)

第 4 步:定義輸入函數


要將加利福尼亞州住房數據導入 LinearRegressor(剛剛配置好的線性迴歸模型),咱們須要定義一個輸入函數,讓它告訴 TensorFlow 如何對數據進行預處理,以及在模型訓練期間如何批處理、隨機處理和重複數據。(看不明白接着往下看)

咱們在輸入如數據以前,得將數據先處理好(按照大小啊,數據的特性啊),就像以前給數據分類爲數值的仍是分類的同樣,由於要使用小批量隨機梯度降低法,因此數據還須要按固定大小分批一會兒


首先,咱們將 Pandas 特徵數據轉換成 NumPy 數組字典。而後,咱們可使用 TensorFlow Dataset API根據咱們的數據構建 Dataset 對象,並將數據拆分紅大小爲 batch_size 的多批數據,以按照指定週期數 (num_epochs) 進行重複。

不知道你還能不能記得一開始導入包時候的代碼註釋

import numpy as np //numpy是python的科學計算包,提供了許多高級的數值編程工具
import pandas as pd        //pandas是基於numpy的數據分析包,是爲了解決數據分析任務而建立的

這裏的大概過程就至關於使用_Pandas_的轉換工具將咱們從California的住房集種抽出來的數據來一個格式轉換,目的是爲了讓接下來的數據更好更容易的被處理,好比炸薯條的話,得先給土豆削皮,而後就得切條了,對於刀工很差的人,應該是挺但願這時候的土豆是一個標準的長方體的吧,這樣切起來很爽很舒服,在這裏的格式轉換就是這個目的,土豆仍是土豆。

下面是對即將使用的函數的參數的說明


注意:若是將默認值 num_epochs=None 傳遞到 repeat(),輸入數據會無限期重複。

而後,若是 shuffle 設置爲 True,則咱們會對數據進行隨機處理,以便數據在訓練期間以隨機方式傳遞到模型。buffer_size 參數會指定 shuffle 將從中隨機抽樣的數據集的大小。

# 自定義個輸入函數
# 輸入的參數分別爲 
# features:特徵值(房間數量)
# targets: 目標值(房屋價格中位數)
# batch_size:每次處理訓練的樣本數(這裏設置爲1)
# shuffle: 若是 `shuffle` 設置爲 `True`,則咱們會對數據進行隨機處理
# num_epochs:將默認值 `num_epochs=None` 傳遞到 `repeat()`,輸入數據會無限期重複

def my_input_fn(features, targets, batch_size=1, shuffle=True, num_epochs=None):
    # dict(features).items():將輸入的特徵值轉換爲dictinary(python的一種數據類型,
    # lalala = {'Google': 'www.google.com', 'Runoob': 'www.runoob.com'})
    # 經過for語句遍歷,獲得其全部的一一對應的值(key:value)
    features = {key:np.array(value) for key,value in dict(features).items()}                                           
    # Dataset.from_tensor_slices((features,targets))將輸入的兩個參數拼接組合起來,
    # 造成一組一組的**切片**張量{(房間數,價格),(房間數,價格)....}
    ds = Dataset.from_tensor_slices((features,targets)) # warning: 2GB limit
    # batch(batch_size):將ds數據集按照batch_size大小組合成一個batch
    # repeat(num_epochs):repeat表明從ds這個數據集要重複讀取幾回,在這裏num_epochs=None
    # 表明無限次重複下去,可是由於ds數據集有容量上限,因此會在上限出中止重複
    ds = ds.batch(batch_size).repeat(num_epochs)
    # Shuffle the data, if specified
    # 如今ds中得數據集已經時按照batchsize組合成得一個一個batch,存放在隊列中,而且是重複了n次
    # 這樣子得話,不斷重複,後面數據是沒有意義,因此要將其隨機打亂
    # shuffle(buffer_size=10000):表示打亂得時候使用得buffer大小是10000,即ds中按順序取10000個出來
    # 打亂放回去,接着從後面再取10000個,按順序來
    if shuffle:
      ds = ds.shuffle(buffer_size=10000)
    # Return the next batch of data
    # make_one_shot_iterator():最簡單的一種迭代器,僅會對數據集遍歷一遍
    # make_one_shot_iterator().get_next():迭代的時候返回全部的結果    
    features, labels = ds.make_one_shot_iterator().get_next()
    # 向 LinearRegressor 返回下一批數據
    return features, labels

第 5 步:訓練模型


如今,咱們能夠在 linear_regressor 上調用 train() 來訓練模型。咱們會將 my_input_fn 封裝在 lambda 中,以即可以將 my_featuretarget 做爲參數傳入,首先,咱們會訓練 100 步。


_ = linear_regressor.train(
 input_fn = lambda:my_input_fn(my_feature, targets),
 steps=100
)
  • lambda的用法是將(匿名)函數封裝,在此處就是將my_input_fu()封裝一下,返回已經處理好的數據集ds
my_lambda = lambda arg : arg + 1
result = my_lambda(123)

第 6 步:評估模型


咱們基於該訓練數據作一次預測,看看咱們的模型在訓練期間與這些數據的擬合狀況。

注意:訓練偏差能夠衡量您的模型與訓練數據的擬合狀況,但並不能衡量模型泛化到新數據的效果。在後面的練習中,將探索如何拆分數據以評估模型的泛化能力。

  • 泛化:泛化能力(generalization ability)是指機器學習算法對新鮮樣本的適應能力。學習的目的是學到隱含在數據對背後的規律,對具備同一規律的學習集之外的數據,通過訓練的網絡也能給出合適的輸出,該能力稱爲泛化能力。--百度百科

# 上一步已經將數據輸入,並訓練了一百步,因此如今的模型的參數是已經調整過的
# 如今咱們來得到**偏差**,對偏差進行分析,以衡量訓練了一百步的模型效果怎麼樣
# 獲取偏差的方式很簡單,仍是採用原來的數據集輸入,此次不是訓練,而是直接預測,返回預測結果
prediction_input_fn =lambda: my_input_fn(my_feature, targets, num_epochs=1, shuffle=False)
predictions = linear_regressor.predict(input_fn=prediction_input_fn)
# 將預測結果取出,格式化爲numpy數組,來進行偏差分析
predictions = np.array([item['predictions'][0] for item in predictions])
# 計算均方偏差(MSE),即Sum((target-predictions)²)/N,
mean_squared_error = metrics.mean_squared_error(predictions, targets)
# 再對均方偏差開根,獲得均方根偏差(RMSE),目的就是看看預測值和真實的target相差了多少
root_mean_squared_error = math.sqrt(mean_squared_error)
# 輸出MSE和RMSE
print "Mean Squared Error (on training data): %0.3f" % mean_squared_error
print "Root Mean Squared Error (on training data): %0.3f" % root_mean_squared_error

結果爲

Mean Squared Error (on training data): 56367.025
Root Mean Squared Error (on training data): 237.417

這時候咱們須要判斷這個模型的效果怎麼樣,這樣大小的數值到底意義是什麼,您如何判斷偏差有多大?
因爲均方偏差 (MSE) 很難解讀,所以咱們常常查看的是均方根偏差 (RMSE),這也是咱們引入RMSE的意義。RMSE 的一個很好的特性是,它能夠在與原目標相同的規模下解讀(由於開過根,與target是同一個數量級的,不過固然啦,這個值是越小越好的呢)。

咱們來比較一下 RMSE 與目標最大值和最小值的差值


min_house_value = california_housing_dataframe["median_house_value"].min()
max_house_value = california_housing_dataframe["median_house_value"].max()
min_max_difference = max_house_value - min_house_value

print "Min. Median House Value: %0.3f" % min_house_value
print "Max. Median House Value: %0.3f" % max_house_value
print "Difference between Min. and Max.: %0.3f" % min_max_difference
print "Root Mean Squared Error: %0.3f" % root_mean_squared_error

結果是

Min. Median House Value: 14.999
Max. Median House Value: 500.001
Difference between Min. and Max.: 485.002
Root Mean Squared Error: 237.417

從數據中能夠看出,咱們的偏差跨越目標值的近一半範圍,能夠進一步縮小偏差嗎?
其實着也是每一個模型開發者都會煩惱的問題,到底該怎樣縮小偏差,難道單純的要靠大量數據嗎?
其實咱們能夠來制定一些基本策略,以下降模型偏差。


首先,咱們能夠了解一下根據整體摘要統計信息,預測和目標的符合狀況

# 使用pdndas的工具來對數據簡單處理分析
calibration_data = pd.DataFrame()
# pd.Series就是將參數中的list(一維的矩陣),添加到其中,具體效果看輸出的表格
calibration_data["predictions"] = pd.Series(predictions)
calibration_data["targets"] = pd.Series(targets)
calibration_data.describe()
predictions targets
count 17000.0 17000.0
mean 0.1 207.3
std 0.1 116.0
min 0.0 15.0
25% 0.1 119.4
50% 0.1 180.4
75% 0.2 265.0
max 1.9 500.0

這個數據不用圖表分析,一看就知道差距超級大了,可是咱們仍是畫個圖看看吧,比較直觀

首先,咱們將得到均勻分佈的隨機數據樣本,取300對數據,用來繪製個散點圖

sample = california_housing_dataframe.sample(n=300)

而後,咱們根據模型的誤差項和特徵權重繪製學到的線,並繪製散點圖。該線會以紅色顯示。

# Get the min and max total_rooms values.
x_0 = sample["total_rooms"].min()
x_1 = sample["total_rooms"].max()

# 從目前的訓練模型中取出訓練獲得的weight(權重)和bias(b:y=w1x1+w2x2+...+b其中的b(不知道要怎麼翻))
weight = linear_regressor.get_variable_value('linear/linear_model/total_rooms/weights')[0]
bias = linear_regressor.get_variable_value('linear/linear_model/bias_weights')

# 使用目前訓練獲得權值去估計x_0和x_1對應的y_0和y_1(由於訓練獲得的預測結果是線性的,只要知道直線端點就ok)
y_0 = weight * x_0 + bias 
y_1 = weight * x_1 + bias

# 還記得一開始導入的一個2D圖形庫matplotlib嗎,其是python的最主要的可視化庫
# 能夠利用其繪製散點圖、直方圖和箱形圖,及修改圖表屬性等
# 下面使用其plot(二維線條畫圖函數),c='r'是線條參數,紅色
plt.plot([x_0, x_1], [y_0, y_1], c='r')

# 設置座標軸lable
plt.ylabel("median_house_value")
plt.xlabel("total_rooms")

# scatter()繪製散點圖,在此繪製sample中的對應的total_rooms和median_house_value的散點圖
plt.scatter(sample["total_rooms"], sample["median_house_value"])

plt.show()

結果以下

這條初始線看起來與目標相差很大,很明顯的緣由就是weight過小和bias不太對?
那麼咱們是否有解決的辦法呢?

調整模型超參數


對於本練習,爲方便起見,已將上述全部代碼放入一個函數中。您可使用不一樣的參數調用該函數,以瞭解相應效果。
我將會在 10 個等分的時間段內使用此函數,以便觀察模型在每一個時間段的改善狀況。
對於每一個時間段,咱們都會計算訓練損失並繪製相應圖表。這能夠幫助您判斷模型收斂的時間,或者模型是否須要更多迭代。
此外,咱們還會繪製模型隨着時間的推移學習的特徵權重和誤差項值的曲線圖。您還能夠經過這種方式查看模型的收斂效果。

# 定義個函數融合上面全部的操做,如下是參數說明,並順便複習如下上面的內容
  # learning_rate:學習速率(步長),能夠調節梯度降低的速度
  # steps:訓練步數,越久效果通常會越準確,但花費的時間也是越多的
  # batch_size:每次處理訓練的樣本數(將原來數據打包成一塊一塊的,塊的大小)
  # input_feature:輸入的特徵
def train_model(learning_rate, steps, batch_size, input_feature="total_rooms"):
  periods = 10
  #    將步長分十份,用於每訓練十分之一的步長就輸出一次結果
  steps_per_period = steps / periods

  # 如下是準備數據,分別是my_feature_data 和 targets
  my_feature = input_feature
  my_feature_data = california_housing_dataframe[[my_feature]]
  my_label = "median_house_value"
  targets = california_housing_dataframe[my_label]

  # 建立特徵列
  feature_columns = [tf.feature_column.numeric_column(my_feature)]
  
  # 建立輸入函數(訓練和預測)
  training_input_fn = lambda:my_input_fn(my_feature_data, targets, batch_size=batch_size)
  prediction_input_fn = lambda: my_input_fn(my_feature_data, targets, num_epochs=1, shuffle=False)
  
  # 建立線性迴歸模型
  my_optimizer = tf.train.GradientDescentOptimizer(learning_rate=learning_rate)
  my_optimizer = tf.contrib.estimator.clip_gradients_by_norm(my_optimizer, 5.0)
  linear_regressor = tf.estimator.LinearRegressor(
      feature_columns=feature_columns,
      optimizer=my_optimizer
  )

  # 設置每一個階段的輸出
  # 新建繪畫窗口,自定義畫布的大小爲15*6
  plt.figure(figsize=(15, 6)) 
  # 設置畫布劃分以及圖像在畫布上輸出的位置1行2列,繪製在第1個位置
  plt.subplot(1, 2, 1)
  plt.title("Learned Line by Period")
  plt.ylabel(my_label)
  plt.xlabel(my_feature)
  sample = california_housing_dataframe.sample(n=300)
  plt.scatter(sample[my_feature], sample[my_label])
  # np.linspace(-1, 1, periods):用於輸出等差數列,起始-1,結尾1,periods=10,10等分(不寫的話默認50等分)
  # cm.coolwarm(x):設置顏色,用於十條線顯示不一樣顏色
  colors = [cm.coolwarm(x) for x in np.linspace(-1, 1, periods)]

  # 週期評估並輸出(把訓練分十次,並輸出)
  print "Training model..."
  print "RMSE (on training data):"
  root_mean_squared_errors = []
  for period in range (0, periods):
    linear_regressor.train(
        input_fn=training_input_fn,
        steps=steps_per_period
    )
    predictions = linear_regressor.predict(input_fn=prediction_input_fn)
    predictions = np.array([item['predictions'][0] for item in predictions])
    
    root_mean_squared_error = math.sqrt(
        metrics.mean_squared_error(predictions, targets))

    print "  period %02d : %0.2f" % (period, root_mean_squared_error)
    root_mean_squared_errors.append(root_mean_squared_error)
  # 取出十次訓練獲得的w和b,用於繪製
    y_extents = np.array([0, sample[my_label].max()])
    
    weight = linear_regressor.get_variable_value('linear/linear_model/%s/weights' % input_feature)[0]
    bias = linear_regressor.get_variable_value('linear/linear_model/bias_weights')

    x_extents = (y_extents - bias) / weight
    x_extents = np.maximum(np.minimum(x_extents,
                                      sample[my_feature].max()),
                           sample[my_feature].min())
    y_extents = weight * x_extents + bias
    plt.plot(x_extents, y_extents, color=colors[period]) 
  print "Model training finished."

  # 輸出RMSE曲線圖
  plt.subplot(1, 2, 2)
  plt.ylabel('RMSE')
  plt.xlabel('Periods')
  plt.title("Root Mean Squared Error vs. Periods")
  plt.tight_layout()
  plt.plot(root_mean_squared_errors)

  # 輸出預測target的對比
  calibration_data = pd.DataFrame()
  calibration_data["predictions"] = pd.Series(predictions)
  calibration_data["targets"] = pd.Series(targets)
  display.display(calibration_data.describe())

  print "Final RMSE (on training data): %0.2f" % root_mean_squared_error

調節模型


接下來是調整超參數的代碼以及效果

# 調用train_model
# learning_rate=0.00002:學習速率翻倍,有限步長可能會計算的更接近
# steps=500:訓練500步
# batch_size=5:一批5組數據
train_model(
    learning_rate=0.00002,
    steps=500,
    batch_size=5
)

結果:

Training model...
RMSE (on training data):
period 00 : 225.63
period 01 : 214.42
period 02 : 204.04
period 03 : 194.62
period 04 : 186.60
period 05 : 180.00
period 06 : 175.44
period 07 : 171.57
period 08 : 168.84
period 09 : 167.53
Model training finished.
predictions targets
count 17000.0 17000.0
mean 115.3 207.3
std 95.0 116.0
min 0.1 15.0
25% 63.7 119.4
50% 92.7 180.4
75% 137.4 265.0
max 1654.1 500.0

Final RMSE (on training data): 167.53

有適用於模型調整的標準啓發法嗎?


這是一個常見的問題。簡短的答案是,不一樣超參數的效果取決於數據。所以,不存在必須遵循的規則,您須要對本身的數據進行測試。

即使如此,仍在下面列出了幾條可爲您提供指導的經驗法則:

  • 訓練偏差應該穩步減少,剛開始是急劇減少,最終應隨着訓練收斂達到平穩狀態。
  • 若是訓練還沒有收斂,嘗試運行更長的時間。
  • 若是訓練偏差減少速度過慢,則提升學習速率也許有助於加快其減少速度。

    • 但有時若是學習速率太高,訓練偏差的減少速度反而會變慢。
  • 若是訓練偏差變化很大,嘗試下降學習速率。

    • 較低的學習速率和較大的步數/較大的批量大小一般是不錯的組合。
  • 批量大小太小也會致使不穩定狀況。不妨先嚐試 100 或 1000 等較大的值,而後逐漸減少值的大小,直到出現性能下降的狀況。

重申一下,切勿嚴格遵循這些經驗法則,由於效果取決於數據。請始終進行試驗和驗證

嘗試其餘特徵

使用 population 特徵替換 total_rooms 特徵,看看可否取得更好的效果。

train_model(
    learning_rate=0.00002,
    steps=1000,
    batch_size=5,
    input_feature="population"
)

結果

Training model...
RMSE (on training data):
period 00 : 225.63
period 01 : 214.62
period 02 : 204.86
period 03 : 196.26
period 04 : 189.52
period 05 : 184.46
period 06 : 180.84
period 07 : 178.30
period 08 : 176.60
period 09 : 176.02
Model training finished.
predictions targets
count 17000.0 17000.0
mean 119.8 207.3
std 96.2 116.0
min 0.3 15.0
25% 66.2 119.4
50% 97.8 180.4
75% 144.2 265.0
max 2990.2 500.0

Final RMSE (on training data): 176.02
33.png

相關文章
相關標籤/搜索