8

小さな可変列ベクトルと巨大な定数行列(多くの行と少数の列)f(x)=exp(A*x)を繰り返し計算する必要があります。言い換えれば、数は少ないが、数は多い。私の問題の次元は、exp() 部分と同じくらいの実行時間がかかるようなものです。xAxA*xA*x

テイラー展開と値の範囲の事前計算 ( の値exp(y)の範囲が既知であると仮定)とは別に、MATLAB が独自に行っていることに関して (精度を維持しながら) 大幅に高速化することができませんでした。いくつかの値を事前に計算できるようにするために、問題を分析的に再説明することを考えています。yA*x

たとえば、私はそれを見つけますexp(A*x)_i = exp(\sum_j A_ij x_j) = \prod_j exp(A_ij x_j) = \prod_j exp(A_ij)^x_j

これにより、事前計算exp(A)を 1 回行うことができますが、ループで必要な累乗は、元の関数呼び出しと同じくらいコストがかかりexp()、さらに乗算 (\prod) を実行する必要があります。

私が従うことができる他のアイデア、または見逃した可能性のある MATLAB 内のソリューションはありますか?

編集:いくつかの詳細

Aは 26873856 x 81 のサイズです (そうです、これはとても大きいです)。つまり、81 x x1 nnz(A) / numel(A)です。を表すために既に疎行列を使用していますが、疎行列の exp() はもはや疎ではありません。実際、私は非スパースを保存し、どちらが高速/低速であることが判明したかを計算します( x は非スパースであるため、とにかく非スパースだと思います)は sparse を持つ方法ですが、遅いです. さらに遅いバリアントは、(スパース型の非スパース行列のメモリへの影響が 2 倍になる) と(これも非スパース結果を生成します) です。0.0012nnz(A*x) / numel(A*x)0.0075Axexp(full(A*x))full(exp(A*x))A*xexp(full(A*sparse(x)))A*xexp(A*sparse(x))full(exp(A*sparse(x))

sx = sparse(x);
tic, for i = 1 : 10, exp(full(A*x)); end, toc
tic, for i = 1 : 10, full(exp(A*x)); end, toc
tic, for i = 1 : 10, exp(full(A*sx)); end, toc
tic, for i = 1 : 10, exp(A*sx); end, toc
tic, for i = 1 : 10, full(exp(A*sx)); end, toc

Elapsed time is 1.485935 seconds.
Elapsed time is 1.511304 seconds.
Elapsed time is 2.060104 seconds.
Elapsed time is 3.194711 seconds.
Elapsed time is 4.534749 seconds.

はい、要素ごとの exp を計算します。それを反映するように上記の式を更新します。

もう1つの編集:私は賢くしようとしましたが、ほとんど成功しませんでした:

tic, for i = 1 : 10, B = exp(A*x); end, toc
tic, for i = 1 : 10, C = 1 + full(spfun(@(x) exp(x) - 1, A * sx)); end, toc
tic, for i = 1 : 10, D = 1 + full(spfun(@(x) exp(x) - 1, A * x)); end, toc
tic, for i = 1 : 10, E = 1 + full(spfun(@(x) exp(x) - 1, sparse(A * x))); end, toc
tic, for i = 1 : 10, F = 1 + spfun(@(x) exp(x) - 1, A * sx); end, toc
tic, for i = 1 : 10, G = 1 + spfun(@(x) exp(x) - 1, A * x); end, toc
tic, for i = 1 : 10, H = 1 + spfun(@(x) exp(x) - 1, sparse(A * x)); end, toc

Elapsed time is 1.490776 seconds.
Elapsed time is 2.031305 seconds.
Elapsed time is 2.743365 seconds.
Elapsed time is 2.818630 seconds.
Elapsed time is 2.176082 seconds.
Elapsed time is 2.779800 seconds.
Elapsed time is 2.900107 seconds.
4

1 に答える 1

2

コンピュータは実際には指数を計算しません。あなたは彼らがそうしていると思うかもしれませんが、彼らがしているのは高精度の多項式近似です.

参考文献:

最後のリファレンスはかなり良さそうでした。おそらくそれが最初だったはずです。

画像に取り組んでいるので、離散数の強度レベル (通常は 255) がある可能性があります。これにより、「A」の性質に応じて、サンプリングまたはルックアップを減らすことができます。これを確認する 1 つの方法は、「x」の値の十分に代表的なグループに対して次のようなことを行うことです。

y=Ax
cdfplot(y(:))

画像を「より興味深い」と「それほど重要ではない」に事前にセグメント化できた場合 - X 線を見て、すべての「人体の外側」の場所を切り取ってクランプすることができる場合のようにゼロを使​​用してデータを事前にスパース化すると、一意の値の数が減る可能性があります。データ内の一意の「モード」ごとに前のものを考慮することができます。

私のアプローチには次のものが含まれます。

  • 精度は低いが高速な exp(x) の別の定式化を見てください。
  • 「x」のレベルが十分にない場合は、テーブル ルックアップを検討してください
  • テーブルルックアップを行うには「少し多すぎる」レベルがある場合は、補間とテーブルルックアップの組み合わせを検討してください
  • セグメント化されたモードに基づく単一のルックアップ (または別の定式化) を検討してください。それが骨であることがわかっていて、静脈を探している場合は、適用される高コストのデータ処理を少なくする必要があります。

ここで、exp(A*x)*x の反復を何度も繰り返している理由を自問する必要があります。周波数/波数領域と時間/空間領域を行き来しているのかもしれません。また、exp(x) を基礎として使用して確率を処理し、ベイジアンを楽しむこともできます。exp(x) が適切な共役事前分布であることを知らないので、フーリエ マテリアルを使用します。

その他のオプション: - 行列を指定して fft、fft2、または fftn の使用を検討してください。これらは高速であり、探しているものの一部を実行する可能性があります。

私は、次のように forier ドメインのバリエーションがあると確信しています。

ウッドベリー行列を使用して、ルックアップと計算を組み合わせることができる場合があります。確かに、それについていくつか考えなければならないでしょう。(リンク) ある時点で、重要なこと (CFD、FEA、FFT) はすべて逆行列に関するものだと知っていましたが、それ以来、特定の詳細を忘れてしまいました。

MatLab を使用している場合は、MatLab コードを C コードに変換する「コーダー」の使用を検討してください。インタープリターがどれほど楽しいものであっても、優れた C コンパイラーははるかに高速です。私が使用しているニーモニック (あまり野心的でないことを願っています) をここに示します:リンクは 13:49 頃から始まります。これは非常に単純ですが、標準的なインタープリター言語 (python) とコンパイルされたバージョン (cython/c) の違いを示しています。

もう少し詳細があり、要求された場合は、より具体的に関連する回答にもっと積極的に関与できると確信しています.

従来のハードウェアでそれを行う良い方法がない場合は、GPGPU のようなものを検討してください。CUDA とそのピアには、数枚のビデオ カードのコストで大幅な高速化を可能にする大規模な並列操作があります。いくつかの ALU の作業を実行する何千もの「コア」(過大評価されたパイプライン) を使用できます。ジョブが適切に並列化可能であれば (このように)、はるかに高速に実行できます。

編集:

エウレカのことを考えていた。開発用の「大きな鉄」があり、本番用ではない場合に検討する1つのオプションは、Eureqa製品を使用して、十分に高速で正確な近似を考え出すことです.

「A」行列の「迅速な」特異値分解を実行すると、支配的なパフォーマンスが 81 個の固有ベクトルによって支配されることがわかります。固有値を調べて、81 個の固有ベクトルのうち、ほとんどの情報を提供する固有ベクトルがわずかしかないかどうかを確認します。その場合は、他のものをゼロにクランプして、単純な変換を構築できます。

さて、私だったら指数から「A」を取り出したいと思います。81x81 の固有ベクトル行列と "x" を見て、線形代数と、ベクトルを投影する空間について少し考えていただけないでしょうか。次のような関数を作成する方法はありますか。

f(x) = B2 * exp( B1 * x )

そのような

B1××

現在のランクよりもはるかに低いランクです

斧。

于 2014-05-05T14:03:04.773 に答える