Я пытаюсь определить несколько известных ядер, таких как 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, но его производительность не так хороша, как ядро 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\
})
Этот код работает только для одного входа (X), и я не смог найти способ изменить его для моего случая (два входа с двумя разными размерами. Функция ядра получает матрицы с формой (m, n) и (l, n) и выводит (m,l) в соответствии с svm документы ). Думаю, мне нужно только заменить K[i,j] = np.exp(-1*np.linalg.norm(x-y)**2)
из первого кода во втором, чтобы ускорить его. Любая помощь будет оценена по достоинству.