Matlab和Python读取二进制文件不同

时间:2015-02-24 23:22:14

标签: python matlab file numpy binary

我正在将相同的二进制文件读入Python和Matlab并将其放入矩阵中。当我采用这个矩阵的范数时,我会得到不同的结果。

我正在使用相应的smatload函数来加载二进制文件。

的Python:

def smatload(filename):
    #print 'opening: ', filename
    f = open(filename, 'rb')
    m = np.fromfile(f,'q',1)
    n = np.fromfile(f,'q',1)
    nnz = np.fromfile(f,'q',1)
    print 'reading %d x %d with %d non-zeros' % (m,n,nnz)
    S = np.fromfile(f,'d',3*nnz)
    f.close()
    S = S.reshape((nnz,3))
    rows = S[:,0].astype(int) - 1
    cols = S[:,1].astype(int) - 1
    vals = S[:,2]
    return csr_matrix((vals,(rows,cols)),shape=(m,n))

Matlab的:

function [A] = smatload(filename)

fid = fopen(filename,'r');
if( fid == -1 )
    disp(sprintf('Error: Unable to open file [%s], fid=%d\n',filename,fid));
    A = [-1];
    fclose(fid);
    return;
end

m   = fread(fid,[1 1],'uint64');
n   = fread(fid,[1 1],'uint64');
nnz = fread(fid,[1 1],'uint64');

fprintf('Reading %d x %d with %d non-zeros\n',m,n,nnz);

S = fread(fid,[3 nnz],'double');
fclose(fid);
A = sparse(S(1,:)',S(2,:)',S(3,:)',m,n);

我得到的返回矩阵规范的结果是

Matlab:规范(A。'来回')= 0.018317077159881

Python:np.linalg.norm(A)= 0.018317077159760

我已经确认他们正在读取正确数量的值(6590x7126矩阵,122526个非零),并且我对两者使用相同的标准(frobenius)。

关于可能导致这种情况的任何想法?

3 个答案:

答案 0 :(得分:4)

快速浏览Frobenius Norm表明它需要对所有值进行平方并将它们加在一起。

由于你在read命令中有uint64,看起来你可能正在填充浮点存储。当您将两个二进制数相乘时,需要两倍的位来存储答案。这意味着您需要128位来存储所有十进制值。如果Python和MATLAB以不同的方式执行此操作,则可以解释为什么您的十进制值不同。

有关MATLAB和Python如何处理浮点精度的信息,请参阅这两个链接:

的Python: https://docs.python.org/2/tutorial/floatingpoint.html

MATLAB: http://blogs.mathworks.com/cleve/2014/07/07/floating-point-numbers/

答案 1 :(得分:2)

Matlab肯定似乎对稀疏和密集阵列有不同的实现。使用4425x7126稀疏矩阵A和您链接到的54882非零条目以及以下命令:

FA=full(A);
av=A(:);
fav=FA(:);

我希望以下命令都能产生相同的值,因为它们都计算A的(非零)元素的平方和的平方根:

norm(A,'fro')
norm(av,2)
norm(FA,'fro')
norm(fav,2)

sqrt( sum(av .* av) )
sqrt( sum(av .^ 2) )

sqrt( sum(fav .* fav) )
sqrt( sum(fav .^ 2) )

事实上,我们看到三个略有不同的答案:

 norm(A,'fro')             0.0223294051001499
 norm(av,2)                0.0223294051001499
 norm(FA,'fro')            0.0223294051001499
 norm(fav,2)               0.0223294051001499

 sqrt( sum(av .* av) )     0.0223294051001521
 sqrt( sum(av .^ 2) )      0.0223294051001521

 sqrt( sum(fav .* fav) )   0.0223294051001506
 sqrt( sum(fav .^ 2) )     0.0223294051001506

事实上,即使报告的A的稀疏和密集表示的元素总和(有点)也不同:

sum(A(:))                 1.00000000000068
sum(FA(:))                1.00000000000035

这些差异似乎与您在Python和Matlab规范之间看到的数量级相同。

答案 2 :(得分:1)

不是答案,但我没有足够的代表发表评论。尝试将问题缩小一点是否值得?如果将原始矩阵划分为4个子矩阵(左上角,右上角,左下角,右下角),并将Matlab和Python中报告的Frobenius范数与每个子矩阵进行比较,您是否仍然看到任何值之间存在差异?如果是,则冲洗并重复该子标准。如果不是,那么请不要浪费时间阅读这篇评论。 :-)