tensorflow.js Pauses Working While Browser Window Is Invisible - gpu

I'm working on tensorflow.js examples. After fit function executed, epoches starts working without any problem.
But when i minimize browser window or open another tab or open another program window, Epoches pauses working and when open browser tensorflow.js example again, it continues to fit and epoches logs to the console.
My system is Windows 10, i tried Chrome, Firefox and Edge with same state.
I tried both CPU and CPU but nothing changed.
I googled and searched on stackoverflow but nobody reported this issue. And then i check and reset my power management settings but nothing changed.
At documents of tensorflow.js i can't find about this setting.
What may i do to tensorflow.js continues to fit and epoches logs to the console while browser minimized, etc.
My script code like below:
<html>
<head>
<!-- Load TensorFlow.js -->
<!-- Get latest version at https://github.com/tensorflow/tfjs -->
<script src="https://cdn.jsdelivr.net/npm/#tensorflow/tfjs">
</script>
</head>
<body>
<div id="output_field"></div>
</body>
<script>
async function learnLinear(){
const model = tf.sequential();
model.add(tf.layers.dense({units: 1, inputShape: [1]}));
const optimizer = tf.train.adam(0.1);
model.compile({
loss: 'meanSquaredError',
metrics: ['accuracy'],
optimizer: optimizer
});
const xs = tf.tensor2d([-40, -10, 0, 8, 15, 22, 38], [7, 1]);
const ys = tf.tensor2d([-40, 14, 32, 46, 59, 72, 100], [7, 1]);
const history = await model.fit(xs, ys, {
epochs: 500,
callbacks:{
onEpochEnd: async(epoch, logs) =>{
console.log("Epoch: " + epoch + " Loss: " + logs.loss);
}
}
});
document.getElementById('output_field').innerText =
model.predict(tf.tensor2d([100.0], [1, 1]));
}
learnLinear();
</script>
<html>

Related

Tensorflowjs - Reshape/slice 4d tensor into image

I am trying to apply style transfer to a webcam capture. I am reading a frozen model I've previously trained in python and converted for TFjs. The output tensor's shape and rank is as follows:
I am having issues in the last line of this function, when I try to apply tf.browser.toPixels
function predictWebcam() {
tf.tidy(() => {
loadmodel().then(model=>{
//let tensor= model.predict(tf.expandDims(tf.browser.fromPixels(video)));
let tensor= model.predict(tf.browser.fromPixels(video, 3).toFloat().div(tf.scalar(255)).expandDims());
console.log('shape', tensor.shape);
console.log('rank', tensor.rank);
tf.browser.toPixels(tensor, resultImage);
});
});
}
I get this error. I cannot figure out how to reshape or modify the tensor to get an image out of it:
Uncaught (in promise) Error: toPixels only supports rank 2 or 3 tensors, got rank 4.
Maybe I have to replicate tensor_to_image function from python to javascript as in the example in the website.
Thanks in advance!
given your tensor is [1, 15, 20, 512]
you can remove any dims with value of 1 (same dim you've added by running expandDims) by running
const squeezed = tf.squeeze(tensor)
that will give you shape of [15, 20, 512]
but that still doesn't make sense - what is width, height and channels (e.g. rgb) here?
i think that model result needs additional post-processing, that is not an image.

TensorFlow JS (React Native) empty response

I trained a model on GCloud AutoML Vision, exported it as a TensorFlow.js model, and loaded it on the application start. Looking at the model.json, the model is definitely expecting a 224x224 image. I had to do the tensor.reshape because it was rejecting my tensor when I ran a prediction on a tensor of [224, 224, 3].
Base64 comes in from camera. I believe I am preparing this image correctly, but I have no way of knowing for sure.
const imgBuffer = decodeBase64(base64) // from 'base64-arraybuffer' package
const raw = new Uint8Array(imgBuffer)
const imageTensor = decodeJpeg(raw)
const resizedImageTensor = imageTensor.resizeBilinear([224, 224])
const reshapedImageTensor = resizedImageTensor.reshape([1, 224, 224, 3])
const res = model.predict(reshapedImageTensor)
console.log('response', res)
But the response I get doesn't seem to have much...
{
"dataId":{},
"dtype":"float32",
"id":293,
"isDisposedInternal":false,
"kept":false,
"rankType":"2",
"scopeId":5,
"shape":[
1,
1087
],
"size":1087,
"strides":[
1087
]
}
What does this type of response mean? Is there something I'm doing wrong?
You need to use dataSync() to download the actual predictions of the model.
const res = model.predict(reshapedImageTensor);
const predictions = res.dataSync();
console.log('Predictions', predictions);

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.

Draw a line of varying width in p5.js

I wish to draw lines on my canvas with width that gradually vary from start to end. That is, say the line starts at (0, 0) with width = 1 (equivalently, strokeWeight) and ends at (50, 50) with width = 3, and the width must (linearly) increase from 1 to 3 from start to end.
Any ideas on how to achieve this? Can't scrape it out of the web.
The key is to separate the line into for example 30 segments. You draw each segment with increasing strokeWeight(). The more segments you have, the smoother the line will look.
You can use lerp() to find x,y coordinates for points between two ends.
You can use lerp() to find strokeWeight() for lines between two ends.
function setup() {
createCanvas(200, 200);
background("black");
stroke("white");
gradientLine(0, 0, 50, 50, 1, 3, 30);
noLoop();
}
function gradientLine(
start_x,
start_y,
end_x,
end_y,
start_weight,
end_weight,
segments
) {
let prev_loc_x = start_x;
let prev_loc_y = start_y;
for (let i = 1; i <= segments; i++) {
let cur_loc_x = lerp(start_x, end_x, i / segments);
let cur_loc_y = lerp(start_y, end_y, i / segments);
push();
strokeWeight(lerp(start_weight, end_weight, i / segments));
line(prev_loc_x, prev_loc_y, cur_loc_x, cur_loc_y);
pop();
prev_loc_x = cur_loc_x;
prev_loc_y = cur_loc_y;
}
}
<script src="https://cdn.jsdelivr.net/npm/p5#1.0.0/lib/p5.min.js"></script>
EDIT:
Also, in case one is working with colours with alpha < 255, such artifacts can appear:
This happens because the default capping for strokes is set to ROUND. Setting strokeCap(SQUARE) will fix this problem:
This needs to be set in the push()...pop() block in gradientLine(...) function. (Note: This will make the ends of the line look flat, and that needs more refined work.)
You could also just draw the line "as a trapezoid" using beginShape() / endShape() and transforming each end of the line into two separate points. See the code snippet below:
function setup() {
createCanvas(400, 400);
noStroke();
fill(220);
}
function draw() {
background(20);
drawVaryingWidthLine(0, 0, 50, 50, 1, 3);
drawVaryingWidthLine(80, 20, 200, 140, 1, 5);
drawVaryingWidthLine(30, 60, 230, 260, 10, 3);
drawVaryingWidthLine(210, 180, 360, 330, 40, 20);
}
function drawVaryingWidthLine(x1, y1, x2, y2, startWidth, endWidth) {
const halfStartWidth = startWidth / 2
const halfEndwidth = endWidth / 2
beginShape();
vertex(x1 + halfStartWidth, y1 - halfStartWidth);
vertex(x2 + halfEndwidth, y2 - halfEndwidth);
vertex(x2 - halfEndwidth, y2 + halfEndwidth);
vertex(x1 - halfStartWidth, y1 + halfStartWidth);
vertex(x1 + halfStartWidth, y1 - halfStartWidth);
endShape();
}
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.10.2/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.10.2/addons/p5.sound.min.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
<meta charset="utf-8" />
</head>
<body>
<script src="sketch.js"></script>
</body>
</html>
Compared to #ffmaer's solution, this one doesn't have any smoothness / transparency artifacts.
I assume that mine is somewhat faster because you only draw one shape per line (though I haven't tested it). However, this version here is currently limited to lines of the angle asked for in the original post (45 degrees downward right). It could be quite easily adapted to arbitrary angles by adjusting the corner positions of the trapezoid.
Edit: now using trapezoids instead of triangles, based on #ffmaer's comment.

How to add Images in a tensorflow.js model and train the model for given images labels

We are using TensorFlow.js to create and train the model. We use tf.fromPixels() function to convert an image into tensor.
We want to create a custom model with the below properties:
AddImage( HTML_Image_Element, 'Label'): Add an imageElement with a custom label
Train() / fit() : Train this custom model with associated labels
Predict(): Predict the images with their associated label, and it will return the predicted response with the attached label of every image.
For better understanding let's take an example:
Let's say we have three images for prediction i.e: img1, img2, img3 with three labels 'A', 'B' and 'C' respectively.
So we want to create and train our model with these images and respective labels like below :
When user want to predict 'img1' then it shows the prediction 'A', similarly, for 'img2' predict with 'B' and for 'img3' predict with 'C'
Please suggest to me how can we create and train this model.
This is webpage we used to create a model with images and its associate labels:
<apex:page id="PageId" showheader="false">
<head>
<title>Image Classifier with TensorFlowJS</title>
<script src="https://cdn.jsdelivr.net/npm/#tensorflow/tfjs#0.11.2"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<div id="output_field"></div>
<img id="imgshow" src="{!$Resource.cat}" crossorigin="anonymous" width="400" height="300" />
<script>
async function learnlinear(){
//img data set
const imageHTML = document.getElementById('imgshow');
console.log('imageHTML::'+imageHTML.src);
//convert to tensor
const tensorImg = tf.fromPixels(imageHTML);
tensorImg.data().then(async function (stuffTensImg){
console.log('stuffTensImg::'+stuffTensImg.toString());
});
const model = tf.sequential();
model.add(tf.layers.conv2d({
kernelSize: 5,
filters: 20,
strides: 1,
activation: 'relu',
inputShape: [imageHTML.height, imageHTML.width, 3],
}));
model.add(tf.layers.maxPooling2d({
poolSize: [2, 2],
strides: [2, 2],
}));
model.add(tf.layers.flatten());
model.add(tf.layers.dropout(0.2));
// Two output values x and y
model.add(tf.layers.dense({
units: 2,
activation: 'tanh',
}));
// Use ADAM optimizer with learning rate of 0.0005 and MSE loss
model.compile({
optimizer: tf.train.adam(0.0005),
loss: 'meanSquaredError',
});
await model.fit(tensorImg, {epochs: 500});
model.predict(tensorImg).print();
}
learnlinear();
</script>
</apex:page>
we got the following error while running the code snippet:
tfjs#0.11.2:1 Uncaught (in promise) Error: Error when checking input: expected conv2d_Conv2D1_input to have 4 dimension(s). but got an array with shape 300,400,3
at new t (tfjs#0.11.2:1)
at standardizeInputData (tfjs#0.11.2:1)
at t.standardizeUserData (tfjs#0.11.2:1)
at t. (tfjs#0.11.2:1)
at n (tfjs#0.11.2:1)
at Object.next (tfjs#0.11.2:1)
at tfjs#0.11.2:1
at new Promise ()
at __awaiter$15 (tfjs#0.11.2:1)
at t.fit (tfjs#0.11.2:1)
This error coming while passing this sample error
You simply need to reshape your tensor data.
The data you passed in to your model should be one dimension bigger than the inputShape. Actually predict takes an array of elements of shape InputShape. The number of elements is the batch size. Therefore your image data should have the following shape [batchsize, ...inputShape] (using the ellipsis for rest parameter to indicate that the later part of the shape is equal to that of inputShape)
Since you're training with only one element (which does not really happen in real case) one simply needs to use a batchsize of 1.
model.predict(tensorImg.expandDims(0)).print()
TLDR: You simply have to resize your data using np.expand_dims() or np.reshape().
First, let's generate some random tensor that mimics your current tensor input -
# Some random numpy array
In [20]: x = np.random.random((2,2,4))
In [21]: x
Out[21]:
array([[[0.8454901 , 0.75157647, 0.1511371 , 0.53809724],
[0.50779498, 0.41321185, 0.45686143, 0.80532259]],
[[0.93412402, 0.02820063, 0.5452628 , 0.8462806 ],
[0.4315332 , 0.9528761 , 0.69604215, 0.538589 ]]])
# Currently your tensor is a similar 3D shape like x
In [22]: x.shape
Out[22]: (2, 2, 4)
Now you can convert it to a 4D tensor like so -
[23]: y = np.expand_dims(x, axis = 3)
In [24]: y
Out[24]:
array([[[[0.8454901 ],
[0.75157647],
[0.1511371 ],
[0.53809724]],
[[0.50779498],
[0.41321185],
[0.45686143],
[0.80532259]]],
[[[0.93412402],
[0.02820063],
[0.5452628 ],
[0.8462806 ]],
[[0.4315332 ],
[0.9528761 ],
[0.69604215],
[0.538589 ]]]])
In [25]: y.shape
Out[25]: (2, 2, 4, 1)
You can find the np.expand_dims documentation here.
EDIT: Here's a one-liner
np.reshape(np.ravel(x), (x.shape[0], x.shape[1], x.shape[2], 1)).shape
You can see thenp.reshape documentation here.