RBF、双曲線正接、フーリエなどのいくつかの有名なカーネルをライブラリのsvm.SVR
メソッドに定義しようとしています。sklearn
私は作業を開始しrbf
(svm に rbf 用のデフォルトのカーネルがあることは知っていますが、後でカスタマイズできるように定義する必要があります)、ここでいくつかの有用なリンクを見つけて、これを選択しました:
def my_kernel(X,Y):
K = np.zeros((X.shape[0],Y.shape[0]))
for i,x in enumerate(X):
for j,y in enumerate(Y):
K[i,j] = np.exp(-1*np.linalg.norm(x-y)**2)
return K
clf=SVR(kernel=my_kernel)
これを使用したのは、形状が異なる電車 ([3850,4] の形状) とテスト データ ([1200,4] の形状) に使用できるためです。しかし問題は、処理が遅すぎて、結果が出るまで長い間待たなければならないことです。cython で static-typing と memoryviews も使用しましたが、そのパフォーマンスはデフォルトのsvm
rbf カーネルほど良くありません。私はまた、同じ問題についてのこのリンクを見つけましたがnumpy.einsum
、numexpr.evaluate
私にとっては少し混乱しています。これは、速度パフォーマンスの点で最高のコードであることがわかりました。
scipy.linalg.blas からインポート sgemm
def app2(X, gamma, var):
X_norm = -gamma*np.einsum('ij,ij->i',X,X)
return ne.evaluate('v * exp(A + B + C)', {\
'A' : X_norm[:,None],\
'B' : X_norm[None,:],\
'C' : sgemm(alpha=2.0*gamma, a=X, b=X, trans_b=True),\
'g' : gamma,\
'v' : var\
})
このコードは 1 つの入力 (X) に対してのみ機能し、私の場合に合わせて変更する方法が見つかりませんでした (2 つの異なるサイズの 2 つの入力 - カーネル関数は形状 (m,n) および (l,n) の行列を取得します)。svm docsに従って (m,l) を出力します)。K[i,j] = np.exp(-1*np.linalg.norm(x-y)**2)
高速化するには、最初のコードを2番目のコードに置き換えるだけでよいと思います。どんな助けでもいただければ幸いです。