jsdoでconvnetjs その2

#概要
jsdoでwebfontで学習したデータを使って、アルファベットの手書き認識をやってみた。
#写真
![abc.jpg](https://qiita-image-store.s3.amazonaws.com/0/18104/59e9d6b1-9fb1-38fa-62e2-2c2fdbb603fb.jpeg)

#実際
http://jsdo.it/ohisama1/q8KV
#サンプルコード
```
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;
var symbols = [
    'a', 'A', 'b', 'B', 'Cc', 'd', 'D', 'e', 'E', 'f', 'F', 'g9', 'G6', 'h', 'H', 
    'iI1l', 'Jj', 'k', 'K', 'L', 'm', 'M', 'n', 'N', 'Oo0', 'Pp', 'q', 'Q', 'r',
    'R', 'Ss5', 't', 'T', 'Uu', 'vV', 'Ww', 'Xx', 'Yy', 'Zz2', '3', '4', '7', '8',
];
/*
layer_defs = [];
layer_defs.push({
    type: 'input', 
    out_sx: 28, 
    out_sy: 28, 
    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: 18, 
    stride: 1, 
    pad: 2, 
    activation: 'relu'
});
layer_defs.push({
    type: 'pool', 
    sx: 5, 
    stride: 2
});
layer_defs.push({
    type: 'softmax', 
    num_classes: "+symbols.length+"
});
*/
var load_from_json = function() {
    $.getJSON("/assets/y/k/R/Z/ykRZc", function(json) {
        net = new convnetjs.Net();
        net.fromJSON(json);
        trainer = new convnetjs.SGDTrainer(net, {
            method: 'adadelta', 
            batch_size: 20, 
            l2_decay: 0.001
        });
    });
}
var maxmin = cnnutil.maxmin;
var f2t = cnnutil.f2t;
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 === '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++)
                {
                    draw_activations(filters_div, L.filters[j], 2);
                }
                filters_div.appendChild(document.createElement('br'));
                filters_div.appendChild(document.createTextNode('Gradients:'));
                filters_div.appendChild(document.createElement('br'));
                for (var j = 0; j < L.filters.length; j++) 
                {
                    draw_activations(filters_div, L.filters[j], 2, true);
                }
            }
            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'));
        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);
    }
}
function sample_test_instance() {    
    var p = getImageBuffer(context, 32, 32);
    var x = new convnetjs.Vol(32, 32, 1, 0.0);
    var W = 32 * 32;
    for (var i = 0; i < W; i++) 
    {
        x.w[i] = p[i] / 255.0;
    }
    x = convnetjs.augment(x, 28);
    return {
        x: x, 
        label: 1, 
        isval: 1.0 > 0.9
    };
}
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 = sample.label;
        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';
        div.style.backgroundColor = (preds[0].k === y) ? 'rgba(85,187,85,0.5)' : 'rgba(187,85,85,0.5)';
        var t = '';
        for (var k = 0; k < Math.min(3, symbols.length); 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 + ';\">' + symbols[preds[k].k] + '</div>'
        }
        probsdiv.innerHTML = t;
        div.appendChild(probsdiv);
        $("#testset_acc").append(div).fadeIn(1000);
    }
}    
load_from_json();


```