0

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 も使用しましたが、そのパフォーマンスはデフォルトのsvmrbf カーネルほど良くありません。私はまた、同じ問題についてのこのリンクを見つけましたがnumpy.einsumnumexpr.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番目のコードに置き換えるだけでよいと思います。どんな助けでもいただければ幸いです。

4

2 に答える 2