Week09: Neural Network

Colour predictor.
Powerd by Daniel Shiffman’s Toy-Neural-Network library.
Inspired by Jabril’s SEFD Science.

I actually tried to deal with more interesting subjects such as a facial expression predictor, but soon realized that one of the biggest problems to do those things is collecting the training data set.
So I just made a simple colour predictor system.
This system predicts the background colour, and the prediction will be one of these: Reddish, Orangish, Yellowish, Greenish, Bluish, Purplish
A user can additionally train the system by clicking YES(in the case, the user agrees with.) or NO(in the case, the user doesn’t agree with.)
The user can also choose not to train the system by simply choosing SKIP.

The target answer for the training set were decided only by the hue values, but the neural network learn the colour prediction based on all three values of hue, saturation, and brightness.

Following is the code for this system. (I don’t write the code of the neural network and matrix library.)

[index.html]

<!DOCTYPE html><html><head>
    <script src="libraries/p5.min.js"></script>
    <script src="libraries/p5.dom.min.js"></script>
    <script src="libraries/p5.sound.min.js"></script>
    <link rel="stylesheet" type="text/css" href="style.css">
    <meta charset="utf-8">
  </head>
  
  <body>
    
    <div class="ui show" id="container01">
      <div class="click">Click!</div>
    </div>
    <div class="ui hide" id="container02">
      <div class="guess" id="isthiscolour"></div>
      <div class="buttons">
      	<div class="btn" id="yes">YES</div><div class="btn" id="no">NO</div><div class="btn" id="dontcare">SKIP</div>
      </div>
    </div>
    <div class="ui hide" id="container03">
      <div class="guess">What color is it?</div>
      <div class="buttons">
        <div class="btn" id="red">Reddish</div>
        <div class="btn" id="orange">Orangish</div>
        <div class="btn" id="yellow">Yellowish</div>
      </div>
      <div class="buttons">
        <div class="btn" id="green">Greenish</div>
        <div class="btn" id="blue">Bluish</div>
        <div class="btn" id="purple">Purplish</div>
      </div>
    </div>
    
    <script src="libraries/nn.js"></script>
    <script src="libraries/matrix.js"></script>
    <script src="sketch.js"></script>

  </body>
</html>

[style.css]

@import url('https://fonts.googleapis.com/css?family=Arimo:400,400i,700,700i');

html, body {
  margin: 0;
  padding: 0;
  font-family: 'Arimo', sans-serif;
}

body {
  position: relative;
}

.ui {
  width: 600px;
  height: 405px;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 10;

  transition: display 0.2s;

}

.show {
   
  display: -webkit-flex;
  display: -ms-flex;
  display: flex;
  flex-direction: column;
  
  justify-content: center;
  align-items: center;
   
}


.hide {
  display: none;
}

.click {

  font-family: 'Arimo', sans-serif;
  font-size: 50pt;
  color: white;
  font-style: italic;
  font-weight: 700;
}

.click:hover {
  cursor: pointer;
}

.guess {
  width: 600px;
  text-align: center;
  margin-bottom: 20px;
  font-family: 'Arimo', sans-serif;
  font-size: 40pt;
  color: white;
  font-style: italic;
  font-weight: 700;
}

.buttons {
  width: 600px;
  display: -webkit-flex;
  display: -ms-flex;
  display: flex;
  
  justify-content: center;
  
  margin-top: 20px;
}

.btn {
  font-family: 'Arimo', sans-serif;
  font-size: 20pt;
  color: white;
  text-shadow: 1px 1px 4px rgba(0,0,0,0.34);
  font-style: normal;
  font-weight: 700;
  
  margin-left: 30px;
  margin-right: 30px;
}

#red {
  color: red;
}

#orange {
  color: orange;
}

#yellow {
  color: yellow;
}

#green { 
  color: green;
}

#blue {
  color: blue;
}

#purple {
  color: purple;
}

.btn:hover {
 	color: black; 
  cursor: pointer;
}

#red:hover {
  color: black;
}

#orange:hover {
  color: black;
}

#yellow:hover {
  color: black;
}

#green:hover { 
  color: black;
}

#blue:hover {
  color: black;
}

#purple:hover {
  color: black;
}

[sketch.js]

// Yeonhee Lee 
// Used Daniel Shiffman's Toy Neural Network
// Inspired by Daniel Shiffman's colour picker and Daniel was inspired by Jabril's SEFD Science

// Daniel Shiffman
// http://codingtra.in

// Color Predictor
// https://youtu.be/KtPpoMThKUs

// Inspired by Jabril's SEFD Science
// https://youtu.be/KO7W0Qq8yUE
// https://youtu.be/iN3WAko2rL8

let state = 0;
let h, s, b;
let brain;

let colours = ['reddish', 'orangish', 'yellowish', 'greenish', 'bluish', 'purplish']; 

let clk;
let isthiscolour, container01, container02, container03;
let yesBtn, noBtn, dontCareBtn;
let redBtn, orgBtn, yllwBtn, grnBtn, blBtn, pplBtn;

isthiscolour = document.querySelector('#isthiscolour');
container01 = document.querySelector('#container01');
container02 = document.querySelector('#container02');
container03 = document.querySelector('#container03');
  
yesBtn = document.querySelector('#yes');
noBtn = document.querySelector('#no');
dontCareBtn = document.querySelector('#dontcare');
  
redBtn = document.querySelector('#red');
orgBtn = document.querySelector('#orange');
yllwBtn = document.querySelector('#yellow');
grnBtn = document.querySelector('#green');
blBtn = document.querySelector('#blue');
pplBtn = document.querySelector('#purple');


let isSpinning = false;

let iPredict;


function randomColour() {
  h = random(360);
  s = random(100, 360);
  b = random(200, 360);
}


function setup() {

  createCanvas(600, 405);
  colorMode(HSB, 360);
  frameRate(10);
  
  brain = new NeuralNetwork(3, 3, colours.length);

  for (let i = 0; i < 10000; i++) {
    let training_h = random(360);
    let training_s = random(100, 360);
    let training_b = random(200, 360);
    let targets = trainColor(training_h);
    let inputs = [training_h / 360, training_s / 260, training_b / 160];
    brain.train(inputs, targets);
    if(i==9999) isSpinning = true;
  }
  
 console.log(isSpinning);

}

function draw() {
  
  if(isSpinning) {
   	 randomColour();
  }
  
  background(h, s, b);
}

container01.addEventListener('click', isThisColour, false);


function isThisColour(e) {
      // background colour is decided
  e.preventDefault();
  
  isSpinning = false;
  
  let cPredict = colorPredictor(h, s, b);
   
    isthiscolour.innerHTML = "Is this color... <br/>" + cPredict + '?';
    container01.classList.remove("show");
    container01.classList.add("hide");
    container02.classList.remove("hide");
    container02.classList.add("show");
  
  	yesBtn.addEventListener('click', theColourIsCorrect, false);
    noBtn.addEventListener('click', theColourIsWrong, false);
    dontCareBtn.addEventListener('click', iDontCare, false);
  
}

function theColourIsCorrect(e) {
  
  console.log("YES is clicked.");
  console.log(iPredict);
  let idx = iPredict;

  teachColour(idx);
  
  reset();
  
}

function theColourIsWrong(e) {
  
  console.log("No is clicked");
  container02.classList.remove("show");
  container02.classList.add("hide");
  container03.classList.remove("hide");
  container03.classList.add("show");
  
  redBtn.addEventListener('click', function() {
    correctBrain(0)
  }, false);
  orgBtn.addEventListener('click', function() {
    correctBrain(1)
  }, false);
  yllwBtn.addEventListener('click', function() {
    correctBrain(2)
  }, false);
  grnBtn.addEventListener('click', function() {
    correctBrain(3)
  }, false);
  blBtn.addEventListener('click', function() {
    correctBrain(4)
  }, false);
  pplBtn.addEventListener('click', function() {
    correctBrain(5)
  }, false);
  
}

function correctBrain(i) {
  
  teachColour(i);
  
  container01.classList.remove("hide");
  container01.classList.add("show");
  container03.classList.remove("show");
  container03.classList.add("hide");
  
  isSpinning = true;
}

function teachColour(idx) {
  
  console.log("OK. This colour is " + colours[idx] + ". Train the brain...");
  
  // train()
  let targets = [];
  for(let i=0; i<colours.length; i++) {
    if(i == idx) targets[i] = 1;
    else targets[i] = 0;
  }
  console.log(targets);
  
  let inputs = [h / 360, s / 260, b / 160];
  brain.train(inputs, targets);
  
} 

function iDontCare(e) {
  console.log("I don't give a shit.");
  reset();
}

function reset() {
  container01.classList.remove("hide");
  container01.classList.add("show");
  container02.classList.remove("show");
  container02.classList.add("hide");
  
  isSpinning = true;  
}

function trainColor(h_) {

  if((h_ >= 0 && h_ < 13) || (h_ >= 327 && h_ < 360)) {
    return [1, 0, 0, 0, 0, 0];
  } else if(h_ >= 13 && h_ < 42) {
    return [0, 1, 0, 0, 0, 0];
  } else if(h_ >= 42 && h_ < 70) {
    return [0, 0, 1, 0, 0, 0];
  } else if(h_ >= 70 && h_ < 167) {
    return [0, 0, 0, 1, 0, 0];
  } else if(h_ >= 167 && h_ < 264) {
    return [0, 0, 0, 0, 1, 0];
  } else if(h_ >= 264 && h_ < 327) {
    return [0, 0, 0, 0, 0, 1];
  } else {
    console.log("error!");
      return [1, 0, 0, 0, 0, 0];
  }
  
}

function colorPredictor(h, s, b) {

  let inputs = [h / 360, s / 260, b / 160];
  console.log(inputs);
  let outputs = brain.predict(inputs);
  console.log(outputs);
  
  let res = Math.max(...outputs);
  console.log(res);
  
  for(let i=0; i<colours.length; i++) {
    if(outputs[i] == res) {
       console.log("predicted colour: ", colours[i]);
      iPredict = i;
      return colours[i];
    }
  }
  
}

And this is the working sketch:

I might, later, be able to make a much cooler neural network system with data that I collected from the internet using Python.

Leave a Reply

Your email address will not be published. Required fields are marked *