1. 程式人生 > >演算法工程師修仙之路:吳恩達機器學習作業(一)

演算法工程師修仙之路:吳恩達機器學習作業(一)

吳恩達機器學習筆記及作業程式碼實現中文版

第一個程式設計作業:單變數線性迴歸(python程式碼實現)


一元線性迴歸

  • 問題描述

    • 在本練習的這一部分中,您將使用只有單變數的線性迴歸方法預測餐車的利潤。
    • 假設你是一家連鎖餐廳的執行長,正在考慮在不同的城市開設一家新店。
    • 這家連鎖公司已經在不同的城市擁有餐車,你也有這些城市的利潤和人口資料。
    • 您希望使用這些資料來幫助您選擇要擴充套件到下一個城市。
    • 檔案ex1data1.txt包含線性迴歸問題的資料集。
    • 第一列是一個城市的人口,第二列是該城市一輛餐車的利潤。
    • 利潤的負值表示虧損。
  • 繪製資料

    • 在開始任何任務之前,通過視覺化來理解資料通常是有用的。

    • 對於這個資料集,您可以使用散點圖來視覺化資料,因為它只有兩個屬性需要繪製(利潤和總體)。

    • 你在現實生活中遇到的許多其他問題是多維的,不能在二維圖上畫出來。

    • 首先,我們匯入三個python庫:numpy,pandas,matplotlib:

      import numpy as np 
      import pandas as pd 
      import matplotlib.pyplot as plt 
      
    • 然後我們使用pandas的read_csv函式讀入檔案ex1data1.txt,並打印出結果:

      path = 'ex1data1.txt'
      data = pd.read_csv(path, header = None, names = ['Population', 'Profit'])
      data.head()
      print(data) 
      
    • 結果如下表所示,僅展示前五行內容:
      在這裡插入圖片描述

    • 接著我們給上表增加描述,得到一張新的表,表的內容已全部展示:

      data1 = data.describe()
      print(data1)
      

      在這裡插入圖片描述

    • 最後用plot方法得到訓練資料散點圖:

      data.plot(kind = 'scatter', x = 'Population', y = 'Profit', figsize = (12, 8))
      plt.show()
      

      在這裡插入圖片描述

  • 梯度下降法

    • 現在讓我們使用梯度下降來實現線性迴歸,以最小化成本函式。

    • 首先,我們將建立一個以引數θ為特徵函式的代價函式:

      • J ( θ ) = 1 2 m i = 1 m ( h θ ( x ( i ) ) y ( i ) ) 2 J\left( \theta \right)=\frac{1}{2m}\sum\limits_{i=1}^{m}{{{\left( {{h}_{\theta }}\left( {{x}^{(i)}} \right)-{{y}^{(i)}} \right)}^{2}}}
      • 其中: h θ ( x ) = θ T X = θ 0 x 0 + θ 1 x 1 + θ 2 x 2 + . . . + θ n x n {{h_\theta }}\left( x \right)={\theta^T}X={\theta _0}{x_0}+{\theta _1}{x_1}+{\theta_2}{x_2}+...+{\theta _n}{x_n}
        def computeCost(X, y, theta):
            inner = np.power(((X * theta.T)) - y, 2)
            return np.sum(inner) / (2 * len(X))
        
    • 讓我們在訓練集中新增一列,以便我們可以使用向量化的解決方案來計算代價和梯度。

      data.insert(0, 'ones', 1)
      
    • 現在我們來做一些變數初始化。

      cols = data.shape[1]
      X = data.iloc[:, 0:cols-1]
      y = data.iloc[:, cols-1:cols]
      
    • 觀察下 X (訓練集) and y (目標變數)是否正確。

      print(X.head())
      print(y.head())
      

      在這裡插入圖片描述
      在這裡插入圖片描述

    • 代價函式應該是numpy矩陣,所以我們需要轉換X和Y,然後才能使用它們,所以我們還需要初始化theta。

      X = np.matrix(X.values)
      y = np.matrix(y.values)
      theta = np.matrix(np.array([0, 0]))
      print(theta)
      
    • 此時theta已經是一個(1,2)矩陣[[0, 0]],看下維度:

      print(X.shape, theta.shape, y.shape)
      
    • 得到三個矩陣維度分別為:((97, 2), (1, 2), (97, 1))。

    • 計算代價函式 (theta初始值為0):

      result = computeCost(X, y, theta)
      print(result)
      
    • 得到結果為:32.0727338775。

  • 批量梯度下降

    • 確認梯度下降的一個好方法是觀察J(θ),然後檢查其值是否隨每一步計算而減少。假設您已經實現梯度下降法和computeCost正確,你的J(θ)不應該增加,而是應該收斂於一個穩定值的演算法。

    • 先給出公式: θ j = θ j α J ( θ 0 , θ 1 , . . . , θ n ) θ j \theta_j=\theta_j-\alpha*\frac{\partial J(\theta_0, \theta_1, ..., \theta_n)}{\partial \theta_j}

      def gradientDescent(X, y, theta, alpha, iters):
          temp = np.matrix(np.zeros(theta.shape))
          parameters = int(theta.ravel().shape[1])
          cost = np.zeros(iters)
      
          for i in range(iters):
              error = (X * theta.T) - y
      
              for j in range(parameters):
                  term = np.multiply(error, X[:, j])
                  temp[0, j] = theta[0, j] - ((alpha / len(X)) * np.sum(term))
              
              theta = temp
              cost[i] = computeCost(X, y, theta)
      
          return theta, cost
      
    • 初始化一些附加變數:學習速率α和要執行的迭代次數。

      alpha = 0.01
      iters = 1000
      
    • 現在讓我們執行梯度下降演算法來將我們的引數θ適合於訓練集。

      g, cost = gradientDescent(X, y, theta, alpha, iters)
      print(g)
      
    • 得到了一個g的矩陣:[[-3.24140214 1.1272942 ]]。

    • 最後,我們可以使用我們擬合的引數計算訓練模型的代價函式(誤差)。

      result1 = computeCost(X, y, g)
      print(result1)
      
    • 得到最後的代價值為:4.51595550308。

    • 現在我們來繪製線性模型以及資料,直觀地看出它的擬合。

      x = np.linspace(data.Population.min(), data.Population.max(), 100)
      f = g[0, 0] + (g[0, 1] * x)
      
      fig, ax = plt.subplots(figsize = (12, 8))
      ax.plot(x, f, 'r', label = 'Prediction')
      ax.scatter(data.Population, data.Profit, label = 'Traning Data')
      ax.legend(loc = 2)
      ax.set_xlabel('Population')
      ax.set_ylabel('Profit')
      ax.set_title('Predicted Profit vs. Population Size')
      plt.show()
      
    • 結果如下圖所示: 在這裡插入圖片描述

    • 由於梯度方程式函式也在每個訓練迭代中輸出一個代價的向量,所以我們也可以繪製。請注意,代價總是降低說明這是凸優化問題的一個例子。

      fig, ax = plt.subplots(figsize = (12,8))
      ax.plot(np.arange(iters), cost, 'r')
      ax.set_xlabel('Iterations')
      ax.set_ylabel('Cost')
      ax.set_title('Error vs. Training Epoch')
      plt.show()
      

      在這裡插入圖片描述