在任意向量的正交空间中采样

本文介绍了一种在高维空间中寻找与一组给定向量正交的向量的方法。利用奇异值分解(SVD)获取基底,并通过构造特定矩阵实现向量的正交化。此外,还讨论了如何在特定条件下对目标向量进行正交投影。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

有时候我们需要在特定的空间中采样,观察样本的性质。

现有一组 D D D维空间中的向量 x 1 , x 2 , ⋯ x N \mathbf{x}^1, \mathbf{x}^2, \cdots \mathbf{x}^N x1,x2,xN,其中 x n = ( x 1 n , x 2 n , ⋯   , x D n ) \mathbf{x}^n = (x^n_1,x^n_2,\cdots,x^n_D) xn=(x1n,x2n,,xDn),( D > N D>N D>N),采样 s \mathbf{s} s,使得 s \mathbf{s} s与所有 x n \mathbf{x}^n xn正交。

我们要找 x n x^n xn空间的一组基底,用特征值分解就好。 X = U Σ V ⊤ X=U\Sigma V^\top X=UΣV
其中, X X X是按行排列的 x n , n ∈ { 1 , 2 , ⋯ N } \mathbf{x}^n, n\in\{1,2,\cdots N \} xn,n{1,2,N},并用 0 0 0填充空行。
Σ = ( λ 1 λ 2 ⋱ λ K 0 ⋱ 0 ) \Sigma=\left( \begin{array}{ccc} \lambda_1& & & & \\ & \lambda_2 & & & \\ & & \ddots & & \\ & & & \lambda_K & \\ & & & & 0 \\ & & & & & \ddots & & \\ & & & & & & 0 \\ \end{array} \right) Σ=λ1λ2λK00
K K K 为非零特征值个数。
即通过线性变换 U U U V ⊤ V^\top V,我们得到 x n \mathbf{x}^n xn的一组基底 Σ \Sigma Σ。显然,与 Σ \Sigma Σ正交的空间的一组基底为
B = ( O K × K O K × ( D − K ) O ( D − K ) × K I ( D − K ) × ( D − K ) ) B=\left( \begin{array}{ccc} O_{K\times K} & O_{K\times (D-K)}\\ O_{ (D-K)\times K} & I_{ (D-K)\times (D-K)} \\ \end{array} \right) B=(OK×KO(DK)×KOK×(DK)I(DK)×(DK))
O O O为零矩阵, I I I为单位矩阵。那么,与 x n \mathbf{x}^n xn正交的空间的一组基底为 U B V ⊤ UB V^\top UBV

import numpy as np

z_dim = 512 # number of dimensions
n_vectors = 10 # number of Xs
assert n_vectors < z_dim
n_samples = 1000 # number of samples to orthogonal Xs

Xs = np.random.rand(n_vectors, z_dim)
Xs = np.concatenate((Xs,np.zeros((z_dim-n_vectors, z_dim))))

U, s, V = np.linalg.svd(Xs)
assert np.linalg.norm(np.dot(np.dot(U, np.diag(s)), V) - Xs) < 1e-8

num_lambdas = np.sum(s>1e-8)

bases = np.eye(z_dim)
bases[range(num_lambdas),range(num_lambdas)] = 0
bases = np.dot(np.dot(U, bases), V)

samples = np.random.rand(z_dim, n_samples)
samples = np.dot(bases.T, samples)

assert np.mean(np.abs(np.dot(Xs, samples))) < 1e-8

另外,还可以使用旋转矩阵,参见python n维向量向任意方向旋转,求旋转矩阵

= = =
正文到此为止,下面是一些小的尝试。

接下来,给定目标向量 x t x^{t} xt,可以计算其在正交空间中的投影,正交化,或者,只靠近 x t x^{t} xt而与 x i , i ∈ { 1 , 2 , ⋯ N } x^i, i\in \{1,2,\cdots N \} xi,i{1,2,N}距离不变。

x_target = np.random.rand(1, z_dim)
x_proj = np.concatenate((x_target, np.zeros((z_dim-1,z_dim))))
x_proj = np.dot(np.dot(U.T, x_proj), V.T)
# x_proj = x_proj[:,0]
x_proj[:, :num_lambdas] = 0
x_proj = np.dot(np.dot(U, x_proj), V)

assert np.linalg.norm(np.dot(Xs, x_proj[0,:])) < 1e-8

# The defination of projection matrix
P = np.dot(Xs.T, np.linalg.inv((Xs + bases).T))
x_proj_check = np.dot(np.eye(z_dim)-P, x_target[0,:])

assert np.linalg.norm(np.dot(Xs, x_proj_check)) < 1e-8
assert np.linalg.norm(x_proj[0,:]-x_proj_check) < 1e-8

从原点出发,向 x t x^{t} xt移动而与 x i , i ∈ { 1 , 2 , ⋯ N } x^i, i\in \{1,2,\cdots N \} xi,i{1,2,N}相切的点的运动轨迹

import numpy as np

z_dim = 512 # number of dimensions
n_vectors = 2 # number of Xs
assert n_vectors < z_dim

Xs = np.random.rand(n_vectors, z_dim)
Xs = np.concatenate((Xs,np.zeros((z_dim-n_vectors, z_dim))))

x_target = np.random.rand(1, z_dim)

# debug for n_vector=1
dist_X_target = np.linalg.norm(Xs[:n_vectors,:]-x_target, axis=1)
# debug for n_vector=1

while True:
        U, s, V = np.linalg.svd(Xs)

        num_lambdas = np.sum(s>1e-8)

        bases = np.eye(z_dim)
        bases[range(num_lambdas),range(num_lambdas)] = 0
        bases = np.dot(np.dot(U, bases), V)

        x_proj = np.concatenate((x_target, np.zeros((z_dim-1,z_dim))))
        x_proj = np.dot(np.dot(U.T, x_proj), V.T)
        # x_proj = x_proj[:,0]
        x_proj[:, :num_lambdas] = 0
        x_proj = np.dot(np.dot(U, x_proj), V)

        assert np.linalg.norm( np.dot(Xs, x_proj[0,:])) < 1e-8

        x_step = 0.1 * x_proj[[0],:]
        Xs[:n_vectors,:] = Xs[:n_vectors,:] - x_step
        x_target = x_target - x_step

        dist_Xs_step = np.linalg.norm(Xs)
        dist_target_step = np.linalg.norm(x_target)
        # print([dist_Xs_step, dist_target_step])
        dist = np.linalg.norm(x_target),np.linalg.norm(Xs[:n_vectors,:], axis=1)
        print([dist_X_target, dist])
        if np.linalg.norm(x_step)<1e-5:
                break

上面假设了 D > N D>N D>N。当 D ≤ N D\leq N DN,且 r a n k ( X ) < D rank(X)<D rank(X)<D,我们仍可以用上面的方法。当 X X X张成整个空间,即 r a n k ( X ) = D rank(X)=D rank(X)=D,无法找到一个切线,这是一个只有零解的线性规划问题:
max ⁡ v x t v s . t .   X v = 0 \max_{v} x^{t}v \\ s.t. \ Xv=0 vmaxxtvs.t. Xv=0
如果将这个问题进行一下放缩,例如用拉格朗日乘子法: max ⁡ v , δ x t v − δ ∣ X v ∣ \max_{v,\delta} x^{t}v - \delta |Xv| v,δmaxxtvδXv
δ ∈ R N \delta\in \R^N δRN是拉格朗日乘子,还可以继续求解。这里不展开了。

当然,还有一个取巧的办法,仍然使用svd分解。矩阵 Σ \Sigma Σ中,特征值按从大到小的顺序排列。特征值的大小其实代表了这一维度的权重,最大的特征值对应的主方向,代表样本朝向这个主方向的分量最多(参考主成分分析PCA)。那么我们取特征值最小的主方向,沿着这个方向投影 x t x^t xt即得所求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值