疎行列の例 |
上記の疎行列には、非ゼロ要素が9個しかなく、ゼロ要素が26個あります。疎度は74%、密度は26%です。 |

数値解析や科学計算において、疎行列または疎配列とは、要素のほとんどがゼロである行列のことである。 [ 1 ]行列が疎であるとみなされるゼロ値要素の割合に関する厳密な定義はないが、一般的な基準としては、非ゼロ要素の数が行または列の数とほぼ等しいということである。対照的に、要素のほとんどが非ゼロである場合、その行列は稠密であるとみなされる。[ 1 ]ゼロ値要素の数を要素の総数(たとえば、m × n 行列の場合は m × n)で割った値は、行列の疎性と呼ばれること がある。
概念的には、スパース性は相互作用の少ないシステムに対応します。例えば、バネで一つ一つのボールから次のボールへとつながれた一列のボールを考えてみましょう。これは隣接するボール同士のみが結合されているスパースシステムです。対照的に、同じ一列のボールがバネで他のすべてのボールとつながれている場合、このシステムは稠密行列に対応します。スパース性の概念は、組み合わせ論や、ネットワーク理論や数値解析などの応用分野で有用です。これらの分野では、一般に重要なデータや接続の密度は低いからです。大規模なスパース行列は、偏微分方程式を解く科学技術アプリケーションでよく登場します。
疎行列をコンピュータに保存したり操作したりする場合、行列の疎構造を利用する専用のアルゴリズムとデータ構造を使用すると便利であり、多くの場合必要になります。疎行列専用のコンピュータが作られており、 [ 2 ]機械学習の分野では一般的です。[ 3 ]標準的な密行列構造とアルゴリズムを使用した操作は、処理とメモリがゼロで浪費されるため、大きな疎行列に適用すると遅く非効率的です。疎データは本質的に圧縮しやすいため、必要なストレージが大幅に少なくなります。非常に大きな疎行列の中には、標準的な密行列アルゴリズムを使用して操作できないものもあります。
帯行列は、非ゼロ要素が主対角線付近に集中する特殊な疎行列です。帯行列は、下側バンド幅と上側バンド幅によって特徴付けられます。これらは、すべての非ゼロ要素が含まれる主対角線の下側と上側の対角線の数を表します。
正式には、行列Aの下側帯域幅とは、 i > j + pのときに要素a i , j が0となる最小の数pです。同様に、上側帯域幅とは、i < j − p のときにa i , j = 0となる最小の数pです(Golub & Van Loan 1996 , §1.2.1)。例えば、三角行列の下側帯域幅は1、上側帯域幅は1です。別の例として、次の疎行列の下側帯域幅と上側帯域幅はどちらも3です。わかりやすいように、ゼロはドットで表されていることに注意してください。
上側と下側の帯域幅が適度に小さい行列はバンド行列と呼ばれ、一般的なスパース行列よりも単純なアルゴリズムに適している場合が多くあります。また、密行列アルゴリズムを適用して、インデックスの数を減らしてループするだけで効率を向上できる場合もあります。
行列Aの行と列を並べ替えることで、より低い帯域幅を持つ行列A ′が得られる可能性があります。帯域幅を最小化するアルゴリズムは数多く存在します。
対角行列は、上側と下側の帯域幅がゼロである帯行列の極端な例です。対角行列は、主対角成分のみを1次元配列として格納することで効率的に格納できるため、 n × n対角行列はメモリに n個の成分のみを必要とします。
対称疎行列は、無向グラフの隣接行列として発生し、隣接リストとして効率的に格納できます。
ブロック対角行列は、対角ブロックに沿った部分行列から構成される。ブロック対角行列Aは次の形式をとる。
ここで、A kは、すべてのk = 1, ..., nに対して正方行列です。
行列のフィルインとは、アルゴリズムの実行中に、初期値がゼロから非ゼロ値に変化する要素のことです。アルゴリズム実行中に使用されるメモリ使用量と演算回数を削減するには、行列の行と列を入れ替えることでフィルインを最小限に抑えることが有効です。記号コレスキー分解を用いると、実際のコレスキー分解を行う前に、最悪のフィルインを計算することができます。
コレスキー分解以外にも、様々な手法が用いられています。例えば、最小二乗法で問題を解く場合などには、直交化手法(QR分解など)が一般的です。理論的な補完は同じですが、実際には「偽の非ゼロ値」は手法によって異なる場合があります。これらのアルゴリズムの記号版は、記号コレスキー分解と同様に、最悪のケースの補完を計算するために使用できます。
スパース行列を解くには 反復法と直接法の両方が存在します。
共役勾配法やGMRES法などの反復法は、疎行列における行列-ベクトル積の高速計算を利用します。前処理を用いることで、このような反復法の収束を大幅に加速することができます。
行列は通常、2次元配列として保存されます。配列の各エントリは行列の要素a i , jを表し、2つのインデックスiとjによってアクセスされます。慣例的に、iは行インデックス(上から下へ番号付け)、jは列インデックス(左から右へ番号付け)です。m × n行列の場合、この形式で行列を保存するために必要なメモリ量は m × n に比例します(行列の次元も保存する必要があるという事実は考慮しません)。
疎行列の場合、非ゼロ要素のみを格納することで、メモリ使用量を大幅に削減できます。非ゼロ要素の数と分布に応じて異なるデータ構造を使用でき、基本的なアプローチと比較してメモリ使用量を大幅に削減できます。ただし、トレードオフとして、個々の要素へのアクセスがより複雑になり、元の行列を一意に復元するために追加の構造が必要になります。
フォーマットは 2 つのグループに分けられます。
DOKは、(行, 列)のペアを要素の値にマッピングする辞書で構成されています。辞書に存在しない要素はゼロとみなされます。この形式は、ランダムな順序で疎行列を段階的に構築するのに適していますが、辞書式順序で非ゼロ値を反復処理するには適していません。通常、この形式で行列を構築し、その後、処理のためにより効率的な別の形式に変換します。[ 4 ]
LILは行ごとに1つのリストを格納し、各エントリには列インデックスと値が含まれます。通常、これらのエントリは列インデックスでソートされ、検索を高速化します。これは、増分的な行列構築に適したもう1つの形式です。[ 5 ]
COOは(行、列、値)のタプルのリストを格納します。理想的には、エントリはまず行インデックスでソートされ、次に列インデックスでソートされることで、ランダムアクセス時間が向上します。これは、増分的な行列構築に適したもう1つの形式です。[ 6 ]
圧縮スパース行(CSR)または圧縮行ストレージ(CRS)あるいはYale形式は、行列Mを3つの(1次元)配列で表現します。配列はそれぞれ、非ゼロ値、行の範囲、列インデックスを含みます。COOに似ていますが、行インデックスを圧縮するため、この名前が付けられています。この形式は、高速な行アクセスと行列ベクトル乗算(M x)を可能にします。CSR形式は少なくとも1960年代半ばから使用されており、最初の完全な記述は1967年に登場しました。[ 7 ]
CSR形式は、3つの(1次元)配列(V、COL_INDEX、ROW_INDEX)を用いて、 m × nの疎行列Mを行形式で格納します。NNZはM内の非ゼロ要素の数を表します。(ここではゼロベースのインデックスを使用することに注意してください。)
例えば、行列 は4つの非ゼロ要素を持つ 4×4行列なので、
V = [ 5 8 3 6 ] COL_INDEX = [ 0 1 2 1 ] ROW_INDEX = [ 0 1 2 3 4 ]
ゼロインデックス言語を想定しています。
行を抽出するには、まず以下を定義します。
row_start = ROW_INDEX[行] row_end = ROW_INDEX[行 + 1]
次に、row_start から row_end まで、V と COL_INDEX からスライスを取得します。
この行列の行1(2行目)を抽出するには、row_start=1と を設定しますrow_end=2。次に、スライスV[1:2] = [8]と を作成しますCOL_INDEX[1:2] = [1]。これで、行1の列1に値が8の要素が1つあることがわかります。
この場合、CSR表現には13個のエントリが含まれますが、元の行列には16個あります。CSR形式は、NNZ < ( m ( n − 1) − 1) / 2の場合にのみメモリを節約します。
別の例として、行列 は4×6行列(24要素)で、8つの非ゼロ要素を持つので、
V = [ 10 20 30 40 50 60 70 80 ] COL_INDEX = [ 0 1 1 3 2 3 4 5 ] ROW_INDEX = [ 0 2 4 7 8 ]
全体は 21 個のエントリとして保存されます ( Vに 8 個、COL_INDEXに 8 個、ROW_INDEXに 5 個) 。
(10, 20) (30, 40) (50, 60, 70) (80) )のインデックスを示します。(10, 20, ...) (0, 30, 0, 40, ...)(0, 0, 50, 60, 70, 0) (0, 0, 0, 0, 0, 80)。この形式では、 ROW_INDEXの最初の値は常に0で、最後の値は常にNNZ であるため、これらはある意味で冗長です(ただし、配列の長さを明示的に格納する必要があるプログラミング言語では、NNZ は冗長ではありません)。とはいえ、これにより、式ROW_INDEX[ i + 1] − ROW_INDEX[ i ]が任意の行iに対して機能することが保証されるため、各行の長さを計算する際に例外的なケースを処理する必要がなくなります。さらに、この冗長なストレージのメモリコストは、十分に大きな行列ではおそらく無視できるでしょう。
(新旧の)Yale疎行列形式はCSRスキームのインスタンスです。旧Yale形式は上記と全く同じように動作し、3つの配列を使用します。新形式ではROW_INDEXとCOL_INDEXを1つの配列に統合し、行列の対角成分を個別に扱います。[ 9 ]
論理隣接行列の場合、行配列にエントリが存在するだけでバイナリ隣接関係をモデル化できるため、データ配列は省略できます。
この形式は、1977年にイェール大学コンピュータサイエンス学部の「イェール・スパース・マトリックス・パッケージ」レポートで提案されたため、イェール形式として知られていると考えられます。[ 10 ]
CSC は CSR と似ていますが、値が最初に列ごとに読み取られ、各値の行インデックスが格納され、列ポインタが格納されます。たとえば、CSC は(val, row_ind, col_ptr)です。ここで、valは行列の (上から下、次に左から右の) 非ゼロ値の配列です。row_indは値に対応する行インデックスです。col_ptr は各列が始まる val インデックスのリストです。名前は、列インデックス情報が COO 形式に対して圧縮されているという事実に基づいています。通常、構築には別の形式 (LIL、DOK、COO) が使用されます。この形式は、算術演算、列スライス、および行列ベクトル積に効率的です。これは、MATLAB で (関数を介して) 疎行列を指定するための従来の形式ですsparse。
多くのソフトウェアライブラリが疎行列をサポートし、疎行列方程式のソルバーを提供しています。以下はオープンソースです。
スパース行列という用語は、いくつかの先駆的な研究を開始したものの、その後この分野から去ったハリー・マーコウィッツによって作られたと考えられます。 [ 11 ]
大規模な疎行列と密行列の乗算です。数値解析の分野では、疎行列とは、主にゼロ要素で構成される行列のことです。一方、行列内の非ゼロ要素の数が比較的多い場合、一般的に密行列とみなされます。行列内のゼロ要素(非ゼロ要素)の割合は、疎性(密度)と呼ばれます。標準的な密行列構造とアルゴリズムを用いた演算は、大規模な疎行列に適用すると比較的遅く、大量のメモリを消費します。
WSEには、AI向けに最適化された40万個のコンピューティングコアが搭載されています。SLAC™(Sparse Linear Algebra Cores)と呼ばれるこれらのコンピューティングコアは、柔軟性とプログラミング性を備え、すべてのニューラルネットワークコンピューティングの基盤となるスパース線形代数向けに最適化されています。
は、面積46,225平方ミリメートルで史上最大のチップであり、最大のグラフィックス処理装置の56.7倍の大きさです。AIに最適化されたコンピューティングコアは78倍、高速オンチップメモリは3,000倍、メモリ帯域幅は10,000倍、通信帯域幅は33,000倍に増加しています。
scipy.sparse.dok_matrixscipy.sparse.lil_matrixscipy.sparse.coo_matrix