在本節中將經過一個預測房屋價格的實例來說解利用線性迴歸預測房屋價格,以及在tensorflow中如何實現
html
從網上獲得的數據能夠看到房屋價格與房屋尺寸的一個對比關係,以下圖:python
咱們假設x軸(房屋尺寸)而Y軸(房屋價格)依據上表數據繪製折線圖算法
如今咱們使用簡單的線性模型來預測,跨域
接下來須要經過數據來找到a,b的最佳值從而使預測與實際的偏差最小。這次咱們採用SSE(和方差)來判別偏差。該統計參數計算的是擬合數據和原始數據對應點的偏差的平方和,計算公式以下markdown
\[\frac{1}{2}\sum_{k=1}^{n} \ {({y} -{y_p})^2}\]app
在拿到原始的數據後,爲方便運算,咱們將數據進行歸一化處理,歸一化計算公式以下ide
\[\frac{x-x_{min}}{x_{max}-x_{min}}\]函數
咱們將原始的數據進行歸一化處理,歸一化處理後的結果如圖:性能
def normalize(arr): arr_min = np.min(arr) arr_max = np.max(arr) arr_out = [] for item in arr: out = np.divide(np.subtract(item, arr_min), np.subtract(arr_max, arr_min)) arr_out = np.append(arr_out, np.array(out)) return arr_out
def model(x, b, a): # linear regression is just b*x + a, so this model line is pretty simple return tf.multiply(x, b) + a loss = tf.multiply(tf.square(Y - y_model), 0.5)
對sse分別求a,b的偏微分
\[\frac{\partial sse}{\partial a}\]
\[\frac{\partial sse}{\partial b}\]學習
新 a = a – r * ∂SSE/∂a = 0.45-0.01*3.300 = 0.42
新 b = b – r * ∂SSE/∂b= 0.75-0.01*1.545 = 0.73
(r是學習率,表示調整的步長)
# construct an optimizer to minimize cost and fit line to mydata train_op = tf.train.GradientDescentOptimizer(0.01).minimize(loss)
而後再重複上一步驟計算,直到所設定的次數完成
for i in range(500): for (x, y) in zip(trX, trY): output = sess.run(train_op, feed_dict={X: x, Y: y})
經過剛纔幾步的組合,程序便能計算出最合適的a,b的值,完成代碼清單以下:
import tensorflow as tf import numpy as np sess = tf.Session() # 線性模型 y=bx+a def model(x, b, a): return tf.multiply(x, b) + a # 歸一化函數 def normalize(arr): arr_min = np.min(arr) arr_max = np.max(arr) arr_out = [] for item in arr: out = np.divide(np.subtract(item, arr_min), np.subtract(arr_max, arr_min)) arr_out = np.append(arr_out, np.array(out)) return arr_out # 原始數據 trX_i = [1100., 1400., 1425., 1550., 1600., 1700., 1700., 1875., 2350., 2450.] trY_i = [199000., 245000., 319000., 240000., 312000., 279000., 310000., 308000., 405000., 324000.] # 數據歸一化 trX = normalize(trX_i) trY = normalize(trY_i) X = tf.placeholder(tf.float32) Y = tf.placeholder(tf.float32) # 設一個權重變量b,和一個誤差變量a b = tf.Variable(0.0, name="weights") # create a variable for biases a = tf.Variable(0.0, name="biases") y_model = model(X, b, a) # 損失函數 loss = tf.multiply(tf.square(Y - y_model), 0.5) # 梯度降低 train_op = tf.train.GradientDescentOptimizer(0.01).minimize(loss) init = tf.global_variables_initializer() sess.run(init) # 訓練數據 for i in range(500): for (x, y) in zip(trX, trY): output = sess.run(train_op, feed_dict={X: x, Y: y}) print('b:' + str(sess.run(b)) + ' || a:' + str(sess.run(a))) ---result b:0.682465 || a:0.1512
在房價預測例子中,咱們發現房價數據呈一種比較明顯的線性關係,那麼天然咱們可能會選擇簡單線性迴歸對數據進行擬合,首先從線性模型着手:
\[y_p=ax+b\]
從上面的二元一次方程看出,咱們的輸入x是已知向量,只要咱們求出a,b的值,就能經過上述公式進行房價預測了,這就是簡單線性迴歸的思想。
如上一節中講的咱們須要找出SSE最小化時的a,b的值,採用的這種方法就叫作梯度降低。梯度降低不只僅侷限於最小化這個函數,也可能根據實際狀況須要最大化某個函數,這種狀況叫作梯度上升。單純從數學上講,對一個函數來講,梯度表示某個向量的偏導數,同時還表明了該向量的方向,在這個方向上,函數增長得最快,在相反的方向上,函數減少得最快。
利用梯度這一性質,咱們採用梯度降低算法去最小化咱們的損失函數,咱們在梯度的反方向跨域一小步,再從一個新起點開始重複這個過程,直到咱們找到損失函數的最小值,最後肯定咱們的a, b值。
咱們須要最小化的函數爲(又稱爲損失函數):
\[sse=\frac{1}{2}\sum_{k=1}^{n} \ {({y} -{y_p})^2}=\frac{1}{2}\sum_{k=1}^{n} \ {(y_k-ax_k-b)^2}\]
對a,b分別求偏導,並令偏導等於0:
\[\frac{\partial sse}{\partial a}=- \sum_{k=1}^n \ x_k(y_k-ax_k-b) \ =0\]
\[\frac{\partial sse}{\partial b}=- \sum_{k=1}^n \ (y_k-ax_k-b) =0\]
最後,輸入已知的x和y值(均爲向量),解兩個一次方程就計算出a,b的確切值。
爲了求SSE的最小值,咱們須要向梯度相反的方法移動,每移動一步,梯度逐漸下降,可是移動多少才合適呢,這須要咱們謹慎的選擇步長。目前,主流的選擇方法有:
• 使用固定步長
• 隨時間增加逐步減少步長
• 在每一步中經過最小化目標函數的值來選擇合適的步長
在上一例子中,咱們選擇固定步長r=0.01,其實,最後一種方法很好,但它的計算代價很大。咱們還能夠嘗試一系列步長,並選出使目標函數值最小的那個步長來求其近似值。
stepSizes=[10, 1, 0.1, 0.01, 0.001]
損失函數是用來評價模型的預測值與真實值的不一致程度,它是一個非負實值函數。一般使用L(Y,f(x))來表示,損失函數越小,模型的性能就越好。
在預測房價的例子中,咱們使用了和方差來計算偏差,並把該函數稱爲損失函數,即計算實際值和預測值的偏差平方和。爲何要選擇這一函數來計算偏差,而不採用絕對值偏差,或偏差的三次方,四次方來定義偏差函數是由於:
除上面提到的損失函數外,還有其餘的一些常見的損失函數:
若是預測值與標值不等,則記爲1;若是相等,則標記爲0
\[L(Y, f(x)) = \left\{ \begin{array}{ll} 1 & \textrm{$Y\neq f(x)$}\\ 0 & \textrm{$Y= f(x)$} \end{array} \right. \]
在邏輯迴歸中損失函數的推導是假設樣本服從伯努利分佈(0-1分佈),而後求知足該分佈的似然函數,最後推導出順勢函數的公式爲:\[L(Y,P(Y|X)) = -logP(Y|X)\]
出如今Adaboost算法中
\[L(y,f(x))=\frac{1}{n}\sum_{i=1}^{n}\ {exp[-y_if(x_i)]}\]
在線性支持向量機中,Hinge的損失函數標準形式爲:
\[L(y)=\frac{1}{n}\sum_{i=1}^{n}\ {l(wx_i+by_i)}\]
\[L(y,f(x))=|Y-f(x)|\]
對於多屬性的樣本,咱們在作分類預測的時候,應該把每一個屬性看做同等重要,不能讓某個屬性的計算結果嚴重影響模型的預測結果。例如,如下有一個樣本數據:
玩遊戲所耗時間百分比 | 描述每一年得到的飛行常客里程數 | 每週消費的冰淇淋公升數 |
---|---|---|
0.8 | 400 | 0.5 |
12 | 134000 | 0.9 |
0 | 20000 | 1.1 |
67 | 32000 | 0.1 |
若是咱們採用KNN算法作分類預測,在計算歐式距離的時候,好比計算樣本3和樣本4之間的距離,很明顯咱們發現每一年得到的飛行常客里程數因爲自己數值很大,其計算結果的影響將遠遠大於其餘兩個特徵值的影響,對於三個等權重的特徵之一,咱們不能讓它嚴重的影響計算結果,因此,咱們一般會採用特徵歸一化的方法把值處理爲0到1或者-1到1之間。
\[\sqrt{(0-67)^2+(20000-32000)^2+(1.1-0.1)^2}\]
即上面提到的公式:
\[\frac{x-x_{min}}{x_{max}-x_{min}}\]
其中\(x_{min}\)和\(x_{max}\)是特徵向量x的最小值和最大值,這樣經過對每一個特徵向量進行歸一化處理,全部特徵值的計算都統一了,而計算獲得的結果就更加準確。
在以前預測房價的例子中,咱們對已有的特徵向量,即房屋大小和實際價格作了歸一化處理,即使是隻有一個特徵向量,咱們仍然須要這樣作,其目的與上面的樣本數據同樣,好比假設咱們須要在該房屋預測中增長房間數量或房屋年齡等特徵進行房屋價格預測,咱們均可以採用同一類方法進行處理,以減小各特徵值對計算結果的影響。
參考連接
【1】:http://www.kdnuggets.com/2017/04/simple-understand-gradient-descent-algorithm.html