LoginSignup
3

More than 5 years have passed since last update.

ConvNetJsの仕様と使い方

Last updated at Posted at 2018-02-03

ConvNetJsの日本語の資料が少なかったので、このページをひと通り訳してみました。
まだ執筆中です。間違いは指摘してくださると助かります。もともとはConvNetJsの使い方を個人用に非公開でまとめたかったのですが、間違って記事を公開設定にしちゃった(非公開に戻せなかった)ので、そのまま公開用に転用してます。

Vol

ConvNetJsの核となる概念と言えます。簡単に言うと3次元の配列です。Volはこれに加えて、トレーニングの際に計算される勾配や、Layerのサイズなどの情報も保持しています。

//32x32x3のVolを生成
const v = new convnetjs.Vol(32, 32, 3);
//生成する際、要素を全て0で初期化
const v = new convnetjs.Vol(32, 32, 3, 0.0); 
//1x1x3サイズのVolを生成
const v = new convnetjs.Vol(1, 1, 3);

//1x1x3のVolを生成して、1.2, 3.5, 3.6で初期化
const v = new convnetjs.Vol([1.2, 3.5, 3.6]);

// Volの係数(w)や傾き(dw)を取り出す
v.w[0] // =1.2
v.dw[0] // =0 (傾きは0で初期化されている)

// 次のようにVolの値を直接セットしたり、取り出したりできる
const vol3d = new convnetjs.Vol(10, 10, 5);
vol3d.set(2,0,1,5.0); // (2,0,1) の要素の値を5.0にセット
vol3d.get(2,0,1) // =5

Net

複数のLayerを保持します。こいつにVolを放り込むとニューラルネットの計算が実行されて、最終層の値が帰ってきます。ちなみに学習を行うときはNetの各層がbackward()を実行して、それぞれのニューロンで勾配を計算します。

Layer

NetはLayerが連なったものです。先頭は入力層('Input')、最後はloss layer(後述 Layerの種類を参照)でなければなりません。各層はVolが受け取ると、新たなVolを生成して次の層に受け渡す仕組みです, which is why I prefer to refer to them as transformers.
次の例を見てみましょう

var layer_defs = [];
// minimal network: a simple binary SVM classifer in 2-dimensional space
layer_defs.push({type:'input', out_sx:1, out_sy:1, out_depth:2});
layer_defs.push({type:'svm', num_classes:2});

// Netを生成
var net = new convnetjs.Net();
net.makeLayers(layer_defs);

// 1x1x2のVolを生成し、要素を[0.5,-1.3]にセット
var x = new convnetjs.Vol(1,1,2);
x.w[0] = 0.5;
x.w[1] = -1.3;

//Netに先程のVolを渡す。scoreには最終層から渡されたVolがはいる。
var scores = net.forward(x);
console.log('score for class 0 is assigned:'  + scores.w[0]);

Layerの種類

Netの構成要素となるLayerの種類を紹介します。

Input Layer (入力層)

先頭はこのLayerでなければなりません。ここでレイヤーで入力層のサイズを宣言することになります。

// 1x1x20の入力層を設定
{type:'input', out_sx:1, out_sy:1, out_depth:20}
// 24x24の画像をRGBで入力したいときは、次のように設定します
{type:'input', out_sx:24, out_sy:24, out_depth:3}

Fully Connected Layer (中間層)

Layerの中の各ニューロンは前層のニューロンの値の重み付き平均を計算し、結果を活性化関数に渡します。ReLUはよく使われる活性化関数ですが、使うときは注意が必要で、learning rateを小さめに設定しないと勾配発散の原因となります。

// ニューロン数10の層を作る。活性化関数なし。
{type:'fc', num_neurons:10}
// 活性化関数を指定して、ニューロン数10の層を作る。
{type:'fc', num_neurons:10, activation:'sigmoid'}
{type:'fc', num_neurons:10, activation:'tanh'}
{type:'fc', num_neurons:10, activation:'relu'}

// maxoutの層。num_neuronsは偶数でなければなりません。
// 原理的に次元が減少します。この場合出力のサイズは5になります。
{type:'fc', num_neurons:10, activation:'maxout'} 

// maxoutで最大値を計算する層の数を指定します。
//当然num_neuronsはgroup_sizeで割り切れる必要があります
// この場合出力のサイズは12/4 = 3になります。
{type:'fc', num_neurons:12, group_size: 4, activation:'maxout'}
// 学習でドロップアウトを使用するとき、無視するニューロンの割合を指定します。
{type:'fc', num_neurons:10, activation:'relu', drop_prob: 0.5}

Loss Layer Classifier Layers

Deep Learningで入力データを特定の種類に分類したいときは、こちらを使いましょう。softmaxはデータの合計が1になるように出力します。SVMは確率ではなく、スコアを学習させたいときに用いてください。

layer_defs.push({type:'softmax', num_classes:2});
layer_defs.push({type:'svm', num_classes:2});

When you are training a classifier layer, your classes must be numbers that begin at 0. For a binary problem, these would be class 0 and class 1. For K classes, the classes are 0..K-1.

Loss layers L2 Regression Layer

えいご難しくて読めなかったので後で書く

畳み込みニューラルネットワーク

今は省略

Trainer (学習)

各種Layerの扱いは以上です。続いて学習の役割を担うTrainerについて見ていきましょう。TrainerクラスにNetと学習データを与えると、ニューラルネットの係数を補正して学習が行われます。用意した教師データ全体にわたって学習を行わせることで、徐々に正しい結果を得られるようになります。

// Momentum SGD で学習させる例. 学習データ10個毎に、係数を補正します。
var trainer = new convnetjs.Trainer(net, {
    method: 'sgd', learning_rate: 0.01,
    l2_decay: 0.001, momentum: 0.9,
    batch_size: 10, l1_decay: 0.001});

// adadelta で学習させる例。初心者向き。
var trainer = new convnetjs.Trainer(net, {
    method: 'adadelta', l2_decay: 0.001,
    batch_size: 10});

// adagrad で学習させる例。
var trainer = new convnetjs.Trainer(net, {
    method: 'adagrad', l2_decay: 0.001,
    l1_decay: 0.001, batch_size: 10});

学習方法は'method'を'sgd' 'adagrad' 'adadelta'のいずれかに指定することで変えられます。これら3つの学習方法の関係はこの論文を参照してください。関連して、ConvNetJsではMNISTのデモでこれらを比較したものを公開しています。また、以下のTipsも参考にしてください。

  • 初心者の方にはAdadeltaかAdagradがおすすめです。学習係数を自動で補正してくれる上、比較的容易に意図した結果が得られます。
  • SGDはMomentumを使用するときに実装します。慣例的には0.9に設定して使うことが多いです。また学習係数を少しずつ慎重に調整する必要があります。ReLUを用いる場合、学習係数が大きすぎると最適な係数に収束しないうえ、勾配発散が起きる可能性もあります。かと言って学習係数が小さすぎると、学習がなかなか進みません。学習の際のcostの遷移を見ながら、学習係数を調整してください。
  • l2_decayは高く設定するとネットワーク will be regularized very strongly. 教師データが少ない場合はl2_decayを高めにするのが有効です。また学習エラーが少ない場合も、少し高めにしておくとより良い結果が得られることがあります。学習エラーが多い場合は、この値を小さくしてみましょう。
  • Use l1_decay instead of l2_decay if you'd like your network to have sparse weights at the end, as l1 norm on weights is sparsity encouraging. なんのことかわからないようであれば、0のままにしてください。(デフォルトでは0になってます)
  • 通常batch_sizeは1にします。batch_sizeはネットワークのgradient stepsをがどれくらい正確になるかを制御するときに使います。1つのbatchで100個の教師データを与えると、学習の際に係数補正の正確さが向上します。が、実際は1にしておくのが適切でしょう。
  • どの学習方法を使えば良いのかわからなければ、まずはadadeltaで試してみましょう。

実際に例を見ていきます。

var x = new convnetjs.Vol(1,1,d);
x.w[0] = 1; // 1つ目の要素の値を1にセット

// if your loss on top is
// layer_defs.push({type:'svm', num_classes: 5});
// use something like... (lets say x is class 3)
var stats = trainer.train(x, 3);

// if your loss on top is
// layer_defs.push({type:'regression', num_neurons: 1});
// use something like... (note the LIST!)
var stats = trainer.train(x, [0.7]);
// if your loss on top is
// layer_defs.push({type:'regression', num_neurons: 3});
// use something like
var stats = trainer.train(x, [0.7, 0.1, 0.3]);

Trainerから返されるオブジェクトにはcostや、計算にかかった時間なども含まれています。
最後の例を見てみましょう。ループを用いたより実践的な例です。

var trainer = new convnetjs.SGDTrainer(net, {
    learning_rate:0.01, momentum:0.9,
    batch_size:16, l2_decay:0.001});
for(var i=0;i<my_data.length;i++) {
  var x = new convnetjs.Vol(1,1,2,0.0); //要素を0に初期化して1x1x2のVolを生成
  x.w[0] = my_data[i][0]; // Vol.wはデータの配列です
  x.w[1] = my_data[i][1];
  trainer.train(x, my_labels[i]);
}

JSONを使った学習データの読み込み・書き出し

toJSON()やfromJSON()関数でデータの読み書きが可能です。

// ネットワークのデータをJSONに変換
var json = net.toJSON(); //オブジェクトとして出力される
var str = JSON.stringify(json); //文字列として出力される

// JSONデータからネットワークを再構成
var json = JSON.parse(str); // 文字列をオブジェクトに直す
var net2 = new convnetjs.Net(); // 空のNetを作る
net2.fromJSON(json); // JSONから全てのデータが引き継がれます

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3