我正在使用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
在这种情况下,它将负值变为零并保持正数不变?
答案 0 :(得分:4)
看起来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.然后我们使用{{1}将结果向量转换回对角矩阵并将这些片段重新组合在一起得到diag
,A
的修改形式。
请注意,我们可以跳过Haskell中的一些步骤Y
(及其“经济大小的”伙伴svd
)返回特征值的向量,而不是大多数0'd对角矩阵。
thinSVD
高于(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
特征值Vector
,然后s
(来自diag
)重新定位Numeric.Container
} Vector
之前的Matrix
。稍微考虑一下,很容易看出multiply
只是max 0
应用于单个元素。
答案 1 :(得分: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
表示法将此元素与.*
相乘,则将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 ]
因此,您需要编写自己的函数,该函数将返回正值,并将负值设置为零。
而且,u
和v
的维度不匹配,对于一般的SVD分解,所以你实际上需要REDIAGONALIZE pos(diagS - Tau),以便u* diagnonalized_(diagS -tau)
agrres到v