How to get the value of the element i, j of a tensor - tensorflow.js

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>

Related

How to get indices of a specific value in a tensor in tensorflow-js?

For example, If I have a 2D tensor of [[1,3],[2,1]], how can I get indices of the value 1? (It should return [[0,0],[1,1]]).
I took a look into tf.where but the API is complicated and I don't think that would solve the problem for me
You can achieve this using tf.whereAsync.
Just create a mask which checks if the values in the input Tensor are of the value 1 and turn them into boolean values.
Mask:
"Tensor
[[true , false],
[false, true ]]"
tf.whereAsync() returns the coordinates of true elements of the condition which in this case come from the mask.
(async function getData() {
const x = tf.tensor2d([[1, 3], [2, 1]])
const mask = x.equal([1]).asType('bool');
const coords = await tf.whereAsync(mask);
coords.print();
}());
Input:
"Tensor
[[1, 3],
[2, 1]]"
Output:
"Tensor
[[0, 0],
[1, 1]]"

how to multiply the array element in to the next element and output as an array in Swift

var numbers = [2, 4, 3, 7]
var computed = numbers
print(computed)
I want to multiply the first element to next, until the last will multiply to the first element
example:
2*4, 4*3, 3*7, 7*2
and the output will be [8, 12, 21, 14]
I don't know the Swift language but the algorithm is pretty simple and does not depend on any technology. Try with this one:
let numbers = [2, 4, 3, 7]
let indexAndNum = numbers.enumerated().map { (index, element) in
return element * numbers[(index + 1) % numbers.count]
}
print(indexAndNum)
Live demo here
var resultArray = [Int]()
for (index, number) in numbers.enumerated() {
if index < numbers.count - 1 {
resultArray.append(number * numbers[index + 1])
} else {
resultArray.append(number * numbers[0])
}
}
print(resultArray)
Succincter version of Sebastian Kaczmarek's answer:-
let numbers = [2, 4, 3, 7]
let computed = numbers.enumerated().map { $1 * numbers[($0 + 1) % numbers.count] }
print(computed)
Output:-
[8, 12, 21, 14]

TensorflowJS with earlyStopping and Training Logs does not work

TensorflowJS does not seem to work when we define early stopping and a training log function at the same time. The examples above is taken from the TensorflowJS docs, I just added the onTrainBegin callback -- but it fails.
const model = tf.sequential();
model.add(tf.layers.dense({
units: 3,
activation: 'softmax',
kernelInitializer: 'ones',
inputShape: [2]
}));
const xs = tf.tensor2d([1, 2, 3, 4], [2, 2]);
const ys = tf.tensor2d([[1, 0, 0], [0, 1, 0]], [2, 3]);
const xsVal = tf.tensor2d([4, 3, 2, 1], [2, 2]);
const ysVal = tf.tensor2d([[0, 0, 1], [0, 1, 0]], [2, 3]);
model.compile(
{loss: 'categoricalCrossentropy', optimizer: 'sgd', metrics: ['acc']});
const onTrainBegin = function onTrainBegin(logs){
console.log("onTrainBegin");
}
// Without the EarlyStopping callback, the val_acc value would be:
// 0.5, 0.5, 0.5, 0.5, ...
// With val_acc being monitored, training should stop after the 2nd epoch.
const history = await model.fit(xs, ys, {
epochs: 10,
validationData: [xsVal, ysVal],
callbacks: [onTrainBegin, tf.callbacks.earlyStopping({monitor: 'val_acc'})]
});
// Expect to see a length-2 array.
console.log(history.history.val_acc);
This code yields the error message:
An error occured this.getMonitorValue is not a function
https://js.tensorflow.org/api/latest/#callbacks.earlyStopping
You are mixing different things. OntrainBegin specifies when the callback function is to be executed and tf.callbacks.earlyStopping({monitor: 'val_acc'}) is a function
(async() => {
const model = tf.sequential();
model.add(tf.layers.dense({
units: 3,
activation: 'softmax',
kernelInitializer: 'ones',
inputShape: [2]
}));
const xs = tf.tensor2d([1, 2, 3, 4], [2, 2]);
const ys = tf.tensor2d([[1, 0, 0], [0, 1, 0]], [2, 3]);
const xsVal = tf.tensor2d([4, 3, 2, 1], [2, 2]);
const ysVal = tf.tensor2d([[0, 0, 1], [0, 1, 0]], [2, 3]);
model.compile(
{loss: 'categoricalCrossentropy', optimizer: 'sgd', metrics: ['acc']});
const onTrainBegin = logs => {
console.log("onTrainBegin");
}
// Without the EarlyStopping callback, the val_acc value would be:
// 0.5, 0.5, 0.5, 0.5, ...
// With val_acc being monitored, training should stop after the 2nd epoch.
const history = await model.fit(xs, ys, {
epochs: 10,
validationData: [xsVal, ysVal],
callbacks: [
tf.callbacks.earlyStopping({monitor: 'val_acc'}), new tf.CustomCallback({
onEpochEnd: onTrainBegin()}),
]
});
// Expect to see a length-2 array.
console.log(history.history.val_acc);
})()
<html>
<head>
<!-- Load TensorFlow.js -->
<script src="https://cdn.jsdelivr.net/npm/#tensorflow/tfjs#latest"> </script>
</head>
<body>
</body>
</html>
Below an example of the working code for using earlyStopping and tf.CustomCallback in model training in tfjs.
await model.fitDataset(convertedTrainingData,
{epochs: 50,
validationData: convertedTestingData,
callbacks:[
new tf.CustomCallback({
onEpochEnd: async(epoch, logs) =>{
acc = logs.acc;
console.log("Epoch: " + epoch
+ " Loss: " + logs.loss.toFixed(4)
+ " Accuracy: " + logs.acc.toFixed(4)
+ " Val Loss: " + logs.val_loss.toFixed(4)
+ " Val Accuracy: " + logs.val_acc.toFixed(4));
},
onTrainEnd: async() =>{
console.log("training done");
if (acc>0.4) {
repeat = false;
console.log(repeat);
}
}
}),
tf.callbacks.earlyStopping({monitor: 'loss'})
]});

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

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>

qr decomposition of a matrix

I want to compute the qr decomposition of a matrix
Here is my code
const a = tf.tensor([1, 2, 3, 4], [2, 2]);
a.print()
const [b, c] = tf.qr(a)
b.print()
But it is throwing the following error
tf.qr is not a function or its return value is not iterable
The documentation is not clear about tf.qr and tf.gramSchmidt. You need to use tf.linalg.qr and tf.linalg.gramSchmidt instead as you can see in the unit test code here
const [b, c] = tf.linalg.qr(a)
const a = tf.tensor([1, 2, 3, 4], [2, 2]);
a.print()
const [b, c] = tf.linalg.qr(a)
b.print()
<html>
<head>
<!-- Load TensorFlow.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/tensorflow/0.12.4/tf.js"> </script>
</head>
<body>
</body>
</html>

Resources