我知道有一些帖子有类似的主题。但是,我还没有找到任何不是特定问题和更一般的问题。
请,我不是在找一个解决方法 - 即"如果"声明如果足够接近,则强制值为零。
在我的问题中,我正在研究将矩阵转换为Hessenberg形式的结果(即应用变换将零引入矩阵 - 这里的数学细节不是问题)。我最初在MATLAB中为一个类编写了代码,现在也希望在Python中使用代码(所有使用基本操作 - 没有"黑盒"这里的操作)。我已经成功地完成了这项任务,但是对于应该为零的条目,我得到的答案却略有不同。
例如:
一些应为零的条目报告为1.77635684e-15和4.44089210e-16 - 它们都接近机器精度2.2204460E-16。
这有什么根本原因吗?
修改
稍微改善一下我的问题......
我最终得到的是减去几乎相等的数字 - 我知道一般来说这是一个坏主意 - 对于那些值应该为零的条目。因为它们几乎相等且非常小,所以存在精度损失的形式。
这让我觉得MATLAB和python如何处理这样的评估可能会有所不同......
编辑编辑
这是困扰我的输出(" py" = Python输出," mat" = MATLAB输出)。我可以忍受差异达到〜第15位 - 这是机器精度。困扰我的是第四栏。这里是几乎相等数量的减法发挥作用的地方,我们真正看到了差异(第2-4行是相互负面的!)
供参考,这是我的python代码:
A = [[1.,2.,3.,4.],[5.,6.,7.,8.],[9.,10.,11.,12.],[13.,14.,15.,16.]]
test = fctns.hess(A)
print(test)
def hess(A):
# This function reduces any mxm matrix to Hessenberg form
# through orthogonality similarity transforms. For symmetric A, the
# Hessenberg form will be tridiagonal.
dumA = np.array(A)
n = np.shape(dumA)[1] # obtains n in (m,n) matrix
v = []
for k in np.arange(0,n-2):
x = np.zeros((n-(k+1),1))
for idx in np.arange(0,len(x)):
x[idx]=dumA[k+1+idx,k]
tmp = np.shape(x)[0]
if np.sign(x[0][0]) == 0:
tmpsign = 1;
else:
tmpsign = np.sign(x[0][0]);
dum = tmpsign*norm(x,tmp)*np.eye(tmp,1) + x;
v.append(dum/norm(dum,tmp));
dumA[k+1:,k:] = dumA[k+1:,k:] - 2*np.dot(v[k],np.dot(np.transpose(v[k]),dumA[k+1:,k:]));
dumA[:,k+1:] = dumA[:,k+1:] - 2*np.dot(np.dot(dumA[:,k+1:],v[k]),np.transpose(v[k]));
return(dumA)
这是我的MATLAB代码:
function [ dumA ] = tridiag( A0 )
% This function reduces any mxm matrix to tridiagonal form
% through orthogonality similarity transforms. For symmetric cases, the
% Hessenberg form will be tridiagonal.
dumA = A0;
tmp = size(dumA);
m = tmp(1);
v = cell(1,length(1:m-2));
for k = 1:m-2
x = dumA(k+1:m,k);
tmp = size(x);
if sign(x(1)) == 0
tmpsign = 1;
else
tmpsign = sign(x(1));
end
dum = tmpsign*norm(x,2)*eye(tmp(1),1) + x;
if sum(x) == 0
v{k} = dum;
continue
end
v{k} = dum/norm(dum,2);
dumA(k+1:m,k:m) = dumA(k+1:m,k:m) - 2*v{k}*(v{k}'*dumA(k+1:m,k:m));
dumA(1:m,k+1:m) = dumA(1:m,k+1:m) - 2*(dumA(1:m,k+1:m)*v{k})*v{k}';
end
end
答案 0 :(得分:0)
您的python代码无法按原样运行,并且与MATLAB代码不同。我修好了:
dumA = np.array(A)
n = np.shape(dumA)[1] # obtains n in (m,n) matrix
v = []
for k in np.arange(n-2):
x = dumA[k+1:,k:k+1]
tmp = np.shape(x)[0]
tmpsign = np.sign(x[0]);
if not tmpsign:
tmpsign = 1.
dum = tmpsign*norm(x,2)*np.eye(tmp,1) + x;
if not x.sum():
v.append(dum)
continue
v.append(dum/norm(dum,2));
dumA[k+1:,k:] -= 2.*(v[k] @ (v[k].T @ dumA[k+1:,k:]));
dumA[:,k+1:] -= 2.*((dumA[:,k+1:] @ v[k]) @ v[k].T);
print(dumA)
我做了一些测试,对于第一次迭代,一切都是相同的,直到循环的倒数第二行(从dumA
到倒数第二次)。此代码出现此问题:dumA[:,k+1:] @ v[k]
,dumA(1:m,k+1:m)*v{k}
。矩阵乘积的最后一个元素有一个非常小的数值差异,约为2e-16。这可能归结为略有不同的实现。
MATLAB和numpy似乎都在使用相同版本的MKL进行计算,但由于无法看到MATLAB源代码,因此无法准确说出其差异所在。