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 function」をグーグルで検索しても、役立つものは何も見つかりませんでした。(明らかに、私はMATLABをあまり知りません)

ちなみに、これは TILT アルゴリズムがノイズの多い、歪んだ画像から低ランクのテクスチャを復元するためのものです。たとえ数学が私をはるかに超えていたとしても、私はそれについて非常に興奮しています!

pos 関数が別の MATLAB ファイルで定義されているようです。

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

これが何をしているのか完全に解読できません。ブール値が「True」== 1.0 および「False」== 0.0 の double にキャストされると仮定します。

その場合、負の値をゼロにして、正の値を変更しませんか?

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 と HaskellMatrixとの区別はありません。Vector

しかし、その Matlab フラグメントをさらに分析する価値があります。http://www.mathworks.com/help/matlab/ref/svd.htmlによると、最初の行は の「経済規模の」特異値分解、つまり次のような 3 つの行列を計算します。Y

U * S * V = Y

Yここで、はm x nUm x nSn x n対角線、 は とV仮定しn x nます。さらに、 と の両方が正規直交である必要がありますUV線形代数の用語では、これは線形変換Yを 2 つの「回転」コンポーネントと中央の固有値スケーリング コンポーネントに分離します。

は対角なのでS、 を使用してその対角をベクトルとして抽出し、ベクトルでなければならないdiag(S)項を減算します。tauこれにより、固有値として適切に解釈できない負の値を含む対角線pos生成される可能性があるため、負の固有値を削除して 0 に設定する必要がありますdiag。を取得するAには、 の修正された形式ですY

svdHaskell (およびその「経済サイズ」のパートナーthinSVD) は、ほとんどが 0 の対角行列ではなく、固有値のベクトルを返すため、Haskell のいくつかのステップをスキップできることに注意してください。

(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 に再膨張させます。少し考えれば、それが1 つの要素に適用されているだけであることが簡単にわかります。VectorsdiagNumeric.ContainerVectorMatrixmultiplymax 0pos

于 2014-01-02T03:18:08.003 に答える