机器学习:SVM代码实现,第一个变量选择最偏离KKT条件的样本点,第二个变量随机
生活随笔
收集整理的這篇文章主要介紹了
机器学习:SVM代码实现,第一个变量选择最偏离KKT条件的样本点,第二个变量随机
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- SMO算法描述:
- 代碼實現
- 確定第一個變量:
- 確定第二個變量:
- 更新alpha值:
- 更新dw,db,y^,注意參數傳入的方法:
- 主要處理程序(一):一個回合的處理
- 主要處理程序(二):整體epoch處理
- 其他輔助函數:
SMO算法描述:
代碼實現
確定第一個變量:
# 找第一個樣本def _pick_first(self,tol):# mask,漏出需要的元素con1 = self._alpha >0con2 = self._alpha <self._c# 復制成3分# 預測值通過局部更新方式更新err1 = self._y *self._prediction_cache -1err2 = err1.copy()err3 = err1.copy()# 三種情況的處理err1[(con1 & (err1 <= 0)) | (~con1 & (err1 > 0))] = 0err2[((~con1 | ~con2) & (err2 != 0)) | ((con1 & con2) & (err2 == 0))] = 0err3[(con2 & (err3 >= 0)) | (~con2 & (err3 < 0))] = 0# 算出損失最大的那個err = err1**2 + err2**2 + err3**2idx = np.argmax(err)# 如果該項的損失等于0,返回,否則返回選取的下標if err[idx] < tol:returnreturn idx確定第二個變量:
# 找第二個樣本,這里實現的是隨機挑選def _pick_second(self,idx1):idx = np.random.randint(len(self._y))while idx == idx1:idx = np.random.randint(len(self._y))return idx更新alpha值:
def _update_alpha(self,idx1,idx2):l,h = self._get_lower_bound(idx1, idx2), self._get_upper_bound(idx1, idx2)y1, y2 = self._y[idx1],self._y[idx2]e1 = self._prediction_cache[idx1] - y1e1 = self._prediction_cache[idx2] - y2# dK = K11 + K22 -2K12eta = self._gram[idx1][idx1] + self._gram[idx2][idx2] - 2*self._gram[idx1][idx2]a2_new = self._alpha[idx2] + (y2*(e1-e2)) / eta# 約束條件約束if a2_new > h:a2_new = helif a2_new < l:a2_new = la1_old, a2_old = self._alpha[idx1],self._alpha[idx2]da2 = a2_new - a2_oldda1 = -y1*y2*da2# 更新alphaself._alpha[idx1] +=da1self._alpha[idx2] = a2_new# 根據da來更新dw,db,y^self._update_dw_cache(idx1, idx2, da1, da2, y1, y2)self._update_dw_cache(idx1, idx2, da1, da2, y1, y2, e1, e2)# 注意參數傳入的方法self._update_pred_cache(idx1, idx2)更新dw,db,y^,注意參數傳入的方法:
# 更新dwdef _update_dw_cache(self, idx1, idx2, da1, da2, y1, y2):self._dw_cache = np.array([da1*y1,da2*y2])# 更新bdef _updata_b_cache(self, idx1, idx2, da1, da2, y1, y2, e1, e2):gram_12 = self._gram[idx1][idx2]b1 = -e1 - y1 * self._gram[idx1][idx1] * da1 - y2 * gram_12 * da2b2 = -e2 - y1 * gram_12 * da1 - y2 * self._gram[idx2][idx2] * da2# 這里分兩種情況,兩種情況下都是(b1 + b2) * 0.5self._db_cache = (b1 + b2) * 0.5self._b += self._db_cache # y^ = y^ + dw1K1 + dw2k2 + db ,注意參數傳入的方法 def _update_pred_cache(self,*args):self._prediction_cache += self._db_cacheif len(args) == 1:self._prediction_cache += self._dw_cache * self._gram[args[0]]else:self._prediction_cache += self._dw_cache.dot(self._gram[args, ...])主要處理程序(一):一個回合的處理
def _fit(self,sample_weight, tol):idx1 = self._pick_first(tol)# 如果所有的樣本誤差均小于閾值if idx1 is None:return Trueidx2 = self._pick_second(idx1)# 更新self._update_alpha(idx1,idx2)主要處理程序(二):整體epoch處理
def fit(self, x, y, kernel="rbf", epoch=10**4, **kwargs):self._x, self._y = np.atleast_2d(x), np.array(y)if kernel == "poly":# 對于多項式,默認使用kernelconfig中的default_p作為p的值_p = kwargs.get("p", KernelConfig.default_p)self._kernel_name = "Polynomial"self._kernel_param = "degree = {}".format(_p)self._kernel = lambda _x, _y : KernelBase._poly(_x,_y,_p)elif kernel == "rbf":# 對于rbf使用屬性個數的倒數為gamma_gamma = kwargs.get("gamma", 1 / self._x.shape[1])self._kernel_name = "RBF"self._kernel_param = "gamma = {}".format(_gamma)self._kernel = lambda _x, _y : KernelBase._rbf(_x,_y,_gamma) # 初始化參數self._alpha = np.zeros(len(x))self._w = np.zeros(len(x))self._prediction_cache = np.zeros(len(x))self._gram = self._kernel(self._x, self._x)self._b = 0# 調用——prepare方法進行特殊參數的初始化self._prepare(**kwargs)# 獲取在循環體中會用到的參數_fit_args = []for _name, _args in zip(self._fit_args_names, self._fit_args):if _name in kwargs:_arg = kwargs[_name]_fit_args.append(_arg)for _ in range(epoch):# 如果所有的樣本誤差均足夠下,退出訓練if self._fit(sample_weight, *_fit_args):breakself._update_params()其他輔助函數:
# 定義計算多項式核矩陣函數@staticmethoddef _poly(x, y, p):return (x.dot(y.T) + 1)**p# 定義計算RBF核矩陣函數# x[...,None,:]為升維@staticmethoddef _rbf(x, y, gamma):return np.exp(-gamma*np.sum((x[...,None,:] - y)**2), axis=2)class KernelConfig:default_p = 3default_c = 1# 更新w,b,這里的w不同于我們的w,是w . K + b的wdef _update_params(self):self._w = self._alpha * self._y# 取O·C最大的a_idx = np.argmax((self._alpha !=0) & (self._alpha != self._c))self._b = self._y[idx] - np.sum(self._alpha * self._y * self._gram[_idx])# 初始化懲罰因子def _prepare(self,**kwargs):self._c = kwargs.get("c", KernelConfig.default_c) 與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的机器学习:SVM代码实现,第一个变量选择最偏离KKT条件的样本点,第二个变量随机的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 机器学习:SVM代码实现,朴素实现基础上
- 下一篇: 机器学习:SVM多分类,SVM回归(SV