- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在尝试在 Python 上实现最小二乘曲线拟合算法,我已经在 Matlab 上编写了它。但是,我无法获得正确的变换矩阵,而且问题似乎发生在求解步骤。 (编辑:我的变换矩阵在 Matlab 中非常准确,但在 Python 中完全不准确。)
我在网上看了很多资源,它们都表明要翻译 Matlab 的“mldivide”,如果矩阵是方阵和非奇异矩阵,则必须使用“np.linalg.solve”,而“np.linalg.lstsq” ' 否则。但是我的结果不匹配。
问题是什么?如果它与函数的实现有关,那么 mldivide 在 numpy 中的正确翻译是什么?
我在下面附上了两个版本的代码。它们本质上是完全相同的实现,除了求解部分。
Matlab代码:
%% Least Squares Fit
clear, clc, close all
% Calibration Data
scr_calib_pts = [0,0; 900,900; -900,900; 900,-900; -900,-900];
cam_calib_pts = [-1,-1; 44,44; -46,44; 44,-46; -46,-46];
cam_x = cam_calib_pts(:,1);
cam_y = cam_calib_pts(:,2);
% Least Squares Fitting
A_matrix = [];
for i = 1:length(cam_x)
A_matrix = [A_matrix;1, cam_x(i), cam_y(i), ...
cam_x(i)*cam_y(i), cam_x(i)^2, cam_y(i)^2];
end
A_star = A_matrix'*A_matrix
B_star = A_matrix'*scr_calib_pts
transform_matrix = mldivide(A_star,B_star)
% Testing Data
test_scr_vec = [200,400; 1600,400; -1520,1740; 1300,-1800; -20,-1600];
test_cam_vec = [10,20; 80,20; -76,87; 65,-90; -1,-80];
test_cam_x = test_cam_vec(:,1);
test_cam_y = test_cam_vec(:,2);
% Coefficients for Transform
coefficients = [];
for i = 1:length(test_cam_x)
coefficients = [coefficients;1, test_cam_x(i), test_cam_y(i), ...
test_cam_x(i)*test_cam_y(i), test_cam_x(i)^2, test_cam_y(i)^2];
end
% Mapped Points
results = coefficients*transform_matrix;
% Plotting
test_scr_x = test_scr_vec(:,1)';
test_scr_y = test_scr_vec(:,2)';
results_x = results(:,1)';
results_y = results(:,2)';
figure
hold on
load seamount
s = 50;
scatter(test_scr_x, test_scr_y, s, 'r')
scatter(results_x, results_y, s)
Python代码:
# Least Squares fit
import numpy as np
import matplotlib.pyplot as plt
# Calibration data
camera_vectors = np.array([[-1,-1], [44,44], [-46,44], [44,-46], [-46,-46]])
screen_vectors = np.array([[0,0], [900,900], [-900,900], [900,-900], [-900,-900]])
# Separate axes
cam_x = np.array([i[0] for i in camera_vectors])
cam_y = np.array([i[1] for i in camera_vectors])
# Initiate least squares implementation
A_matrix = []
for i in range(len(cam_x)):
new_row = [1, cam_x[i], cam_y[i], \
cam_x[i]*cam_y[i], cam_x[i]**2, cam_y[i]**2]
A_matrix.append(new_row)
A_matrix = np.array(A_matrix)
A_star = np.transpose(A_matrix).dot(A_matrix)
B_star = np.transpose(A_matrix).dot(screen_vectors)
print A_star
print B_star
try:
# Solve version (Implemented)
transform_matrix = np.linalg.solve(A_star,B_star)
print "Solve version"
print transform_matrix
except:
# Least squares version (implemented)
transform_matrix = np.linalg.lstsq(A_star,B_star)[0]
print "Least Squares Version"
print transform_matrix
# Test data
test_cam_vec = np.array([[10,20], [80,20], [-76,87], [65,-90], [-1,-80]])
test_scr_vec = np.array([[200,400], [1600,400], [-1520,1740], [1300,-1800], [-20,-1600]])
# Coefficients of quadratic equation
test_cam_x = np.array([i[0] for i in test_cam_vec])
test_cam_y = np.array([i[1] for i in test_cam_vec])
coefficients = []
for i in range(len(test_cam_x)):
new_row = [1, test_cam_x[i], test_cam_y[i], \
test_cam_x[i]*test_cam_y[i], test_cam_x[i]**2, test_cam_y[i]**2]
coefficients.append(new_row)
coefficients = np.array(coefficients)
# Transform camera coordinates to screen coordinates
results = coefficients.dot(transform_matrix)
# Plot points
results_x = [i[0] for i in results]
results_y = [i[1] for i in results]
actual_x = [i[0] for i in test_scr_vec]
actual_y = [i[1] for i in test_scr_vec]
plt.plot(results_x, results_y, 'gs', actual_x, actual_y, 'ro')
plt.show()
编辑(根据建议):
# Transform matrix with linalg.solve
[[ 2.00000000e+01 2.00000000e+01]
[ -5.32857143e+01 7.31428571e+01]
[ 7.32857143e+01 -5.31428571e+01]
[ -1.15404203e-17 9.76497106e-18]
[ -3.66428571e+01 3.65714286e+01]
[ 3.66428571e+01 -3.65714286e+01]]
# Transform matrix with linalg.lstsq:
[[ 2.00000000e+01 2.00000000e+01]
[ 1.20000000e+01 8.00000000e+00]
[ 8.00000000e+00 1.20000000e+01]
[ 1.79196935e-15 2.33146835e-15]
[ -4.00000000e+00 4.00000000e+00]
[ 4.00000000e+00 -4.00000000e+00]]
% Transform matrix with mldivide:
20.0000 20.0000
19.9998 0.0002
0.0002 19.9998
0 0
-0.0001 0.0001
0.0001 -0.0001
最佳答案
有趣的是,使用 np.linalg.lstsq
和 np.linalg.solve
会得到完全不同的结果。
x1 = np.linalg.lstsq(A_star, B_star)[0]
x2 = np.linalg.solve(A_star, B_star)
两者都应该为方程 Ax = B 提供一个解。但是,它们给出了两个完全不同的数组:
In [37]: x1
Out[37]:
array([[ 2.00000000e+01, 2.00000000e+01],
[ 1.20000000e+01, 7.99999999e+00],
[ 8.00000001e+00, 1.20000000e+01],
[ -1.15359111e-15, 7.94503352e-16],
[ -4.00000001e+00, 3.99999999e+00],
[ 4.00000001e+00, -3.99999999e+00]]
In [39]: x2
Out[39]:
array([[ 2.00000000e+01, 2.00000000e+01],
[ -4.42857143e+00, 2.43809524e+01],
[ 2.44285714e+01, -4.38095238e+00],
[ -2.88620104e-18, 1.33158696e-18],
[ -1.22142857e+01, 1.21904762e+01],
[ 1.22142857e+01, -1.21904762e+01]])
两者都应该给出线性方程组的准确(精确到计算精度)解,对于非奇异矩阵,只有一个解。
一定是哪里出了问题。让我们看看这两个候选者是否可以是原始方程的解:
In [41]: A_star.dot(x1)
Out[41]:
array([[ -1.11249392e-08, 9.86256055e-09],
[ 1.62000000e+05, -1.65891834e-09],
[ 0.00000000e+00, 1.62000000e+05],
[ -1.62000000e+05, -1.62000000e+05],
[ -3.24000000e+05, 4.47034836e-08],
[ 5.21540642e-08, -3.24000000e+05]])
In [42]: A_star.dot(x2)
Out[42]:
array([[ -1.45519152e-11, 1.45519152e-11],
[ 1.62000000e+05, -1.45519152e-11],
[ 0.00000000e+00, 1.62000000e+05],
[ -1.62000000e+05, -1.62000000e+05],
[ -3.24000000e+05, 0.00000000e+00],
[ 2.98023224e-08, -3.24000000e+05]])
他们似乎给出了相同的解决方案,这与 B_star
本质上应该是一样的。这引导我们走向解释。通过简单的线性代数,我们可以预测 A 。 (x1-x2) 应该非常接近于零:
In [43]: A_star.dot(x1-x2)
Out[43]:
array([[ -1.11176632e-08, 9.85164661e-09],
[ -1.06228981e-09, -1.60071068e-09],
[ 0.00000000e+00, -2.03726813e-10],
[ -6.72298484e-09, 4.94765118e-09],
[ 5.96046448e-08, 5.96046448e-08],
[ 2.98023224e-08, 5.96046448e-08]])
确实如此。因此,方程 Ax = 0 似乎有一个非平凡的解,解为 x = x1-x2,这意味着矩阵是奇异的,因此 Ax=B 有无限多个不同的解。
因此问题不在 NumPy 或 Matlab 中,而是在矩阵本身。
但是,在这个矩阵的情况下,情况有点棘手。根据上面的定义,A_star
似乎是单数(对于 x<>0,Ax=0)。另一方面,它的行列式不为零,也不是奇异的。
在这种情况下,A_star
是一个数值不稳定但非奇异矩阵的示例。 solve
方法使用简单的逆乘法求解。在这种情况下,这是一个糟糕的选择,因为逆包含非常大和非常小的值。这使得乘法容易出现舍入误差。这可以通过查看矩阵的条件数看出:
In [65]: cond(A_star)
Out[65]: 1.3817810855559592e+17
这是一个非常高的条件数,矩阵是病态的。
在这种情况下,使用逆来解决问题是一种糟糕的方法。如您所见,最小二乘法可提供更好的结果。但是,更好的解决方案是重新调整输入值,使 x 和 x^2 在同一范围内。一种非常好的缩放比例是缩放 -1 和 1 之间的所有内容。
您可能会考虑的一件事是尝试使用 NumPy 的索引功能。例如:
cam_x = np.array([i[0] for i in camera_vectors])
相当于:
cam_x = camera_vectors[:,0]
你可以这样构造你的数组A
:
A_matrix = np.column_stack((np.ones_like(cam_x), cam_x, cam_y, cam_x*cam_y, cam_x**2, cam_y**2))
无需创建列表列表或任何循环。
关于python - Numpy 的 'linalg.solve' 和 'linalg.lstsq' 没有给出与 Matlab 的 '\' 或 mldivide 相同的答案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25001753/
在 Matlab 中,您可以选择创建新的“示例”脚本文件以及脚本、函数、类等。创建它们时,它们会获得一个脚本图标。 它们与其他标准脚本文件的处理方式有何不同? 是否有关于这些示例脚本类型的预期用途的文
我正在运行一个不是我自己编写的大 m 文件,它依赖于某些子函数。我想知道是否在所有嵌套函数的任何地方都使用了特定函数(在我的例子中是函数 eig.m(计算特征值))。有没有快速的方法来做到这一点? 亲
Matlab中有一个函数叫 copulafit .我怎样才能看到这个函数背后的代码?许多 Python 的 numpy 和 scipy 函数在 Github 上很容易开源,但由于某种原因我在 Gith
我定义了一个抽象基类measurementHandler < handle它定义了所有继承类的接口(interface)。这个类的两个子类是a < measurementHandler和 b < me
假设有一个矩阵 A = 1 3 2 4 4 2 5 8 6 1 4 9 例如,我有一个 Vector 包含该矩阵每一列的“类”
我有一个在后台运行的 Matlab 脚本。随着计算的进行,它会不断弹出进度栏窗口。这很烦人。 问题是我没有自己写 Matlab 脚本,这是一段很长很复杂的代码,我不想搞砸。那么如何在不修改 Matla
有没有办法从一个 matlab 程序中检测计算机上正在运行多少个 matlab 进程? 我想要恰好有 n 个 matlab 进程在运行。如果我的数量太少,我想创建它们,如果数量太多,我想杀死一些。您当
我正在测试我们在 Matlab 中开发的一个独立应用程序,当时我注意到它的内存使用量(根据 Windows 任务管理器)达到了 16gb 以上的数倍峰值。我决定在编译版本后面的脚本上使用 profil
我面临着一个相当棘手的问题。在 Matlab 中,命令 S = char(1044) 将俄语字母 д 放入变量 S。但是 disp(S) 返回空白符号,尽管内容实际上是正确的: >> S = char
我在这行 MATLAB 代码中遇到内存不足错误: result = (A(1:xmax,1:ymax,1:zmax) .* B(2:xmax+1,2:ymax+1,2:zmax+1) +
我正在寻找一种在 MATLAB 中比较有限顺序数据与非确定性顺序的方法。基本上,我想要的是一个数组,但不对包含的元素强加顺序。如果我有对象 a = [x y z]; 和 b = [x z y]; 我希
我有一个由 1 和 0 组成的二维矩阵。 mat = [0 0 0 0 1 1 1 0 0 1 1 1 1 1 0 0 1 0 0 0 1 0 1 1 0 0 1]; 我需
我可以在 Matlab 中用一组 x,y 点绘制回归线。但是,如果我有一组点(如下图),假设我有四组点,我想为它们绘制四条回归线……我该怎么做?所有的点都保存在 x,y 中。没有办法将它们分开并将它们
我正在尝试使用以下代码在 MATLAB 中绘制圆锥体。但是,当 MATLAB 生成绘图时,曲面中有一个间隙,如下图所示。谁能建议关闭它的方法? clearvars; close all; clc; [
我有一个 map称为 res_Map,包含一组不同大小的数组。我想找到用于存储 res_Map 的总内存。 正如您在下面看到的,看起来 res_Map 几乎不占用内存,而 res_Map 中的各个元素
有没有办法在 MATLAB 中组合 2 个向量,这样: mat = zeros(length(C),length(S)); for j=1:length(C) mat(j,:)=C(j)*S;
已结束。此问题不符合 Stack Overflow guidelines 。它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答它。 关闭 5 年前
我正在尝试将MatLab中的t copula适配到我的数据,并且我的功能是: u = ksdensity(range_1, range_1,'function','cdf'); v = ksdens
大家好,我目前正在尝试使用论文“多尺度形态学图像简化”中的 SMMT 运算符 Dorini .由于没有订阅无法访问该页面,因此我将相关详细信息发布在这里: 请注意,我将相关文章的部分内容作为图片发布。
我在MATLAB中编写代码,需要使用一个名为modwt的函数,该函数同时存在于两个我同时使用的工具箱(Wavelet和WMTSA)中。问题在于,一个版本仅返回一个输出,而另一个版本则返回三个输出。我应
我是一名优秀的程序员,十分优秀!