【问题标题】:What is the Haskell / hmatrix equivalent of the MATLAB pos function?MATLAB pos 函数的 Haskell / hmatrix 等效项是什么?
【发布时间】:2014-01-02 01:40:57
【问题描述】:

我正在使用 hmatrix 库将一些 MATLAB 代码转换为 Haskell。进展顺利,但是 我在 pos 函数上磕磕绊绊,因为我不知道它是做什么的,也不知道它与 Haskell 的等价物是什么。

MATLAB 代码如下所示:

[U,S,V] = svd(Y,0);
diagS = diag(S);
...
A = U * diag(pos(diagS-tau)) * V';
E = sign(Y) .* pos( abs(Y) - lambda*tau );
M = D - A - E;

到目前为止我的 Haskell 翻译:

(u,s,v) = svd y
diagS = diag s
a = u `multiply` (diagS - tau) `multiply` v

这实际上类型检查正常,但当然,我错过了“pos”调用,它会抛出错误:

inconsistent dimensions in matrix product (3,3) x (4,4)

所以我猜 pos 对矩阵大小有什么影响?谷歌搜索“matlab pos 函数”没有发现任何有用的东西,所以非常感谢任何指针! (显然我对MATLAB了解不多)

顺便说一下,这是为了让 TILT 算法从嘈杂的扭曲图像中恢复低等级纹理。我对此感到非常兴奋,即使数学远远超出我的能力!

看起来 pos 函数是在不同的 MATLAB 文件中定义的:

function P = pos(A)
P = A .* double( A > 0 );

我无法完全理解这是在做什么。假设布尔值转换为双精度值,其中 "True" == 1.0 和 "False" == 0.0

在这种情况下,它会将负值变为零并保持正数不变?

【问题讨论】:

  • pos 是否可能在 matlab 源代码的其他地方定义?
  • 谢谢@DanielWagner,原来如此。

标签: matlab haskell hmatrix


【解决方案1】:

看起来pos 找到了矩阵的正数部分。你可以直接用mapMatrix实现这个

pos :: (Storable a, Num a) => Matrix a -> Matrix a
pos = mapMatrix go where
  go x | x > 0     = x
       | otherwise = 0

虽然 Matlab 不像 Haskell 那样区分 MatrixVector

但值得进一步分析 Matlab 片段。根据http://www.mathworks.com/help/matlab/ref/svd.html,第一行计算Y 的“经济规模”奇异值分解,即三个矩阵使得

U * S * V = Y

其中,假设Ym x n,那么Um x nSn x n 和对角线,Vn x n。此外,UV 都应该是正交的。在线性代数术语中,这将线性变换Y 分为两个“旋转”分量和中心特征值缩放分量。

由于S 是对角线,我们使用diag(S) 提取该对角线作为向量,然后减去也必须是向量的项tau。这可能会产生一个包含负值的对角线,无法正确解释为特征值,因此pos 用于修剪负特征值,将它们设置为 0。然后我们使用diag 转换得到的向量回到对角矩阵,然后将这些部分相乘,得到AY 的修改形式。

请注意,我们可以跳过 Haskell 中的一些步骤,因为 svd(及其“经济型”合作伙伴 thinSVD)返回特征值向量,而不是大多数为 0 的对角矩阵。

(u, s, v) = thinSVD y

-- note the trans here, that was the ' in Matlab
a = u `multiply` diag (fmap (max 0) s) `multiply` trans v

fmap 上方将max 0 映射到特征值sVector 之上,然后diag(来自Numeric.Container)将Vector 重新膨胀为Matrix 之前的@98765453稍加思考,很容易看出max 0 只是pos 应用于单个元素。

【讨论】:

【解决方案2】:

(A>0) 返回 A 中大于零的元素的位置, 例如,如果你有

A = [ -1 2 -3 4
       5 6 -7 -8 ]

然后B = (A > 0) 返回

B = [ 0 1 0 1
      1 1 0 0]

请注意,我们有一个对应于大于零的 A 的元素,否则为 0。

现在,如果您使用.* 表示法将此元素与A 相乘,那么您将A 中大于零的每个元素乘以1,否则乘以零。也就是A .* B的意思是

[ -1*0   2*1   -3*0   4*1
   5*1   6*1   -7*0  -8*0 ]

最终给予,

[ 0 2 0 4
  5 6 0 0 ]

因此,您需要编写自己的函数,该函数将原封不动地返回正值,并将负值设置为零。

而且,uv 在维度上不匹配,对于一般的 SVD 分解,因此您实际上需要重诊断 pos(diagS - Tau),以便 u* diagnonalized_(diagS -tau) agrres 到 v

【讨论】:

  • 我发现 Alberto Ruiz 对 hmatrix 的介绍非常有用(它有一个在 haskell 和 matlab 之间的命令翻译列表)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-04
  • 2012-08-16
相关资源
最近更新 更多