Neural network in Javascript not learning properly - javascript

I've tried to rewrite neural network found here to javascript. My javascript code looks like this.
function NeuralFactor(weight) {
var self = this;
this.weight = weight;
this.delta = 0;
}
function Sigmoid(value) {
return 1 / (1 + Math.exp(-value));
}
function Neuron(isInput) {
var self = this;
this.pulse = function() {
self.output = 0;
self.input.forEach(function(item) {
self.output += item.signal.output * item.factor.weight;
});
self.output += self.bias.weight;
self.output = Sigmoid(self.output);
};
this.bias = new NeuralFactor(isInput ? 0 : Math.random());
this.error = 0;
this.input = [];
this.output = 0;
this.findInput = function(signal) {
var input = self.input.filter(function(input) {
return signal == input.signal;
})[0];
return input;
};
}
function NeuralLayer() {
var self = this;
this.pulse = function() {
self.neurons.forEach(function(neuron) {
neuron.pulse();
});
};
this.neurons = [];
this.train = function(learningRate) {
self.neurons.forEach(function(neuron) {
neuron.bias.weight += neuron.bias.delta * learningRate;
neuron.bias.delta = 0;
neuron.input.forEach(function(input) {
input.factor.weight += input.factor.delta * learningRate;
input.factor.delta = 0;
})
})
}
}
function NeuralNet(inputCount, hiddenCount, outputCount) {
var self = this;
this.inputLayer = new NeuralLayer();
this.hiddenLayer = new NeuralLayer();
this.outputLayer = new NeuralLayer();
this.learningRate = 0.5;
for(var i = 0; i < inputCount; i++)
self.inputLayer.neurons.push(new Neuron(true));
for(var i = 0; i < hiddenCount; i++)
self.hiddenLayer.neurons.push(new Neuron());
for(var i = 0; i < outputCount; i++)
self.outputLayer.neurons.push(new Neuron());
for (var i = 0; i < hiddenCount; i++)
for (var j = 0; j < inputCount; j++)
self.hiddenLayer.neurons[i].input.push({
signal: self.inputLayer.neurons[j],
factor: new NeuralFactor(Math.random())
});
for (var i = 0; i < outputCount; i++)
for (var j = 0; j < hiddenCount; j++)
self.outputLayer.neurons[i].input.push({
signal: self.hiddenLayer.neurons[j],
factor: new NeuralFactor(Math.random())
});
this.pulse = function() {
self.hiddenLayer.pulse();
self.outputLayer.pulse();
};
this.backPropagation = function(desiredResults) {
for(var i = 0; i < self.outputLayer.neurons.length; i++) {
var outputNeuron = self.outputLayer.neurons[i];
var output = outputNeuron.output;
outputNeuron.error = (desiredResults[i] - output) * output * (1.0 - output);
}
for(var i = 0; i < self.hiddenLayer.neurons.length; i++) {
var hiddenNeuron = self.hiddenLayer.neurons[i];
var error = 0;
for(var j = 0; j < self.outputLayer.neurons.length; j++) {
var outputNeuron = self.outputLayer.neurons[j];
error += outputNeuron.error * outputNeuron.findInput(hiddenNeuron).factor.weight * hiddenNeuron.output * (1.0 - hiddenNeuron.output);
}
hiddenNeuron.error = error;
}
for(var j = 0; j < self.outputLayer.neurons.length; j++) {
var outputNeuron = self.outputLayer.neurons[j];
for(var i = 0; i < self.hiddenLayer.neurons.length; i++) {
var hiddenNeuron = self.hiddenLayer.neurons[i];
outputNeuron.findInput(hiddenNeuron).factor.delta += outputNeuron.error * hiddenNeuron.output;
}
outputNeuron.bias.delta += outputNeuron.error * outputNeuron.bias.weight;
}
for(var j = 0; j < self.hiddenLayer.neurons.length; j++) {
var hiddenNeuron = self.hiddenLayer.neurons[j];
for(var i = 0; i < self.inputLayer.neurons.length; i++) {
var inputNeuron = self.inputLayer.neurons[i];
hiddenNeuron.findInput(inputNeuron).factor.delta += hiddenNeuron.error * inputNeuron.output;
}
hiddenNeuron.bias.delta += hiddenNeuron.error * hiddenNeuron.bias.weight;
}
};
this.train = function(input, desiredResults) {
for(var i = 0; i < self.inputLayer.neurons.length; i++) {
var neuron = self.inputLayer.neurons[i];
neuron.output = input[i];
}
self.pulse();
self.backPropagation(desiredResults);
self.hiddenLayer.train(self.learningRate);
self.outputLayer.train(self.learningRate);
};
}
Now I'm trying to learn it how to resolve XOR problem. I'm teaching it like this:
var net = new NeuralNet(2,2,1);
var testInputs = [[0,0], [0,1], [1,0], [1,1]];
var testOutputs = [[1],[0],[0],[1]];
for (var i = 0; i < 1000; i++)
for(var j = 0; j < 4; j++)
net.train(testInputs[j], testOutputs[j]);
function UseNet(a, b) {
net.inputLayer.neurons[0].output = a;
net.inputLayer.neurons[1].output = b;
net.pulse();
return net.outputLayer.neurons[0].output;
}
The problem is that all results that I get is close to 0.5 and pretty random, no matter what arguments I use. For example:
UseNet(0,0) => 0.5107701166677714
UseNet(0,1) => 0.4801498747476413
UseNet(1,0) => 0.5142463167153447
UseNet(1,1) => 0.4881829364416052
What can be wrong with my code?

This network is big enough for the XOR problem and I can't see any obvious mistakes, so I suspect it's getting stuck in a local minimum.
Try going through the training set 10,000 times instead of 1000; this gives it a better chance of breaking out of any minima and converging. You can also increase convergence a lot by upping the number of hidden neurons, tweaking η (the learning rate) or adding momentum. To implement the latter, try using this as your training function:
this.train = function(learningRate) {
var momentum = 0 /* Some value, probably fairly small. */;
self.neurons.forEach(function(neuron) {
neuron.bias.weight += neuron.bias.delta * learningRate;
neuron.bias.delta = 0;
neuron.input.forEach(function(input) {
input.factor.weight += (input.factor.delta * learningRate) + (input.factor.weight * momentum);
input.factor.delta = 0;
})
})
}
I've had good results changing the learning rate to 1.5 (which is pretty high) and momentum to 0.000001 (which is pretty small).
(Incidentally, have you tried running the .NET implementation with a few different seeds? It can take quite a while to converge too!)

This system uses fuzzy logic. As it says in the article don't use integers instead use "close" real numbers as the article suggests -- try
UseNet(0.1,0.1) =>
UseNet(0.1,0.9) =>
UseNet(0.9,0.1) =>
UseNet(0.9,0.9) =>
For the results anything above 0.5 is a 1 and below is 0

Hmmmm
Try instead of:
var testInputs = [[0,0], [0,1], [1,0], [1,1]];
var testOutputs = [[1],[0],[0],[1]];
This:
var testInputs = [[0.05,0.05], [0.05,0.95], [0.95,0.05], [0.95,0.95]];
var testOutputs = [[1],[0],[0],[1]];
or
var testInputs = [[0,0], [0,1], [1,0], [1,1]];
var testOutputs = [[0.95],[0.05],[0.05],[0.95]];

Related

Forward to different users depending on labels - Gmail Apps Script

I am trying to create an Apps Script for Gmail, so that all messages labelled product-related and product-a are forwarded to the producta#gmail.com address, and all messages labelled "product-related" and product-b are forwarded to the productb#gmail.com address.
The script will be launched via a card, so there is no need for more automation.
Here's the code I did:
function testforward1() {
var label = "product-related";
//var interval = 2000;
//var date = new Date();
//var timeFrom = Math.floor(date.valueOf()/1000) - 60 * interval;
var threads = GmailApp.search('label:' + label);
for (var i = 0; i < threads.length; i++) {
if (label == "product-a" && "product-related") {
var recipient = 'producta#gmail.com';
var messages = threads[i].getMessages();
//var attachment = messages[i].getAttachments();
for (var j = 0; j < messages.length; j++) {
var body = messages[j].getBody();
messages[j].forward(recipient, {
htmlBody: body
});
}
}
if (label == "product-b" && "product-related") {
var recipient1 = 'productb#gmail.com';
var messages1 = threads[i].getMessages();
//var attachment1 = messages1[i].getAttachments();
for (var j = 0; j < messages1.length; j++) {
var body1 = messages1[j].getBody();
messages1[j].forward(recipient1, {
htmlBody: body1
});
}
}
}
}
I guess I did something wrong with the variables, but I'm a total beginner with Google Apps Scripts, and I already spent more than 10 hours on this, with no success.
I got no email transferred with this, but the execution gives no error. And I was wondering if the var label = "product-related"; should be replaced with something else?
I will be grateful if you could give me some help on this!
I made it work (I think)! :)
function testforward1() {
var threadsa = GmailApp.search('label: product-related label: product-a');
for (var i = 0; i < threadsa.length; i++) {
var recipient = 'producta#gmail.com';
var messages = threadsa[i].getMessages();
for (var j = 0; j < messages.length; j++) {
var body = messages[j].getBody();
messages[j].forward(recipient,{htmlBody: body});
}
}
var threadsb = GmailApp.search('label: product-related label: product-b');
for (var i = 0; i < threadsb.length; i++) {
var recipient = 'productb#gmail.com';
var messages = threadsb[i].getMessages();
for (var j = 0; j < messages.length; j++) {
var body = messages[j].getBody();
messages[j].forward(recipient,{htmlBody: body});
}
}
}
Now I still have a few more functions to implement, but the basic forwarding function works, and it's the most important.

Uncaught TypeError: Cannot read property 'show' of undefined at draw (sketch.js:49)

I am specifying the function show() inside the function Spot() but still I am getting this error of Uncaught TypeError and its saying its undefined at draw().
This is the Javascript code and I am using p5.js as library.
var cols = 5;
rows = 5;
var grid = new Array(cols);
var w,h;
function Spot(i,j){
this.x = i;
this.y = j;
this.f = 0;
this.g = 0;
this.h = 0;
this.show = function(){
fill(255);
stroke(0);
rect(this.x*w,this.y*h,w-1,h-1);
}
}
function setup(){
createCanvas(400,400);
console.log('A*');
w = width/cols;
h = height/rows;
for(var i = 0; i < cols;i++){
grid[i] = new Array(rows);
}
console.log(grid);
for(var i = 0; i < cols;i++)
{
for(var j = 0; i < rows;i++)
{
grid[i][j] = new Spot(i,j);
}
}
}
function draw(){
background(0);
for(var i = 0; i < cols-1;i++)
{
for(var j = 0; j < rows-1; j++)
{
grid[i][j].show();
}
}
}
body {
padding: 0;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/sketch.js/1.1/sketch.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/p5.min.js"></script>
I am getting this error in chrome console and i am running the html as a web server on my local pc.(localhost:8000)
This is the attached image for the error in google chrome console
I have just started with java script and not able to resolve this error despite extensive searching about it.
It would be helpful if someone knows about it.
Thanks in advance
Have a look in your setup loop.
In the nested loop, you are increasing the i value, instead of the j value.
And your also counting the rows/columns indexes different in the setup and draw.
This might be what you want, just thought I would point it out.
( rows/cols-1 vs cols/rows)
var cols = 5;
var rows = 5;
var grid = new Array(cols);
var w,h;
function Spot(i,j){
this.x = i;
this.y = j;
this.f = 0;
this.g = 0;
this.h = 0;
this.show = function(){
fill(255);
stroke(0);
rect(this.x*w,this.y*h,w-1,h-1);
}
}
function setup(){
createCanvas(400,400);
console.log('A*');
w = width/cols;
h = height/rows;
for(var i = 0; i < cols;i++){
grid[i] = new Array(rows);
}
console.log('grid: ', grid);
for(var i = 0; i < cols-1;i++)
{
for(var j = 0; j < rows-1;j++)
{
grid[i][j] = new Spot(i,j);
}
}
}
function draw(){
background(0);
for(var i = 0; i < cols-1;i++)
{
for(var j = 0; j < rows-1; j++)
{
grid[i][j].show();
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/sketch.js/1.1/sketch.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/p5.min.js"></script>

Can I do For loop on Google Script?

I was trying to put some information of my sheet in a array, to use in a graphic later. But this error keeps showing :(
Error: Syntax error (line 8, archive "Código")
function onOpen() {
var proposta = SpreadsheetApp.getActive().getSheetByName('Proposta de solução');
var ids = proposta.getRange('A10:A26');
var names = proposta.getRange('B10:B26');
var esforcos = proposta.getRange('F10:F26');
var name = [
for (var i = 0; i < 17; i++) {
names.getCell(i, 1).getValue();
}
]
var id = [
for(var j = 0; j < 17; j++) {
ids.getCell(j,1).getValue();
}
]
var esforco = [
for(var k = 0; k < 17; k++) {
esforcos.getCell(k,1).getValue();
}
]
}
This should get the results you want:
function onOpen() {
var proposta = SpreadsheetApp.getActive().getSheetByName('Proposta de solução');
var ids = proposta.getRange('A10:A26');
var names = proposta.getRange('B10:B26');
var esforcos = proposta.getRange('F10:F26');
var name = [];
var id = [];
var esforco = [];
for (var i = 0; i < 17; i++) {
name.push(names.getCell(i, 1).getValue());
id.push(ids.getCell(i, 1).getValue());
esforco.push(esforcos.getCell(i, 1).getValue());
}
}

Make other nodes follow when dragging a node in Cytoscape.js

I'm new to cytoscape.js, I just want to make other nodes follow when dragging one node.
Appreciate your help
Write a listener, and update the other node positions appropriately in your callback:
eles.on()
node.position()
Here is how I did it. Note you have to save off the original positions at the grab event, and then update during the drag event.
function add_drag_listeners()
{
var all = cy.elements("node");
for (j = 0; j < all.length; j++)
{
cynode = all[j];
cynode.on("grab",handle_grab);
cynode.on("drag",handle_drag);
}
}
var grab_x = 0;
var grab_y = 0;
var drag_subgraph = [];
function handle_grab(evt)
{
grab_x = this.position().x ;
grab_y = this.position().y ;
var succ = this.successors();
drag_subgraph = [];
var succstr = "";
for (i = 0; i < succ.length; i++)
{
if (succ[i].isNode())
{
var old_x = succ[i].position().x;
var old_y = succ[i].position().y;
succstr += " " + succ[i].data("id");
drag_subgraph.push({old_x:old_x, old_y:old_y, obj:succ[i]});
}
}
}
function handle_drag(evt)
{
var new_x = this.position().x;
var new_y = this.position().y;
var delta_x = new_x - grab_x;
var delta_y = new_y - grab_y;
for (i = 0; i < drag_subgraph.length; i++)
{
var obj = drag_subgraph[i].obj;
var old_x = drag_subgraph[i].old_x;
var old_y = drag_subgraph[i].old_y;
var new_x = old_x + delta_x;
var new_y = old_y + delta_y;
obj.position({x:new_x, y:new_y});
}
}

Detect coherent neighbors / neighborhood in 2d array

Im having an arbitrary 2d array and each field has an id and a teamid (here illustrated as colors 1).
I want for every neighborhood an array with the ids
in it.
A neighborhood consists of fields with neighbors with the same teamid horizontally and vertically (not diagonally)
e.g.:
This is what i have:
array[0][0] = {id:1,teamId:1}
array[1][0] = {id:2,teamId:1}
array[2][0] = {id:3,teamId:0}
array[3][0] = {id:4,teamId:2}
array[4][0] = {id:5,teamId:2}
array[5][0] = {id:6,teamId:0}
array[0][1] = {id:7,teamId:1}
array[1][1] = {id:8,teamId:1}
array[2][1] = {id:9,teamId:1}
array[3][1] = {id:10,teamId:2}
array[4][1] = {id:11,teamId:2}
array[5][1] = {id:12,teamId:0}
//and so on..
This is what i want:
neighborhood[1] = [1,2,7,8,9,13,14]
neighborhood[2] = [4,5,10,11]
neighborhood[3] = [16,22,23,24,29,30]
neighborhood[4] = [25,31,32,37,38]
neighborhood[5] = [35,41]
I am not searching for the images, but for the array
neighborhood
thanks in advance!
You can use the logic from dots and block games. A block belongs to a player if he has surrounded it with the walls. So, you need for each cell also 4 walls except for the outer cells. To test if a cell is closed you can use 4 class variables:
var Block = function() {
this.isclosed=0;
this.left=0;
this.top=0;
this.right=0;
this.bottom=0;
return this;
}
Block.prototype = {
isClosed : function () {
if (this.isclosed==true) {
return false;
} else if (this.left && this.top && this.right && this.bottom) {
this.isclosed=true;
return true;
} else {
return this.left && this.top && this.right && this.bottom;
}
}
}
You can try my implementations of dots and blocks game # https://dotsgame.codeplex.com/.
The method for solving this issue is refered as Connected Component Labelling
A similar question was asked once before from which i have my solution:
// matrix dimensions
var row_count = 20;
var col_count = 20;
var numOfTeams = 2;
// the input matrix
var m = [];
// the labels, 0 means unlabeled
var label = [];
var source = document.getElementById("source");
for (var i = 0; i < row_count; i++) {
var row = source.insertRow(0);
m[i] = [];
label[i] = [];
for (var j = 0; j < col_count; j++) {
//m[i][j] = Math.round(Math.random());
m[i][j] = getRandomInt(0, numOfTeams + 1);
label[i][j] = 0;
var cell1 = row.insertCell(0);
cell1.innerHTML = m[i][j];
}
}
// direction vectors
var dx = [1, 0, -1, 0];
var dy = [0, 1, 0, -1];
function dfs(x, y, current_label, team) {
if (x < 0 || x == row_count) return; // out of bounds
if (y < 0 || y == col_count) return; // out of bounds
if (label[x][y] || team != m[x][y]) return; // already labeled or not marked with 1 in m
// mark the current cell
label[x][y] = current_label;
// recursively mark the neighbors
for (var direction = 0; direction < 4; ++direction) {
dfs(x + dx[direction], y + dy[direction], current_label, team);
}
}
function find_components() {
var component = 0;
for (var i = 0; i < row_count; ++i) {
for (var j = 0; j < col_count; ++j) {
if (!label[i][j] && m[i][j]) dfs(i, j, ++component, m[i][j]);
}
}
}
find_components();
var result = document.getElementById("result");
for (var i in label) {
var string = ""
var row = result.insertRow(0);
for (var j in label[i]) {
string += label[i][j] + " "
var cell1 = row.insertCell(0);
cell1.innerHTML = label[i][j];
}
}
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
table tr td {
min-width: 14px
}
<div style="float:left">
<table id="source"></table>
</div>
<div style="float:right">
<table id="result"></table>
</div>

Categories

Resources