Tensorflow.Js Problem: "Error: Number of coordinates in get() must match the rank of the tensor" - tensorflow.js

What is this ?
Im learning tensorflow.js with youtube video "6.3: TensorFlow.js: Variables & Operations - Intelligence and Learning".
Everything works well until i try this get().
const getRandomInt = (max) => {
return Math.floor(Math.random() * Math.floor(max));
};
const values = [];
for (let i = 0; i< 30; i++) {
values[i] = getRandomInt(10);
}
const shape = [2, 5, 3];
const matriisi = tf.tensor3d(values, shape, 'int32');
console.log(matriisi.get(3));
And web console says:
"Error: Number of coordinates in get() must match the rank of the tensor"

The number of parameters to the get function should match the rank of your tensor.
Your tensor is or rank 3 which means that get should have 3 parameters. The third element in your tensor has the following coordinates: [0, 1, 0]. You rather need to use matriisi.get(0, 1, 0).
Another way to get an element by its index is to use dataSync() or data() in order to get an array-like element that you can access by index.
const a = tf.randomNormal([2, 5, 3], undefined, undefined, undefined, 3);
const indexToCoords = (index, shape) => {
const pseudoShape = shape.map((a, b, c) => c.slice(b + 1).reduce((a, b) => a * b, 1));
let coords = [];
let ind = index;
for (let i = 0; i < shape.length; i++) {
coords.push(Math.floor(ind / pseudoShape[i]));
ind = ind % pseudoShape[i];
}
return coords
}
const coords = indexToCoords(3, [2, 5, 3]);
// get the element of index 3
console.log(a.get(...coords));
// only dataSync will do the trick
console.log(a.dataSync()[3])
<html>
<head>
<!-- Load TensorFlow.js -->
<script src="https://cdn.jsdelivr.net/npm/#tensorflow/tfjs#0.13.0"> </script>
</head>
<body>
</body>
</html>

Related

How to create data structure that supports carousel behavior?

It's a simple Vue.js test application and the code looks as following:
<template>
<div>
<button #click="onPrevious">Previous</button>
<button #click="onNext">Next</button>
<br><br>
<div v-for="(a, index) in chunkedArr()" :key="index">
<div v-for="(i, index) in a" :key="index">{{ i }}</div>
-
</div>
</div>
</template>
<script>
export default {
data() {
return {
input: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
newInput: [],
currentIndex: 0
}
},
mounted() {
const temp = []
for (let i = 0; i < this.input.length; i += 3) {
let chunk = this.input.slice(i, i + 3)
if (chunk.length === 1) {
chunk = chunk.concat(this.input.slice(0, 2))
}
if (chunk.length === 2) {
chunk = chunk.concat(this.input.slice(0, 1))
}
temp.push(chunk)
}
this.newInput = temp.flat()
},
methods: {
chunkedArr() {
if (this.newInput.length === 0) {
return
}
const output = []
for (let i = this.currentIndex; i < this.newInput.length; i += 3) {
let chunk = this.newInput.slice(i, i + 3)
output.push(chunk)
}
console.log(output)
return output
},
onNext () {
this.chunkedArr()
},
onPrevious () {
// TODO
}
},
}
</script>
We could simulate carousel with Next and Previous buttons. Suppose we have some array of elements that should be displayed in carousel.
But, in this carousel we should display 3 elements at once. It means 3 elements should be visible only on each click Next/Previous. For example, if we have an array of elements: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, the initial state is to display: 1, 2, 3. On first click on Next, carousel should display 4, 5, 6 and so on. There are 3 cases at the end of array. The array can have 1, 2 or 3 elements at the end. If it has 3 elements, everything is easy. But if it has 1 or 2 elements, we need to add 2 or 1 elements respectively. In case of having 1 element at the end we need to add first 2 elements of array in order to display 3 elements. In case of having 2 elements at the end (our test case) we need to add first element only in order to display 3 elements. The rotating should go further based on previously described scenario.
Please, take a look at the screenshot attached:
In real case I need that data structure for BootstrapVue's Carousel.
UPDATE:
There are 4 subarrays in output array. Please, take a look at the screenshot below:
UPDATE:
const example = [1, 2, 3, 4, 5];
const subArrayIterator = subArrayGenerator(example);
console.log('init: ' + subArrayIterator.next().value); // init
const prevBtn = document.getElementById('prev');
const nextBtn = document.getElementById('next');
prevBtn.onclick = () => {
console.log(subArrayIterator.next(false).value);
}
nextBtn.onclick = () => {
console.log(subArrayIterator.next().value);
}
function* subArrayGenerator(inputArray, subArrayLength=3) {
let prev = false;
for (let i = 0; i < inputArray.length;) {
if (prev) {
let diff = subArrayLength*2;
if (diff > inputArray.length) {
diff = diff % inputArray.length;
}
diff = i - diff;
i = diff < 0 ? inputArray.length + diff : diff;
}
const subArray = [];
for (let j = 0; j < subArrayLength; j++) {
subArray.push(inputArray[i]);
i = i < inputArray.length - 1 ? i + 1 : 0;
}
prev = (yield subArray) === false;
}
}
<button type="button" id="prev">prev</button>
<button type="button" id="next">next</button>
Another approach:
Rotate the array by appending a splice of input from 0 to currentIndex:
input.push(...input.splice(0, currentIndex))
Pad the array to a max length of 12 by appending a slice of input from 0 to the pad length:
while (12 - input.length > 0) {
input.push(...input.slice(0, 12 - input.length))
}
Split the array into slices of 3 by Array(size).fill().map():
const output = Array(Math.ceil(input.length / 3)).fill().map((_, i) => input.slice(i * 3, i * 3 + 3))
demo

Find and return the element which occurs most frequently in an array

I need to implement a function called findMode to find the mode of an array. Assuming the array contains integer numbers only. When the function is called and the array is empty it returns 0. When the function is called and the array isn't empty it should return the element which occurs most frequently in an array. If an array contains multiple modes it should return the smallest value of the modes. I need to create an intermediate array, another array of numbers to count the number of times each value occurs. This array should use the index numbers of the array to track of how many times a number in b has been counted.
below is what I have so far:
import { print } from "....";
export let main = async () => {
let input = [2, 1, 1, 2, 1, 0]
print(mode(input))
};
export let findMode = (b: number[]): number => {
let newArr: number[] = []; /** this is the new number array created to store count, this is the intermediate array */
if (b.length === 0) {
return 0;
for (let i = 0; i < b.length; i++) {
};
main();
Here are the expected/actual results:
If the array is b[2,1,1,2,1,0] then 1 should be returned, and if we printed the array we created to store the count it should print newArr[1,3,2] because element 0 has 1 occurrence, element 1 has 3 occurrences, and element 2 has 2 occurrences. The idea is to go from 0 as an element in our input array to it 0 being an index in our intermediate array. so lastly we see which is our max occurrences ( or max element in our intermediate array) which is 3 at index 1, so the mode is 1.
If the array is b[0,0,0,1,1,2,1,1] then 1 should be returned. If the array is b[4,4,7,4,0,7] then 4 should be returned. If the array is b[-4,-4,-1,3,5] then -4 should be returned. If the array is b[1,1,2,3,2] then 1 should be returned since its the smallest of the modes. If the array is b[10,10,10,20,20,30] then 10 should be returned.
Would something like this work?
export let findMode = (b: number[]): number => {
// we'll store the values in b and the number of times they occur here
const counts: Array<{ value: number, count: number }> = [];
// it helps to check that b is defined before you check length, this avoids ReferenceErrors
if (!b || !b.length) {
return 0;
}
for (let i = 0; i < b.length; i++) {
const val = b[i];
const count = counts.find(count => count.value === val);
if (count) {
count.count++;
} else {
counts.push({ value: val, count: 1 });
}
}
// get the mode by sorting counts descending and grabbing the most occuring
const mode = counts.sort((c1, c2) => c2.count - c1.count)[0];
// and now if you *need* an intermediate array with the index mapped to the value and value mapped to the count:
const largestNumber = counts.sort((c1, c2) => c2.value - c1.value)[0];
// initialize an empty as long as the largest number
let newArr = new Array(largestNumber);
newArr = newArr.map((val, i) => {
const count = counts.find(count => count.value === i);
if (count) {
return count.count;
} else {
return 0; // 'i' occurs 0 times in 'b'
}
});
};
You can use Array#reduce method to achieve the result with an additional object for keeping count.
export let findMode = (b: number[]): number => {
// object for keeping count of each element
// initially set `0` with 0 count (default value)
let ref = {
'0': 0
};
return b.reduce((value, num) => {
// define count as 0 if not defined
ref[num] = ref[num] || 0;
// increment element count
ref[num]++;
// if number count is gretater than previous element count
// then return current element
if (ref[num] > ref[value]) {
return num;
// if counts are same then return the smallest value
} else if (ref[num] === ref[value]) {
return num < value ? num : value;
}
// else return the previous value
return value;
// set initial value as 0(default)
}, 0);
};
let findMode = b => {
let ref = {
'0': 0
};
return b.reduce((value, num) => {
ref[num] = ref[num] || 0;
ref[num]++;
if (ref[num] > ref[value]) {
return num;
} else if (ref[num] === ref[value]) {
return num < value ? num : value;
}
return value;
}, 0);
};
[
[2, 1, 1, 2, 1, 0],
[1, 3, 2],
[0, 0, 0, 1, 1, 2, 1, 1],
[4, 4, 7, 4, 0, 7],
[-4, -4, -1, 3, 5],
[1, 1, 2, 3, 2],
[10, 10, 10, 20, 20, 30]
].forEach(v => console.log(findMode(v)))

How to tell TypeScript that I'm returning an array of arrays of the input type?

I have a function that chunks arrays:
const chunkArray = (inputArray: any[], chunks: number) => {
const chunkedArray = [];
let i = 0;
const n = inputArray.length;
while (i < n) {
chunkedArray.push(inputArray.slice(i, (i += chunks)));
}
return chunkedArray;
};
export default chunkArray;
I would like my linter to know for a given input array, what the output array looks like. For example for
const chunkedArrays = chunkArray([1, 2, 3, 4, 5], 2); // [[1, 2], [3, 4], [5]]
my linter should now, that chunkedArrays is an array of arrays of numbers. Currently it says it's an array of arrays of any.
How can I achieve that?
You need to add a generic type parameter to your function. The type parameter will capture the actual type of the elements in the input array and then you can use this generic type to specify how it relates to your result:
const chunkArray = <T>(inputArray: T[], chunks: number) => {
const chunkedArray: T[][] = []; // use T as the type for chunkedArray
let i = 0;
const n = inputArray.length;
while (i < n) {
chunkedArray.push(inputArray.slice(i, (i += chunks)));
}
return chunkedArray;
};
const chunkedArrays = chunkArray([1, 2, 3, 4, 5], 2); // number[][]
const chunkedArraysString = chunkArray(["1", "2", "3", "4", "5"], 2); // string[][]

How to search a subarray of numbers inside an array of numbers

my issue is this in TypeScript (now latest is v3.1)
I have a array of numbers
let mainArray : Array<number> = [1,2,3,4];
I have to find subarray of [2,3], how can i do?
My actual workaround is converting both arrays in string (toString()) and using .includes (ES6) function, and it works but i think is not the best solution.
Thank you!
You can use filter for this
let mainArray : Array<number> = [1,2,3,4];
var findArry = [2, 3];
var subArray = mainArray.filter(function(val) {
return findArry.indexOf(val) != -1 ? true : false;
});
console.log(subArray);
Well its more algorithm problem then typescript problem. But this solution should work for checking if there is subarray which matched with searched array:
const toTuples = (n) => (item, index, originalArr) => {
const arr = [];
for(let i = 0; i < n; i++) {
arr.push(originalArr[index + i]);
}
return arr;
}
const arr = [1,2,3,4,2,3];
const search = [2, 3];
const mapped = arr.map(toTuples(search.length));
console.log(mapped.some((currArray) => currArray.every((item) => search.includes(item))));

How to get the value of the element i, j of a tensor

I have a 2d tensor and I would like to get the value of the element of index i,j value.
There are many ways one can retrieve the value of the element [i,j] of a tensor2d
Consider the following:
Using slice to retrieve directly the tensor2d starting at the coordinate [i, j] that has the size [1, 1]
h.slice([i, j], 1).as1D().print()
Get the row i as a tensor2d with gather and then the element j with slice
h.gather(tf.tensor1d([i], 'int32')).slice([0, j], [1, 1]).as1D().print()
Using stack to retrieve the row i as tensor1d and slice to retrieve the desired element
h.unstack()[i].slice([j], [1]).print()
const h = tf.tensor2d([45, 48, 45, 54, 5, 7, 8, 10, 54], [3, 3]);
// get the element of index [1, 2]
h.print()
h.gather(tf.tensor1d([1], 'int32')).slice([0, 2], [1, 1]).as1D().print()
h.slice([1, 2], 1).as1D().print()
h.unstack()[1].slice([2], [1]).print()
<html>
<head>
<!-- Load TensorFlow.js -->
<script src="https://cdn.jsdelivr.net/npm/#tensorflow/tfjs#0.12.0"> </script>
</head>
<body>
</body>
</html>
If the goal is to get the element [i, j] in order to use it in other tensor computation like divide/multiply the matrix by the element, you will need to convert the element to a scalar.
h.slice([i, j], 1).as1D().asScalar()
If you want to return that value to a javascript variable (of type number), then you will need dataSync() or data() as described in this answer
h.slice([i, j], 1).as1D().dataSync()[0]
// or
const data = await h.slice([i, j], 1).as1D().data()
const h = tf.tensor2d([45, 48, 45, 54, 5, 7, 8, 10, 54], [3, 3]);
// get the element of index [1, 2]
h.print()
// sync method
const val = h.unstack()[1].slice([2], [1]).dataSync()
console.log(val[0]);
// async method
(async () => {
const val = await h.slice([1, 2], 1).as1D().data()
console.log(val[0])
})()
<html>
<head>
<!-- Load TensorFlow.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/tensorflow/0.12.4/tf.js"> </script>
</head>
<body>
</body>
</html>
You can use .dataSync() or if you can wait for it .data() to retrieve an 1d array containing all values of a tensor.
Now we only have to calculate an 1d-index from the 2d-coordinates using the formula:
index = rowlength * rownumber + columnnumber
The following code shows how to use each version.
Notice the async and await in the asynchronous method: async makes the function async, so we can use await to wait for another promise to resolve (.data() retuns a promise). Because an async function returns a promise we have to wait for it before logging it using .then()
function getValSync(t, i, j) {
const data = t.dataSync();
return data[t.shape[0] * j + i]; //Or *i+j, depending on what the dimension order is
}
async function getValAsync(t, i, j) {
const data = await t.data();
return data[t.shape[0] * j + i];
}
const t2d = tf.tensor2d([1, 2, 3, 4], [2, 2]);
t2d.print();
console.log("1,0:", getValSync(t2d, 1, 0));
console.log("1,1:", getValSync(t2d, 1, 1));
getValAsync(t2d, 0, 0).then(v => console.log("0,0:", v));
<script src="https://cdn.jsdelivr.net/npm/#tensorflow/tfjs#0.12.0">
</script>

Resources