How do I mutate value of a tensor in Tensorflow.js? - tensorflow

How do I mutate value of a tensor in Tensorflow.js? For example if I have a tensor created like this:
const a = tf.tensor1d([1,2,3,4])
How do I change the value of the third element of the tensor? I know that tensors are immutable and variables are mutable.
Doing this: const a = tf.variable(tf.tensor1d([1,2,3,4])) doesn't seem to solve the problem. I cannot do:
const a = a[0].assign(5)
I am able to do this in python tensorflow like this:
a = tf.Variable([1,2,3,4])
a = a[0].assign(100)
with tf.Session() as sess:
sess.run(tf.global_variables_iniliazer())
print sess.run(a)
This outputs [100, 2,3,4]

Does tf.buffer work for you?
// Create a buffer and set values at particular indices.
const a = tf.tensor1d([1, 2, 3, 4]);
const buffer = tf.buffer(a.shape, a.dtype, a.dataSync());
buffer.set(5, 0);
const b = buffer.toTensor();
// Convert the buffer back to a tensor.
b.print();
Tensor
[5, 2, 3, 4]

I had to do this using mulStrict and addStrict which do element-wise multiplication and addition.
const a = tf.tensor1d([1,2,3,4]);
tf.mulStrict(a, tf.tensor1d([0,1,1,1]))
.addStrict(tf.tensor1d([100, 0, 0, 0]);
This was based on asnwer
here

Related

Tensorflow JS remove a dimension in a tensor

I created my first model, but the predictions are not in the right format. How I do I remove a dimension on my prediction output (or change my last layer to get the correct one)?
const actualYs = [1,2,3] // The shape of my values Y
const predictions = [[1],[2],[3]] // The shape of my predictions
// My last layer looks like this:
model.add(tf.layers.dense({ units: 1, useBias: true }))
So from my limited understanding. I could maybe remove a dimension to predictions or change the last layer? But I already put 1, so not sure what else I could set it to.
In case this helps, this is my actual console.log
MY Y VALUES
Tensor
[0.0862738, 0.0862553, 0.0861815, ..., 0.0054516, 0.0043004, 0.0037461]
PREDICTIONS
Tensor
[[0.1690691],
[0.1659686],
[0.1698797],
...,
[0.1118171],
[0.1092742],
[0.1096415]]
I want predictions to look like my actual Y values.
Thanks in advance.
reshape or squeeze can be used
const x = tf.tensor([[1],[2],[3]] ).reshape([-1]);
// or
const x = tf.tensor([[1],[2],[3]] ).squeeze();

How to use vectors created by P5 createVector as a tensor in tensorflow.js

I am using p5 to return the vector path of a drawn line. All the vectors in the line are pushed into an array that holds all the vectors. I'm trying to use this as a tensor but I keep getting an error saying
Error when checking model input: the Array of Tensors that you are passing to your model is not the size the model expected. Expected to see 1 Tensor(s), but instead got the following list of Tensor(s):
When I opened the array on the dev tool, each vector was printed like this:
0: Vector {p5: p5, x: 0.5150300601202404, y: -0.25450901803607207, z: 0}
could it be the p5 text in the vector array that's giving me the error? Here's my model and fit code:
let vectorpath = []; //vector path array
// model, setting layers till next '-----'
const model = tf.sequential();
model.add(tf.layers.dense({units: 4, inputShape: [2, 2], activation: 'sigmoid'}));
model.add(tf.layers.dense({units: 2, activation: 'sigmoid'}));
console.log(JSON.stringify(model.outputs[0].shape));
model.weights.forEach(w => {
console.log(w.name, w.shape);
});
// -----
//this is under the draw function so it is continually updated
const labels = tf.randomUniform([0, 1]);
function onBatchEnd(batch, logs) {
console.log('Accuracy', logs.acc);
}
model.fit(vectorpath, labels, {
epochs: 5,
batchSize: 32,
callbacks: {onBatchEnd}
}).then(info => {
console.log('Final accuracy', info.history.acc);
});
What could be causing the error? and how can I fix it?
The question's pretty vague but I'm really just not sure.

Tensorflow.js: expandDims() + cast() issue

I need to provide a float32 tensor for my model. I need to use expandDims(tensor, axis=0) to change its shape from [240, 320, 3] to [1, 240, 320, 3]. However, it appears that the expandDims() operation casts my tensor to int32.
When I perform cast(tensor, "float32") on this tensor, it appears that the cast operation squeezes my tensor back to [240, 320, 3].
image_v = (tf.cast(image_raw, "float32") / 255.0) - 0.5;
image_v = tf.expandDims(image_raw, 0);
console.log(image_v.shape) // shape: [1, 240, 320, 3]
console.log(image_v.dtype) // dtype: "int32"
image_v = tf.cast(image_raw, "float32")
console.log(image_v.shape) // shape: [240, 320, 3]
console.log(image_v.dtype) // dtype: "float32"
I am looking for a way to expand dims on a float32 tensor in tensorflow.js and have the tensor's dtype remain float32. Any help would be appreciated!
You seem to think, that operations like tf.cast work on the original tensor. But that is not the case. To quote the docs:
A tf.Tensor object represents an immutable, multidimensional array of numbers that has a shape and a data type.
That means, whenever you call a function like tf.cast or tf.expandDims a new tensor is created. Therefore, your tf.cast(image_raw, "float32") call will not change the original tensor, but create a new one.
Solution
To cast your tensor, you should use image_v instead of image_raw as the latter tensor was never changed.
image_v = tf.cast(image_raw, "float32");
Also, the beginning of your script is not working for another reason (which is not responsible for the problem you are facing, though). Normal JavaScript operations do not work on tensors. Check out tf.div and tf.sub instead.
So, all in all, your code should look like this:
image_v = tf.cast(image_raw, "float32").div(255).sub(0.5);
image_v = tf.expandDims(image_v, 0);
console.log(image_v.shape) // should now be: [1, 240, 320, 3]
console.log(image_v.dtype) // and this should be: dtype: "int32"
Like the other answer already suggested, you should also check out tf.tidy to prevent memory leaks.
Tfjs can't use JS operations on tensors, you have to use tf.div() and tf.sub().
image_v = (tf.cast(image_raw, "float32") / 255.0) - 0.5;
image_v is now NaN, because ({}/255)-0.5 === NaN
image_v = tf.expandDims(image_raw, 0);
Now you expand the original image, wich wasn't modified.
image_v = tf.cast(image_raw, "float32")
You reused the original image_raw, because in tf operations don't modify the tensor. They always create a new one.
And I recommend don't reusing variables or working outside tf.tidy(), because you can easily forget to .dispose() and thus creating a memory leak.
const image_raw = tf.zeros([240, 320, 3]);
const modified = tf.tidy(() => {
const image_v_casted = tf.cast(image_raw, "float32").div(255).sub(0.5);
const image_v_expanded = tf.expandDims(image_v_casted, 0);
return image_v_expanded;
});
console.log('shape', modified.shape);
console.log('dtype', modified.dtype);
<script src="https://cdn.jsdelivr.net/npm/#tensorflow/tfjs#1.0.0/dist/tf.min.js"></script>

Tensorflow multiply 3D batch tensor with a 2D weight

I've got two tensors with the shape shown below,
batch.shape = [?, 5, 4]
weight.shape = [3, 5]
by multiplying the weight with every element in the batch, I want to get
result.shape = [?, 3, 4]
what is the most efficient way to achieve this?
Try this:
newbatch = tf.transpose(batch,[1,0,2])
newbatch = tf.reshape(newbatch,[5,-1])
result = tf.matmul(weight,newbatch)
result = tf.reshape(result,[3,-1,4])
result = tf.transpose(result, [1,0,2])
Or more compactly:
newbatch = tf.reshape(tf.transpose(batch,[1,0,2]),[5,-1])
result = tf.transpose(tf.reshape(tf.matmul(weight,newbatch),[3,-1,4]), [1,0,2])
Try this:
tf.einsum("ijk,aj-> iak",batch,weight)
A generalized contraction between tensors of arbitrary dimension Refer this for more information

Tensorflow custom op -- how do I read and write from Tensors?

I'm writing a custom Tensorflow op using the tutorial and I'm having trouble understanding how to read and write to/from Tensors.
let's say I have a Tensor in my OpKernel that I get from
const Tensor& values_tensor = context->input(0); (where context = OpKernelConstruction*)
if that Tensor has shape, say, [2, 10, 20], how can I index into it (e.g. auto x = values_tensor[1, 4, 12], etc.)?
equivalently, if I have
Tensor *output_tensor = NULL;
OP_REQUIRES_OK(context, context->allocate_output(
0,
{batch_size, value_len - window_size, window_size},
&output_tensor
));
how can I assign to output_tensor, like output_tensor[1, 2, 3] = 11, etc.?
sorry for the dumb question, but the docs are really tripping me up here and the examples in the Tensorflow kernel code for built-in ops somehow obfuscate this to the point that I get very confused :)
thank you!
The easiest way to read from and write to tensorflow::Tensor objects is to convert them to an Eigen tensor, using the tensorflow::Tensor::tensor<T, NDIMS>() method. Note that you have to specify the (C++) type of elements in tensor as template parameter T.
For example, to read a particular value from a DT_FLOAT32 tensor:
const Tensor& values_tensor = context->input(0);
auto x = value_tensor.tensor<float, 3>()(1, 4, 12);
To write a particular value to a DT_FLOAT32 tensor:
Tensor* output_tensor = ...;
output_tensor->tensor<float, 3>()(1, 2, 3) = 11.0;
There are also convenience methods for accessing a scalar, vector, or matrix.