PyTorchの畳み込みニューラルネットワークのライブラリ化の試み

PyTorchで作成した手書き数字認識プログラムを手軽に使えるようにライブラリ化できないかなぁっという思いで、以前、PyTorchで作成した全結合のニューラルネットワークの学習したパラメータを、Cythonで作成した自前のニューラルネットワークに読み込ませるといったことをしました。

今回は、それを畳み込みニューラルネットワーク(CNN)でやってみました。

 

元となるPyTorchのモデル

class MyNet(torch.nn.Module):
    def __init__(self):
        super(MyNet, self).__init__()
        self.conv1 = torch.nn.Conv2d(1, 20, 5, 1)
        self.conv2 = torch.nn.Conv2d(20, 50, 5, 1)
        self.fc1 = torch.nn.Linear(4*4*50, 500)
        self.fc2 = torch.nn.Linear(500, 10)

    def forward(self, x):
        x = F.relu(self.conv1(x))
        x = F.max_pool2d(x, 2, 2)
        x = F.relu(self.conv2(x))
        x = F.max_pool2d(x, 2, 2)
        x = x.view(-1, 4*4*50)
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return F.log_softmax(x, dim=1)

参照元:
PyTorchでシンプルな畳み込みニューラルネットワークを作ろう
https://qiita.com/sudamasahiko/items/fd6a52f958f3f9013f0f

 

以前、このモデルで、手書き数字の判別をさせてみると正解率95%以上という結果でした。
そこで、前回、勉強がてら、PyTorchで学習したパラメータを利用して、生Pythonで実装した畳み込み演算で画像判別をするということを行いました。今回、これをCython化して高速化しました。

結果、生Pythonでは、1文字1.609秒かかる処理が0.062秒になり、およそ25倍高速化しました。まずまずですが、まだ少し物足りない・・・かな。

 

過程を書くと、
・1文字もコードを変えずにCython化すると0.929秒(1.7倍)
・クラスをcdef化し、def内整数と実数をcdefで宣言すると0.311秒(5.2倍)
・Cython内のみで使用する配列をポインタ化すると0.062秒(26.0倍)
となり、ポインタ化がすごく効いてきます。

 

今回のソースは、PyTorchでのモデル定義をなるべくそのまま使えるような形を意識しており、Python側でモデルを定義できます。それゆえ、各関数の出力データは、生Pythonで扱えるlistオブジェクトで返してます。そのlistの生成に時間がかかっている気がします。

 

ちなみにlistの代わりにnumpyの配列(メモリービュー)も試しましたが、あまり速くならず、というかlistより遅くなりました。listと違い、要素の型を指定するので高速化するはずなのですが、処理ごとに配列を生成する書き方をしているので、生成に時間がかかってしまっているのかなと。モジュールをインポートした際に、必要な配列を用意しておく書き方にすれば、たぶんもうちょっと高速化するのだろうけど、今回はここまでにします。

 

そもそも、手書き数字認識ライブラリを作ることを目的とするなら、モデルの定義をPython側で柔軟にできるようにする必要もなく、Cython側で固定してしまって、全てのデータを配列なりポインタなりで扱えば、もっと大幅に高速化するはずです。その方向性でのを次回試すことにします。
追記:さらに約6倍高速化しました。

 

(さらに…)

Pythonで画像の畳み込みニューラルネットワーク処理のコーディング(学習なし)

前回、PyTorchで手書き数字の識別する畳み込みニューラルネットワーク(CNN)を試しました。モデルは元祖CNNであるLeNet形で、今回はその畳み込み演算をPythonで書いてみました。

 

外枠だけニューラルネットワークの形にしてはいますが、画像の1画素をニューロンとみなして畳み込み演算のフィルタを機械学習可能にしたCNNのコーディングとは、たぶん別物です。

元々の目的がPyTorchで学習したCNNモデルのパラメータ使ってCythonで自前のライブラリを作ることで、今回は理解している処理が正しいのか確認するための勉強コーディングになります。

そのため学習(逆伝播)を実装するつもりがないので、一般的(だと思う)な畳み込み演算をそのままコーディングしています。おそらく学習するんであれば、ニューロンのクラス化等々、相応のやり方があるんだろうなぁと想像します。

 

ここからCythonで高速化することが、本番ですが、畳み込み演算の実際の処理を理解したい人とか、CNNの処理の流れ理解したい人とかには役立つかなぁと思って投稿します。まぁ、ホントはなんの書物等の手助けもなく出来たことが嬉しかったんで投稿しとこうってだけなのですが^^;

 

追記:Cython化しました

(さらに…)

Pythonで手書き数字のORCにトライ(その3)

以前、PyTorchで全結合のニューラルネットワークで、手書き数字認識を行い、自分の文字の正解率6~8割くらいでした。その後、線化処理などを加えた全結合のニューラルネットワークで試すと、9割くらいになりました。

今回は、畳み込みニューラルネットワーク(CNN)を試しました。モデルは、1998年に考案された元祖CNN、LeNetを模したモデルでやってみました。

結果、NMISTのテストデータでは99%以上の正解率、自分の文字の正解率は96%でした。すげぇー。

ただ、文字を中心に配置してサイズ調整する処理を加えない場合は、正解率は82%に落ちてしまったので、画像の前処理が肝となりそうです。

 

(さらに…)

サムネイル作成ツールを作成

あけましておめでとうございます。新年一発目の記事がこんなんになってしまいましたが、ソフトウェアサイトにサムネイル作成ツールを追加しました。

https://software.tiblab.net/pc/img_thumbs_console/

 

なぜこんなソフトを作ったかと言いますと、会社のストレージが1年半ほど前にNASからオンラインストレージサービスに切り替わったのですが(コロナ前でラッキーでした)、サムネイルの表示が遅くなったというか、実質的にできなくなって、ほしい画像を見つけるのが大変で仕方がなくなったからです。

 

特に、エクスプローラのファイル検索が機能しないのが不便で、特定の画像を探したいとき、ファイル検索で拡張子を指定して、表示をサムネイルにし、次々と生成されるサムネイルをスクロールしながら探し出すという技が使えなくなりました。

 

そこで、その技を代替する方法として、下層フォルダを含めて存在する全ての画像のサムネイル画像を、一つのフォルダに集約するツールを作りました。まぁ、生成にめっちゃ時間がかかるので事前に作成しとかなくてはいけないんですが。
また、そのフォルダをオフライン編集可の設定しとくとか、キャッシュに残っている内はエクスプローラでサムネイル表示できるんですが、そうでないときはできないので、HTMLを作成して、ブラウザでサムネイル一覧を見れるようにしました。

 

今回、GUIを作るでもなくコンソールプログラムです。
元々は、サムネイルを作成・表示するビュアーを作ろうしたのですが、動的にサムネイルを追加していくとスクロールがカクカクするとか、ウィンドウ幅を変えた際のサムネイルの再配置が劇遅とか、GUI制御絡みで詰まりそうだったので、一旦、GUIなし最低限機能で完成させることにしました。

ビュアーが欲しいことには変わりないので、作りたいとは思いますが・・・、いつになるやら。

PyTorchニューラルネットワークのライブラリ化の試み

前回、PyTorchでニューラルネットワークを組んで手書き数字の認識を行いまして、9割くらいの正解率になりました。
昔、勉強にニューラルネットワークをPythonで組んだことがありますが、実用的な使い方がわからず、書いてみた仕舞いでしたが、初めて実用性を実感しました。

そこで、学習させたネットワークのライブラリ化ができないかなぁと思って、実施したことのメモです。

 

要約すると、実行ファイル(exe)化はできなかったので、PyTorchで学習させた重み等のパラメータを、Cythonで組んだ自前のニューラルネットワークライブラリに読み込ませるということを行いました。

 

(さらに…)