POSTD PRODUCED BY NIJIBOX

POSTD PRODUCED BY NIJIBOX

ニジボックスが運営する
エンジニアに向けた
キュレーションメディア

POSTD PRODUCED BY NIJIBOX

POSTD PRODUCED BY NIJIBOX

ニジボックスが運営する
エンジニアに向けた
キュレーションメディア

FeedlyRSSTwitterFacebook
Tine

本記事は、原著者の許諾のもとに翻訳・掲載しております。

ニューラルネットワークは複雑な非線形問題を解決する可能性を提供してくれるもので、信号の分類や時系列的な予測、パターン認識など様々な領域で利用できます。ニューラルネットワークは人間の脳から着想を得たモデルで、接続された複数のニューロンから構成されます。ネットワークには入力ニューロンの層(情報が入ってくるところ)と出力ニューロンの層(結果が得られるところ)、そしてその間にある「隠れ層」と呼ばれるいくつかの層があります。

neuronal network scheme

より深い理解のために、 Neural Networks and Deep Learning をチェックすることをお勧めします。

ここ数年、ニューラルネットワークを色々な目的のために作成・訓練・利用する助けになるJavaScriptフレームワークがいくつも開発されました。このブログ記事では、画像の分類のためにネットワークをセットアップする方法を学んでいきます。

ニューラルネットワークの入門の一般的な例として、手書きの数字の分類があります。よい結果を得るためにはネットワークを適切に学習させる必要があるため、「訓練データ」と呼ばれるデータセットが必要となります。私たちの例ではMNISTの数字のデータを用います。これは、0から9の手書き数字の28x28pxの二値化画像が大量に集まったデータセットです。

mnist numbers

MNISTデータベースには60,000個の訓練データと10,000個のテストデータがあり、 LeCunのウェブサイト からダウンロードできます。データベースをダウンロードして実画像に変換する代わりに、 MNIST digits という便利なライブラリを使って、テストデータと訓練データのデータセットを自動的に生成することができます。

const mnist = require('mnist'); 

const set = mnist.set(700, 20);

const trainingSet = set.training;
const testSet = set.test;

上記のコードでは、700個の画像からなる訓練データセットと、20個の画像からなるテストデータセットを生成しています。データセットを手動で生成する場合は、データセット内に重複がないことを確認することが重要になります。もしMNIST digitsライブラリを使う場合、これは自動的にチェックされます。

訓練とテストのデータを作成したあとは、ネットワークをセットアップします。ここでは、ニューラルネットワークの作成と様々なパラメータの設定を機能として提供してくれる synaptic.js というライブラリを用います。まず最初に、必要な入力・出力ニューロンの数を決める必要があります。全ての画像サイズが28x28pxなので、ネットワークが入力として取るべきピクセルの数は28 x 28 = 784となります。数字は10個の分類のうちの1つに当てはめられるので、出力ニューロンの数は10となります。さらに、ネットワークは少なくとも1つの隠れ層を持つ必要があり、この例ではその中に100個のニューロンが含まれています。

以上で説明したネットワークをセットアップするコードが以下です。

const synaptic = require('synaptic');

const Layer = synaptic.Layer;
const Network = synaptic.Network;
const Trainer = synaptic.Trainer;

const inputLayer = new Layer(784);
const hiddenLayer = new Layer(100);
const outputLayer = new Layer(10);

inputLayer.project(hiddenLayer);
hiddenLayer.project(outputLayer);

const myNetwork = new Network({
    input: inputLayer,
    hidden: [hiddenLayer],
    output: outputLayer
});

訓練データセットでネットワークを訓練するために、synaptic.jsが提供するTrainerを利用できます。 train() 関数の引数は、訓練用データと、Trainerの設定のためのパラメータのリストです。

const trainer = new Trainer(myNetwork);
trainer.train(trainingSet, {
    rate: .2,
    iterations: 20,
    error: .1,
    shuffle: true,
    log: 1,
    cost: Trainer.cost.CROSS_ENTROPY
});

オプションとして、訓練における学習率となる’rate’をセットすることができます。また、’iterations’は、「何回繰り返した後に訓練結果を確定させるか」を定義します。’error’は訓練中に到達しうる最小誤差で、もし誤差がこの値にまで到達した場合には訓練を終了します。’shuffle’オプションをセットすることで、訓練データセットの順番をランダムにするかしないかを決められます。利用可能な全てのオプションに関するさらに詳しい情報は synaptic.jsのドキュメンテーション からご覧になれます。

一般的な考えを習得するために、今回の例では最大繰り返し回数を20回にして、訓練が終了するまで何時間も待つ必要がないようにします。たった20回の繰り返しではネットワークを十分に訓練できないことに注意してください。よりよい結果を得るためには、この回数を増やして辛抱強く待つ必要があります。

訓練の進行状況を見たい場合は、’log’オプションを利用してネットワークの現在の誤差を書き出すことができます。誤差が小さくなるほどネットワークがよく訓練された状態になります。

error log

誤差は一貫して減少するのではなく、やや変動するということに気づくかもしれません。しかし、大局的には小さくなっていきます。もしそうならない場合は、学習率(‘rate’)を下げてみてください。

訓練が終わったあとは、テストデータセットを利用して、ネットワークによる分類がどれほどうまくいくかをチェックすることができます。これにはネットワークの activate() 関数を用いることができます。この関数のパラメータは分類すべき要素となります。結果を確認するために、結果を出力して期待される結果と比較できます。

console.log(myNetwork.activate(testSet[0].input));
console.log(testSet[0].output);

この例のネットワークではあまりいい結果は得られないことにご注意ください。訓練データセットの要素のうち50%程度しか正しく分類できません。これは、訓練データセットが小さいことと、訓練のための繰り返し回数が少なかったことに起因します。結果を向上させたければこの両者を増加させるべきです。注意:これにより、訓練にかかる時間はずっと長くなります!

一般的なMNISTの例の他にも、ニューラルネットワークが有用になる応用先はたくさんあります。ほかにsynaptic.jsを用いた面白い実験としては、ニューラルネットワークがT-Rexゲームを学習した T-Rex ML Player があります。

ニューラルネットワークを作れる他の似たようなJavaScriptライブラリを見てみたい場合、チェックしてみるべきプロジェクトには以下のようなものがあります。

監修者
監修者_古川陽介
古川陽介
株式会社リクルート プロダクト統括本部 プロダクト開発統括室 グループマネジャー 株式会社ニジボックス デベロップメント室 室長 Node.js 日本ユーザーグループ代表
複合機メーカー、ゲーム会社を経て、2016年に株式会社リクルートテクノロジーズ(現リクルート)入社。 現在はAPソリューショングループのマネジャーとしてアプリ基盤の改善や運用、各種開発支援ツールの開発、またテックリードとしてエンジニアチームの支援や育成までを担う。 2019年より株式会社ニジボックスを兼務し、室長としてエンジニア育成基盤の設計、技術指南も遂行。 Node.js 日本ユーザーグループの代表を務め、Node学園祭などを主宰。