|
NumSharpの優れた新しい配列スライシング機能のおかげで、.NETコミュニティは強力なオープンソースの機械学習プラットフォームに一歩近づきました。 Pythonは機械学習言語であり、NumPyやTensorFlowのような優れたライブラリがあるからです。 しかし、C#開発者は機械学習やデータサイエンスのための強力なオープンソースライブラリも強く必要としています。 SciSharp STACK組織のNumPy C#移植版であるNumSharpは、最近大きな一歩を踏み出し、スライシング機能を完全に実装し、N次元配列の任意のサブセットを生データの効率的なビューとして作成できるようになりました。 これにより、TensorFlow.NET と組み合わせてC#を機械学習に使う際に役立つツールとなっています。
何がそんなに大したことなんだ?
NumPyを使ったことがなければ、スライシングの素晴らしさをご存じないかもしれません。 Python配列は、以下のように一連の要素をインデックスすることで配列のスライスを返すことができます。a[start:stop:step]。 しかし、スライシングが真に強力なデータ操作技術となるのは、NumPyの複雑な配列実装であり、機械学習やデータサイエンスが実現しなければ想像もつかないでしょう。 幸いなことに、機械学習のためにPythonに切り替えられない、あるいは切り替えたくない人(私も作ったものです)のために、NumSharpはこの機能を.NETの世界にもたらしています。 NumSharpの開発者の一人として、C#のサンプルコードスニペットを使った重要なスライシングのユースケースをご紹介しました。 言語の構文の違いにより、C#ではPythonと同じ方法でインデックス作成を行うことはできません。 しかし、スライス定義にはPythonの構文を残すことに決め、C#でスライスをインデックスするために文字列を使いました。 この例を見て、NumSharpがNumPyにどれほど近いかがわかります。
Python/NumPyでマトリックスから列を切り取ってくださいC#でNumSharpを使って書くと、コードはほぼ同一です。 スライスはインデクサのパラメータとして文字列を用いてわずかに異なるインデックス付けをします。
C#/NumSharpでマトリックスから列を切り抜くご覧の通り、NumSharpチームはコードをできるだけPythonに似せるために多大な努力を注いでいます。 これは非常に重要です。なぜなら、NumPyに依存している既存のPythonコードを簡単にC#に移植できるからです。
ユースケース:同じデータの複数のビューを使う
基底データ(すなわち大きな画像の小さな部分)をコピーせずに関数内で出力できるのは、特に大規模なデータセットにおいてランタイムパフォーマンスに不可欠です。 スライスはローカル座標でインデックスされるため、アルゴリズムはデータのグローバル構造を知る必要がなく、作業を簡素化し、不要な重複を避けるために最大のパフォーマンスを確保します。
ユースケース:スパースビューと再帰スライシング
配列のスパースビューは、スライス範囲の開始と終了を超えるステップを指定することで作成できます。 私の知る限り、新しい配列スライス構文を使ったC# 8.0でもこれができません。 この機能はインターリーブデータ扱いにおいて非常に重要です。 連続データを扱うアルゴリズムを設計し、連続データソースを模倣したスパーススライスを用意することで、アルゴリズムの複雑さを最小限に抑えることができます。
スライスはさらにスライス可能で、これは高次元データを扱う際に非常に重要な機能です。 これにより、再帰的にスライスすることでデータの次元を下げられるため、アルゴリズムの複雑さを軽減するのにも役立ちます。
ユースケース:高次元データの効率的な処理
データの配列をボリュームとして考え、その部分を扱いながらも複雑な座標変換計算をしなくても済むなら、.reshape() があなたの味方です。 すべての配列は.reshape()で作成され、元のデータのビューにすぎません。 ビューに要素を反復、読み込み、書き込むと、生のデータ配列にアクセスできます。 NumSharpは適切なインデックス変換を透過的に行ってくれるので、相対座標でスライスをインデックス付けできます。
ユースケース:追加コストなしで要素の順序を逆にできる
ネガティブステップを使うスライスは、実際にはスライスの順序を逆にしています。 この方法の利点は、IEnumerable.Reverse()と同様に、データをコピーしたり列挙したりする必要がないことです。 違いは、ビュー(演算a["::-1"]の結果)がデータを逆順に表示し、列挙せずにその逆さまの列にインデックスできる点です。
ユースケース:寸法を小さくして複雑さを削減する
高次元データを扱う場合、そのデータのアルゴリズムも非常に複雑になることがあります。 使用中では、任意の高次元体積を出力することができます。 ToString()のNumSharpメソッドNDArrayを使ったとき、NDボリュームを体系的かつ再帰的に(N-1)Dボリュームに分割することで、アルゴリズムがいかにシンプルで美しくなっているかに気づきました。 この分割統治方式は、NumSharpのインデックス記号を使って範囲記号をスライスすることで、低次元のサブボリュームを返します。 レンジ記号とインデックス記号の違い範囲記号[「スタート:ストップ:ステップ」]を使うと、同じ寸法の体積のサブレンジにアクセスできます。 ですので、2次元行列の1列だけを切り取っても、1列だけの2次元行列になります。 これを示す短いC#コードがあります:
範囲記号で列をスライスします
インデックス記号は、N次元親体積の指定された位置に(N-1)次元のスライスを示します。 2次元行列からインデックス記号を使って列を切り取ると、1次元ベクトルが得られます:
インデックス記号を用いた列のスライス
もし一目で違いが見えなかったなら、上記の2つのスライスの定義、ange[":2:3"]とindex[":,2"]を並べて示します。これらは結果に大きな影響を与えます。 新しいスライス記号の詳細な参照はNumSharpのウィキで確認できます。
注意:<T>ArraySlice
N次元ビューのスライシングを実装する際、.NETの他の多くの分野にも面白いと結論づけ、SliceAndDiceという独立したライブラリに分解しました。 ArraySliceなど、あらゆるC#データ構造のインデックス化に軽量なラッパーとして機能し<T>、他の重い数値計算を省くことなく、同じリモデリング、スライス、表示の仕組みを利用できます。 数百行のコードで優れたスライシング機能を実現できます! T[]IList(イリスト)<T>
ラップアラウンド
NumSharpも最近、同じスライスと閲覧メカニズムが導入されており、NumPyは間違いなくPython機械学習エコシステムの中で最も重要なライブラリの一つとなっています。 SciSharp STACKは、同じ機能を.NETの世界にもたらすために懸命に取り組んできた少数の熟練開発者によるオープンソース組織です。 NumSharpの最新の改良は、これを実現するための重要な基盤となっています。 翻訳元:ハイパーリンクのログインが見えます。
|