在 Matlab 中分离 'entangled' 个向量
separate 'entangled' vectors in Matlab
我有一组三个向量(存储在一个 3xN 矩阵中),它们是 'entangled'(例如,第二行中的某个值应该在第三行中,反之亦然)。 'entanglement' 是基于查看绘制了 alpha2 的图形。为了分离向量,我使用了一种基于差异的方法,在这种方法中,我计算了一个值与下一个三个值的差异(例如,将 (1,i) 与 (:,i+1) 进行比较)。然后我取最小值并存储它。该方法适用于分离三个向量中的两个,但不适用于最后一个。
我想知道你们是否可以与我分享你们如何解决这个问题的想法(如果可能的话)。我在下面添加了我的代码。
提前致谢!
数字问题:
clear all; close all; clc;
%%
alpha2 = [-23.32 -23.05 -22.24 -20.91 -19.06 -16.70 -13.83 -10.49 -6.70;
-0.46 -0.33 0.19 2.38 5.44 9.36 14.15 19.80 26.32;
-1.58 -1.13 0.06 0.70 1.61 2.78 4.23 5.99 8.09];
%%% Original
figure()
hold on
plot(alpha2(1,:))
plot(alpha2(2,:))
plot(alpha2(3,:))
%%% Store start values
store1(1,1) = alpha2(1,1);
store2(1,1) = alpha2(2,1);
store3(1,1) = alpha2(3,1);
for i=1:size(alpha2,2)-1
for j=1:size(alpha2,1)
Alpha1(j,i) = abs(store1(1,i)-alpha2(j,i+1));
Alpha2(j,i) = abs(store2(1,i)-alpha2(j,i+1));
Alpha3(j,i) = abs(store3(1,i)-alpha2(j,i+1));
[~, I] = min(Alpha1(:,i));
store1(1,i+1) = alpha2(I,i+1);
[~, I] = min(Alpha2(:,i));
store2(1,i+1) = alpha2(I,i+1);
[~, I] = min(Alpha3(:,i));
store3(1,i+1) = alpha2(I,i+1);
end
end
%%% Plot to see if separation worked
figure()
hold on
plot(store1)
plot(store2)
plot(store3)
通过polyfit
外推的解决方案:
这个想法非常简单:遍历所有位置 i
并使用 polyfit
将 d
次的多项式拟合到 [=18= 的 d+1
值] 最多 F(:,i)
。使用这些多项式来推断函数值 F(:,i+1)
。然后计算最适合这些外推的实数值 F(:,i+1)
的排列。如果只涉及几个函数,这应该工作得很好。当然还有一些改进的余地,但对于您的简单设置来说应该足够了。
function F = untangle(F, maxExtrapolationDegree)
%// UNTANGLE(F) untangles the functions F(i,:) via extrapolation.
if nargin<2
maxExtrapolationDegree = 4;
end
extrapolate = @(f) polyval(polyfit(1:length(f),f,length(f)-1),length(f)+1);
extrapolateAll = @(F) cellfun(extrapolate, num2cell(F,2));
fitCriterion = @(X,Y) norm(X(:)-Y(:),1);
nFuncs = size(F,1);
nPoints = size(F,2);
swaps = perms(1:nFuncs);
errorOfFit = zeros(1,size(swaps,1));
for i = 1:nPoints-1
nextValues = extrapolateAll(F(:,max(1,i-(maxExtrapolationDegree+1)):i));
for j = 1:size(swaps,1)
errorOfFit(j) = fitCriterion(nextValues, F(swaps(j,:),i+1));
end
[~,j_bestSwap] = min(errorOfFit);
F(:,i+1) = F(swaps(j_bestSwap,:),i+1);
end
初步解决方案:(不太好 - 跳过这部分)
这是一个类似的解决方案,它试图将导数的总和最小化到向量值函数的某种程度 F = @(j) alpha2(:,j)
。它通过遍历位置 i
并检查 i
坐标的所有可能排列以获得函数 F(1:i)
的最小半范数来实现。
(我现在实际上想知道是否有任何规范的数学方法来定义半范数,以便我们得到预期的结果......我最初打算使用 H^1
和 H^2
半范数,但他们没有不太管用...)
function F = untangle(F)
nFuncs = size(F,1);
nPoints = size(F,2);
seminorm = @(x,i) sum(sum(abs(diff(x(:,1:i),1,2)))) + ...
sum(sum(abs(diff(x(:,1:i),2,2)))) + ...
sum(sum(abs(diff(x(:,1:i),3,2)))) + ...
sum(sum(abs(diff(x(:,1:i),4,2))));
doSwap = @(x,swap,i) [x(:,1:i-1), x(swap,i:end)];
swaps = perms(1:nFuncs);
normOfSwap = zeros(1,size(swaps,1));
for i = 2:nPoints
for j = 1:size(swaps,1)
normOfSwap(j) = seminorm(doSwap(F,swaps(j,:),i),i);
end
[~,j_bestSwap] = min(normOfSwap);
F = doSwap(F,swaps(j_bestSwap,:),i);
end
用法:
命令 alpha2 = untangle(alpha2);
将解开您的函数:
它甚至应该适用于更复杂的数据,比如这些打乱的 sine-waves:
nPoints = 100;
nFuncs = 5;
t = linspace(0, 2*pi, nPoints);
F = bsxfun(@(a,b) sin(a*b), (1:nFuncs).', t);
for i = 1:nPoints
F(:,i) = F(randperm(nFuncs),i);
end
备注:我想如果你已经知道你的函数将是二次函数或其他一些特殊形式,RANSAC 将是一个更好的主意,用于更多的函数.如果函数没有以相同的 x-value 间距给出,这也可能有用。
我有一组三个向量(存储在一个 3xN 矩阵中),它们是 'entangled'(例如,第二行中的某个值应该在第三行中,反之亦然)。 'entanglement' 是基于查看绘制了 alpha2 的图形。为了分离向量,我使用了一种基于差异的方法,在这种方法中,我计算了一个值与下一个三个值的差异(例如,将 (1,i) 与 (:,i+1) 进行比较)。然后我取最小值并存储它。该方法适用于分离三个向量中的两个,但不适用于最后一个。
我想知道你们是否可以与我分享你们如何解决这个问题的想法(如果可能的话)。我在下面添加了我的代码。
提前致谢!
数字问题:
clear all; close all; clc;
%%
alpha2 = [-23.32 -23.05 -22.24 -20.91 -19.06 -16.70 -13.83 -10.49 -6.70;
-0.46 -0.33 0.19 2.38 5.44 9.36 14.15 19.80 26.32;
-1.58 -1.13 0.06 0.70 1.61 2.78 4.23 5.99 8.09];
%%% Original
figure()
hold on
plot(alpha2(1,:))
plot(alpha2(2,:))
plot(alpha2(3,:))
%%% Store start values
store1(1,1) = alpha2(1,1);
store2(1,1) = alpha2(2,1);
store3(1,1) = alpha2(3,1);
for i=1:size(alpha2,2)-1
for j=1:size(alpha2,1)
Alpha1(j,i) = abs(store1(1,i)-alpha2(j,i+1));
Alpha2(j,i) = abs(store2(1,i)-alpha2(j,i+1));
Alpha3(j,i) = abs(store3(1,i)-alpha2(j,i+1));
[~, I] = min(Alpha1(:,i));
store1(1,i+1) = alpha2(I,i+1);
[~, I] = min(Alpha2(:,i));
store2(1,i+1) = alpha2(I,i+1);
[~, I] = min(Alpha3(:,i));
store3(1,i+1) = alpha2(I,i+1);
end
end
%%% Plot to see if separation worked
figure()
hold on
plot(store1)
plot(store2)
plot(store3)
通过polyfit
外推的解决方案:
这个想法非常简单:遍历所有位置 i
并使用 polyfit
将 d
次的多项式拟合到 [=18= 的 d+1
值] 最多 F(:,i)
。使用这些多项式来推断函数值 F(:,i+1)
。然后计算最适合这些外推的实数值 F(:,i+1)
的排列。如果只涉及几个函数,这应该工作得很好。当然还有一些改进的余地,但对于您的简单设置来说应该足够了。
function F = untangle(F, maxExtrapolationDegree)
%// UNTANGLE(F) untangles the functions F(i,:) via extrapolation.
if nargin<2
maxExtrapolationDegree = 4;
end
extrapolate = @(f) polyval(polyfit(1:length(f),f,length(f)-1),length(f)+1);
extrapolateAll = @(F) cellfun(extrapolate, num2cell(F,2));
fitCriterion = @(X,Y) norm(X(:)-Y(:),1);
nFuncs = size(F,1);
nPoints = size(F,2);
swaps = perms(1:nFuncs);
errorOfFit = zeros(1,size(swaps,1));
for i = 1:nPoints-1
nextValues = extrapolateAll(F(:,max(1,i-(maxExtrapolationDegree+1)):i));
for j = 1:size(swaps,1)
errorOfFit(j) = fitCriterion(nextValues, F(swaps(j,:),i+1));
end
[~,j_bestSwap] = min(errorOfFit);
F(:,i+1) = F(swaps(j_bestSwap,:),i+1);
end
初步解决方案:(不太好 - 跳过这部分)
这是一个类似的解决方案,它试图将导数的总和最小化到向量值函数的某种程度 F = @(j) alpha2(:,j)
。它通过遍历位置 i
并检查 i
坐标的所有可能排列以获得函数 F(1:i)
的最小半范数来实现。
(我现在实际上想知道是否有任何规范的数学方法来定义半范数,以便我们得到预期的结果......我最初打算使用 H^1
和 H^2
半范数,但他们没有不太管用...)
function F = untangle(F)
nFuncs = size(F,1);
nPoints = size(F,2);
seminorm = @(x,i) sum(sum(abs(diff(x(:,1:i),1,2)))) + ...
sum(sum(abs(diff(x(:,1:i),2,2)))) + ...
sum(sum(abs(diff(x(:,1:i),3,2)))) + ...
sum(sum(abs(diff(x(:,1:i),4,2))));
doSwap = @(x,swap,i) [x(:,1:i-1), x(swap,i:end)];
swaps = perms(1:nFuncs);
normOfSwap = zeros(1,size(swaps,1));
for i = 2:nPoints
for j = 1:size(swaps,1)
normOfSwap(j) = seminorm(doSwap(F,swaps(j,:),i),i);
end
[~,j_bestSwap] = min(normOfSwap);
F = doSwap(F,swaps(j_bestSwap,:),i);
end
用法:
命令 alpha2 = untangle(alpha2);
将解开您的函数:
它甚至应该适用于更复杂的数据,比如这些打乱的 sine-waves:
nPoints = 100;
nFuncs = 5;
t = linspace(0, 2*pi, nPoints);
F = bsxfun(@(a,b) sin(a*b), (1:nFuncs).', t);
for i = 1:nPoints
F(:,i) = F(randperm(nFuncs),i);
end
备注:我想如果你已经知道你的函数将是二次函数或其他一些特殊形式,RANSAC 将是一个更好的主意,用于更多的函数.如果函数没有以相同的 x-value 间距给出,这也可能有用。