我正在使用 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 );
我不太明白这是在做什么。假设 bool 值转换为 double 值,其中“True”== 1.0 和“False”== 0.0
在那种情况下,它将负值变为零并保持正数不变?
最佳答案
看起来 pos
找到了矩阵的正数部分。您可以直接使用 mapMatrix
pos :: (Storable a, Num a) => Matrix a -> Matrix a
pos = mapMatrix go where
go x | x > 0 = x
| otherwise = 0
尽管与 Haskell 不同,Matlab 不区分 Matrix
和 Vector
。
但值得对 Matlab 片段进行更多分析。每http://www.mathworks.com/help/matlab/ref/svd.html第一行计算 Y
的“经济规模”奇异值分解,即三个矩阵使得
U * S * V = Y
其中,假设 Y
是 m x n
那么 U
是 m x n
,S
是 n x n
和对角线,V
是 n x n
。此外,U
和 V
都应该是正交的。在线性代数术语中,这将线性变换 Y
分成两个“旋转”分量和中心特征值缩放分量。
由于 S
是对角线,我们使用 diag(S)
将该对角线提取为向量,然后减去一个 tau
项,它也必须是一个向量。这可能产生一个包含负值的对角线,不能正确解释为特征值,所以 pos
可以去除负特征值,将它们设置为 0。然后我们使用 diag
将生成的向量转换回对角矩阵并将这些部分相乘得到 A
,Y
的修改形式。
请注意,我们可以跳过 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
映射到特征值 s
的 Vector
上,然后是 diag
(来自 Numeric.Container
)在 multiply
之前将 Vector
重新膨胀为 Matrix
。稍加思考就很容易看出 max 0
只是应用于单个元素的 pos
。
关于matlab - MATLAB pos 函数的 Haskell/hmatrix 等价物是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20875182/