Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python SVM-如何对核化的gram矩阵进行矢量化?_Python_Numpy_Machine Learning_Svm_Cvxopt - Fatal编程技术网

Python SVM-如何对核化的gram矩阵进行矢量化?

Python SVM-如何对核化的gram矩阵进行矢量化?,python,numpy,machine-learning,svm,cvxopt,Python,Numpy,Machine Learning,Svm,Cvxopt,我使用cvxopt qp解算器在python中实现了一个支持向量机,其中我需要计算两个向量的gram矩阵,每个元素上都有一个核函数。我使用for循环正确地实现了它,但这种策略需要大量计算。我想把代码矢量化 例如: 以下是我写的: 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循环的情况下对上述

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

例如:

以下是我写的:

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循环的情况下对上述代码进行矢量化,以更快地获得相同的结果?

核函数计算高斯核

这篇文章的第二页解释了这个问题

这是我的全部内容

编辑:下面是一个快速代码片段,它以非矢量化的形式运行我需要矢量化的内容

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))

谢谢

这是一个矢量化版本。非多边形分支有两种变体,一种是直接分支,另一种是节省内存分支,以防功能数量过多:

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)))
从sklearn.datasets导入make_gaussian_分位数;
输入numpy作为np;
十、 y=生成高斯分位数(平均值=无,cov=1.0,n_样本=100,n_特征=2,n_类=2,混洗=真,随机_状态=5);
Y、 _u=make_gaussian_分位数(平均值=None,cov=1.0,n_样本=200,n_特征=2,n_类=2,随机状态=2);
m=X.shape[0];
n=Y.形状[0]
def内核(a,b,d=20,poly=True,sigma=0.5):
如果(多边形):
返回np.内部(a、b)**d;
其他:
返回np.exp(-np.linalg.norm((a-b)**2)/sigma**2)
#需要对这些循环进行矢量化
多边形=假
低_MEM=0
K=np.array([kernel(X[i],Y[j],poly=poly)
对于范围内的i(m)
对于范围(n)内的j。重塑((m,n))
def kernel_v(X,Y=None,d=20,poly=True,sigma=0.5):
如果Y不是其他Y,则Z=X
如果是多边形:
返回np.einsum('ik,jk',X,Z)**d
elif X.shape[1]<低内存:
返回np.exp(-np.sqrt(((X[:,None,:]-Z[None,:,:])**4.sum(axis=-1))/sigma**2)
如果Y为无或Y为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)
返回np.exp(-np.sqrt(np.max(0,H+H.T))/sigma**2)
其他:
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))
返回np.exp(-np.sqrt(np.max(0,E))/sigma**2)
打印(np.allclose(K,kernel_v(X,Y,poly=poly)))

请通过包含相关位(本例中的内核函数)和一些模拟数据,让那些试图帮助您的人变得容易,这样他们就可以直接运行您的示例。更新的问题谢谢!你能解释一下einsum在做什么吗?
einsum('ik,jk',X,X)
X
的元素与
X
的元素相乘,输出将有一个类似于第一个
X
的轴,因为规范字符串中的
i
是唯一的,而类似于第二个“X”中第一个的轴是唯一的,因为“j”是唯一的。所以对于这两个轴,它的行为就像一个外积。这两个因素的第二个轴未展开,单个产品沿该轴求和,因为“k”出现在两个规格中。这是爱因斯坦的约定,因此称为“einsum”,所以相对于第二个轴,它的行为就像一个内积
out_ij=sum_k X_ik X_jk
如果还有一个输出规范,如
np.einsum('ij,ij->i',X2,X2)
在这种情况下,这意味着
i
没有求和,也没有外部扩展,因此
out_i=sum_j X2_ij X2_ij
我希望你能自己找出其他的。谢谢你的解释。你为什么要把3*X2和4*X相乘?只是一些诡计
(a-b)^4=a^4-4a^3b+6a^2b^2-4a^3+b^4
。因为我们这样做是“外部的”,并且a和b的向量都是
X
,我们可以计算术语的前半部分,然后后半部分就是转置。由于术语的数量是奇数,我们需要将中间的术语一分为二,因此
3