VII.應用-推薦系統-基於RBM的推薦演算法
受限玻爾茲曼機-推導過程
受限玻爾茲曼機示意圖如下:
假設一個RBM有n個可見單元和m個隱單元,RBM作為一個系統所具備的能量定義為
同時的聯合概率為
對於一個實際問題,我們最關心的是由RBM所定義的關於觀測數據v的分布,即聯合概率的邊際分布,也稱為似然函數(likehood function),根據概率的加法原則可以得到
同理:
RBM的任務就是求出參數的值,參數用最大似然方法求得(假設有T個樣本),即
由於:
則對數似然函數關於的梯度為
其中:
第二個期望的求解過程如下:
求解上述公式中的,因為,所以需要分別求偏導:
求解第一個期望的過程與第二個很類似。
最後得到:
受限玻爾茲曼機-對比散度
- 計算
- 計算 ,然後進行採樣
- 計算
- 更新公式為:
受限玻爾茲曼機-推薦演算法
# coding:utf-8import timeimport numpy as npimport pandas as pdclass BRBM(object): def __init__(self, n_visible, n_hiddens=2, learning_rate=0.1, batch_size=10, n_iter=300): self.n_hiddens = n_hiddens self.learning_rate = learning_rate self.batch_size = batch_size self.n_iter = n_iter self.components_ = np.asarray(np.random.normal(0, 0.01, (n_hiddens, n_visible)), order=fortran) self.intercept_hidden_ = np.zeros(n_hiddens, ) self.intercept_visible_ = np.zeros(n_visible, ) self.h_samples_ = np.zeros((batch_size, n_hiddens)) def transform(self, x): h = self._mean_hiddens(x) return h def reconstruct(self, x): h = self._mean_hiddens(x) v = self._mean_visible(h) return v def gibbs(self, v): h_ = self._sample_hiddens(v) v_ = self._sample_visibles(h_) return v_ def fit(self, x): n_samples = x.shape[0] n_batches = int(np.ceil(float(n_samples) / self.batch_size)) batch_slices = list(self._slices(n_batches * self.batch_size, n_batches, n_samples)) for iteration in xrange(self.n_iter): for batch_slice in batch_slices: self._fit(x[batch_slice]) return self def _sigmoid(self, x): return 1.0 / (1.0 + np.exp(-x)) def _mean_hiddens(self, v): p = np.dot(v, self.components_.T) p += self.intercept_hidden_ return self._sigmoid(p) def _mean_visible(self, h): p = np.dot(h, self.components_) p += self.intercept_visible_ return self._sigmoid(p) def _sample_hiddens(self, v): p = self._mean_hiddens(v) return np.random.random_sample(size=p.shape) < p def _sample_visibles(self, h): p = self._mean_visible(h) return np.random.random_sample(size=p.shape) < p def _free_energy(self, v): return (- np.dot(v, self.intercept_visible_) - np.logaddexp(0, np.dot(v, self.components_.T) + self.intercept_hidden_).sum(axis=1)) def _fit(self, v_pos): h_pos = self._mean_hiddens(v_pos) v_neg = self._sample_visibles(self.h_samples_) h_neg = self._mean_hiddens(v_neg) lr = float(self.learning_rate) / v_pos.shape[0] update = np.dot(v_pos.T, h_pos).T update -= np.dot(h_neg.T, v_neg) self.components_ += lr * update self.intercept_hidden_ += lr * (h_pos.sum(axis=0) - h_neg.sum(axis=0)) self.intercept_visible_ += lr * (np.asarray(v_pos.sum(axis=0)).squeeze() - v_neg.sum(axis=0)) h_neg[np.random.uniform(size=h_neg.shape) < h_neg] = 1.0 # sample binomial self.h_samples_ = np.floor(h_neg, h_neg) def _slices(self, n, n_packs, n_samples=None): start = 0 for pack_num in range(n_packs): this_n = n // n_packs if pack_num < n % n_packs: this_n += 1 if this_n > 0: end = start + this_n if n_samples is not None: end = min(n_samples, end) yield slice(start, end, None) start = end
推薦閱讀:
TAG:推薦演算法 |