// Cloned by atharva joshi on 4 Dec 2021 from World "New World" by atharva joshi
// Please leave this clone trail here.
//---- normal P5 code -------------------------------------------------------
$.getScript("/uploads/atharva/prepareData.js")
//$.getScript ( "https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.2.0/p5.min.js")
$.getScript("https://unpkg.com/ml5@0.7.1/dist/ml5.min.js")
$.getScript("https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@0.11.7")
thehtml = '<h1>Doodle Classifier</h1> '
AB.msg(thehtml, 1);
thehtml = '<h2>Click the Train button to train the Model, then the Test button to pass it a test image.</h2> '
AB.msg(thehtml, 2);
thehtml = '<button class="train" id="train">train</button>';
AB.msg(thehtml, 4);
// 3 Training header
thehtml = '<span class="alert alert-primary" id="training-alert" role="alert">Training...</span>';
AB.msg(thehtml, 7);
thehtml = '<span class="alert1 alert-primary" id="Accuray-alert" role="alert"></span>';
AB.msg(thehtml, 8);
// thehtml = '<textarea class="testpercentage"></textarea>'
// AB.msg ( thehtml, 7 );
thehtml = '<h2>Draw a Train, Rainbow or Cat and click the Guess button.</h2> '
AB.msg(thehtml, 9);
// 5 Testing header
thehtml = '<button class="guess" id="guess">guess</button>';
AB.msg(thehtml, 10);
thehtml = '<button class="btn btn-success" id="generate">Generate</button>';
AB.msg(thehtml, 12);
// 7 Demo header
thehtml = '<button class="clear" id="clear">clear</button>';
AB.msg(thehtml, 14);
thehtml = '<span id="output" class="alert alert-success" role="alert">๐๐Draw a cat/flower/bird and Guess๐๐</span>';
AB.msg(thehtml, 17);
AB.newDiv('canvas')
let dataObjectsArray = [];
// Contains the arrays of preloaded data
let dataPreload = [];
let temp_training_data;
let temp_training_labels;
// Model
let model;
let nn;
// Tensors
xs = {};
ys = {};
testing_xs = {};
testing_ys = {};
const numberOfEachDoodle = 1000;
const data_proportion = 0.8;
function preload() {
console.log("Preloading data");
let filename;
for (let i = 0; i < doodleLabelList.length; i++) {
filename = doodleLabelList[i].toLowerCase();
dataPreload[i] = loadBytes("/uploads/atharva/" + filename + ".bin");
}
console.log(dataPreload);
console.log("Done");
}
// Setup function of p5.js (called after preload)
async function setup() {
let canvas = createCanvas(280, 280);
canvas.parent("canvas");
background(0);
initializeData();
console.log("Creating training tensors");
let rTensors = prepareData(training_data, training_labels);
temp_training_data = training_data;
temp_training_labels = training_labels;
xs = rTensors[0];
ys = rTensors[1];
console.log("Done");
console.log("Creating testing tensors");
// TODO: Something less cancerous
rTensors = prepareData(testing_data, testing_labels);
testing_xs = rTensors[0];
testing_ys = rTensors[1];
// Log progress
console.log("Done");
// Log progress
console.log("Creating model");
// Let's build the model
model = buildModel();
// Log progress
console.log("Done");
let trainButton = select("#train");
let trainingAlert = document.getElementById("training-alert");
trainingAlert.style.display = "none";
let accurayalert = document.getElementById("Accuray-alert");
accurayalert.style.display = "none";
trainButton.mousePressed(
// Log progress
() => {
trainingAlert.style.display = "inline";
accurayalert.style.display = "inline";
console.log("Training model");
// Let's train the model (this .then(() => thingy is an application of the
// new ES6 functionnality combined with the js promises).
train(trainingAlert, accurayalert).then(async () => {
// Log progress
console.log("Done");
trainingAlert.style.display = "none";
trainingAlert.className = "btn btn-disabled";
// const saveResult = await model.save("indexeddb://my-model");
});
}
);
// const model = await tf.loadModel('indexeddb://my-model');
let guessButton = select("#guess");
guessButton.mousePressed(function() {
let inputs = [];
let inputImage = [];
let img = get();
img.resize(28, 28);
img.loadPixels();
// Convert black in white drawings to white in black drawings(training doodles are white on black)
for (let i = 0; i < dataLength; i++) {
let alpha = img.pixels[i * 4];
// normalize the pixels
inputs[i] = alpha / 255.0;
}
// We need to create a 2D array with this pixel because the model has been
// trained with 2D tensors.
inputImage[0] = inputs;
// convert array to tensor
let tensorToPredict = tf.tensor2d(inputImage);
console.log(tensorToPredict);
// predict the doodle
let guess = model.predict(tensorToPredict);
let argMax = guess.argMax(1);
let classifiedLabel = argMax.dataSync()[0];
let classifiedDoodleLabel = doodleLabelList[classifiedLabel];
const output = select("#output");
output.html(classifiedDoodleLabel + "!!!");
console.log("Guessed: " + classifiedDoodleLabel);
});
let clearButton = select("#clear");
clearButton.mousePressed(function() {
background(0);
const output = select("#output");
output.html("");
});
//////////////Genrating a Random image from dataset that is cat,flower,bird
let generateButton = select("#generate");
generateButton.mousePressed(function() {
background(0);
const output = select("#output");
output.html("");
let randomIndex = floor(
random(
numberOfEachDoodle * doodleLabelList.length * (1 - data_proportion)
)
);
let offset = randomIndex * dataLength;
let doodlePixels = testing_xs
.dataSync()
.subarray(offset, offset + dataLength);
let otherOffset = randomIndex * doodleLabelList.length;
let labelsResult = testing_ys
.dataSync()
.subarray(otherOffset, otherOffset + doodleLabelList.length);
let doodleIndex;
for (let i = 0; i < labelsResult.length; i++) {
if (labelsResult[i] === 1) {
doodleIndex = i;
}
}
console.log(doodleLabelList[doodleIndex]);
let img = createImage(28, 28);
img.loadPixels();
for (let i = 0; i < dataLength; i++) {
let val = doodlePixels[i] * 255;
img.pixels[i * 4 + 0] = val;
img.pixels[i * 4 + 1] = val;
img.pixels[i * 4 + 2] = val;
img.pixels[i * 4 + 3] = 255;
}
img.updatePixels();
img.resize(280, 280);
image(img, 0, 0);
});
}
function draw() {
strokeWeight(12);
stroke(255);
if (mouseIsPressed) {
line(pmouseX, pmouseY, mouseX, mouseY);
}
}
////////////////////////////////////// dataobject
class DataObject {
constructor(label) {
this.label = label;
this.totalData = [];
this.trainingData = [];
this.testingData = [];
this.trainingLabels = [];
this.testingLabels = [];
this.data_proportion = 0.8;
this.numberOfEachDoodle = 1000;
this.bytesArrayLength = 784;
this.numberOfDoodles = 1000;
}
get trainingData() {
return this._trainingData;
}
get testingData() {
return this._testingData;
}
get trainingLabels() {
return this._trainingLabels;
}
get testingLabels() {
return this._testingLabels;
}
set trainingData(data) {
this._trainingData = data;
}
set testingData(data) {
this._testingData = data;
}
set trainingLabels(data) {
this._trainingLabels = data;
}
set testingLabels(data) {
this._testingLabels = data;
}
loadBytesData() {
let index = doodleLabelList.indexOf(this.label);
let bytesObject = dataPreload[index];
// bytesObject.bytes is the actual bytes array
this.totalData = bytesObject.bytes;
}
splitData() {
console.log(this.numberOfDoodles);
for (let i = 0; i < this.numberOfDoodles; i++) {
// keeping track of index
let offset = i * this.bytesArrayLength;
// threshold for test/train data split
let threshold = floor(this.data_proportion * this.numberOfDoodles);
if (i < threshold) {
// 1 - 800
this.trainingData[i] = this.totalData.subarray(
offset,
offset + this.bytesArrayLength
);
this.trainingLabels[i] = this.label;
} else {
// 1 - 200
this.testingData[i - threshold] = this.totalData.subarray(
offset,
offset + this.bytesArrayLength
);
this.testingLabels[i - threshold] = this.label;
}
}
}
}
//////// training and testing
function buildModel() {
const options = {
task: 'imageClassification', // or 'regression'
inputs: [128,128,4,255], // r, g, b
debug: true
}
nn = ml5.neuralNetwork(options)
;
for (j=0; j<temp_training_data ;j++){
let offset = j * dataLength;
let doodlePixels = temp_training_data
.dataSync()
.subarray(offset, offset + dataLength);
let otherOffset = randomIndex * doodleLabelList.length;
let labelsResult = temp_training_labels
.dataSync()
.subarray(otherOffset, otherOffset + doodleLabelList.length);
let doodleIndex;
for (let i = 0; i < labelsResult.length; i++) {
if (labelsResult[i] === 1) {
doodleIndex = i;
}
}
console.log(doodleLabelList[doodleIndex]);
let img = createImage(28, 28);
img.loadPixels();
for (let i = 0; i < dataLength; i++) {
let val = doodlePixels[i] * 255;
img.pixels[i * 4 + 0] = val;
img.pixels[i * 4 + 1] = val;
img.pixels[i * 4 + 2] = val;
img.pixels[i * 4 + 3] = 255;
}
img.updatePixels();
img.resize(280, 280);
nn.addData({image : img } , {labels : labelsResult})
}
nn.normalizeData();
/*let tempModel = tf.sequential();
const hiddenLayer1_Units = 256;
const hiddenLayers_Activation = "sigmoid";
const hiddenLayer4_Units = 512;
const hiddenLayer4 = tf.layers.dense({
units: hiddenLayer4_Units,
activation: hiddenLayers_Activation,
});
const hiddenLayer1 = tf.layers.dense({
units: hiddenLayer1_Units,
inputShape: dataLength,
activation: hiddenLayers_Activation,
});
const hiddenLayer2_Units = 128;
const hiddenLayer2 = tf.layers.dense({
units: hiddenLayer2_Units,
activation: hiddenLayers_Activation,
});
const hiddenLayer3_Units = 64;
const hiddenLayer3 = tf.layers.dense({
units: hiddenLayer3_Units,
activation: hiddenLayers_Activation,
});
/*
//output layer
const outputLayer_Activation = "softmax";
const output = tf.layers.dense({
units: doodleLabelList.length,
activation: outputLayer_Activation,
});
tempModel.add(hiddenLayer1);
tempModel.add(hiddenLayer2);
tempModel.add(hiddenLayer3);
tempModel.add(output);
const model_LearningRate = 0.5;
const model_Optimizer = tf.train.adagrad(model_LearningRate);
const model_Loss = "meanSquaredError";
tempModel.compile({
optimizer: model_Optimizer,
loss: model_Loss,
metrics: ["accuracy"],
debug: true
});
//tempModel.compile(optimizer=tf.train.adagrad(model_LearningRate), loss=tf.keras.losses.CategoricalCrossentropy(), metrics = ["accuracy"]);*/
return nn;
}
async function train(alert, alert1) {
/*const training_DoShuffle = true;
const training_ValidationSplit = 0.2;
const training_BatchSize = 16;
const training_NumEpochs = 50;
await model.fit(xs, ys, {
shuffle: training_DoShuffle,
validationSplit: training_ValidationSplit,
batchSize: training_BatchSize,
epochs: training_NumEpochs,
callbacks: {
onEpochEnd: (epochs, logs) => {
console.log("Epoch: " + (epochs + 1));
console.log("Loss: " + logs.loss);
console.log("Accuracy: " + logs.acc.toFixed(2));
alert.innerHTML = `Training ${epochs * 2}% done...`;
alert1.innerHTML = `Accuracy: ${100 * logs.acc.toFixed(2)}`;
},
},
});*/
nn.train({epochs : 50}, function (){ alert.innerHTML = `Training ${epochs * 2}% done...`;
alert1.innerHTML = `Accuracy: ${100 * logs.acc.toFixed(2)}` })
}