Python實現大規模機器學習和隨機梯度下降法

    上一片講解了Python實現批梯度下降法(batch gradient desent),不同於感知機算法每次計算一個樣本就更新一次結果,BGD算法 在計算完所有樣本一輪以後才更新一次權重,這樣當樣本量巨大的時候極大的影響了效率,因而出現了新的隨機梯度算法(Stochastic gradient desent)其也被稱爲迭代/在線梯度下降,其每次只用一個樣本對權重進行更新。除此之外還有最小批學習(mini-batch learning),使用一部分樣本進行權重更新。

代碼實現如下:(下載鏈接:https://github.com/Airuio/Implementing-Stochastic-gradient-descent-by-using-Python-)

import numpy as np
from numpy.random import seed

class AdalineSGD(object):
    def __init__(self,eta=0.01,n_iter=10,shuffle=True,random_state=None):
        self.eta = eta    #學習率
        self.n_iter = n_iter  #迭代輪數
        self.shuffle = shuffle   #打亂排序樣本
        self.w_initialized = False   #初始化標識
        if random_state:         #隨機種子(此處可不要,不影響程序)
            seed(random_state)
            
    def fit(self,X,y):
        self._initialize_weights(X.shape[1])    #初始化權重並標記已經初始化
        self.cost_ = []
        for i in range(self.n_iter):
            if self.shuffle:                    #每輪開始時重新給樣本排序
                X,y = self._shuffle(X,y)
            cost = []
            for xi, target in zip(X,y):         
                cost.append(self._update_weights(xi, target))  #更新權重值
            agv_cost = sum(cost)/len(y)
            self.cost_.append(agv_cost)   #記錄本輪的損失函數均值
        return self
    
    def partial_fit(self,X,y):       #實現在線學習,實時更新權重時調用此函數
        if not self.w_initialized:   #檢查是否存在權重w,不存在則初始化。
            self._initialize_weights(X.shape[1])
        if y.reval().shape[0] > 1:
            for xi, target in zip(X,y):     #調用新數據進行更新
                self._updata_weights(xi,target)
        else:
            self._update_weights(x,y)
        return self
        
    def _initialize_weights(self,m):     #初始化權重,標記
        self.w_ = np.zeros(1+m)
        self.w_initialized = True
        
    def _shuffle(self,X,y):     #隨機排序
        r = np.random.permutation(len(y))
        return X[r],y[r]
    
    def _update_weights(self,xi,target):
        output = self.net_input(xi)    #計算預測值
        errors = (target - output)   #統計誤差
        self.w_[1:] += self.eta*xi.dot(errors)
        self.w_[0] += self.eta * errors
        cost = (errors**2).sum()/2.0  #損失函數
        return cost
    
    def net_input(self,X):    #計算預測值
        return np.dot(X,self.w_[1:]) + self.w_[0]
    
    def activation(self,X):    #激活函數~~此處等於預測值
        return self.net_input(X) 

    def predict(self, X):    #返回預測輸出

        return np.where(self.activation(X) >= 0.0, 1, -1) 


同樣的本文使用鳶尾花lris數據集進行試驗,代碼如下:

from AdalineSGD import AdalineSGD
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap

df = pd.read_excel(io = 'lris.xlsx',header = None)    #讀取數據爲Dataframe結構,沒有表頭行
y = df.iloc[0:100,4].values         #取前100列數據,4列爲標識
y = np.where(y == 'Iris-setosa', -1,1)
X = df.iloc[0:100,[0,2]].values  #iloc爲選取表格區域,此處取二維特徵進行分類,values爲返回不含索引的表
X_std = np.copy(X)                #將樣本特徵歸一化、標準化
X_std[:,0] = (X[:,0] - X[:,0].mean()) / X[:,0].std()
X_std[:,1] = (X[:,1] - X[:,1].mean()) / X[:,1].std()

ada = AdalineSGD(eta = 0.01, n_iter = 15,random_state = None)
ada.fit(X_std,y)
def plot_decision_region(X,y,classifier,resolution = 0.02):
    markers = ('s','x','o','~','v')
    colors = ('red','blue','lightgreen','gray','cyan')
    cmap = ListedColormap(colors[:len(np.unique(y))])
    #畫出界面
    x1_min, x1max = X[:,0].min() - 1, X[:,0].max() + 1   
    x2_min, x2max = X[:,1].min() - 1, X[:,1].max() + 1  
    xx1,xx2 = np.meshgrid(np.arange(x1_min,x1max,resolution),  
                          np.arange(x2_min,x2max,resolution))   #生成均勻網格點,
    '''meshgrid的作用是根據傳入的兩個一維數組參數生成兩個數組元素的列表。如果第一個參數是xarray,
    維度是xdimesion,第二個參數是yarray,維度是ydimesion。那麼生成的第一個二維數組是以xarray爲行,
    ydimesion行的向量;而第二個二維數組是以yarray的轉置爲列,xdimesion列的向量。'''

    Z = classifier.predict(X = np.array([xx1.ravel(),xx2.ravel()]).T)
    Z = Z.reshape(xx1.shape)
    #在全圖上每一個點(間隔0.2)計算預測值,並返回1或-1
    
    plt.contourf(xx1,xx2,Z,alpha = 0.5,cmap = cmap) #畫出等高線並填充顏色
    plt.xlim(xx1.min(),xx1.max())
    plt.ylim(xx2.min(),xx2.max())

    #畫上分類後的樣本
    for idx,cl in enumerate(np.unique(y)):
        plt.scatter(x=X[y==cl,0], y=X[y==cl,1],alpha=0.8,
                    c=cmap(idx),marker=markers[idx],label=cl)
 
plot_decision_region(X_std, y, classifier = ada)    #展示分類結果
plt.xlabel('sepal lenth [nondimensional]')
plt.ylabel('petal lenth [nondimensional]')    
plt.legend(loc = 2)
plt.show()

plt.plot(range(1,len(ada.cost_)+1),ada.cost_,marker = 'o')   #展示損失函數誤差收斂過程
plt.xlabel('Epoches')
plt.ylabel('Average cost_')

plt.show()    

運行結果如下:


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章