SCIPY - 確率勾配降下のためのスパース行列コードをさらに最適化する方法
-
21-12-2019 - |
質問
Scipyを使ってスパース行列を使用して推奨システムの確率勾配降下アルゴリズムの実装に取り組んでいます。
これは、最初の基本的な実装がどのように見えるかです。
N = self.model.shape[0] #no of users
M = self.model.shape[1] #no of items
self.p = np.random.rand(N, K)
self.q = np.random.rand(M, K)
rows,cols = self.model.nonzero()
for step in xrange(steps):
for u, i in zip(rows,cols):
e=self.model-np.dot(self.p,self.q.T) #calculate error for gradient
p_temp = learning_rate * ( e[u,i] * self.q[i,:] - regularization * self.p[u,:])
self.q[i,:]+= learning_rate * ( e[u,i] * self.p[u,:] - regularization * self.q[i,:])
self.p[u,:] += p_temp
.
残念ながら、私のコードはまだほとんど遅いですが、小さい4×5の評価マトリックスでも。私はこれがおそらくループのスパース行列によるものであると考えていました。私はQとPの変化を表現しようとしました。
スパース行列の行と列を明示的に繰り返すのを避けることができた方法についてのポインタはありますか?
解決
推薦システムについてはほとんど忘れているので、私はあなたのコードを誤って翻訳しているかもしれませんが、それぞれのループの中のself.model-np.dot(self.p,self.q.T)
を再評価するかもしれませんが、私はほとんど確信していません。
それからあなたが手で行列乗算するように思われるようです、それはおそらく直接行列のミュージプレクション(numpyやscipyがあなたより速くそれを手で早くする)でスピードアップすることができるようです、そのようなもの:
for step in xrange(steps):
e = self.model - np.dot(self.p, self.q.T)
p_temp = learning_rate * np.dot(e, self.q)
self.q *= (1-regularization)
self.q += learning_rate*(np.dot(e.T, self.p))
self.p *= (1-regularization)
self.p += p_temp
. 他のヒント
あなたはSGDを実装していますか?各ステップでは、すべての格付け行列の誤差ではなく、1つのユーザー評価の誤差を計算する必要があります。
e=self.model-np.dot(self.p,self.q.T) #calculate error for gradient
.
およびSCIPYライブラリの場合は、スパース行列の要素に直接アクセスしたい場合は、遅いボトルネックがあると確信しています。SCIPY-SPARSE-MATRIXからの格付け行列の要素にアクセスする代わりに、各ステップで特定の行と列をRAMに持ち込み、その後計算を実行できます。
所属していません StackOverflow