我有一个支持向量机,它使用决策超平面将我的数据分成两部分(出于可视化目的,这是一个具有三个维度的示例数据集),如下所示: 现在我想执行基础更改,以便超平面平放在x/y 平面,这样从每个样本点到决策超平面的距离就是它们的 z 坐标。
为此,我知道我需要更改基础。SVM 的超平面由它们的系数(3d 向量)和截距(标量)给出,使用(据我所知)数学平面的一般形式:ax+by+cz=d
,a,b,c 是系数的坐标d 是截距。当绘制为 3d 向量时,系数是与平面正交的向量(在图像中它是青色线)。
现在改变基:如果没有截距,我可以假设作为系数的向量是我的新基的一个向量,另一个可以是平面上的随机向量,第三个是简单的交叉两者的乘积,产生三个正交向量,它们可以是变换矩阵的列向量。下面代码中使用的 z 函数来自平面的一般形式的简单术语重新排列ax+by+cz=d <=> z=(d-ax-by)/c
:
z_func = lambda interc, coef, x, y: (interc-coef[0]*x -coef[1]*y) / coef[2]
def generate_trafo_matrices(coefficient, z_func):
normalize = lambda vec: vec/np.linalg.norm(vec)
uvec2 = normalize(np.array([1, 0, z_func(1, 0)]))
uvec3 = normalize(np.cross(uvec1, uvec2))
back_trafo_matrix = np.array([uvec2, uvec3, coefficient]).T
#in other order such that its on the xy-plane instead of the yz-plane
trafo_matrix = np.linalg.inv(back_trafo_matrix)
return trafo_matrix, back_trafo_matrix
然后将这个变换矩阵应用于所有点,如下所示:
def _transform(self, points, inverse=False):
trafo_mat = self.inverse_trafo_mat if inverse else self.trafo_mat
points = np.array([trafo_mat.dot(point) for point in points])
return points
现在,如果截距为零,那将完美运行,并且平面将在 xy 轴上平坦。但是,一旦我有一个截距!= 零,飞机就不再平坦了:
我理解是这种情况,因为这不是简单的基础更改,因为我的另一个基础的坐标原点不在 (0,0,0) 而是在不同的位置(超平面可能穿过系数向量在任何时候),但是我尝试将截距添加到转换中都没有导致正确的结果:
def _transform(self, points, inverse=False):
trafo_mat = self.inverse_trafo_mat if inverse else self.trafo_mat
intercept = self.intercept if inverse else -self.intercept
ursprung_translate = trafo_mat.dot(np.array([0,0,0])+trafo_matrix[:,0]*intercept)
points = np.array([point+trafo_matrix[:,0]*intercept for point in points])
points = np.array([trafo_mat.dot(point) for point in points])
points = np.array([point-ursprung_translate for point in points])
return points
例如是错误的。我在 StackOverflow 上而不是在数学 StackExchange 上问这个问题,因为我认为我无法将相应的数学转换为代码,我很高兴我能走到这一步。
我创建了一个 github gist,其中包含进行转换的代码并在https://gist.github.com/cstenkamp/0fce4d662beb9e07f0878744c7214995上创建图,可以在链接https://mybinder.org/v2下使用 Binder 启动/gist/jtpio/0fce4d662beb9e07f0878744c7214995/master?urlpath=lab%2Ftree%2Fchange_of_basis_with_translate.ipynb如果有人想玩代码本身。
任何帮助表示赞赏!