機器學習入門——線性迴歸


本人從2017年起,開始涉獵機器學習。作爲入門,首先學習的是斯坦福大學Andrew Ng(吳恩達)教授的Coursera課程


2 單變量線性迴歸

線性回歸屬於監督學習(Supervise Learning),就是Right answer is given。 課程中,舉了一個估計房產價格的例子,在此,我就直接使用兩組數據去作爲例子使用線性迴歸,擬合出效果最好的曲線。


2.1 單變量線性迴歸算法的思路

  1. 根據數據的分佈,確定模型
    預測函數
    其中,h(x)是假設函數(Hypothesis Fuction),θ1θ0 是關於線性迴歸的參數
  2. 確定代價函數(Cost Fuction)
    代價函數
    其中,J(θ)是代價函數,也是誤差函數,m代表數據個數,這樣顯然,目標函數就是:
    目標函數
  3. 確定是實現目標函數的方法,就是使J(θ)最小的方法。在這裏,我們使用梯度下降法(Gradient Descent )
    梯度下降
    對於此式,往下作解釋。

下面我舉一個很淺顯的例子,驗證線性迴歸算法的作用。
假設,有兩組數據:
train_x = [1,2,3,4,5,6,7,8,9,10,11,12,13,14]
train_y = [3,5,7,9,11,13,15,17,19,21,23,25,27,29]
仔細觀察這兩組數據,發現它們滿足:y = 2x +1這個函數關係,那麼怎麼使用線性迴歸得出這個結果呢?從機器學習的角度來說,就是怎麼使得計算機能從已知的有限個數據中,擬合出最合適的曲線,並預測其他x值對應的y值。

2.2 線性模型

針對已知的數據,如果使用線性模型,由於只有一個特徵/輸入變量(此處指的是x),則屬於單變量線性迴歸。預測函數爲:
預測函數
Python中使用Tensorflow庫的實現:

#Input data
train_x = np.asarray([1,2,3,4,5,6,7,8,9,10,11,12,13,14])
train_y = np.asarray([3,5,7,9,11,13,15,17,19,21,23,25,27,29])

#Create the linear model
X = tf.placeholder("float")
W = tf.Variable(np.random.randn(),name="theta1")
b = tf.Variable(np.random.randn(),name="theta0")
pred = tf.add(tf.mul(W,X),b)

2.3 代價函數

建立基本模型之後,就要對模型誤差進行評估,而這個評估的函數,就是代價函數
這裏我們使用預測數據值和偏差的平方去表示模型的誤差,式子如2.1所示。在tensorflow中實現:

m = train_x.shape[0]  #數據總個數
cost = tf.reduce_sum(tf.pow(pred-Y, 2))/(2*m)

2.4目標函數的建立及實現

構造模型的目標,當然是是模型誤差最小化,因此,目標函數爲:
目標函數
而怎麼實現呢?在本例中,我們使用梯度下降,即:
梯度下降
其中,該式針對本例的意思,是:

這樣,每進行一次運算,J(θ)的值就會進一步減少。

2.5 理清概念

模型理解的關鍵是切實理清假設函數和代價函數的作用。如下圖所示:


注:圖像均使用python下的matplotlib.pyplot和mpl_toolkits.mplot3d庫所作。
顯然,預測函數是根據訓練數據而定的,而代價函數是爲假設函數服務的,通過優化代價函數,就能找出最佳的參數賦給假設函數,從而找出最佳的模型。同時,由上圖可見,當參數θ有兩個的時候,代價函數是一個三維圖,所以當參數更多的時候就是更多維的圖。

2.6 程序實現線性迴歸

程序源碼:

#!/usr/bin/env python2
#-*- coding:utf-8 -*-
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import sys

reload(sys)
sys.setdefaultencoding('utf8')

#Input data
train_x = np.asarray([1,2,3,4,5,6,7,8,9,10,11,12,13,14])
train_y = np.asarray([3,5,7,9,11,13,15,17,19,21,23,25,27,29])

X = tf.placeholder("float")
Y = tf.placeholder("float")

#W,b分別代表θ1,θ0
#np.random.rann()用於初始化W和b
W = tf.Variable(np.random.randn(),name="theta1")
b = tf.Variable(np.random.randn(),name="theta0")

#1 假設函數的確定
pred = tf.add(tf.mul(W,X),b)

#2 代價函數的確定
m = train_x.shape[0]  #
cost = tf.reduce_sum(tf.pow(pred-Y, 2))/(2*m)

#3 梯度下降
learning_rate = 0.01
optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)
#至此模型構建完成

#Initialize the variables
init = tf.initialize_all_variables()

#Lauch the graph
with tf.Session() as sess:
    sess.run(init)
    for epoch in range(1000):   #進行100次的迭代訓練
        for (x,y) in zip(train_x,train_y):
            sess.run(optimizer,feed_dict={X:x,Y:y})          
        #display
        if(epoch+1)%50==0:
            c=sess.run(cost,feed_dict={X:train_x,Y:train_y})
            print "step:%04d, cost=%.9f, θ1=%s, θ0=%s"%((epoch+1),c,sess.run(W),sess.run(b))
    print "Optimzer finished!"
    #training_cost = sess.run(cost,feed_dict={X:train_x,Y:train_y})

    print "The final is y=%sx+%s"%(sess.run(W),sess.run(b))
    plt.plot(train_x,train_y,'ro',label="Original data")
    plt.grid(True)
    plt.plot(range(1,))
    plt.plot(train_x,sess.run(W)*train_x+sess.run(b),label="Fitted line")
    plt.legend()
    plt.show()

程序運行結果:

step:0050, cost=0.068827711, θ1=1.92573, θ0=1.77617
step:0100, cost=0.055033159, θ1=1.93359, θ0=1.69404
step:0150, cost=0.044003420, θ1=1.94061, θ0=1.62061
step:0200, cost=0.035184156, θ1=1.9469, θ0=1.55494
step:0250, cost=0.028132409, θ1=1.95252, θ0=1.49622
step:0300, cost=0.022494031, θ1=1.95754, θ0=1.44372
step:0350, cost=0.017985778, θ1=1.96203, θ0=1.39677
step:0400, cost=0.014381131, θ1=1.96605, θ0=1.35479
step:0450, cost=0.011498784, θ1=1.96964, θ0=1.31725
step:0500, cost=0.009194137, θ1=1.97285, θ0=1.28368
step:0550, cost=0.007351381, θ1=1.97573, θ0=1.25366
step:0600, cost=0.005878080, θ1=1.97829, θ0=1.22682
step:0650, cost=0.004699936, θ1=1.98059, θ0=1.20282
step:0700, cost=0.003757860, θ1=1.98265, θ0=1.18136
step:0750, cost=0.003004675, θ1=1.98448, θ0=1.16217
step:0800, cost=0.002402445, θ1=1.98612, θ0=1.14501
step:0850, cost=0.001920973, θ1=1.98759, θ0=1.12967
step:0900, cost=0.001535962, θ1=1.9889, θ0=1.11595
step:0950, cost=0.001228108, θ1=1.99008, θ0=1.10368
step:1000, cost=0.000981987, θ1=1.99113, θ0=1.09271
Optimzer finished!
The final is y=1.99113x+1.09271


顯然,最終得出的曲線很接近y=2x+1,如果增加訓練的次數會更加接近。成功驗證了線性迴歸算法!

發佈了39 篇原創文章 · 獲贊 112 · 訪問量 21萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章