Amazon

2017年10月
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        

最近のトラックバック

無料ブログはココログ

Amazon2

« RaspberryPi用のヒートシンクを購入しました | トップページ | ニューラルネットワーク(機械学習)をC#で実装してみる その2 »

2016年12月30日 (金)

ニューラルネットワーク(機械学習)をC#で実装してみる その1


さて、最近データ分析の勉強などを細々としています。その中でも最近は
AIに関するニュースが非常に多く、AI=機械学習(=DeepLearning?)みたいな
記事もよく見かけます。技術的に見ても機械学習は非常に興味のある分野
です。加えて(実装は)結構簡単そうなので、理解する為にも試しに実装して
みました。

・目次
  ・その1 実装編 (ソースコードあり) ★今回の記事です
  ・その2 数式を学習してみる(シンプル編) 





・はじめに

今回の記事は全面的にえどふの技術記事 C#で実装するニューラルネットワーク その1
参考にさせて頂きました。


今回は、ニューラルネットワークの単純パーセプトロンを実装してみます。
そもそものきっかけは以下の様な事でした。

  ・解説書等の数式を見てなんとなく理解した気になっても実装方法が分からない
    実装しようとすると全く手が動かない
  ・なんとなくニューラルネットワーク(単純パーセプトロン)はオブジェクト指向と相性が良さそう
    「あの丸をオブジェクト化して連鎖すれば良いのでしょ?」程度の理解
  ・しかし、オブジェクト指向的な実装を全然見かけない
    向いていそうなのに…

色々判らない事だらけだったので、上記のサイトを参考にさせて頂きながら、
オブジェクト指向っぽくC#で実装してみました。なんとか形になった気がしますので
何回かに分けて記事にしてみたいと思います。

尚、実装した処理は全てえどふの技術記事 C#で実装するニューラルネットワーク その1の処理に
準じています(多分…)、処理内容・解説等は是非リンク先の記事を参考にして下さい。

・ニューラルネットワークをC#で実装してみる

今回の記事のきっかけは、ニューラルネットワークについて学習を進めていた時に
ふと思った事です。

  1. ニューロンは状態を持っている
  2. ニューロンとニューロンの連鎖でニューラルネットワークは構成されている
    → つまり、ニューロンを1つのクラスとした実装が判りやすいし、扱い易い筈

上記から、私は「これはオブジェクト指向的にはニューロンをオブジェクトにして、
自然に連鎖させれば簡単だな」と思い、その様な視点で色々他の方々のソースコードを
眺めていましたが、以下の様な点に気が付きました。

  1. C#での実装が少ない
  2. オブジェクト指向的な発想のロジックが少ない

では、見つからないから試しに組んでみようかな…と、思い今回の記事を
思い付きました。

以下の様に実装してみました。

  クラス構成
    INeuron
      Neuronの振舞の定義
    NeuronBase
      InputScalar/Perceptron/OutputScalarの基底クラス
      共通の機能を実装します。
    InputScalar
      入力層用のNeuronです。入力値を伝搬します。(逆伝搬は無視)
    Perceptron
      ニューロンの実体です。入力信号に反応して出力します。
      入出力側のニューロンを知っています。
      また、誤差逆伝搬も処理します。
    OutputScalar
      出力層から値を取り出す為の出力値クラスです。
      また、誤差逆伝搬も実施します。

考え方としては単純で、それぞれオブジェクト化されていますので、
INeuronは入力層すべてから信号を受信すると、自動的に次の層へ
信号を伝搬します。逆伝搬も同様です。

従って、入力層(InputScalar)に値を設定すると自動的に出力層(OutputScalar)から
結果が取得出来る様になります。

・ソースの解説

今回は珍しくソースコードだらけです。なお、ソースコードは下記からダウンロードが可能です。
  ※ソースコードの使用に際して、不具合/不都合があった場合に当方は責任を負いません※
  ソースコード : SimplePerceptron.zip

・INeuron
Nuronの振舞を定義しています。名称(Name)は無くても動作しますが、デバッグ時に
正しいネットワークを組めているか確認するのに重宝します。


・NeuronBase
NeuronBaseはInputScalar/Perceptron/OutputScalarの基底クラスとなっており
共通の機能を実装します。入力側のニューロンと出力側のニューロンを保持します。
また、ヘルプ機能ですがGetInstanceメソッドを持ち、指定された数のニューロンを
インスタンス化して返します。


・InputScalar
InputScalarは入力層用のNeuronです。入力値を次のニューロンに伝搬する機能だけ持ちます。
誤差逆伝搬は一応受け付けます(NeuronBaseが受け付ける)が無視します。


・Perceptron
ニューロンの実体です。全ての入力側からの信号が届くと重み付け計算をして
出力側に計算された信号を伝搬します。
このクラスが今回のニューラルネットワークの肝となります。ポイントは以下です。
  ・乱数はstaticで処理している
    疑似乱数に変な偏りが出ない様に、一つのSystem.Randomを使い回しています
  ・伝達関数にはシグモイド関数を使用しています

また、誤差逆伝搬も処理します。全ての出力側からの信号が届くと逆方向に伝搬します。



・OutputScalar
出力層から値を取り出す為の出力値クラスです。本当は作りたくなかったのですが、
逆伝搬する際に必要なので作成しました。出力層と対で同じ数だけ作成し、出力層の
値を取り出すのと、逆伝搬を開始する為に使用します。


以上のソースでニューラルネットワークを構成するニューロンの実装は完了です。
思っていたより、ずっとシンプルなコード量でニューロンが記述できました。

・ニューラルネットワークを使ってみる

続いて、それを実際に使用するコードを記載します。

やっている事は至ってシンプルです。ネットワークを構成して、訓練用データで
10000回の学習。その後、予測を実施しています。下記では
入力層 = 2, 隠れ層 = 2, 出力層=1 のニューラルネットワークを構成しています。



訓練用の教師データは以下の通りです。

  new InputData(new double[] {0.0,0.0}, new double[] {0.0}),
  new InputData(new double[] {1.0,0.0}, new double[] {1.0}),
  new InputData(new double[] {0.0,1.0}, new double[] {1.0}),
  new InputData(new double[] {1.0,1.0}, new double[] {0.0})

これは、要するに座標で考えると以下の様に教えている事になります。

(0,0) は グループ0
(1,0) は グループ1
(0,1) は グループ1
(1,1) は グループ0

出力結果は以下の様に表示されます。ニューロンをランダムに初期化するので
必ずしも同じ結果にはなりませんが、何度か繰り返し実行すると、
大体同じ様な結果になるはずです。結果の部分がグループが0なのか1なのかを
実数で示しています。(初期値次第では残念な結果になる事もあります)

下記の例では、(1,0)と(0,1)が0.99なのでほぼ学習データ通りの結果を返しています。


如何でしょう。思っていた以上に簡単な実装となりましたが、とりあえず学習には
成功しました。しかし、これだけでは面白くありませんので次回以降でもう少し
複雑な処理をさせてみたいと思います

また、ニューラルネットワークと言われると、学習処理にかかる時間も気になります。
気になる速度は…このレベルの計算処理であれば、もちろん一瞬です。私の
貧弱なPCであっても全然問題ありません。しかし、次回以降は…
とりあえず、実装してみましたってレベルで次回に続きます! 次回はもう少し大量の
点(サンプル)を使用して、複雑な物を学習させてみたいと思います。







さて、今回はC#での実装でしたが、機械学習の分野ではPythonが全盛となっています。
最近は至る所でPythonを見かけますし、そろそろ勉強した方が良いのかもしれません。
しかし、私はC#はとっても洗練されていて好きな言語です。最近はC#もver6となり、
言語仕様が拡張され、格段にコーディングしやすくなりました。今回のコードもなるべく
新機能を使用して書いたつもりです。











« RaspberryPi用のヒートシンクを購入しました | トップページ | ニューラルネットワーク(機械学習)をC#で実装してみる その2 »

データサイエンティスト・データ分析」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

トラックバック

この記事のトラックバックURL:
http://app.f.cocolog-nifty.com/t/trackback/1680410/69036339

この記事へのトラックバック一覧です: ニューラルネットワーク(機械学習)をC#で実装してみる その1:

« RaspberryPi用のヒートシンクを購入しました | トップページ | ニューラルネットワーク(機械学習)をC#で実装してみる その2 »