使用TensorFlow的基本步骤
學習任務
學習使用TensorFlow,并以california的1990年的人口普查中的城市街區的房屋價值中位數作為預測目標,使用均方根誤差(RMSE)評估模型的準確率,并通過調整超參數提高模型的準確率
設置
加載必要的庫+數據導入以及一些簡單的處理
加載必要庫
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 調整為以千為單位,這樣更符合現實生活中的習慣,并且模型就能夠以常用范圍內的學習速率較為輕松地學習這些數據。
//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
| 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()//輸出關于各列的一些實用統計信息快速摘要:樣本數、均值、標準偏差、最大值、最小值和各種分位數| 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 負責處理大量低級別模型搭建工作,并會提供執行模型訓練、評估和推理的便利方法。
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,我們需要指定每個特征包含的數據類型。在本練習及今后的練習中,我們主要會使用以下兩類數據:
- 分類數據:一種文字數據。在本練習中,我們的住房數據集不包含任何分類特征,但您可能會看到的示例包括家居風格以及房地產廣告詞。
- 數值數據:一種數字(整數或浮點數)數據以及您希望視為數字的數據。有時您可能會希望將數值數據(例如郵政編碼)視為分類數據(我們將在稍后的部分對此進行詳細說明)。
在 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=ax2+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_feature 和 target 作為參數傳入,首先,我們會訓練 100 步。
_ = linear_regressor.train(
input_fn = lambda:my_input_fn(my_feature, targets),
steps=100
)
- lambda的用法是將(匿名)函數封裝,在此處就是將my_input_fu()封裝一下,返回已經處理好的數據集ds
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)2)/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.025Root 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.999Max. 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()
| 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.
| 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.
| 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
?原文:https://blog.csdn.net/weixin_34240520/article/details/88875487
總結
以上是生活随笔為你收集整理的使用TensorFlow的基本步骤的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Tensorflow的基本运行方式--d
- 下一篇: Tensorflow基本开发步骤——以逻