Backpropagation in an Tensorflow.js Neural Network - javascript

When I have been attempting to implement this function tf.train.stg(learningRate).minimize(loss)into my code in order to conduct back-propagation. I have been getting multiple errors such The f passed in variableGrads(f) must be a function. How would I implement the function above into the code bellow successfully? and Why does this error even occur?
Neural Network:
var X = tf.tensor([[1,2,3], [4,5,6], [7,8,9], [10,11,12]])
var Y = tf.tensor([[0,0,0],[0,0,0], [1,1,1]])
var m = X.shape[0]
var a0 = tf.zeros([1,3])
var y_hat = tf.zeros([1,3])
var parameters = {
"Wax": tf.randomUniform([1,3]),
"Waa": tf.randomUniform([3,3]),
"ba": tf.zeros([1,3]),
"Wya": tf.randomUniform([3,3]),
"by": tf.zeros([1,3])
}
function RNN_cell_Foward(xt, a_prev, parameters){
var Wax = parameters["Wax"]
var Waa = parameters["Waa"]
var ba = parameters["ba"]
var a_next = tf.sigmoid(tf.add(tf.add(tf.matMul(xt, Wax), tf.matMul(a_prev , Waa)),ba))
return a_next
}
function RNN_FowardProp(X, a0, parameters){
var T_x = X.shape[0]
var a_next = a0
var i = 1
var Wya = parameters["Wya"]
var by = parameters["by"]
var l = 1
for(; i <= T_x; i++){
var X_i = X.slice([i-1,0],[1,-1])
for(; l <= X.shape[1]; l++){
var xt = X_i.slice([0,l-1],[1,1])
var a_next = RNN_cell_Foward(xt, a_next, parameters)
}
var y_pred = tf.sigmoid((tf.add(tf.matMul(a_next, Wya), by)))
l = 1
if (i == 1){
var y_pred1 = y_pred
} else if (i == 2) {
var y_pred2 = y_pred
} else if (i == 3) {
var y_pred3 = y_pred
}
}
var y_predx = tf.concat([y_pred1, y_pred2, y_pred3])
return y_predx
}
const learningRate = 0.01;
var optimizer = tf.train.sgd(learningRate);
var model = RNN_FowardProp(X, a0, parameters)
var loss = tf.losses.meanSquaredError(Y, model)
for (let f = 0; f < 10; f++) {
optimizer.minimize(loss)
}
This is a neural network for sentiment classification which has a many to one structure.

The error says it all:
The f passed in variableGrads(f) must be a function
optimizer.minimize is expecting a function as parameter and not a tensor. Since the code is trying to minimize the meanSquaredError, the argument of minimize can be a function that computes the meanSquaredError between the predicted value and the expected one.
const loss = (pred, label) => pred.sub(label).square().mean();
for (let f = 0; f < 10; f++) {
optimizer.minimize(() => tf.losses.meanSquaredError(Y, model))
}
Does it solve the issue, not completely yet ? The error will change for something like:
variableGrads() expects at least one of the input variables to be trainable
What does it mean ? When the optimizer is used, it expects the function passed as argument to contains variables whose values will be updated to minimize the function output.
Here is the changes to be made:
var Y = tf.tensor([[0,0,0],[0,0,0], [1,1,1]]).variable() // a variable instead
// var loss = tf.losses.meanSquaredError(Y, model)
// computed below in the minimize function
const learningRate = 0.01;
var optimizer = tf.train.sgd(learningRate);
var model = RNN_FowardProp(X, a0, parameters);
const loss = (pred, label) => pred.sub(label).square().mean();
for (let f = 0; f < 10; f++) {
optimizer.minimize(() => tf.losses.meanSquaredError(Y, model))
}

Related

If cell is empty, make reference to another cell of other column in the same row

I would like to do this in G column : If Cell 'G8' is Blank Then (=K8) for example. My difficulty is to make reference of same row in K of empty cell in G.
I've tryed to adapt this script but I get a shift at some point and I don't know why.
function updatewithformula() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Sheet 1');
var range = sheet.getDataRange()
var source = sheet.getRange('G1:G13').getDisplayValues()
var index = []
for (var i = 1; i<source.length; i++){
if (source[i][0] == ""){
index.push(i+1)
}
}
index.push(range.getLastRow()+1)
Logger.log(index)
for(var i = 0;i<index.length-1;i++){
var rangetomodify = sheet.getRange(index[i],7,1,1)
var l = index[i+1]-index[i]-1
rangetomodify.setFormulaR1C1("=R["+l+"]C[4]")
}
}
As another approach, how about the following modification?
Modification points:
About I've tryed to adapt this script but I get a shift at some point and I don't know why., in your script, "=R[" + l + "]C[4]" is used with var l = index[i + 1] - index[i] - 1. In this case, when l is not 0, the other row is used. I thought that this might be the reason for your issue. In your script, I think that it is not required to use var l = index[i + 1] - index[i] - 1. When your script is simply modified, it becomes as follows.
function updatewithformula() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Sheet 1');
var range = sheet.getDataRange();
var source = sheet.getRange('G1:G13').getDisplayValues();
var index = [];
for (var i = 1; i < source.length; i++) {
if (source[i][0] == "") {
index.push(i + 1);
}
}
index.push(range.getLastRow() + 1);
for (var i = 0; i < index.length - 1; i++) {
var rangetomodify = sheet.getRange(index[i], 7, 1, 1);
rangetomodify.setFormulaR1C1("=R[0]C[4]");
}
}
But, in this case, getRange and setFormulaR1C1 are used in a loop. In this case, the process cost becomes high.
When your script is modified by reducing the process cost, how about the following modification?
Modified script:
function updatewithformula() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Sheet 1');
var source = sheet.getRange('G2:G13').getDisplayValues();
var ranges = source.reduce((ar, [g], i) => {
if (!g) ar.push(`G${i + 2}`);
return ar;
}, []);
sheet.getRangeList(ranges).setFormulaR1C1("=R[0]C[4]");
}
By RangeList, the process cost can be reduced a little.
References:
reduce()
getRangeList(a1Notations)
setFormulaR1C1(formula) of Class RangeList
There are better, easy and short methods to do it, I have used offset here.
The below works for me
function updatewithformula(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Sheet 1');
var range = sheet.getDataRange()
var source = sheet.getRange('G1:G13').getValues();
Logger.log(source);
var index = [];
for (var i in source){
if(source[i][0] == ""){
var j = +i;
index.push(("G"+(j+1)));
}
}
for (var i in index){
var TEMP = sheet.getRange(index[i]);
var TEMP1 = TEMP.offset(0,4).getA1Notation();
const formula = `=${TEMP1}`;
TEMP.setFormula(formula);
}
}
References - OFFSET

Passed value to function becomes undefined [duplicate]

This question already has answers here:
Get an error when I call object's properties in Array
(4 answers)
Closed 3 years ago.
I'm trying to write a script to disable layers in photoshop. So far the first part (first function) works, and it just grabs all the red layers and puts them in an array. Then I call the second function which takes one by one name from the array and passes it to the disabler (showBounds function). However, I'm looking at the input the showBounds receives ("name") and suddenly it stars saying it's getting "undefined". How can this be? what is happening?
var doc = app.activeDocument;
var theLayers = [];
function fillLayerArray(){
// get number of layers;
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var applicationDesc = executeActionGet(ref);
var theNumber = applicationDesc.getInteger(stringIDToTypeID("numberOfLayers"));
// process the layers;
//var theOthers = new Array;
for (var m = 0; m <= theNumber; m++) {
var ref = new ActionReference();
ref.putIndex( charIDToTypeID( "Lyr " ), m);
var layerDesc = executeActionGet(ref);
var isBackground = layerDesc.getBoolean(stringIDToTypeID("background"));
var layerSet = typeIDToStringID(layerDesc.getEnumerationValue(stringIDToTypeID("layerSection")));
var theName = layerDesc.getString(stringIDToTypeID('name'));
var theColor = layerDesc.getEnumerationValue(stringIDToTypeID("color"));
globColor = theColor;
if (typeIDToStringID(theColor) == "red" && layerSet != "layerSectionEnd" ) {
theLayers.push(theName);
}
};
hideLayers(theNumber);
//showBounds(doc.layerSets);
}
function hideLayers(theNumber){
for (var i = 0; i <= theLayers.length; i++) {
//app.activeDocument.activeLayer.visible = false;
currentLayerName = theLayers[i];
//alert(currentLayerName)
alert(currentLayerName);
showBounds(doc.layerSets, currentLayerName);
}
}
function showBounds(layerNode, name) {
for (var i=0; i<layerNode.length; i++) {
showBounds(layerNode[i].layerSets);
for(var layerIndex=0; layerIndex < layerNode[i].artLayers.length; layerIndex++) {
var layer=layerNode[i].artLayers[layerIndex];
alert(layer.name + name)
try{
if (layer.name == name) {
layer.visible = 0;
}
}catch(e){
}
}
}
}
fillLayerArray();
You have
i <= theLayers.length
Should be
i < theLayers.length
In hideLayers.
(Also in m <= theNumber .... remember arrays are indexed starting from zero in JS)

Getting 6.33 from an equation in Javascript when it should output 8.99

I'm doing some simple math in Javascript, but my equation's result is drastically different than what it should be. The math is:
3.05+(((0.32*0)+3.28)+(1+(0.19*0))*(2.66*1^2))*1;
When I did it out by hand, and then used Wolfram Alpha (https://www.wolframalpha.com/) I get the correct result of 8.99. However, when I use the equation in Javascript I mysteriously get 6.33
The actual equation looks like
VO2move = VO2rest+(((C1*g2)+VO2walkmin)+(1+(C2*g2))*(C3*s2^2))*t2;
but I removed all the variables in an attempt to debug (I thought it might be some error where I needed parseInt)
Here are the whole functions for reference
function calc(){
var temp = 0;
var total = 0;
for(i = 0; i<sArr.length; i++){
total = total + calc2(i);
}
var o = document.getElementById("output");
o.value = total;
}
function calc2(i){
var s = document.getElementById("s"+i);
var g = document.getElementById("g"+i);
var t = document.getElementById("t"+i);
var VO2walkmin = 3.28;
var VO2rest = 3.05;
var C1 = 0.32;
var C2 = 0.19;
var C3 = 2.66;
var Cdecline = 0.73;
var s2 = s.value;
var g2 = g.value;
var t2 = t.value;
var negGrade = g.value;
if(g2 < 0){g2 = 0};
//VO2move = ((C1 * g2)+VO2walkmin)+((1+(C2*g2))*(C3*s2^2)); //ORIGINAL TRANSCRIPTION
//VO2move = VO2rest+(((C1*g2)+VO2walkmin)+(1+(C2*g2))*(C3*s2^2))*t2; // TRANSLATED FROM COPY PASTE
VO2move = 3.05+(((0.32*0)+3.28)+(1+(0.19*0))*(2.66*1^2))*1; // COPY - PASTED FROM EXCEL
return VO2move;
}
Even naked numbers I still get the output of 6.33. I'm totally puzzled, and any help is appreciated.
You need to take the power (exponentiation) operator ** instead of the bitwise XOR operator ^.
console.log(3.05+(((0.32*0)+3.28)+(1+(0.19*0))*(2.66*1**2))*1);

Copy array --> stack or heap overflow?

I have an array named globalArrayAllTrades as you see below. I simply like to INVERT the date in a new copy of the array. So I loop through, create a new object and add it to the new array - simple.
Then function does exactly as expected. BUT if the array contains too many objects the code fails with a "FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - process out of memory".
My laptop has 8 GB of memory...When the NODEJS process crashes it uses about 1.5 GB and about 70% of of totally amount of available memory is used.
I do run the NODEJS app with the parameter: --max_old_space_size=5000 which normally fixes every thing. But not this one and i have tried MANY different ways to code the same function - BUT each and every time - it fails...unless the original array is smaller.
How can I fix this issue?
function invertTrades(){
var original = globalArrayAllTrades.slice();
globalArrayAllTrades.length = 0;
globalListAllTrades.length = 0;
for(var i = 0; i < original.length; i++){
var objS = original[i];
var objE = original[original.length-1-i];
var objInv = new TradePoint(objS.number, objS.matchdate, objE.price, objE.size, objE.issell);
globalArrayAllTrades.push(objInv);
globalListAllTrades[objInv.matchdate] = objInv;
}
}
You can save some memory by making original just contain the properties you need to invert, not the whole TradePoint object. Then you don't need to construct new TradePoint objects, you can modify them in place.
var original = globalArrayAllTrades.map(function(trade) {
return {
trade.price,
trade.size,
trade.issell
};
}).reverse();
globalArrayAllTrades.forEach(function(trade, i) {
trade.price = original[i].price;
trade.size = original[i].size;
trade.issell = original[i].issell;
});
And since all the objects were modified in place, there's no need to update globalListAllTrades.
Another way is to swap the price, size, and issell properties in place between the pairs of elements:
var midpoint = Math.floor(globalArrayAllTrade.length/2);
for (var i = 0; i < midpoint; i++) {
var objS = globalArrayAllTrades[i];
var objE = globalArrayAllTrades[globalArrayAllTrades.length-1-i];
var temp = objS.price;
objS.price = objE.price;
objE.price = temp;
temp = objS.size;
objS.size = objE.size;
objE.size = temp;
temp = objS.issell;
objS.issell = objE.issell;
objE.issell = temp;
}
Have you considered just doing this?
// Copy array and then reverse it
var newArray = [].concat(original).reverse();
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse
I would suggest avoiding to copy that array:
function getInverse(i) {
var objS = globalArrayAllTrades[i];
var objE = globalArrayAllTrades[globalArrayAllTrades.length-1-i];
var objInv = new TradePoint(objS.number, objS.matchdate, objE.price, objE.size, objE.issell);
globalListAllTrades[objInv.matchdate] = objInv;
return objInv;
}
function invertTrades(){
globalListAllTrades.length = 0;
for (var i = 0, l = Math.floor(globalArrayAllTrades.length/2); i < l; i++) {
var j = globalArrayAllTrades.length-1-i;
var a = getInverse(i);
var b = getInverse(j);
globalArrayAllTrades[i] = a;
globalArrayAllTrades[j] = b;
}
}

Console.log gives correct output but when accessing set value it gives wrong output

Called Function:
this.findVerticalPossibleScoring = function(){
var possibilitySet = [];
for (var j = 0; j < 9;j++ ) {
for (var i = 0; i < 7; ){
var tempTile = this._tiles[i][j];
if(this.gameTilesValue[i][j]!=-1){
var tileTagValue = this.gameTilesValue[i][j];
if(this.gameTilesValue[i+1][j]==tileTagValue && this.gameTilesValue[i+2][j]==tileTagValue){
setElement = [];
do{
var tempPoint = this.makeArray(i,j);
setElement.push(tempPoint);
console.log(" verical i:"+i+" j:"+j);
i=i+1;
}while(i<9&&this.gameTilesValue[i][j]==tileTagValue);
possibilitySet.push(setElement);
continue;
}
}
i = i+1;
}
}
return possibilitySet;
};
this.makeArray = function (a,b){
console.log("element i:"+a+" j:"+b);
var arrayTemp = [];
arrayTemp.push(a);
arrayTemp.push(b);
return arrayTemp;
};
Calling function part:
if(scoringPossible == true){
//blast the tiles and add new tiles;
var verticalPossibleScoring = this.findVerticalPossibleScoring();
toBeDeletedTiles = [];
for(var i=0;i<verticalPossibleScoring.length;i++){
var tempSet = verticalPossibleScoring[i];
for(var j = 0;j<tempSet.length;j++){
var tempSetEntry = tempSet[i];
console.log("TILE i:"+tempSetEntry[0]+" j:"+tempSetEntry[1]);
}
}
}
I have added called function as well as calling function if loop as calling function is too big. I know this is infamous javascript loop issue. I am using gc-devkit game engine which is new and I new to it. I had solved the same issue for UIImage in it by creating custom class, but here I don't require custom array for it. Can any one guide me through this issue. Thanks in advance.
You use j as your loop variable when iterating over tempSet but then use i when getting elements from tempSet. Maybe just change
var tempSetEntry = tempSet[i];
to
var tempSetEntry = tempSet[j];

Categories