我使用cvxopt qp解算器在python中实现了一个支持向量机,其中我需要计算两个向量的gram矩阵,每个元素具有内核函数。我使用for循环正确实现了该策略,但是此策略需要大量计算。我想向量化代码。

例:

python - SVM-如何向量化角化的克矩阵?-LMLPHP

这是我写的:

K = np.array( [kernel(X[i], X[j],poly=poly_kernel)
     for j in range(m)
     for i in range(m)]).reshape((m, m))


如何在没有for循环的情况下向量化以上代码以更快地获得相同的结果?

内核函数计算高斯内核。

Here is a quick explanation of an svm with kernel trick.第二页解释了该问题。

这是我完整的code内容。

编辑:这是一个快速的代码片段,以未矢量化的形式运行我需要矢量化的代码

from sklearn.datasets import make_gaussian_quantiles;
import numpy as np;


X,y = make_gaussian_quantiles(mean=None, cov=1.0, n_samples=100, n_features=2, n_classes=2, shuffle=True, random_state=5);

m = X.shape[0];


def kernel(a,b,d=20,poly=True,sigma=0.5):
    if (poly):
        return np.inner(a,b) ** d;
    else:
        return np.exp(-np.linalg.norm((a - b) ** 2)/sigma**2)

# Need to vectorize these loops

K = np.array([kernel(X[i], X[j],poly=False)
    for j in range(m)
    for i in range(m)]).reshape((m, m))


谢谢!

最佳答案

这是向量化版本。 non poly分支有两个变体,直接变体和节省内存的变体,以防功能数量很大:

from sklearn.datasets import make_gaussian_quantiles;
import numpy as np;


X,y = make_gaussian_quantiles(mean=None, cov=1.0, n_samples=100, n_features=2, n_classes=2, shuffle=True, random_state=5);
Y,_ = make_gaussian_quantiles(mean=None, cov=1.0, n_samples=200, n_features=2, n_classes=2, shuffle=True, random_state=2);

m = X.shape[0];
n = Y.shape[0]

def kernel(a,b,d=20,poly=True,sigma=0.5):
    if (poly):
        return np.inner(a,b) ** d;
    else:
        return np.exp(-np.linalg.norm((a - b) ** 2)/sigma**2)

# Need to vectorize these loops

POLY = False
LOW_MEM = 0

K = np.array([kernel(X[i], Y[j], poly=POLY)
              for i in range(m)
              for j in range(n)]).reshape((m, n))

def kernel_v(X, Y=None, d=20, poly=True, sigma=0.5):
    Z = X if Y is None else Y
    if poly:
        return np.einsum('ik,jk', X, Z)**d
    elif X.shape[1] < LOW_MEM:
        return np.exp(-np.sqrt(((X[:, None, :] - Z[None, :, :])**4).sum(axis=-1)) / sigma**2)
    elif Y is None or Y is X:
        X2 = X*X
        H = np.einsum('ij,ij->i', X2, X2) + np.einsum('ik,jk', X2, 3*X2) - np.einsum('ik,jk', X2*X, 4*X)
        return np.exp(-np.sqrt(np.maximum(0, H+H.T)) / sigma**2)
    else:
        X2, Y2 = X*X, Y*Y
        E = np.einsum('ik,jk', X2, 6*Y2) - np.einsum('ik,jk', X2*X, 4*Y) - np.einsum('ik,jk', X, 4*Y2*Y)
        E += np.add.outer(np.einsum('ij,ij->i', X2, X2), np.einsum('ij,ij->i', Y2, Y2))
        return np.exp(-np.sqrt(np.maximum(0, E)) / sigma**2)

print(np.allclose(K, kernel_v(X, Y, poly=POLY)))

关于python - SVM-如何向量化角化的克矩阵?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47945139/

10-15 17:40