Tensorflow.js adding simpleRNN to model() - recurrent-neural-network

I want to build a semi-complex neural network, so I'm not using tf.seqential().
const model = tf.model( {
inputs: [tickInput,boardInput],
outputs:moveChoices,
} );
which has to be created after the outputs get defined as I understand things...
None of the tfjs-examples use a simpleRNN() in a model.
Layers get combined with .apply( inputLayer ); far as I can tell, which changes them to 'built=true' but my simple RNN doesn't have a .shape() so I can't
(node:8616) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'length' of undefined
at Dense.build (m:\javascript\tensorflow\node_modules\#tensorflow\tfjs-layers\src\layers\core.ts:277:48)
at m:\javascript\tensorflow\node_modules\#tensorflow\tfjs-layers\src\engine\topology.ts:991:14
at Object.nameScope (m:\javascript\tensorflow\node_modules\#tensorflow\tfjs-layers\src\common.ts:43:20)
at Dense.Layer.apply (m:\javascript\tensorflow\node_modules\#tensorflow\tfjs-layers\src\engine\topology.ts:977:12)
at test3 (file:///m:/javascript/tensorflow/test2.mjs:105:14)
at file:///m:/javascript/tensorflow/test2.mjs:128:1
This is my code...
const batchSize= 1;
const boardInput = tf.layers.input({batchShape:[batchSize, 160, 40*7]});
const tickMask = tf.input( {
name : "tick",
batchShape : [batchSize, 160, 1],
dtype : 'bool',
})
// I expect other layers on input/output before concatenate()
// but, the conv1d() also wouldn't have a shape.
var concatLayer = tf.layers.concatenate( )
var merge = concatLayer.apply([tickMask, boardInput]);
console.log(JSON.stringify(merge.shape));
const simpleRNNConfig = {
name : 'theBrain',
units : 32,
activation : "relu",
useBias : true,
kernelInializer : 'randomNomral',
recurrentInitializer : 'randomNormal',
biasInitializer : 'randomNormal',
dropout : 0.10,
recurrentDropout : 0,
returnSequences : false,
returnState : false, // or true
goBackwards : false,
stateful : false,
}
var theBrain = tf.layers.simpleRNN( simpleRNNConfig );
theBrain.apply( merge );
console.log( JSON.stringify( theBrain.shape ));
// THE ABOVE CONSOLE.LOG is 'UNDEFINED'
var moveChoices = tf.layers.dense( { units : 40, activation: "softmax" } )
// and then the following line has the above exception
// above 'no .length' because theBrain doesn't have a
// .shape to make the shapeList....
moveChoices.apply( theBrain );

The shape is not on the layer, but on the object return by apply
var theBrain = tf.layers.simpleRNN( simpleRNNConfig );
output = theBrain.apply( merge );
console.log( JSON.stringify( output.shape ));
Here is a simple model doing what you want:
const input1 = tf.input({shape: [2, 2]});
const input2 = tf.input({shape: [2, 3]});
const concatLayer = tf.layers.concatenate();
const concat = concatLayer.apply([input1, input2]);
const rnn = tf.layers.simpleRNN({units: 8, returnSequences: true});
const output = rnn.apply(concat);
console.log(JSON.stringify(output.shape));
<html>
<head>
<!-- Load TensorFlow.js -->
<script src="https://cdn.jsdelivr.net/npm/#tensorflow/tfjs#latest"> </script>
</head>
<body>
</body>
</html>

Related

Syntax error : unexpected token: identifier

I wish to display a mail icon with a counter
With my gnome-shell extension I get an error:
I don't know what the error means.
Keep in mind I do not have much knowledge about gnome..
Syntax error : unexpected token : identifier
const INDICATOR_ICON = 'mail-unread-symbolic';
const PanelMenu = imports.ui.panelMenu;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
class Extension extends PanelMenu.Button {
_init() {
super._init(0.0, null, false);
this._icon = new St.Icon({
icon_name: INDICATOR_ICON,
style_class: 'system-status-icon'});
this._iconBin = new St.Bin({ child: this._icon, x_fill: false, y_fill: false });
this._counterLabel = new St.Label({ text: "0",
x_align: Clutter.ActorAlign.CENTER,
x_expand: true,
y_align: Clutter.ActorAlign.CENTER,
y_expand: true });
this._counterBin = new St.Bin({ style_class: 'mailnag-counter',
child: this._counterLabel,
layout_manager: new Clutter.BinLayout() });
this.add_actor(this._iconBin);
this.add_actor(this._counterBin);
}
}
function enable() {
return New Extension();
}
function disable() {
}

Logic in if else statement to divide path if path shape is two or more '0'

Hi all trying to write some logic in paper.js (also using opentype.js for font data) so that when a number contains two or more consecutive zeros' the zero path is divided so that it is solid.
Things i know a zero path, using my particular font, is made up of an outer path with 19 segments and an inner path made up of 18 segments
So I thought would try to iterate over all paths check if a path has 19 segments and the next path has 18 segments and call path.unite() which kind of works. But I only want it to do this with consecutive '0' eg '100', '1000' but not 10.
So i was trying to do an if else statment where if-else (the current path has 18 segments and the next path is less than 18 segments) if true then do nothin or call path.divide()?
Im sure there is a way better way of doing this. Can you help please.
link to codepen
paper.install(window);
window.onload = () => {
paper.setup("canvas");
opentype.load(
"https://assets.codepen.io/1070/pphatton-ultralight-webfont.woff",
(err, font) => {
if (err) {
console.log(err);
} else {
const fontPath = font.getPath("10k", 0, 100, 100).toSVG();
const count = new paper.CompoundPath(fontPath);
count.unite();
count.children.forEach((child, i) => {
if (
child.segments.length === 19 &&
count.children[i + 1].segments.length === 18
) {
const eye = child.unite();
eye.selected = true;
} else if(
count.children[i + 1].segments.length === 18
&& child.segments.length < 18
) {
console.log('hello');
// const target = child.divide();
count.children[i].fillColor = 'black'
} else{
}
});
// const flatCount = count.children[1].unite()
// console.log(count.children[2].segments.length)
// const flatCountTwo = count.children[5].unite()
// flatCount.translate(5,0)
count.fillColor = "red";
project.activeLayer.fitBounds(view.bounds.scale(0.6));
}
}
);
};
I think that rather than using Font.getPath to retrieve a single svg path for the whole text, you should use Font.getPaths to retrieve an svg path for each character.
This way you can quite simply do your analysis on the input string directly and handle the consecutive 0 differently than other characters.
Edit
In order to detect the consecutive zeros, yes, you could use a regex or loop over the characters, like I did in the following example.
Here's a fiddle showcasing a possible solution.
const handleZero = (path) => {
path.children = path.children.slice(0, 1);
};
const getConsecutiveZerosIndices = (content) => {
const zero = '0';
return [...content]
.map((char, i) => ({ char, i }))
.filter(({ char, i }) => {
const previousCharacter = content?.[i - 1];
const nextCharacter = content?.[i + 1];
return char === zero && (previousCharacter === zero || nextCharacter === zero);
})
.map(({ i }) => i);
};
const drawText = (content, font) => {
const fontPaths = font.getPaths(content, 0, 100, 100);
const consecutiveZerosIndices = getConsecutiveZerosIndices(content);
const paths = fontPaths.map((fontPath, i) => {
const path = new paper.CompoundPath(fontPath.toSVG());
if (consecutiveZerosIndices.includes(i)) {
handleZero(path);
}
return path;
});
const group = new paper.Group(paths);
group.fillColor = 'red';
return group;
};
const draw = (font) => {
const path1 = drawText('10k', font);
const path2 = drawText('100k', font);
const path3 = drawText('1000k', font);
path2.position = path1.position.add(0, path1.bounds.height * 1.2);
path3.position = path2.position.add(0, path2.bounds.height * 1.2);
paper.project.activeLayer.fitBounds(paper.view.bounds.scale(0.6));
};
paper.setup('canvas');
opentype.load(
'https://assets.codepen.io/1070/pphatton-ultralight-webfont.woff',
(err, font) => draw(font)
);

Structure of object fetched to firebase from GAS Google sheet

I have script tied to Google sheet that collects data from 3 columns (date, userID, value) on the sheet and pass them to object that is then fetched to Firebase DB.
The script correctly push the object into Firebase but I have troubles to achieve structure of data object that I need (so the nodes are correctly structured in Firebase). In the “date” column in the sheet I have date under which I want to group userID:value pair but when I iterate over rows in the sheet it only stores last userID:value pair with given date and not all.
My code:
function writeValues() {
// Database reference
const databaseURL = "https://sampledatabaseURL.firebaseio.com/"
const token = ScriptApp.getOAuthToken();
// Get spreadsheet, range of data and all values within
var spreadSheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spreadSheet.getSheetByName("test");
const range = sheet.getDataRange();
const allValues = range.getValues();
// Get indexes for headers in columns
const headers = {};
allValues[0].forEach(function (value, index) {
headers[value] = index
});
const dbData = {};
allValues.forEach(function (row, index) {
if (index === 0) { return } // skip header row
dbData[row[headers.date]] = {
[row[headers.userID]] : row[headers.value]
}
})
const url = databaseURL + "/test.json?access_token=" + encodeURIComponent(token)
const response = UrlFetchApp.fetch(url, {
method: 'put',
payload: JSON.stringify(dbData)
})
Logger.log(response.getResponseCode());
}
Output JSON file it produces and that’s fetched to Firebase:
{
"20180118" : {"userID2" : "value2"},
"20200705" : {"userID4" : "value4"},
"20210324" : {"userID6" : "value6"}
}
Desired output structure:
{
"20180118" : {"userID1" : "value1", "userID2" : "value2"},
"20200705" : {"userID3" : "value3", "userID4" : "value4"},
"20210324" : {"userID5" : "value5", "userID6" : "value6"}
}
I believe your goal as follows.
You want to achieve the following situation.
From: This image is from your question.
To: You want to retrieve the following output as the value of dbData.
{
"20180118" : {"userID1" : "value1", "userID2" : "value2"},
"20200705" : {"userID3" : "value3", "userID4" : "value4"},
"20210324" : {"userID5" : "value5", "userID6" : "value6"}
}
In this case, how about the following modidfication? When your script is modified, it becomes as follows.
From:
const allValues = range.getValues();
// Get indexes for headers in columns
const headers = {};
allValues[0].forEach(function (value, index) {
headers[value] = index
});
const dbData = {};
allValues.forEach(function (row, index) {
if (index === 0) { return } // skip header row
dbData[row[headers.date]] = {
[row[headers.userID]] : row[headers.value]
}
})
To:
const [, ...values] = range.getValues();
const dbData = values.reduce((o, [a,b,c]) => {
if (!o[a]) o[a] = {};
o[a][b] = c;
return o;
}, {});
console.log(dbData)
When above modified script is run for your sample Spreadsheet, the value of dbData is the output you expect.
Reference:
reduce()

Typescript transformer, `node.parent` is undefined

I'm currently using a typescript transformer api, and I found that the node.parent is undefined.
My code is:
const transformerFactory: ts.TransformerFactory<ts.Node> = (
context: ts.TransformationContext
) => {
return (rootNode) => {
function visit(node: ts.Node): ts.Node {
node = ts.visitEachChild(node, visit, context);
// HERE node.parent IS UNDEFINED !
return filterFn(node, context);
}
return ts.visitNode(rootNode, visit);
};
};
const transformationResult = ts.transform(
sourceFile, [transformerFactory]
);
How can I find the parent of the node?
You can parse specifying to set the parent nodes:
const sourceFile = ts.createSourceFile(
"fileName.ts",
"class Test {}",
ts.ScriptTarget.Latest,
/* setParentNodes */ true, // specify this as true
);
Or do some operation on the node to get it to set its parent nodes (ex. type check the program... IIRC during binding it ensures the parent nodes are set).
Update based on comment
If you are creating these from a program, then you can do the following:
const options: ts.CompilerOptions = { allowJs: true };
const compilerHost = ts.createCompilerHost(options, /* setParentNodes */ true);
const program = ts.createProgram([this.filePath], options, compilerHost);

3D force directed graph replacing nodes with images

Ref: 3d Force Directed Graph - Replacing Nodes with Images
How might I add the images to the following excellent code in the same manner as the Stack Overflow answer above?
https://github.com/jexp/neo4j-3d-force-graph/blob/master/particles.html
Assuming that each node may have a property of n.image=/images/imagexxx.jpg how might I apply this image from a local filesystem to its respective node ?
If the property isn't present then render the node as the normal sphere.
Here is my sample code which just renders all nodes as small_image.jpg :
const elem = document.getElementById('3d-graph');
const driver = neo4j.v1.driver("bolt://192.168.1.251", neo4j.v1.auth.basic("neo4j", "test"));
const session = driver.session();
const start = new Date()
session
.run('MATCH (n)-[r]->(m) RETURN { id: id(n), label:head(labels(n)), community:n.name, caption:n.name, size:log(n.links_from+n.links_to)} as source, { id: id(m), label:head(labels(m)), community:m.name, caption:m.name, size:log(m.links_from+m.links_to)} as target, {weight:r.weight, type:type(r), community:case when n.community < m.community then n.community else m.community end} as rel LIMIT $limit', {limit: 5000})
.then(function (result) {
const nodes = {}
const links = result.records.map(r => {
var source = r.get('source');source.id = source.id.toNumber();
nodes[source.id] = source;
var target = r.get('target');target.id = target.id.toNumber();
nodes[target.id] = target;
var rel = r.get('rel'); if (rel.weight) { rel.weight = rel.weight.toNumber(); }
return Object.assign({source:source.id,target:target.id}, rel);
});
session.close();
console.log(links.length+" links loaded in "+(new Date()-start)+" ms.")
const gData = { nodes: Object.values(nodes), links: links}
const Graph = ForceGraph3D()(elem)
.graphData(gData)
.nodeAutoColorBy('community')
.nodeVal('size')
.linkAutoColorBy('community')
.linkWidth(0)
.linkDirectionalParticles('weight')
.linkDirectionalParticleSpeed(0.001)
.nodeLabel(node => `${node.label}: ${node.caption}`)
.onNodeHover(node => elem.style.cursor = node ? 'pointer' : null)
.nodeThreeObject(node => {
var map = new THREE.TextureLoader().load( "small_image.jpg" );
map.minFilter = THREE.LinearFilter;
var material = new THREE.SpriteMaterial( { map: map } );
var sprite = new THREE.Sprite( material );
sprite.scale.set(32,32,1);
return sprite;
});
// Spread nodes a little wider
Graph.d3Force('charge').strength(-150);
})
.catch(function (error) {
console.log(error);
});
const elem = document.getElementById('3d-graph');
const driver = neo4j.v1.driver("bolt://localhost", neo4j.v1.auth.basic("neo4j", "test"));
const session = driver.session();
const start = new Date()
session
.run('MATCH (n:Entity)-[r]->(m:Entity) WHERE n.name="new york" RETURN { id: id(n), label:head(labels(n)), community:n.name, caption:n.name, image:n.image, size:log(n.links_from+n.links_to)} as source, { id: id(m), label:head(labels(m)), community:m.name, caption:m.name, image:m.image, size:log(m.links_from+m.links_to)} as target, {weight:r.weight, type:type(r), community:case when n.community < m.community then n.community else m.community end, image:case when n.image < m.image then n.image else m.image end} as rel LIMIT $limit', {limit: 5000})
.then(function (result) {
const nodes = {}
const links = result.records.map(r => {
var source = r.get('source');source.id = source.id.toNumber();
nodes[source.id] = source;
var target = r.get('target');target.id = target.id.toNumber();
nodes[target.id] = target;
var rel = r.get('rel'); if (rel.weight) { rel.weight = rel.weight.toNumber(); }
return Object.assign({source:source.id,target:target.id}, rel);
});
session.close();
console.log(links.length+" links loaded in "+(new Date()-start)+" ms.")
const gData = { nodes: Object.values(nodes), links: links}
const Graph = ForceGraph3D()(elem)
.graphData(gData)
.nodeAutoColorBy('community')
.nodeVal('size')
.linkAutoColorBy('community')
.linkWidth(0)
.linkDirectionalParticles('weight')
.linkDirectionalParticleSpeed(0.001)
.nodeLabel(node => `${node.label}: ${node.caption}`)
.onNodeHover(node => elem.style.cursor = node ? 'pointer' : null)
.nodeThreeObject(node => {
var map = new THREE.TextureLoader().load((node.image != null ? node.image : ""));
map.minFilter = THREE.LinearFilter;
var material = new THREE.SpriteMaterial( { map: map } );
var sprite = new THREE.Sprite( material );
sprite.scale.set(32,32,1);
if (node.image){
return sprite; }
else return false;
});
// Spread nodes a little wider
Graph.d3Force('charge').strength(-150);
})
.catch(function (error) {
console.log(error);
});

Resources