1. パーセプトロンのアニメーション(2D)

    収束する様子をFlashでアニメーションさせてみました。2次元、2クラスの分類です。



    眺めてるといろいろと面白いです。超平面の近くまで収束していても、誤識別するとけっこう離れてしまうんですね。3次元の場合も面白そうなのでそのうちやってみようかと。

    こちらを参考にさせていただきました。
    http://d.hatena.ne.jp/echizen_tm/20110606/1307378609
    http://gihyo.jp/dev/serial/01/machine-learning/0017



     

    クリックでリセット



    ソースはこんなかんじです。

    package
    {
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;

    public class perceptron extends Sprite
    {

    private const NUM_DATA:int = 100;
    private const NUM_TRAIN:int = 10;

    private var _w:Vector.<Number>;//重みベクトル
    private var _points:Vector.<Vector.<Number>>;//学習用パターン
    private var _labels:Vector.<int>;//正解ラベル

    private var _cnt:int;//訓練回数
    private var _cursor:int;//学習用パターンを指定するカーソル

    public function perceptron()
    {
    init();
    stage.addEventListener(MouseEvent.CLICK,onClick);
    }

    private function predict(x:Vector.<Number>):Number{
    var y:Number = 0;
    for(var i:int = 0 ; i < x.length;i++){
    y += _w[i] * x[i];
    }
    return y;
    }

    private function train(x:Vector.<Number>,t:int):void{
    var y:Number = predict(x);
    if(y * t < 0){
    for(var i:int = 0 ; i < x.length;i++){
    _w[i] += t * x[i];
    }
    }
    }

    private function init():void{
    _cnt = 0;
    _cursor = 0;
    _w = new Vector.<Number>();
    _w[0] = 1;
    _w[1] = 1;
    _points = new Vector.<Vector.<Number>>();
    _labels = new Vector.<int>();

    var randomX:Number = -Math.random() * 5;
    var randomY:Number = Math.random() * 5;
    function divide(x:Number,y:Number):Number{
    return randomX * x + randomY * y;//真の分離平面
    }

    for(var i:int = 0 ; i < NUM_DATA ; i++){
    var p:Vector.<Number> = new Vector.<Number>();
    p[0] = Math.random() * stage.stageWidth;
    p[1] = Math.random() * stage.stageHeight;
    _points.push(p);

    if(divide(p[0],p[1]) > 0){
    _labels.push(1);
    }else{
    _labels.push(-1);
    }

    }
    addEventListener(Event.ENTER_FRAME,onEnterFrame);
    }

    private function draw():void{
    graphics.clear();
    for(var i:int = 0 ; i < NUM_DATA ; i++){
    var p:Vector.<Number> = _points[i];
    var color:uint;
    if(_labels[i] > 0){
    color = 0xFF0000;
    }else{
    color = 0x0000FF;
    }
    graphics.beginFill(color);
    graphics.drawCircle(p[0],p[1],2);
    graphics.endFill();
    }

    graphics.lineStyle(1);
    graphics.moveTo(0,0);
    graphics.lineTo(_w[1],-_w[0]);
    }

    private function onClick(e:MouseEvent):void{
    init();
    }

    private function onEnterFrame(e:Event):void{
    //trace(_w[0],_w[1]);
    if(_cursor >= _points.length){
    _cnt++;
    if(_cnt >= NUM_TRAIN){
    trace("fin");
    removeEventListener(Event.ENTER_FRAME,onEnterFrame);
    return;
    }
    _cursor = 0;
    }
    train(_points[_cursor],_labels[_cursor]);
    _cursor++;

    draw();

    }

    }
    }

    Posted by Takeya Hikage on 2014年01月20日
    Categories flash 機械学習