Machine Learning, Redes Neurais e Inteligência Artificial

Redes Neurais

O termo “Inteligência Artificial” tem sido amplamente usado a bastante tempo. Está presente em filmes de ficção, bots de jogos, busca do Google, e claro, nas máquinas que irão substituir o homem em muitas tarefas. Neste post explicaremos de forma sucinta o que é “Machine Learning”, “Redes Neurais” e “Inteligência Artificial”.

Inteligência Artificial

Inteligência Artificial é definida como o estudo de “agentes inteligentes”: qualquer dispositivo que perceba seu ambiente e realize ações que maximizem sua chance de atingir seus objetivos com sucesso. Em outras palavras, pode-se dizer que “inteligência artificial” é a capacidade da máquina imitar funções através da “aprendizagem” e “resolução de problemas”.

Um exemplo muito simples de inteligência artificial pode ser encontrado na forma de um jogo da velha; se um bot seguir o seguinte algoritmo pré-programado, nunca perderá um jogo:

  • Se houver uma “ameaça” (isto é, duas em sequência), ocupe o quadrado restante.
  • Se um movimento forcar para criar duas ameaças de uma vez, então faça esse movimento. De outra forma,
  • Pegue o quadrado central, se estiver livre. De outra forma,
  • Se o seu adversário jogou em um canto, pegue o canto oposto. De outra forma,
  • Pegue um canto vazio, se houver um. De outra forma,
  • Pegue qualquer quadrado vazio.

Agora, um algoritmo como esse não possui as habilidades cognitivas, de aprendizado ou de resolução de problemas com as quais a maioria das pessoas associa um “AI”. E, no entanto, o algoritmo é simplesmente um agente que leva à solução ótima, dado um problema e seu estado.

Os agentes que se enquadram em IA, mas não em Machine Learning, geralmente são agentes que utilizam exclusivamente árvores de decisão para lógica ou agentes criados com regras e instruções.

Machine Learning: A Habilidade Cognitiva

Arthur Samuel criou o termo “Machine Learning” em 1959, definindo-a como “a capacidade de aprender sem ser programado explicitamente”. Machine Learning, na sua forma mais básica, é a prática de usar algoritmos para analisar dados, aprender com eles e então fazer uma determinação ou previsão sobre algo.

Machine Learning, em sua essência, é realmente apenas fazer uma nova linha melhor do que a anterior, exceto em muitas dimensões. Por exemplo, um modelo de predição de preço de venda de imóveis com base em anúncios publicados analisa milhares de dados, sendo que cada linha de dados contendo várias dimensões como: metragem, contagem de quarto, banheiro, área construída, etc. Então cria-se uma função recebendo estes parâmetros como entrada e então apenas desloca os coeficientes para cada um desses parâmetros, à medida que analisa mais e mais dados. Dessa forma ele compara o resultado com o valor anunciado e evolui com o treinamento.

Esse método de Machine Learning é chamado de “Aprendizado Supervisionado”, em que os dados fornecidos ao modelo incluem a resposta ao problema para cada conjunto de entrada. Basicamente, são dados os parâmetros de entrada, chamados de recursos, e as saídas de cada conjunto de recursos, a partir dos quais o modelo ajusta sua função para corresponder aos dados. Então, quando dados quaisquer outros dados de entrada, o modelo pode executar a mesma função e chegar a uma saída precisa.

Outras modelos de Machine Learning são Aprendizado Não Supervisionado e Aprendizado de Reforço. Concisamente, Aprendizado Não Supervisionado apenas encontra semelhanças nos dados – no nosso exemplo de venda de imóveis, os dados não incluem os preços da habitação (os dados seriam apenas dados, não teriam saída) e o modelo seria capaz de apontar similaridades mas sem ser capaz de prever o preço de um determinado anúncio.

Deep Learning: A Conexão Com os Humanos

O Aprendizado Profundo (Deep Learning) foi inspirado na estrutura e função do cérebro, ou seja, a interconexão de muitos neurônios. Redes neurais são algoritmos que imitam a estrutura biológica do cérebro.

Modelada livremente no cérebro humano, uma rede neural consiste em milhares ou mesmo milhões de nós de processamento simples que são densamente interconectados. A maioria das redes neurais de hoje é organizada em camadas de nós, e elas são “feedforward”, o que significa que os dados passam por elas em apenas uma direção. Um nó individual pode estar conectado a vários nós na camada abaixo dele, da qual recebe dados, e vários nós na camada acima dele, para os quais envia dados.

Para cada uma de suas conexões de entrada, um nó atribuirá um número conhecido como “peso”. Quando a rede está ativa, o nó recebe um item de dados diferente – um número diferente – sobre cada uma de suas conexões e o multiplica pelo peso associado. Em seguida, ele adiciona os produtos resultantes juntos, gerando um único número. Se esse número estiver abaixo de um valor limite, o nó não transmitirá dados para a próxima camada. Se o número exceder o valor limite, o nó “dispara”, o que, nas redes neurais de hoje, geralmente significa enviar o número, a soma das entradas ponderadas, ao longo de todas as conexões de saída.

Quando uma rede neural está sendo treinada, todos os seus pesos e limites são inicialmente definidos para valores aleatórios. Os dados de treinamento são enviados para a camada inferior, a camada de entrada, e passam pelas camadas seguintes, sendo multiplicadas e adicionadas de maneira complexa até chegarem finalmente, radicalmente transformadas, na camada de saída. Durante o treinamento, os pesos e limites são continuamente ajustados até que os dados de treinamento com os mesmos rótulos produzam consistentemente resultados semelhantes.

Deep Learning é basicamente Machine Learning em rede. Existem várias camadas para processar recursos e, geralmente, cada camada extrai algumas informações valiosas. Por exemplo, uma rede neural poderia processar imagens para dirigir um carro autônomo. Cada camada processaria algo diferente, como, por exemplo, o primeiro poderia estar detectando bordas para os lados da estrada. Outra camada poderia estar detectando as linhas de pista na imagem e outros possivelmente outros carros.

Colocando em Prática

A seguir faremos uso da biblioteca Brain.js para desenvolver um aplicativo simples que irá analisar o contraste entre as cores para indicar a melhor combinação para leitura.

Primeiro vamos criar um arquivo HTML e incluir as bibliotecas javascript necessárias. Para facilitar, vamos acessar diretamente de uma CDN.

<!DOCTYPE html>
<html>
<head>
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
  <script src="https://harthur.github.io/brain/brain-0.6.3.js"></script>
  <title>Testando rede neural com brain.js</title>
  <style>body{font-family:Tahoma,Helvetica,Arial,sans-serif;font-size:86%;margin:0}#desc{padding:9px 14px;background-color:#F0F0F0}#container{margin:80px auto 0;width:600px}.section{margin:50px;text-align:center}.section-header{margin-bottom:20px;font-size:1.2em}#subtitle{margin-top:2em;font-size:.95em;color:#555;padding:0 80px}#black-swatch{color:#000}#white-swatch{color:#fff}.swatch:active{-moz-box-shadow:0 0 2px 3px grey;-webkit-box-shadow:0 0 2px 3px grey;box-shadow:0 0 2px 3px grey}.swatch{margin:10px;padding:40px;height:60px;width:70px;cursor:pointer;font-size:.97em}.swatch-box{display:inline-block}.view-code{color:#aaa;cursor:pointer;margin-right:4px;vertical-align:center}.swatch-box.selected .view-code{color:#222}.view-code-arrow{margin-left:.16em;font-size:.8em;display:inline-block}.swatch-box.selected .view-code-arrow{-moz-transform:rotate(90deg);-webkit-transform:rotate(90deg);-o-transform:rotate(90deg)}#test-box{margin-top:50px}.pass-button{color:#333;font-weight:700;font-size:1.6em;font-family:"Lucida Grande",Lucida,sans-serif}#training-box .pass-button{margin-left:310px}#testing-box .pass-button{margin-left:350px}#test-button{background-color:#DDD;box-shadow:#E0E0E0 0 .15em .6em;border:1px solid #CCC;margin-top:40px;padding:6px 14px}.button:active{background-color:#BBB!important}.button{border-radius:4px;cursor:pointer;display:inline-block}#code-box{margin:32px auto}#code-header{margin-bottom:10px;font-weight:700}#code{text-align:left;font-family:"DejaVu Sans Mono",monospace;font-size:13px;white-space:pre-wrap;background-color:#F4F4F4;padding:18px 16px;margin:0 auto;border:1px solid #eee}#progress-box{width:600px;text-align:center;margin:200px auto;font-weight:700;font-size:2em}#progress-bar{height:20px;border:1px solid #ccc;background-color:#f2f2f2;margin-top:20px}#progress-completed{background-color:#d0d0d0;width:0;height:100%}</style>
</head>
...

O próximo passo é criar o container onde será apresentado as opções para treinamento:

<div id="container">
    <div class="section" id="training-box">
      <div class="section-header">
        Qual das caixas é mais fácil a leitura?
      </div>
        <div id="swatches">
		    <div class="swatch-box">
            <div id="black-swatch" class="swatch" onclick="trainer.pickSwatch('black');">
              <div class="swatch-text">Este aqui</div>
            </div></div>
	    <div class="swatch-box">
            <div id="white-swatch" class="swatch" onclick="trainer.pickSwatch('white');">
              <div class="swatch-text">Este aqui</div>
            </div></div>
        </div>
        <div id="training-buttons">
          <span class="pass-button button" onclick="trainer.changeColor();"
                title="skip">&rarr;</span>
        </div>
      <div id="test-box">
        <div id="test-button" onclick="trainer.trainNetwork();" class="button">Treinar a Rede Neural</div>
        <div id="subtitle">Você pode treinar agora a rede, mas quanto mais
testes realizar melhor será a assertividade.
        </div>
      </div>
    </div>
<div id="progress-box">
      <div id="training-message">
        treinando a rede...
      </div>
      <div id="progress-bar">
	    <div id="progress-completed">
	    </div>
      </div>
   </div>

    <div class="section" id="testing-box">
      <div id="swatches">
	      <div id="nn-swatch-box" class="swatch-box">
            <div id="nn-swatch" class="swatch" onclick="tester.viewCode('nn');"
                 title="view neural network code">
              <div class="swatch-text">sua rede neural</div>
            </div>
            <div class="view-code" onclick="tester.viewCode('nn');">Código
	            <div class="view-code-arrow">&#x25B6;</div>
  	        </div>
	      </div>
	      <div id="wcag-swatch-box" class="swatch-box">
          <div id="wcag-swatch" class="swatch"
               onclick="tester.viewCode('wcag');" title="view luminosity code">
          <div class="swatch-text">luminosity algorithm</div>
          </div>
          <div class="view-code" onclick="tester.viewCode('wcag')">Código
	          <div class="view-code-arrow">&#x25B6;</div>
	        </div>
	      </div>
        <div id="yiq-swatch-box" class="swatch-box">
          <div id="yiq-swatch" class="swatch"
               onclick="tester.viewCode('yiq');" title="view yiq code">
               <div class="swatch-text">fórmula YIQ</div>
          </div>
          <div class="view-code" onclick="tester.viewCode('yiq')">Código
	          <div class="view-code-arrow">&#x25B6;</div>
	        </div>
        </div>
      </div>
      <div id="training-buttons">
        <span class="pass-button button" onclick="tester.testRandom();"
              title="next color">&rarr;</span>
      </div>
    </div>
    <div id="code-box">
      <pre id="code"></pre>
    </div>
  </div>

Por fim, colocamos o código Javascript para acionar os testes:

function postProgress(progress) {
    progress.type = 'progress'
    postMessage(JSON.stringify(progress));
}

$(document).ready(function() {
    trainer.changeColor();
    $("#progress-box").hide();
    $("#testing-box").hide();
    $("#code-box").hide();

    // only show nn and yiq
    $("#wcag-swatch-box").hide();
    $("#test-box").hide();
});

var utils = {
    randomColor: function() {
        return {
            r: Math.round(Math.random() * 255),
            g: Math.round(Math.random() * 255),
            b: Math.round(Math.random() * 255)
        };
    },

    toRgb: function(color) {
        return "rgb(" + color.r + "," + color.g + "," + color.b + ")";
    },

    normalize: function(color) {
        return {
            r: color.r / 255,
            g: color.g / 255,
            b: color.b / 255
        };
    }
}

var trainer = {
    currentColor: utils.randomColor(),

    data: [],

    pickSwatch: function(color) {
        var result = {
            input: utils.normalize(this.currentColor),
            output: {
                black: color == 'black' ? 1 : 0
            }
        };
        this.data.push(result);

        this.changeColor();

        // show the "Train network" button after we've selected a few entries
        if (this.data.length == 5) {
            $("#test-box").show();
        }
    },

    changeColor: function() {
        this.currentColor = utils.randomColor();
        var rgb = utils.toRgb(this.currentColor);
        $(".swatch").css("backgroundColor", rgb);
    },

    trainNetwork: function() {
        $("#training-box").hide();
        $("#progress-box").show();


        var net = new brain.NeuralNetwork();
        net.train(this.data, {
            iterations: 9000
        });
        tester.show(net);
    },

    onMessage: function(event) {
        var data = JSON.parse(event.data);
        if (data.type == 'progress') {
            trainer.showProgress(data);
        } else if (data.type == 'result') {
            var net = new brain.NeuralNetwork().fromJSON(data.net);
            tester.show(net);
        }
    },

    onError: function(event) {
        $("#training-message").text("error training network: " + event.message);
    },

    showProgress: function(progress) {
        var completed = progress.iterations / trainer.iterations * 100;
        $("#progress-completed").css("width", completed + "%");
    }
}

var tester = {
    show: function(net) {
        $("#progress-box").hide();
        runNetwork = net.toFunction();
        runNetwork.name = "runNetwork"; // for view code later
        this.testRandom();
        $("#testing-box").show();
    },

    testRandom: function() {
        this.testColor(utils.randomColor());
    },

    testColor: function(color) {
        var rgb = utils.toRgb(color);
        $(".swatch").css("backgroundColor", rgb);

        var color = utils.normalize(color);
        $("#nn-swatch").css("color", nnColor(color));
        $("#wcag-swatch").css("color", wcagColor(color));
        $("#yiq-swatch").css("color", yiqColor(color));
    },

    viewCode: function(type) {
        if (type == 'nn' && !$("#nn-swatch-box").hasClass("selected")) {
            $("#code-header").text("neural network code:");
            var code = "var textColor = " + nnColor.toString() +
                "\n\nvar runNetwork = " + runNetwork.toString();
            $("#code").text(code);
            $(".swatch-box").removeClass("selected");
            $("#nn-swatch-box").addClass("selected");
            $("#code-box").show();
        } else if (type == 'wcag' && !$("#wcag-swatch-box").hasClass("selected")) {
            $("#code-header").text("luminosity algorithm code:");
            var code = "var textColor = " + wcagColor.toString() +
                "\n\nvar contrast = " + contrast.toString() +
                "\n\nvar luminosity = " + luminosity.toString();
            $("#code").text(code);
            $(".swatch-box").removeClass("selected");
            $("#wcag-swatch-box").addClass("selected");
            $("#code-box").show();
        } else if (type == 'yiq' && !$("#yiq-swatch-box").hasClass("selected")) {
            $("#code-header").text("YIQ formula code:");
            var code = "var textColor = " + yiqColor.toString();

            $("#code").text(code);
            $(".swatch-box").removeClass("selected");
            $("#yiq-swatch-box").addClass("selected");
            $("#code-box").show();
        } else {
            $("#code-box").hide();
            $(".swatch-box").removeClass("selected");
        }
    }
}


/* these functions are outside so we can just call toString() for 'view code'*/
var nnColor = function(bgColor) {
    var output = runNetwork(bgColor);
    if (output.black > .5) {
        return 'black';
    }
    return 'white';
}

var wcagColor = function(bgColor) {
    if (contrast(bgColor, {
            r: 1,
            g: 1,
            b: 1
        }) >
        contrast(bgColor, {
            r: 0,
            g: 0,
            b: 0
        }))
        return 'white';
    return 'black';
}

var luminosity = function(color) {
    var r = color.r,
        g = color.g,
        b = color.b;
    var red = (r <= 0.03928) ? r / 12.92 : Math.pow(((r + 0.055) / 1.055), 2.4);
    var green = (g <= 0.03928) ? g / 12.92 : Math.pow(((g + 0.055) / 1.055), 2.4);
    var blue = (b <= 0.03928) ? b / 12.92 : Math.pow(((b + 0.055) / 1.055), 2.4);

    return 0.2126 * red + 0.7152 * green + 0.0722 * blue;
}

var contrast = function(color1, color2) {
    var lum1 = luminosity(color1);
    var lum2 = luminosity(color2);
    if (lum1 > lum2) {
        return (lum1 + 0.05) / (lum2 + 0.05);
    }
    return (lum2 + 0.05) / (lum1 + 0.05);
}

var yiqColor = function(bgColor) {
    var r = bgColor.r * 255,
        g = bgColor.g * 255,
        b = bgColor.b * 255;
    var yiq = (r * 299 + g * 587 + b * 114) / 1000;
    return (yiq >= 128) ? 'black' : 'white';
}

Abaixo o arquivo completo:

<!DOCTYPE html>
<html>
<head>
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
  <script src="https://harthur.github.io/brain/brain-0.6.3.js"></script>
  <title>Testando rede neural com brain.js</title>
  <style>body{font-family:Tahoma,Helvetica,Arial,sans-serif;font-size:86%;margin:0}#desc{padding:9px 14px;background-color:#F0F0F0}#container{margin:80px auto 0;width:600px}.section{margin:50px;text-align:center}.section-header{margin-bottom:20px;font-size:1.2em}#subtitle{margin-top:2em;font-size:.95em;color:#555;padding:0 80px}#black-swatch{color:#000}#white-swatch{color:#fff}.swatch:active{-moz-box-shadow:0 0 2px 3px grey;-webkit-box-shadow:0 0 2px 3px grey;box-shadow:0 0 2px 3px grey}.swatch{margin:10px;padding:40px;height:60px;width:70px;cursor:pointer;font-size:.97em}.swatch-box{display:inline-block}.view-code{color:#aaa;cursor:pointer;margin-right:4px;vertical-align:center}.swatch-box.selected .view-code{color:#222}.view-code-arrow{margin-left:.16em;font-size:.8em;display:inline-block}.swatch-box.selected .view-code-arrow{-moz-transform:rotate(90deg);-webkit-transform:rotate(90deg);-o-transform:rotate(90deg)}#test-box{margin-top:50px}.pass-button{color:#333;font-weight:700;font-size:1.6em;font-family:"Lucida Grande",Lucida,sans-serif}#training-box .pass-button{margin-left:310px}#testing-box .pass-button{margin-left:350px}#test-button{background-color:#DDD;box-shadow:#E0E0E0 0 .15em .6em;border:1px solid #CCC;margin-top:40px;padding:6px 14px}.button:active{background-color:#BBB!important}.button{border-radius:4px;cursor:pointer;display:inline-block}#code-box{margin:32px auto}#code-header{margin-bottom:10px;font-weight:700}#code{text-align:left;font-family:"DejaVu Sans Mono",monospace;font-size:13px;white-space:pre-wrap;background-color:#F4F4F4;padding:18px 16px;margin:0 auto;border:1px solid #eee}#progress-box{width:600px;text-align:center;margin:200px auto;font-weight:700;font-size:2em}#progress-bar{height:20px;border:1px solid #ccc;background-color:#f2f2f2;margin-top:20px}#progress-completed{background-color:#d0d0d0;width:0;height:100%}</style>
</head>
<body>

<div id="container">
    <div class="section" id="training-box">
      <div class="section-header">
        Qual das caixas é mais fácil a leitura?
      </div>
        <div id="swatches">
		    <div class="swatch-box">
            <div id="black-swatch" class="swatch" onclick="trainer.pickSwatch('black');">
              <div class="swatch-text">Este aqui</div>
            </div></div>
	    <div class="swatch-box">
            <div id="white-swatch" class="swatch" onclick="trainer.pickSwatch('white');">
              <div class="swatch-text">Este aqui</div>
            </div></div>
        </div>
        <div id="training-buttons">
          <span class="pass-button button" onclick="trainer.changeColor();"
                title="skip">&rarr;</span>
        </div>
      <div id="test-box">
        <div id="test-button" onclick="trainer.trainNetwork();" class="button">Treinar a Rede Neural</div>
        <div id="subtitle">Você pode treinar agora a rede, mas quanto mais
testes realizar melhor será a assertividade.
        </div>
      </div>
    </div>
<div id="progress-box">
      <div id="training-message">
        treinando a rede...
      </div>
      <div id="progress-bar">
	    <div id="progress-completed">
	    </div>
      </div>
   </div>

    <div class="section" id="testing-box">
      <div id="swatches">
	      <div id="nn-swatch-box" class="swatch-box">
            <div id="nn-swatch" class="swatch" onclick="tester.viewCode('nn');"
                 title="view neural network code">
              <div class="swatch-text">sua rede neural</div>
            </div>
            <div class="view-code" onclick="tester.viewCode('nn');">Código
	            <div class="view-code-arrow">&#x25B6;</div>
  	        </div>
	      </div>
	      <div id="wcag-swatch-box" class="swatch-box">
          <div id="wcag-swatch" class="swatch"
               onclick="tester.viewCode('wcag');" title="view luminosity code">
          <div class="swatch-text">luminosity algorithm</div>
          </div>
          <div class="view-code" onclick="tester.viewCode('wcag')">Código
	          <div class="view-code-arrow">&#x25B6;</div>
	        </div>
	      </div>
        <div id="yiq-swatch-box" class="swatch-box">
          <div id="yiq-swatch" class="swatch"
               onclick="tester.viewCode('yiq');" title="view yiq code">
               <div class="swatch-text">fórmula YIQ</div>
          </div>
          <div class="view-code" onclick="tester.viewCode('yiq')">Código
	          <div class="view-code-arrow">&#x25B6;</div>
	        </div>
        </div>
      </div>
      <div id="training-buttons">
        <span class="pass-button button" onclick="tester.testRandom();"
              title="next color">&rarr;</span>
      </div>
    </div>
    <div id="code-box">
      <pre id="code"></pre>
    </div>
  </div>


<script>
function postProgress(progress) {
    progress.type = 'progress'
    postMessage(JSON.stringify(progress));
}

$(document).ready(function() {
    trainer.changeColor();
    $("#progress-box").hide();
    $("#testing-box").hide();
    $("#code-box").hide();

    // only show nn and yiq
    $("#wcag-swatch-box").hide();
    $("#test-box").hide();
});

var utils = {
    randomColor: function() {
        return {
            r: Math.round(Math.random() * 255),
            g: Math.round(Math.random() * 255),
            b: Math.round(Math.random() * 255)
        };
    },

    toRgb: function(color) {
        return "rgb(" + color.r + "," + color.g + "," + color.b + ")";
    },

    normalize: function(color) {
        return {
            r: color.r / 255,
            g: color.g / 255,
            b: color.b / 255
        };
    }
}

var trainer = {
    currentColor: utils.randomColor(),

    data: [],

    pickSwatch: function(color) {
        var result = {
            input: utils.normalize(this.currentColor),
            output: {
                black: color == 'black' ? 1 : 0
            }
        };
        this.data.push(result);

        this.changeColor();

        // show the "Train network" button after we've selected a few entries
        if (this.data.length == 5) {
            $("#test-box").show();
        }
    },

    changeColor: function() {
        this.currentColor = utils.randomColor();
        var rgb = utils.toRgb(this.currentColor);
        $(".swatch").css("backgroundColor", rgb);
    },

    trainNetwork: function() {
        $("#training-box").hide();
        $("#progress-box").show();


        var net = new brain.NeuralNetwork();
        net.train(this.data, {
            iterations: 9000
        });
        tester.show(net);
    },

    onMessage: function(event) {
        var data = JSON.parse(event.data);
        if (data.type == 'progress') {
            trainer.showProgress(data);
        } else if (data.type == 'result') {
            var net = new brain.NeuralNetwork().fromJSON(data.net);
            tester.show(net);
        }
    },

    onError: function(event) {
        $("#training-message").text("error training network: " + event.message);
    },

    showProgress: function(progress) {
        var completed = progress.iterations / trainer.iterations * 100;
        $("#progress-completed").css("width", completed + "%");
    }
}

var tester = {
    show: function(net) {
        $("#progress-box").hide();
        runNetwork = net.toFunction();
        runNetwork.name = "runNetwork"; // for view code later
        this.testRandom();
        $("#testing-box").show();
    },

    testRandom: function() {
        this.testColor(utils.randomColor());
    },

    testColor: function(color) {
        var rgb = utils.toRgb(color);
        $(".swatch").css("backgroundColor", rgb);

        var color = utils.normalize(color);
        $("#nn-swatch").css("color", nnColor(color));
        $("#wcag-swatch").css("color", wcagColor(color));
        $("#yiq-swatch").css("color", yiqColor(color));
    },

    viewCode: function(type) {
        if (type == 'nn' && !$("#nn-swatch-box").hasClass("selected")) {
            $("#code-header").text("neural network code:");
            var code = "var textColor = " + nnColor.toString() +
                "\n\nvar runNetwork = " + runNetwork.toString();
            $("#code").text(code);
            $(".swatch-box").removeClass("selected");
            $("#nn-swatch-box").addClass("selected");
            $("#code-box").show();
        } else if (type == 'wcag' && !$("#wcag-swatch-box").hasClass("selected")) {
            $("#code-header").text("luminosity algorithm code:");
            var code = "var textColor = " + wcagColor.toString() +
                "\n\nvar contrast = " + contrast.toString() +
                "\n\nvar luminosity = " + luminosity.toString();
            $("#code").text(code);
            $(".swatch-box").removeClass("selected");
            $("#wcag-swatch-box").addClass("selected");
            $("#code-box").show();
        } else if (type == 'yiq' && !$("#yiq-swatch-box").hasClass("selected")) {
            $("#code-header").text("YIQ formula code:");
            var code = "var textColor = " + yiqColor.toString();

            $("#code").text(code);
            $(".swatch-box").removeClass("selected");
            $("#yiq-swatch-box").addClass("selected");
            $("#code-box").show();
        } else {
            $("#code-box").hide();
            $(".swatch-box").removeClass("selected");
        }
    }
}


/* these functions are outside so we can just call toString() for 'view code'*/
var nnColor = function(bgColor) {
    var output = runNetwork(bgColor);
    if (output.black > .5) {
        return 'black';
    }
    return 'white';
}

var wcagColor = function(bgColor) {
    if (contrast(bgColor, {
            r: 1,
            g: 1,
            b: 1
        }) >
        contrast(bgColor, {
            r: 0,
            g: 0,
            b: 0
        }))
        return 'white';
    return 'black';
}

var luminosity = function(color) {
    var r = color.r,
        g = color.g,
        b = color.b;
    var red = (r <= 0.03928) ? r / 12.92 : Math.pow(((r + 0.055) / 1.055), 2.4);
    var green = (g <= 0.03928) ? g / 12.92 : Math.pow(((g + 0.055) / 1.055), 2.4);
    var blue = (b <= 0.03928) ? b / 12.92 : Math.pow(((b + 0.055) / 1.055), 2.4);

    return 0.2126 * red + 0.7152 * green + 0.0722 * blue;
}

var contrast = function(color1, color2) {
    var lum1 = luminosity(color1);
    var lum2 = luminosity(color2);
    if (lum1 > lum2) {
        return (lum1 + 0.05) / (lum2 + 0.05);
    }
    return (lum2 + 0.05) / (lum1 + 0.05);
}

var yiqColor = function(bgColor) {
    var r = bgColor.r * 255,
        g = bgColor.g * 255,
        b = bgColor.b * 255;
    var yiq = (r * 299 + g * 587 + b * 114) / 1000;
    return (yiq >= 128) ? 'black' : 'white';
}
</script>
</body>
</html>

*** A OctalMind é uma empresa especializada no desenvolvimento de sistemas de alta tecnologia.