小批量梯度下降演算法的Python實現
阿新 • • 發佈:2019-01-02
小批量梯度下降演算法的核心思想仍然是基於梯度,通過對目標函式中的引數不斷迭代更新,使得目標函式逐漸靠近最小值。它是批量梯度下降與隨機梯度下降的折中,有著訓練過程較快,同時又能保證得到較為精確的訓練結果。在一些情況下,小批量梯度下降比批量梯度下降和隨機梯度下降的速度都要快。
具體程式碼實現如下:
先匯入要用到的各種包:
%matplotlib notebook
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
讀入資料並檢視資料的相關資訊:
檢視data中前五條資料:
data = pd.read_excel('gongyeyuan.xlsx','Sheet2') data.head()
檢視data的各描述統計量資訊:
data.describe()
繪製原始資料的散點圖:
fig,axes = plt.subplots()
data.plot(kind='scatter',x='Area',y='Price',marker='o',color='k',ax=axes)
axes.set(xlabel='Area',ylabel='Price',title='Price vs. Area')
fig.savefig('p1.png')
向data中新增一列便於矩陣計算的輔助列:
data.insert(0,'Ones',1) data.head()
小批量梯度下降的實現:
# 定義資料特徵和標籤的提取函式: def get_fea_lab(train_data): cols = train_data.shape[1] X = train_data.iloc[:,0:cols-1] # X取data中不包括索引列的前兩列 y = train_data.iloc[:,cols-1:cols] # y取data中的最後一列 X = np.matrix(X.values) y = np.matrix(y.values) return X,y # 定義小批量樣本的代價函式: def computeCost(train_data,theta,k,mb_size): X,y = get_fea_lab(train_data) X = X[k:k+mb_size] y = y[k:k+mb_size] inner = np.power(((X*theta.T)-y),2) term = np.sum(inner)/(2*mb_size) return term #定義小批量梯度下降函式: def mb_gradient_descent(train_data,theta,alpha,mb_size): X,y = get_fea_lab(train_data) temp = np.matrix(np.zeros(theta.shape)) # temp用於存放theta引數的值 parameters = int(theta.shape[1]) # parameter用於存放theta引數的個數 m = len(X) # m用於存放資料集中的樣本個數 cost = np.zeros(int(np.floor(m/mb_size))) # cost用於存放代價函式 st_posi = list(np.arange(0,m,mb_size)) # st_posi用於存放每次小批量迭代開始的位置 new_st_posi = st_posi[:len(cost)] # 去掉最後一次小批量迭代開始的位置 k = 0 for i in new_st_posi: cost[k] = computeCost(train_data,theta,i,mb_size) k = k + 1 error = (X*theta.T) - y for j in range(parameters): t = np.multiply(error,X[:,j]) term = t[i:i + mb_size] temp[0,j] = theta[0,j] - (alpha/mb_size)*(np.sum(term)) theta = temp return theta, cost # 初始化相關引數: theta = np.matrix(np.array([0,0])) alpha = 0.00001 mb_size = 50 # 呼叫隨機梯度下降函式來計算線性迴歸中的theat引數: new_data = data.sample(frac=1) # 打亂資料,沒有這一步也可以 g,cost = mb_gradient_descent(new_data,theta,alpha,mb_size) # g的值為matrix([[0.02717606, 3.3047963 ]])
繪製代價函式的值與迭代次數的關係影象:
fig, axes = plt.subplots()
axes.plot(np.arange(len(cost)), cost, 'r')
axes.set_xlabel('iters')
axes.set_ylabel('cost')
axes.set_title('cost vs. iters')
fig.savefig('p2.png')
本文所用的資料集中一共有5106條資料。在小批量梯度下降演算法中,筆者採用的mini_batch_size(即演算法中的mb_size引數)為50。從上圖中我們可以看到在僅僅迭代了20次後,代價函式的值已經開始在某個值上下進行小範圍波動。經過大約100次迭代後,得到的theta引數值為matrix([[0.02717606, 3.3047963 ]])。而用正規方程求出的theta引數的精確值為matrix([[-2.34868067],[ 3.31348565]]),可以看出兩者差別在一定程度上是可以接受的。關於用正規方程求解線性迴歸引數可以參考:https://blog.csdn.net/qq_41080850/article/details/85292769、https://blog.csdn.net/qq_41080850/article/details/85159645。
根據前文計算出的theta引數值,繪製原始資料的線性擬合圖:
x = np.linspace(data.Area.min(),data.Area.max(),100)
f = g[0,0] + g[0,1]*x
fig,axes = plt.subplots()
axes.plot(x,f,'r',label='Fitted')
axes.scatter(x=data.Area,y=data.Price,label='Trainning data')
axes.legend(loc='best')
axes.set(xlabel='Area',ylabel='Price',title='Area vs. Price')
fig.savefig('p3.png')
參考:Andrew Ng機器學習公開課
PS:本文為博主原創文章,轉載請註明出處。