我有以下代码:
import numpy as np
from sklearn import svm
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import accuracy_score
from functools import partial
import pandas as pd
def tanimotoKernel(xs, ys):
a = 0
b = 0
for x, y in zip(xs, ys):
a += min(x, y)
b += max(x, y)
return a / b
# gammaExp = 1/(np.exp(gamma) - 1), calculated outside the kernel
def tanimotoLambdaKernel(xs,ys, gamma, gammaExp):
return np.exp(gamma * tanimotoKernel(xs,ys) - 1) * gammaExp
class GramBuilder:
def __init__(self, Kernel):
self._Kernel = Kernel
def generateMatrixBuilder(self, X1, X2):
gram_matrix = np.zeros((X1.shape[0], X2.shape[0]))
for i, x1 in enumerate(X1):
for j, x2 in enumerate(X2):
gram_matrix[i, j] = self._Kernel(x1, x2)
return gram_matrix
gammaList = [0.0001, 0.001, 0.01, 0.1, 1, 10, 100]
CList = [0.001, 0.01, 0.1, 1, 10, 100]
X, y = datasets.load_digits(return_X_y=True)
x_train, x_test, y_train, y_test = train_test_split(X, y)
svc_list = [
(svm.SVC(
kernel=GramBuilder(
partial(tanimotoLambdaKernel, gamma = x, gammaExp = 1/(np.exp(x) - 1)))
.generateMatrixBuilder),
x)
for x in gammaList
]
gammas = []
Cs = []
accuracy = []
for svc, gamma in svc_list:
print("Training gamma ", gamma)
clf = GridSearchCV(svc, {'C' : CList}, verbose = 1, n_jobs = -1)
clf.fit(x_train, y_train)
gammas.append(gamma)
Cs.append(clf.best_params_['C'])
accuracy.append(clf.best_score_)
对于这个玩具数据集,我必须等待大约50分钟来执行循环中的所有交叉验证。
我做的第一个改进是计算 gammaExp
在函数之外,我可以保存数百万个指数。而且我乘法比除法快,所以我计算了指数负1的倒数,以节省更多的时间。
有了这些修改,我在训练模型的时候提高了很多,但是我需要它更快,所以我会很感激任何想法。谢谢
1条答案
按热度按时间3b6akqbq1#
您可以使用numpy来加速最小/最大操作。然后,您可以使用numba的jit通过内联调用进一步加快代码的速度。
上面的代码应该是正确的,并且在我的机器上速度要快20倍以上。实际上只花了几分钟就完成了。
我认为,通过删除部分调用并使用numba进行
GramBuilder
类(查看numba文档中的jit类,部分函数可能不受支持,但您可以在类中存储值,并自己完成部分工作)。此外,请注意,许多操作似乎在内核中执行多次。我可能会计算它们一次(用同一个x2多次调用内核,并一次又一次地重新计算max)。