五、完整測試程式碼實現

# coding=utf-8
# 線性迴歸-單特徵梯度下降練習
from numpy import *
import matplotlib.pyplot as plt
from matplotlib import animation
import numpy as np


# 【1】特徵縮放 X:=[X-mean(X)]/std(X) || X:=[X-min(X)]/max(X)-min(X) ;
def feature_scaling(data_set):
    # 特徵縮放參數
    max_value = data_set.max(0)
    min_value = data_set.min(0)
    # avg_value = (min_value + max_value)/2
    diff_value = max_value - min_value
    norm_data_set = zeros(shape(data_set))  # 初始化與data_set結構一樣的零array
    m = data_set.shape[0]
    norm_data_set = data_set - tile(min_value, (m, 1))  # avg_value
    norm_data_set = norm_data_set/tile(diff_value, (m, 1))
    return norm_data_set, diff_value, min_value


# def hy(theta, x_sample):
#      # hypothsis = theta0 + theta1 * x1 + theta2 * x2 .....
#     temp = [thetai * xi for thetai, xi in zip(theta, x_sample)]
#     result = sum(temp)
#     return result
def create_hy(θ1, θ0):
    return lambda xi: θ1*xi + θ0


# 【2】梯度下降  hypothsis = theta0 + theta1 * x1 + theta2 * x2 .....
# α=0.001 0.01 0.03 0.1 0.3 1 3 10
def step_gradient(xa, ya, α=0.001, variance=0.00001):
    # init the parameters to zero
    θ0_temp = θ1_temp = 1.
    θ0_last = θ1_last = 100.
    reduction = 1
    # 迴圈
    while reduction > variance:
        hypothesis = create_hy(θ1_temp, θ0_temp)
        m = len(xa)
        # 計算θ0、θ1
        θ0_temp -= α * (1./2) * sum([hypothesis(xa[i]) - ya[i] for i in range(m)])
        θ1_temp -= α * (1./2) * sum([(hypothesis(xa[i]) - ya[i]) * xa[i] for i in range(m)])
        # 儲存梯度下降過程theta0,theta1
        theta.append((θ0_temp, θ1_temp))
        # 畫線
        reduction = min(abs(θ0_temp - θ0_last), abs(θ1_temp - θ1_last))
        θ0_last = θ0_temp
        θ1_last = θ1_temp
    return θ0_temp, θ1_temp, theta

# 主方法
if __name__ == "__main__":
    # 開啟訓練集檔案
    f = open(r"F:\Users\Share\python\data.csv", "r")
    rows = f.readlines()
    # 設訓練集為房屋價格
    x1 = []  # 房屋大小 平方米 x∈(25,71) avg=48
    y1 = []  # 房屋價格 萬 y∈(30,120) avg=75
    # 轉列表儲存
    for row in [value.split(",") for value in rows]:
        x1.append(float(row[0]))
        y1.append(float(row[1]))
    # 關閉開啟的檔案
    f.close()
    # 特徵縮放
    # x, y = feature_scaling1(x1, y1)
    x, diff_x, min_x = feature_scaling(np.array(x1))
    y, diff_y, min_y = feature_scaling(np.array(y1))
    theta = []

    # 線性迴歸:單特徵梯度下降
    t0, t1, thetaArr = step_gradient(x.tolist()[0], y.tolist()[0])
    print("Final result: theta0_guess:%f theta1_guess:%f" % (t0, t1))
    # 繪圖
    fig = plt.figure()
    # ax = plt.axes(xlim=(-0.6, 0.6), ylim=(-0.6, 0.6))
    ax = plt.axes(xlim=(-0.5, 1.5), ylim=(-0.5, 1.2))
    line, = ax.plot([], [],  color='m', linewidth=2)
    label = ax.text([], [], '')

    # 初始化動畫節點
    def init():
        line.set_data([], [])
        plt.plot(x, y, 'bo')
        plt.title('house detail')
        plt.xlabel('size')
        plt.ylabel('price')
        return line

    xx = [-0.55, 0.0, 0.34, 0.78]  # 畫線點

    # 動畫迴圈
    def animate(i):
        global ax, line, label
        yy = []
        θ = thetaArr[i]
        for xxi in xx:
            yy.append(θ[0]+xxi*θ[1])
        line.set_data(xx, yy)
        label.set_position([θ[0], θ[1]])
        return line, label

    # animation動態記錄
    anim = animation.FuncAnimation(fig, animate, init_func=init, frames=len(theta), interval=1000, repeat=True)
    # 要儲存gif 調小frames引數
    anim.save('D:\MeetYou\Learning\MachineLearning\GradientDescent\GradientDescent.gif'
              , writer='imagemagick', fps=1)
    plt.show()

總結:

從以上python實現示例可以看出:.
  1. 批梯度下降的收斂速度會比較慢
  2. 必要的特徵縮放;
  3. 必要的animation動圖,讓你更瞭解梯度下降過程。

--------------------------------------------我是分割線--------------------------------------------
高峰屹立,積跬步,行不止。