jsdoでconvnetjs

#概要
jsdoでmnistで学習したデータ使って、手書き数字を認識してみた。
#写真
![mnist.JPG](https://qiita-image-store.s3.amazonaws.com/0/18104/41856b2a-91df-54f8-5ae1-699525dd986e.jpeg)

#実際
http://jsdo.it/ohisama1/20xy
#サンプルコード
```
var canvas = $("#canvas").get(0);
var touchableDevice = ('ontouchstart' in window);
if (canvas.getContext)
{
    var context = canvas.getContext('2d');
    var drawing = false;
    var prev = {};
    canvas.width = 2 * $("#canvas").width();
    canvas.height = 2 * $("#canvas").height();
    context.scale(2.0, 2.0);
    context.lineJoin = "round";
    context.lineCap = "round";
    context.lineWidth = 20;
    context.strokeStyle = 'rgb(0, 0, 0)';
    $("#canvas").bind('touchstart mousedown', function(e) {
        e.preventDefault();
        prev = getPointOnCanvas(this, event, e);
        drawing = true;
    });
    $("#canvas").bind('touchmove mousemove', function(e) {
        if (drawing == false) return;
        e.preventDefault();
        curr = getPointOnCanvas(this, event, e);
        context.beginPath();
        context.moveTo(prev.x, prev.y);
        context.lineTo(curr.x, curr.y);
        context.stroke();
        prev = curr;
    });
    $("#canvas").bind('touchend mouseup mouseleave', function(e) {
        drawing = false;
    });
    var getPointOnCanvas = function(elem, windowEvent, touchEvent) {
        return {
            x : (touchableDevice ? windowEvent.changedTouches[0].clientX : touchEvent.clientX) - $(elem).offset().left,
            y : (touchableDevice ? windowEvent.changedTouches[0].clientY : touchEvent.clientY) - $(elem).offset().top
        };
    };
    $("#run_button").click(function() {
        test_predict();
    });
    $("#delete_button").click(function() {
        context.clearRect(0, 0, 280, 280);
    });
    var getImageBuffer = function(context, width, height) {
        var tmpCanvas = $('<canvas>').get(0);
        tmpCanvas.width = width;
        tmpCanvas.height = height;
        var tmpContext = tmpCanvas.getContext('2d');
        tmpContext.drawImage(context.canvas, 0, 0, width, height);
        var image = tmpContext.getImageData(0, 0, width, height);
        var buffer = []
        for (var i = 0; i < image.data.length; i += 4) 
        {
            var sum = image.data[i + 0] + image.data[i + 1] + image.data[i + 2] + image.data[i + 3];
            buffer.push(Math.min(sum, 255));
        }
        return buffer;
    };
}
var layer_defs,
    net,
    trainer;
classes_txt = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
var maxmin = cnnutil.maxmin;
var f2t = cnnutil.f2t;
layer_defs = [];
layer_defs.push({
    type: 'input', 
    out_sx: 24, 
    out_sy: 24, 
    out_depth: 1
});
layer_defs.push({
    type: 'conv', 
    sx: 5, 
    filters: 8, 
    stride: 1, 
    pad: 2, 
    activation: 'relu'
});
layer_defs.push({
    type: 'pool', 
    sx: 2, 
    stride: 2
});
layer_defs.push({
    type: 'conv', 
    sx: 5, 
    filters: 16, 
    stride: 1, 
    pad: 2, 
    activation: 'relu'
});
layer_defs.push({
    type: 'pool', 
    sx: 3, 
    stride: 3
});
layer_defs.push({
    type: 'softmax', 
    num_classes: 10
});
var load_from_json = function() {
    $.getJSON("/assets/W/3/U/T/W3UTB", function(json) {
        net = new convnetjs.Net();
        net.fromJSON(json);
        trainer = new convnetjs.SGDTrainer(net, {
            method: 'adadelta', 
            batch_size: 20, 
            l2_decay: 0.001
        });
    });
}
var draw_activations = function(elt, A, scale, grads) {
    var s = scale || 2;
    var draw_grads = false;
    if (typeof(grads) !== 'undefined') draw_grads = grads;
    var w = draw_grads ? A.dw : A.w;
    var mm = maxmin(w);
    for (var d = 0; d < A.depth; d++) 
    {
        var canv = document.createElement('canvas');
        canv.className = 'actmap';
        var W = A.sx * s;
        var H = A.sy * s;
        canv.width = W;
        canv.height = H;
        var ctx = canv.getContext('2d');
        var g = ctx.createImageData(W, H);
        for (var x = 0; x < A.sx; x++)
        {
            for (var y = 0; y < A.sy; y++)
            {
                if (draw_grads)
                {
                    var dval = Math.floor((A.get_grad(x, y, d) - mm.minv) / mm.dv * 255);
                }
                else
                {
                    var dval = Math.floor((A.get(x, y, d) - mm.minv) / mm.dv * 255);  
                }
                for (var dx = 0; dx < s; dx++) 
                {
                    for (var dy = 0; dy < s; dy++)
                    {
                        var pp = ((W * (y * s + dy)) + (dx + x * s)) * 4;
                        for (var i = 0; i < 3; i++) 
                        {
                            g.data[pp + i] = dval;
                        }
                        g.data[pp + 3] = 255;
                    }
                }
            }
        }
        ctx.putImageData(g, 0, 0);
        elt.appendChild(canv);
    }  
}
var visualize_activations = function(net, elt) {
    elt.innerHTML = "";
    var N = net.layers.length;
    for (var i = 0; i < N; i++) 
    {
        var L = net.layers[i];
        var layer_div = document.createElement('div');
        var activations_div = document.createElement('div');
        activations_div.appendChild(document.createTextNode('Activations:'));
        activations_div.appendChild(document.createElement('br'));
        activations_div.className = 'layer_act';
        var scale = 2;
        if (L.layer_type==='softmax' || L.layer_type==='fc') scale = 10;
        draw_activations(activations_div, L.out_act, scale);
        if (L.layer_type !== 'softmax') 
        {
            var grad_div = document.createElement('div');
            grad_div.appendChild(document.createTextNode('Activation Gradients:'));
            grad_div.appendChild(document.createElement('br'));
            grad_div.className = 'layer_grad';
            var scale = 2;
            if (L.layer_type==='softmax' || L.layer_type==='fc') scale = 10;
            draw_activations(grad_div, L.out_act, scale, true);
            activations_div.appendChild(grad_div);
        }
        if (L.layer_type === 'conv')
        {
            var filters_div = document.createElement('div');
            if (L.filters[0].sx>3) 
            {
                filters_div.appendChild(document.createTextNode('Weights:'));
                filters_div.appendChild(document.createElement('br'));
                for (var j = 0; j < L.filters.length; j++) 
                {
                    filters_div.appendChild(document.createTextNode('('));
                    draw_activations(filters_div, L.filters[j], 2);
                    filters_div.appendChild(document.createTextNode(')'));
                }
                filters_div.appendChild(document.createElement('br'));
                filters_div.appendChild(document.createTextNode('Weight Gradients:'));
                filters_div.appendChild(document.createElement('br'));
                for (var j = 0; j < L.filters.length; j++) 
                {
                    filters_div.appendChild(document.createTextNode('('));
                    draw_activations(filters_div, L.filters[j], 2, true);
                    filters_div.appendChild(document.createTextNode(')'));
                }
            }
            else
            {
                filters_div.appendChild(document.createTextNode('Weights hidden, too small'));
            }
            activations_div.appendChild(filters_div);
        }
        layer_div.appendChild(activations_div);
        layer_div.className = 'layer ' + 'lt' + L.layer_type;
        var title_div = document.createElement('div');
        title_div.className = 'ltitle'
        var t = L.layer_type + ' (' + L.out_sx + 'x' + L.out_sy + 'x' + L.out_depth + ')';
        title_div.appendChild(document.createTextNode(t));
        layer_div.appendChild(title_div);
        if (L.layer_type === 'conv') 
        {
            var t = 'filter size ' + L.filters[0].sx + 'x' + L.filters[0].sy + 'x' + L.filters[0].depth + ', stride ' + L.stride;
            layer_div.appendChild(document.createTextNode(t));
            layer_div.appendChild(document.createElement('br'));
        }
        if (L.layer_type === 'pool') 
        {
            var t = 'pooling size ' + L.sx + 'x' + L.sy + ', stride ' + L.stride;
            layer_div.appendChild(document.createTextNode(t));
            layer_div.appendChild(document.createElement('br'));
        }
        var mma = maxmin(L.out_act.w);
        var t = 'max activation: ' + f2t(mma.maxv) + ', min: ' + f2t(mma.minv);
        layer_div.appendChild(document.createTextNode(t));
        layer_div.appendChild(document.createElement('br'));
        var mma = maxmin(L.out_act.dw);
        var t = 'max gradient: ' + f2t(mma.maxv) + ', min: ' + f2t(mma.minv);
        layer_div.appendChild(document.createTextNode(t));
        layer_div.appendChild(document.createElement('br'));
        if (L.layer_type === 'conv')
        {
            var tot_params = L.sx*L.sy*L.in_depth*L.filters.length + L.filters.length;
            var t = 'parameters: ' + L.filters.length + 'x' + L.sx + 'x' + L.sy + 'x' + L.in_depth + '+' + L.filters.length + ' = ' + tot_params;
            layer_div.appendChild(document.createTextNode(t));
            layer_div.appendChild(document.createElement('br'));
        }
        if (L.layer_type === 'fc') 
        {
            var tot_params = L.num_inputs*L.filters.length + L.filters.length;
            var t = 'parameters: ' + L.filters.length + 'x' + L.num_inputs + '+' + L.filters.length + ' = ' + tot_params;
            layer_div.appendChild(document.createTextNode(t));
            layer_div.appendChild(document.createElement('br'));
        }
        var clear = document.createElement('div');
        clear.className = 'clear';
        layer_div.appendChild(clear);
        elt.appendChild(layer_div);
    }
}
var sample_test_instance = function() {
    var p = getImageBuffer(context, 28, 28);
    var x = new convnetjs.Vol(28, 28, 1, 0.0);
    var W = 28 * 28;
    for (var i = 0; i < W; i++) 
    {
        x.w[i] = p[i] / 255.0;
    }
    var xs = [];
    for (var i = 0; i < 4; i++)
    {
        xs.push(convnetjs.augment(x, 24));
    }
    return {
        x: xs, 
    };
}
var test_predict = function() {
    var num_classes = net.layers[net.layers.length - 1].out_depth;
    document.getElementById('testset_acc').innerHTML = '';
    for (num = 0; num < 1; num++) 
    {
        var sample = sample_test_instance();
        var y = 1;
        var aavg = new convnetjs.Vol(1, 1, num_classes, 0.0);
        var xs = [].concat(sample.x);
        var n = xs.length;
        for (var i = 0; i < n; i++) 
        {
            var a = net.forward(xs[i]);
            aavg.addFrom(a);
        }
        var preds = [];
        for (var k = 0; k < aavg.w.length; k++) 
        {
            preds.push({
                k: k,
                p: aavg.w[k]
            }); 
        }
        preds.sort(function(a, b) {
            return a.p < b.p ? 1 : -1;
        });
        var div = document.createElement('div');
        div.className = 'testdiv';
        draw_activations(div, xs[0], 2);
        var probsdiv = document.createElement('div');
        div.className = 'probsdiv';
        var t = '';
        for (var k = 0; k < 3; k++)
        {
            var col = preds[k].k === y ? 'rgb(85,187,85)' : 'rgb(187,85,85)';
            t += '<div class=\"pp\" style=\"width:' + Math.floor(preds[k].p / n * 100) + 'px; margin-left: 60px; background-color:' + col + ';\">' + classes_txt[preds[k].k] + '</div>'
        }
        probsdiv.innerHTML = t;
        div.appendChild(probsdiv);
        $("#testset_acc").append(div).fadeIn(1000);
    }
}
load_from_json();


```