隨機(jī)梯度下降法:stochastic gradient descent
大綱
1. look --- 大數(shù)據(jù)情況遇到什么問題
2. write --- 隨機(jī)梯度下降法
3. code --- python
Large scale 帶來的問題
每次更新權(quán)值都要計算所有的數(shù)據(jù)點(diǎn)颁股,才能進(jìn)行一次更新
數(shù)據(jù)量大的情況下殷费,性能會很差
stochastic gradient descent
隨機(jī)梯度下降算法刃宵,相比批量梯度下降豹绪,它每讀到一個數(shù)據(jù)點(diǎn)刁绒,都會進(jìn)行一次權(quán)值更新
- 好處:快,幾十萬的數(shù)據(jù)有可能在第幾千個的時候就會收斂
- 壞處:因為是每個數(shù)據(jù)點(diǎn)都會更新權(quán)值,呢些離群點(diǎn)會對算法影響很大,算法噪聲大
解決方法
- 利用洗牌算法觅捆,每次迭代都用隨機(jī)序列防止循環(huán)
- 自適應(yīng)的學(xué)習(xí)率,
a / (b + number of iteration)
麻敌,a,b是常數(shù)栅炒,比固定的學(xué)習(xí)率有更大的機(jī)會達(dá)到最小誤差的收斂點(diǎn)
隨機(jī)梯度下降算法
由圖可見,由于是每個點(diǎn)都進(jìn)行權(quán)值更新,在算法初期收斂速度很快赢赊,又因為是自適應(yīng)的學(xué)習(xí)率乙漓,越接近最小無差點(diǎn),逼近速度越慢
根據(jù)計算得到的分類平面如圖
隨機(jī)梯度很適合在線學(xué)習(xí)释移,因為它不需要所有的訓(xùn)練點(diǎn)就可以進(jìn)行模型訓(xùn)練叭披。同時更加節(jié)約內(nèi)存
Code!P惚蕖趋观!
from numpy.random import seed
class AdalineSGD(object):
# -------- 參數(shù) --------#
# 參數(shù)1 eta:float 學(xué)習(xí)率
# 參數(shù)2 n_iter:int 循環(huán)次數(shù)
# -------- 屬性 --------#
# 屬性1 w_:1d_array 擬合后權(quán)值
# 屬性2 errors_:list 每次迭代的錯誤分類
# 屬性3 shuffles:bool 每次迭代時候打亂順序
# 屬性4 random_state:int 設(shè)置循環(huán)狀態(tài),初始化權(quán)值
# 初始化
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)
# 訓(xùn)練模型
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))
avg_cost = sum(cost)/len(y)
self.cost_.append(avg_cost)
return self
# 不初始化權(quán)值進(jìn)行對訓(xùn)練數(shù)據(jù)進(jìn)行擬合
def partial_fit(self,X,y):
if not self.w_initialized:
self._initialize_weights(X.shape[1])
if y.ravel().shapr[0] > 1:
for xi,target in zip(X,y):
self._update_weights(xi,target)
else:
self._update_weights(X,y)
return self
# 輸入和權(quán)值的點(diǎn)積,即公式的z函數(shù),圖中的net_input
def net_input(self,X):
return np.dot(X,self.w_[1:]) + self.w_[0]
# 線性激活函數(shù)
def activation(self,X):
return self.net_input(X)
# 利用階躍函數(shù)返回分類標(biāo)簽
def predict(self,X):
return np.where(self.activation(X)>=0.0,1,-1)
# 對數(shù)據(jù)進(jìn)行隨機(jī)打亂
def _shuffle(self,X,y):
r = np.random.permutation(len(y)) # 隨機(jī)索引值
return X[r],y[r]
# 初始化權(quán)值向量
def _initialize_weights(self,m):
self.w_ = np.zeros(1+m)
self.w_initialized = True
# 應(yīng)用自適應(yīng)線性神經(jīng)網(wǎng)絡(luò)更新權(quán)值
def _update_weights(self,xi,target):
output = self.net_input(xi)
error = (target-output)
self.w_[1:] += self.eta * xi.dot(error)
self.w_[0] += self.eta * error
cost = 0.5 * error ** 2
return cost