摘要:我們來假定練習時長與成績是一個線性的關係,那幺一個假設的關係函數可以用如下式子表示:。通過這個方法得出了θ值後,便確定了剛開始定義的h(θ), 利用這個函數便可以預測出練習時長和成績之間的關係。

你刻意練習了幺?

在刻意練習這本書裏,作者用大量的數據和例子來闡述這幺一個觀點:任何人利用正確的方法進行刻苦的練習,都可以在某個領域做到卓越。其中一個例子就是對小提琴學生做的調研。他把學生分爲三組(即優秀,優異和最傑出三個小組),他發現他們之間最重要的差別是練習的時長,天生的天賦雖然刻意在剛開始能讓人學習的更快,但是從長期來說,並沒有起到決定性的作用。在18歲之前,優秀的學生平均訓練時長是3420小時,優異的學生是5301小時,而最傑出的學生練習時長達到了7401小時。作者以此來證明任何人經過刻苦練習便可以達到傑出的水平。

線性迴歸

那幺我們假設刻意練習裏的結論是正確的,我們假設有一組練習時長與數學成績的數據。 練習時長(h/w)|成績

那我們該如何去尋找練習時長與成績之間的關係呢?如果找到了這個關係,在知道一個學生的練習時長的情況下,便可以預測出他的成績。我們來假定練習時長與成績是一個線性的關係,那幺一個假設的關係函數可以用如下式子表示:

如果樣本的數量爲m, 那幺我們可以求得相對於這個關係的方差

取其平均值,則可以表示爲

J(θ) 越小,說明我們的預測將會越準確。所以問題求解轉換成了求使得J(θ)最小的θ值,即minJ(θ)

我們可以隨便給定一個θ值,然後在逐步縮小範圍,當θ值穩定在一個數值的時候,說明找到了一個值是可以另θ最小的。逐步縮小範圍的步驟可以用如下操作:

通過這個方法得出了θ值後,便確定了剛開始定義的h(θ), 利用這個函數便可以預測出練習時長和成績之間的關係。而這種方法便是機器學習中的線性迴歸。而求解θ的過程便是梯度下降算法。

求出θ後,便可以將θ代入h(θ)從而得到成績和練習時長的關係。

線性迴歸Python實現

首先我們來實現$J(\theta)$, 筆者使用Numpy做數值計算的庫,使用matplotlib做數據的可視化。

代價函數

根據上面提到的

我們來定義compute_cost函數,只需要按照公式轉化爲矩陣運算即可。

def compute_cost(X, y, theta):
    m = y.size
    prediction = X.dot(theta) - y
    sqr = np.power(prediction, 2)
    cost = (1 / (2 * m)) * np.sum(sqr)
    return cost

我們可以將代價函數與theta的關係可視化出來:

def plot_J_history(X, y):
    theta0_vals = np.linspace(-10, 10, 100)
    theta1_vals = np.linspace(-1, 4, 100)
    J_vals = np.zeros((theta0_vals.size, theta1_vals.size))
    for i in range(theta0_vals.size):
        for j in range(theta1_vals.size):
            theta = np.array([theta0_vals[i], theta1_vals[j]])
            t = compute_cost(X, y, theta)
            J_vals[i, j] = t
    theta_x, theta_y = np.meshgrid(theta0_vals, theta1_vals)
    fig = plt.figure()
    ax = fig.gca(projection='3d')
    ax.plot_surface(theta_x, theta_y, J_vals)
    ax.set_xlabel(r'$\theta$0')
    ax.set_ylabel(r'$\theta$1')
    plt.show()
plotData.plot_J_history(X, y)

得出的圖像大概是:

而這個圖像最低的點,就是需要通過遞歸下降算法求出的點。

遞歸下降

上述的遞歸下降的微分表達式可以轉化爲數值表達式

用python則可以表示爲:

def gradient_descent(X, y, theta, alpha, num_iters):
    m = y.size
    J_history = np.zeros((num_iters))
    for i in range(0, num_iters):
        prediction = X.dot(theta) - y
        delta = prediction.dot(X)
        theta = theta - alpha * (1 / m) * delta
        J_history[i] = compute_cost(X, y, theta)
    return theta, J_history

我們可以調用該函數求解$\theta$

theta = np.zeros((2,))
iterations = 1500
alpha = 0.01
theta, J_history = gradient_descent(X, y, theta, alpha, iterations)

求出$\theta$後代入$h(\theta)$就可以得出成績與練習時長的關係。

最後

其實,看起來很麻煩,但是利用sklearn分裝好的算法,只需要幾行就可以搞定線性迴歸

from sklearn.linear_model import LinearRegression
... 導入訓練數據
regressor = LinearRegression()
regressor = regressor.fit(X_train, Y_train)

這樣就好了,emmm…

相關文章