4

我正在使用 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

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

4

2 回答 2

4

看起来好像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来将该对角线提取为向量。这可能会产生一个包含负值的对角线,这些负值不能被正确解释为特征值,因此可以修剪掉负特征值,将它们设置为 0。然后我们使用将结果向量转换回对角矩阵并将这些部分相乘在一起得到,一种修改形式。diag(S)tauposdiagAY

请注意,我们可以跳过 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之前的a 。稍加思考,很容易看出它只是应用于单个元素。VectorsdiagNumeric.ContainerVectorMatrixmultiplymax 0pos

于 2014-01-02T03:18:08.003 回答
1

(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使用符号相乘,那么您将大于零的.*每个元素乘以1,否则乘以零。A也就是说,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 ]

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

而且,对于一般的 SVD 分解uv尺寸不匹配,因此您实际上需要 REDIAGONALIZE pos(diagS - Tau),以便u* diagnonalized_(diagS -tau)agrresv

于 2014-01-02T03:26:45.060 回答