Files
2026-07-13 12:49:29 +08:00

209 lines
6.5 KiB
JavaScript

var t = "\n\
// lets use an example fully-connected 2-layer ReLU net\n\
var layer_defs = [];\n\
layer_defs.push({type:'input', out_sx:24, out_sy:24, out_depth:1});\n\
layer_defs.push({type:'fc', num_neurons:20, activation:'relu'});\n\
layer_defs.push({type:'fc', num_neurons:20, activation:'relu'});\n\
layer_defs.push({type:'softmax', num_classes:10});\n\
\n\
// below fill out the trainer specs you wish to evaluate, and give them names for legend\n\
var LR = 0.01; // learning rate\n\
var BS = 8; // batch size\n\
var L2 = 0.001; // L2 weight decay\n\
nets = [];\n\
trainer_defs = [];\n\
trainer_defs.push({learning_rate:LR, method: 'sgd', momentum: 0.0, batch_size:BS, l2_decay:L2});\n\
trainer_defs.push({learning_rate:LR, method: 'sgd', momentum: 0.9, batch_size:BS, l2_decay:L2});\n\
trainer_defs.push({learning_rate:LR, method: 'adam', eps: 1e-8, beta1: 0.9, beta2: 0.99, batch_size:BS, l2_decay:L2});\n\
trainer_defs.push({learning_rate:LR, method: 'adagrad', eps: 1e-6, batch_size:BS, l2_decay:L2});\n\
trainer_defs.push({learning_rate:LR, method: 'windowgrad', eps: 1e-6, ro: 0.95, batch_size:BS, l2_decay:L2});\n\
trainer_defs.push({learning_rate:1.0, method: 'adadelta', eps: 1e-6, ro:0.95, batch_size:BS, l2_decay:L2});\n\
trainer_defs.push({learning_rate:LR, method: 'nesterov', momentum: 0.9, batch_size:BS, l2_decay:L2});\n\
\n\
// names for all trainers above\n\
legend = ['sgd', 'sgd+momentum', 'adam', 'adagrad', 'windowgrad', 'adadelta', 'nesterov'];\n\
"
// ------------------------
// BEGIN MNIST SPECIFIC STUFF
// ------------------------
classes_txt = ['0','1','2','3','4','5','6','7','8','9'];
var use_validation_data = false;
var sample_training_instance = function() {
// find an unloaded batch
var bi = Math.floor(Math.random()*loaded_train_batches.length);
var b = loaded_train_batches[bi];
var k = Math.floor(Math.random()*3000); // sample within the batch
var n = b*3000+k;
// load more batches over time
if(step_num%5000===0 && step_num>0) {
for(var i=0;i<num_batches;i++) {
if(!loaded[i]) {
// load it
load_data_batch(i);
break; // okay for now
}
}
}
// fetch the appropriate row of the training image and reshape into a Vol
var p = img_data[b].data;
var x = new convnetjs.Vol(28,28,1,0.0);
var W = 28*28;
for(var i=0;i<W;i++) {
var ix = ((W * k) + i) * 4;
x.w[i] = p[ix]/255.0;
}
x = convnetjs.augment(x, 24);
var isval = use_validation_data && n%10===0 ? true : false;
return {x:x, label:labels[n], isval:isval};
}
var sample_test_instance = function() {
var b = 20;
var k = Math.floor(Math.random()*3000);
var n = b*3000+k;
var p = img_data[b].data;
var x = new convnetjs.Vol(28,28,1,0.0);
var W = 28*28;
for(var i=0;i<W;i++) {
var ix = ((W * k) + i) * 4;
x.w[i] = p[ix]/255.0;
}
x = convnetjs.augment(x, 24);
return {x:x, label:labels[n]};
}
var num_batches = 21; // 20 training batches, 1 test
var data_img_elts = new Array(num_batches);
var img_data = new Array(num_batches);
var loaded = new Array(num_batches);
var loaded_train_batches = [];
var step_num = 0;
// int main
var lossWindows = [];
var trainAccWindows = [];
var testAccWindows = [];
var lossGraph, trainGraph, testGraph;
$(window).load(function() {
$("#layerdef").val(t);
for(var k=0;k<loaded.length;k++) { loaded[k] = false; }
load_data_batch(0); // async load train set batch 0 (6 total train batches)
load_data_batch(20); // async load test set (batch 6)
start_fun();
reload();
});
var reload = function() {
eval($("#layerdef").val()); // fills in trainer_spects[] array, and layer_defs
var N = trainer_defs.length;
nets = [];
trainers = [];
for(var i=0;i<N;i++) {
var net = new convnetjs.Net();
net.makeLayers(layer_defs);
var trainer = new convnetjs.Trainer(net, trainer_defs[i]);
nets.push(net);
trainers.push(trainer);
}
step_num = 0;
lossWindows = [];
trainAccWindows = [];
testAccWindows = [];
for(var i=0;i<N;i++) {
lossWindows.push(new cnnutil.Window(800));
trainAccWindows.push(new cnnutil.Window(800));
testAccWindows.push(new cnnutil.Window(800));
}
lossGraph = new cnnvis.MultiGraph(legend);
trainGraph = new cnnvis.MultiGraph(legend);
testGraph = new cnnvis.MultiGraph(legend);
}
var start_fun = function() {
if(loaded[0] && loaded[20]) {
console.log('starting!');
setInterval(load_and_step, 0); // lets go!
}
else { setTimeout(start_fun, 200); } // keep checking
}
var load_data_batch = function(batch_num) {
// Load the dataset with JS in background
data_img_elts[batch_num] = new Image();
var data_img_elt = data_img_elts[batch_num];
data_img_elt.onload = function() {
var data_canvas = document.createElement('canvas');
data_canvas.width = data_img_elt.width;
data_canvas.height = data_img_elt.height;
var data_ctx = data_canvas.getContext("2d");
data_ctx.drawImage(data_img_elt, 0, 0); // copy it over... bit wasteful :(
img_data[batch_num] = data_ctx.getImageData(0, 0, data_canvas.width, data_canvas.height);
loaded[batch_num] = true;
if(batch_num < 20) { loaded_train_batches.push(batch_num); }
console.log('finished loading data batch ' + batch_num);
};
data_img_elt.src = "mnist/mnist_batch_" + batch_num + ".png";
}
// ------------------------
// END MNIST SPECIFIC STUFF
// ------------------------
// main iterator function
var load_and_step = function() {
step_num++;
var sample = sample_training_instance();
var test_sample = sample_test_instance();
// train on all networks
var N = nets.length;
var losses = [];
var trainacc = [];
testacc = [];
for(var i=0;i<N;i++) {
// train on training example
var stats = trainers[i].train(sample.x, sample.label);
var yhat = nets[i].getPrediction();
trainAccWindows[i].add(yhat === sample.label ? 1.0 : 0.0);
lossWindows[i].add(stats.loss);
// evaluate a test example
nets[i].forward(test_sample.x);
var yhat_test = nets[i].getPrediction();
testAccWindows[i].add(yhat_test === test_sample.label ? 1.0 : 0.0);
// every 100 iterations also draw
if(step_num % 100 === 0) {
losses.push(lossWindows[i].get_average());
trainacc.push(trainAccWindows[i].get_average());
testacc.push(testAccWindows[i].get_average());
}
}
if(step_num % 100 === 0) {
lossGraph.add(step_num, losses);
lossGraph.drawSelf(document.getElementById("lossgraph"));
trainGraph.add(step_num, trainacc);
trainGraph.drawSelf(document.getElementById("trainaccgraph"));
testGraph.add(step_num, testacc);
testGraph.drawSelf(document.getElementById("testaccgraph"));
}
}