blocklyでobjectを動かす。 その13


概要

blocklyでobjectを動かして見る。
tensorflow.js、やってみた。

写真

ステージを作る。

    教師データ<br>
    <div id="out0"></div>
    ロス推移<br>
    <canvas id="canvas" width="300" height="200"></canvas><br>
    最終ロス<br>
    <div id="out1"></div>
    予測<br>
    <div id="out2"></div>

ブロックを書く。


Blockly.Blocks.data = {
    init: function() {
        this.jsonInit({
            message0: "教師データ 01 %1 10 %2 11 %3 00 %4",
            args0: [{
                type: "input_value",
                name: "d01",
                check: "Number",
                align: "RIGHT"
            }, {
                type: "input_value",
                name: "d10",
                check: "Number",
                align: "RIGHT"
            }, {
                type: "input_value",
                name: "d11",
                check: "Number",
                align: "RIGHT"
            }, {
                type: "input_value",
                name: "d00",
                check: "Number",
                align: "RIGHT"
            }],
            previousStatement: null,
            nextStatement: null,
            style: "text_blocks",
            tooltip: Blockly.Msg.TEXT_PRINT_TOOLTIP,
            helpUrl: Blockly.Msg.TEXT_PRINT_HELPURL
        })
    }
};


Blockly.Blocks.model = {
    init: function() {
        this.jsonInit({
            message0: "モデル %1",
            args0: [{
                type: "input_value",
                name: "n",
        check: "Number",
          align: "RIGHT"
            }],
            previousStatement: null,
            nextStatement: null,
            style: "text_blocks",
            tooltip: Blockly.Msg.TEXT_PRINT_TOOLTIP,
            helpUrl: Blockly.Msg.TEXT_PRINT_HELPURL
        })
    }
};


Blockly.Blocks.train = {
    init: function() {
        this.jsonInit({
            message0: "学習、予測 %1",
            args0: [{
                type: "input_value",
                name: "n",
        check: "Number",
          align: "RIGHT"
            }],
            previousStatement: null,
            nextStatement: null,
            style: "text_blocks",
            tooltip: Blockly.Msg.TEXT_PRINT_TOOLTIP,
            helpUrl: Blockly.Msg.TEXT_PRINT_HELPURL
        })
    }
};


フローを書く。

objectを書く。



Blockly.JavaScript.data = function(a) {
  var b = Blockly.JavaScript.valueToCode(a, "d10", Blockly.JavaScript.ORDER_COMMA) || 0;
    var c = Blockly.JavaScript.valueToCode(a, "d01", Blockly.JavaScript.ORDER_COMMA) || 0;
    var d = Blockly.JavaScript.valueToCode(a, "d11", Blockly.JavaScript.ORDER_COMMA) || 0;
    a = Blockly.JavaScript.valueToCode(a, "d00", Blockly.JavaScript.ORDER_COMMA) || 0;
  return "data(" + b + "," + c + "," + d + "," + a + ");\n"
};


Blockly.JavaScript.model = function(a) {
    return "model_(" + (Blockly.JavaScript.valueToCode(a, "n", Blockly.JavaScript.ORDER_NONE) || "''") + ");\n"
};


Blockly.JavaScript.train = function(a) {
    return "train(" + (Blockly.JavaScript.valueToCode(a, "n", Blockly.JavaScript.ORDER_NONE) || "''") + ");\n"
};

tf.setBackend('cpu');
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
function draw(data) {
    var hc = 100;
    ctx.strokeStyle = "#f00";
    ctx.lineWidth = 1;
    ctx.moveTo(0, 80);
    for (var i = 1; i < data.length; i++)
    {
        ctx.lineTo(i, hc - data[i] * 30);
    }
    ctx.stroke();
}
const x = [[1, 0], [0, 1], [1, 1], [0, 0]];
const xs = tf.tensor2d([[1, 0], [0, 1], [1, 1], [0, 0]], [4, 2]);
var y;
var ys;
function data(d10, d01, d11, d00) {
    y = [d10, d01, d11, d00];
    ys = tf.tensor2d([[d10], [d01], [d11], [d00]], [4, 1]);
    var h = '<table><tr><th>a</th><th>b</th><th>c</th></tr>';
    for (var row = 0; row < 4; row++)
    {
    h += '<tr>';
    h += '<td>' + x[row][0] + '<\/td>';
    h += '<td>' + x[row][1] + '<\/td>';
    h += '<td>' + y[row] + '<\/td>';
    h += '<\/tr>';
    }
    h += '<\/table>';
    document.getElementById('out0').innerHTML = h;
}
const model = tf.sequential();
function model_(n) {
    model.add(tf.layers.dense({
    units: n,
    activation: 'tanh',
    inputShape: [2]
    }));
    model.add(tf.layers.dense({
    units: 1,
    activation: 'sigmoid'
    }));
    model.compile({
    optimizer: 'adam',
    loss: 'binaryCrossentropy'
    });
}
function train(n) {
    var c = [];
    model.fit(xs, ys, {
    batchSize: 4, 
    epochs: n,
    callbacks: {
            onEpochEnd: (epoch, logs) => {
                if (epoch % 10 == 0) 
                {
                  c.push(logs.loss);
                  draw(c);
                }
            },
        }
    }).then((d) => {
    var str = "loss = ";
    str += d.history.loss[0]; 
    document.getElementById('out1').innerHTML = str;
    var pre0 = model.predict(tf.tensor2d([1, 0], [1, 2]));
    var r0 = pre0.dataSync() < 0.5 ? 0 : 1;
    var pre1 = model.predict(tf.tensor2d([0, 1], [1, 2]));
    var r1 = pre1.dataSync() < 0.5 ? 0 : 1;
    var pre2 = model.predict(tf.tensor2d([1, 1], [1, 2]));
    var r2 = pre2.dataSync() < 0.5 ? 0 : 1;
    var pre3 = model.predict(tf.tensor2d([0, 0], [1, 2]));
    var r3 = pre3.dataSync() < 0.5 ? 0 : 1;
    const py = [r0, r1, r2, r3];
    var h = '<table><tr><th>a</th><th>b</th><th>c</th></tr>';
    for (var row = 0; row < 4; row++)
    {
      h += '<tr>';
      h += '<td>' + x[row][0] + '<\/td>';
      h += '<td>' + x[row][1] + '<\/td>';
      h += '<td>' + py[row] + '<\/td>';
      h += '<\/tr>';
    }
    h += '<\/table>';
    document.getElementById('out2').innerHTML = h;
    });
}





成果物

以上。