nature of code : 今日の練習「単純なパーセプトロン」

ニューラルネットワークとは

脳に基づいて特定の問題を解決するための計算モデル。複雑系の一種

ニューラルネットワーク - Wikipedia

ニューロン...細胞網に存在している単一細胞で、入力を受け取り、処理し、出力を生成する。
コネクショニスト計算系...情報がネットワーク全域で集合的に並列で処理される

ニューラルネットワークの学習機能

ニューラルネットワークの主な要素の一つ。
ニューラルネットワークは単なる複雑系にあらず。内部を流れる情報に基づいて構造を変化させることができる複雑適応系
普通は重み(二つのニューロン間の信号を制御する数値)を調整することで適合させる。
ニューラルネットワークが適していない出力を使た場合はこの重みを変更して後続の結果を改善する。

いろいろな学習方法

  • 教師あり学習
    ネットワークのだした答えと、正しい答え(教師)を比較して誤差にあわせて調整する。

  • 教師なし学習
    既知の答えのデータがない場合に行う。隠されたパターンを検索するイメージ。適用例にクラスタリングがある。

  • 強化学習
    観察に基づいた方法。結果に従って判断し、環境の観察をする。ロボット工学で広く使われている。

ニューラルネットワークの代表的な使用方法

  • パターン認識(顔認識)
  • 時系列予測(明日の天気など)
  • 信号処理(補聴器のノイズの除去など・・・)
  • 制御(自動運転など)
  • ソフトセンサー(複数の個別センサーを処理して総合的に判断したり)
  • 異常検出

パーセプトロンとは

最も単純なニューラルネットワーク。単一ニューロンの計算モデル。
1つか複数の入力、プロセッサー、出力で構成される。
フィードフォワードモデル(送信、処理、出力)?

入力から出力まで

  1. 入力を受けとる
  2. 重みを入力する(特定のあたいをかける。通常は最初ランダムな0〜1の値で行う。)
  3. 入力に重みをかける
  4. 重み付けされたすべての入力を合計する
  5. 出力を生成する(活性化関数を通じて合計値を渡す。出力するかどうかをパーセプトロンに通知する。)

実装した単純なパーセプトロン

パーセプトロンを使って、単純なパターン認識をする。
与えられた座標が線より上にあるか、下にあるか判断するパーセプトロンを作る。

できたもの↓

See the Pen シンプルパーセプトロン by kanaparty (@kanaparty) on CodePen.

正しい線は背景にうっすら見える紺色の線。
点は教師。1フレームづつ教師の入力をパーセプトロンに渡して訓練させる。
紺色の点は線より上に、黄色い点は線より下にあるとパーセプトロンが判断した位置。
これが正しい線にだんだん近づけば訓練が成功している!

登場人物は2つ。

処理の流れ

  1. 答えが用意されている入力をパーセプトロンにわたす
  2. 答えを推測
  3. エラーを計算(正しいか、間違っているか)
  4. エラーに従ってすべての重みを計算する
  5. (繰り返し)

エラーの定義と重さの定義

  • エラー = 適切な出力 - 推測の出力

  • 新しい重み = 今の重み + 重みの変化量

(重みの変化量 = エラー * 入力)

  • 新しい重み = 重み + エラー * 入力

学習定数(ビークルの操舵のときに出てきたmaxSpeedのような感じで、最大力を制御する変数)を加えると答えに行き着くまでの時間を調整することができる。
学習定数が大きいと短時間で済むが微調整が難しい。小さいと時間がかかるが正確性が増す。

教師オブジェクト

線の上にあるか下にあるかは線の関数を使って調べればよい。f(x)のyよりの上にあるか、ないか。


おしまい

たしかこの章を読み始めたのは7月だったはず・・・。
私には難しくて危うく積ん読になってしまうところだった。 のこす課題はあと3つ。

それにしても教師オブジェクト2000個でも正しい斜めのラインぴったりにはなかなかならないのだなぁ。

参考にしたサイト

ニューラルネットワーク

hokuts.com

イテレータ・ジェネレータ(ついでにシンボルもちょっとだけ)覚えたことメモ

tuitui.hatenablog.com

↑昨年イテレータについて後日読もうと思っていたんですが、ようやくその「後日」が来ました。
イテレータ・ジェネレータ(ついでにシンボルもちょっとだけ)について覚えたことをメモ。
自分でIterableなオブジェクトを書いてもいいし、arrayやstringにはそもそも備わっているということで
なんだ〜となりました。もっと早くちゃんと読んでおけばよかったなと思った次第です。  

Iterationについて

繰り返し処理を行うための決まりに従った実装。
繰り返し処理を適用したときの挙動 → Iteration

IterableとIterator

Iterable = Iteratorを備えた(Symbol.iteratorプロパティにIteratorを返すメソッドを実装している)オブジェクト。Iteratorを備えているのでfor-ofで処理できる。
Iterator = next()メソッドを実装したオブジェクト。nextメソッドを呼ぶと以下2つのプロパティをもったオブジェクトを返す。

  • value 現在の値
  • done 値を出し終えたかどうか

最初からIterableな挙動が備わっているもの

はじめからSymbol.iteratorプロパティにIteratorを返すメソッドが実装されているもの

  • Array
  • String
  • NodeList
  • Generator Object
  • Array, Map, Set が持つ entries(), keys(), values()の戻り値

など。
たとえば文字列で順番にとりだしたいとき以下のように書ける

const s = 'javascript';
const sIterator =  s[Symbol.iterator]();
sIterator.next();//Object {value: "j", done: false}
sIterator.next();//Object {value: "a", done: false}
sIterator.next();//Object {value: "v", done: false}
sIterator.next();//Object {value: "a", done: false}
sIterator.next();//Object {value: "s", done: false}
sIterator.next();//Object {value: "c", done: false}
sIterator.next();//Object {value: "r", done: false}
sIterator.next();//Object {value: "i", done: false}
sIterator.next();//Object {value: "p", done: false}
sIterator.next();//Object {value: "t", done: false}
sIterator.next();//Object {value: undefined, done: true}

for-ofを使ってとりだすとき

const a = ['j','a','v','a','s','c','r','i','p','t'];
const aIterator =  a[Symbol.iterator]();
for (variable of aIterator) {
  console.log(variable);
}
//j
//a
//v
//a
//s
//c
//r
//i
//p
//t

使い方はここ qiita.com

がとてもまとまってました。ありがとうございます。

Symbolについて

オブジェクトに対して、ある状況に応答するためのインターフェースを組み込む(プロトコルを定義する)ために使う。

const sym = Symbol();

で生成できる。newをつけない。
常に別々のユニークな値として生まれる。

オブジェクトのプロパティとして使うとObject.keys()などで無視される。

GlobalSymbolRegistry

グローバルスコープを越えて共有されるSymbolの領域。 iframeなどを隔てたとしても同じSymbolを共有することができる。
Symbol.for(key)メソッドを使うと keyとして渡した値を持ったSymbolがGlobalSymbolRegistryに存在しなければ、新しく生成したSymbolを生成して返す。

Generatorについて

処理を途中で抜けられる。そのときに値を取り出すことができる。 Generatorオブジェクトはnextメソッドを呼びだすと、 yieldの後に置かれている処理を評価するところまで進み、その評価結果を返す。 返ってくるオブジェクトの中身は

  • value : yieldの後の処理
  • done : すべての値を取り出し終えたかどうか

書き方

function* generatorFunc() {
  yield 1;
  yield 2;
  return 3;
}
var g = generatorFunc();
console.log(g.next()); //Object {value: 1, done: false}
console.log(g.next()); //Object {value: 2, done: false}
console.log(g.next()); //Object {value: 3, done: true}

function* と記述すると定義できる。

読書メモ:イシューからはじめよ(1)

バリューのある仕事とは

  • イシュー度(置かれた局面での答えをだす必要性の高さ)と解の質(どこまで明確に答えがだせているかの度合い)が高い仕事
  • 解の質が高い仕事であってもイシュー度が低いと結果的にバリューのある仕事は生まれにくい(犬の道)
  • 誤:「問題かもしれない」 正:「今この局面で白黒はっきりさせるべき問題」

イシューの見極め

  • 相談できる相手をもつ(本当に受け手にとってインパクトがあるのか?)
  • 具体的な仮説を立てる(答えが出せる形になる、必要な情報と分析がわかる、解釈が明確になる ので)
  • 言葉にする
    • 主語と動詞をいれる
    • 「〜はなぜ?」という形にしない、「〜すべきか?」にする
    • 比較表現にする
  • よいイシューの条件を満たす
    • 本質的(イシューは状況に応じて変わる)
    • 深い仮説
    • 答えが出る

イシューが見つけにくい時

  • 変数を削る
  • 視覚化する
  • 後ろから考える
  • so what?を繰り返す
  • 極端な場合をかんがえる

イシューからはじめよ―知的生産の「シンプルな本質」

イシューからはじめよ―知的生産の「シンプルな本質」

nature of code:今日の練習「障害物を避けて獲物に向かうように進化するビークル」

See the Pen 障害物を避けて進化 by kanaparty (@kanaparty) on CodePen.

前回

tuitui.hatenablog.com

のコードをベースに、障害物を設置してそれを避けて通るように進化させる課題。

前回のコードとの大きな違いは、ビークルの表現のクラスのなかの、適応度を更新する部分。

//適応度を更新
  updateFitness() {
    this.fitness = Math.pow(1 / this.RecordDistance * this.finishTime, 4);
    if(this.hitObstcle){
      this.fitness *= 0.01;
    } else if(this.hitTarget){
      this.fitness *= 2;
    }
  }

前回はライフサイクルが終了した時のビークルの位置を見て適応度としていたが、
今回はライフサイクル中に一番近い付いたときの距離と、そのサイクル数の短さが適応度に反映されるようにする。
また、ターゲットにぶつかったときは2倍の適応度に、障害物にぶつかったときは10分の1の適応度にすることで重みをつけている。

この課題、写経なのでなんとなくできている感のある動きになってはいるものの、
適応度を図る部分や突然変異率、母数などちょっとしたことが与える影響がかなり大きくて 自分一人で1から組み立てチューニングできるようになるのは大変なんじゃないかな、と思ったり。。