線性迴歸和梯度下降講解與程式碼
阿新 • • 發佈:2018-11-01
本文也是根據吳恩達機器學習課程作業的答案。
迴歸:預測值是連續的; 分類:預測值是離散的;
建模誤差:預測值與實際值之間的差距;
目標:選擇模型引數,使得建模誤差的平方和能夠最小,即代價函式最小;
代價函式:選擇平方誤差函式,是解決迴歸問題最常用的手段;代價函式是幫助我們選擇最優的引數的方法,即設定標準為引數使得建模誤差最小;
梯度下降:用來求函式最小值的演算法,它背後的思想是,開始時隨機選擇一個引數的組合,計算代價函式,然後尋找下一個能讓代價函式值下降最多的引數組合。持續知道得到一個區域性最小值。實現梯度下降演算法的微妙之處是,同時更新引數;
梯度下降的直觀理解:微分部分是那個點的斜率,右邊部分的曲線的斜率是不斷減小的,區域性最優點的斜率為0(假設代價函式為拋物線);
批量梯度下降:在梯度下降的每一步中,我們都用到了所有的訓練樣本;
在多變數線性迴歸中
為了將特徵向量化,引入x0=1,故該式實際變數為n。特徵矩陣X的維度是m*(n+1)
特徵縮放:保證特徵都具有相似的尺度(-1,1),將幫助梯度下降演算法更快的收斂。
正規方程:求解正規方程找出使得代價函式最小的引數。
線性迴歸程式碼實現最主要的部分就是代價函式的計算和梯度下降(對損失函式進行極小化),即對以下兩個公式的實現。在程式碼最後面專門定義了函式
import matplotlib.pyplot as plt #繪圖框架 import numpy as np from matplotlib.colors import LogNorm #將顏色規範化在log級別的0-1內 from mpl_toolkits.mplot3d import axes3d, Axes3D from computeCost import * from gradientDescent import * from plotData import * #有一個plotData.py的檔案需要把程式碼補齊 # ===================== Part 1: Plotting =====================視覺化為了理解資料 print('Plotting Data...') data = np.loadtxt('ex1data1.txt', delimiter=',', usecols=(0, 1)) #讀取檔案,分隔值的字元,確定讀取的列 X = data[:, 0] #冒號左邊是行範圍,右邊列範圍。取二維陣列中第一列的所有資料 y = data[:, 1] #取二維陣列中第二列的所有資料 m = y.size plt.ion() #開啟互動模式,plt.plot()直接出影象,不需要show()。沒有ioff()關閉的話,影象一閃而過,不會常留 plt.figure(0) plot_data(X, y) #在plotdata.py中定義了一個plot_data的函式 input('Program paused. Press ENTER to continue') # ===================== Part 2: Gradient descent ===================== print('Running Gradient Descent...') X = np.c_[np.ones(m), X] # Add a column of ones to X。np_c按行連線兩個矩陣(矩陣左右相加),行數相等 theta = np.zeros(2) # initialize fitting parameters。 theta = array([0, 0]) # Some gradient descent settings 迭代次數,學習速率(步長) iterations = 1500 alpha = 0.01 # Compute and display initial cost print('Initial cost : ' + str(compute_cost(X, y, theta)) + ' (This value should be about 32.07)') #需要對computerCost.py補全,代價函式=1/2m * sum(f(x)-y)**2),pdf第五頁的公式 theta, J_history = gradient_descent(X, y, theta, alpha, iterations) #在gradientDescent.py處對程式碼補全 print('Theta found by gradient descent: ' + str(theta.reshape(2))) # Plot the linear fit plt.figure(0) line1, = plt.plot(X[:, 1], np.dot(X, theta), label='Linear Regression') plt.legend(handles=[line1]) input('Program paused. Press ENTER to continue') # Predict values for population sizes of 35,000 and 70,000 predict1 = np.dot(np.array([1, 3.5]), theta) print('For population = 35,000, we predict a profit of {:0.3f} (This value should be about 4519.77)'.format(predict1*10000)) predict2 = np.dot(np.array([1, 7]), theta) print('For population = 70,000, we predict a profit of {:0.3f} (This value should be about 45342.45)'.format(predict2*10000)) input('Program paused. Press ENTER to continue') # ===================== Part 3: Visualizing J(theta0, theta1) ===================== print('Visualizing J(theta0, theta1) ...') theta0_vals = np.linspace(-10, 10, 100) #建立等差數列。起始,終止,樣本數 theta1_vals = np.linspace(-1, 4, 100) xs, ys = np.meshgrid(theta0_vals, theta1_vals) #生成一個座標矩陣 J_vals = np.zeros(xs.shape) # Fill out J_vals for i in range(0, theta0_vals.size): for j in range(0, theta1_vals.size): t = np.array([theta0_vals[i], theta1_vals[j]]) J_vals[i][j] = compute_cost(X, y, t) J_vals = np.transpose(J_vals) fig1 = plt.figure(1) ax = fig1.gca(projection='3d') ax.plot_surface(xs, ys, J_vals) plt.xlabel(r'$\theta_0$') plt.ylabel(r'$\theta_1$') plt.figure(2) lvls = np.logspace(-2, 3, 20) plt.contour(xs, ys, J_vals, levels=lvls, norm=LogNorm()) plt.plot(theta[0], theta[1], c='r', marker="x") input('ex1 Finished. Press ENTER to exit') def plot_data(x, y): plt.scatter(x, y, c = 'r', marker = 'o') plt.xlabel('population') plt.ylabel('revenue') plt.show() def compute_cost(X, y, theta): # Initialize some useful values m = y.size cost = 0 cost = np.sum((np.dot(X, theta) - y)**2) / (2*m) return cost def gradient_descent(X, y, theta, alpha, num_iters): # Initialize some useful values m = y.size J_history = np.zeros(num_iters) for i in range(0, num_iters): error = np.dot(X, theta).flatten() - y theta -= (alpha/m)*np.sum(X*error[:, np.newaxis], 0) J_history[i] = compute_cost(X, y, theta) return theta, J_history def gradient_descent_multi(X, y, theta, alpha, num_iters): # Initialize some useful values m = y.size J_history = np.zeros(num_iters) for i in range(0, num_iters): error = np.dot(X, theta).flatten() - y theta -= (alpha / m) * np.sum(X * error[:, np.newaxis], 0) J_history[i] = compute_cost(X, y, theta) return theta, J_history