javascript - 如何在 tensorflow.js 中通过 model.executeAsync(x) 执行 tf.grad
问题描述
我试图传递model.executeAsync(x).reshape([-1]).gather(2))
给tf.grad
它会返回一个错误:
Uncaught (in promise) TypeError: model.executeAsync(...).reshape is not a function
当我删除.reshape([-1])
它返回此错误:
Uncaught (in promise) TypeError: model.executeAsync(...).gather is not a function
当我删除.gather
它返回此错误:
Uncaught (in promise) 错误:f() 返回的结果 y 必须是张量。
<html>
<head>
<!-- Load TensorFlow.js -->
<!-- Get latest version at https://github.com/tensorflow/tfjs -->
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.2.9/dist/tf.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</script>
</head>
<body>
<div id="output_field"></div>
<img id="img_predicted" src="test_img.jpg" style="width: 320px; height: 320px;"/>
<script>
function preprocessImage(image) {
return tf.tidy(() => {
let tensor = tf.browser.fromPixels(image, numChannels=3).toFloat();
let resized = tf.image.resizeBilinear(tensor, [320, 320], alignCorners=true);
let meanImageNetRGB = {red: 0.485, green: 0.456, blue: 0.406};
let stdImageNetRGB = {red: 0.229, green: 0.224, blue: 0.225};
let indices = [tf.tensor1d([0], "int32"),tf.tensor1d([1], "int32"),tf.tensor1d([2], "int32")];
cropImage = (img) => {
const size = 320;
const beginHeight = parseInt((img.shape[1]-size+1)*0.5);
const beginWidth = parseInt((img.shape[0]-size+1)*0.5);
return img.slice([beginWidth , beginHeight, 0], [size, size, 3]);
}
let crop = cropImage(resized);
let toTensor = crop.div(tf.scalar(255.0));
let centeredRGB = {
red: tf.gather(toTensor, indices[0], 2)
.sub(tf.scalar(meanImageNetRGB.red))
.reshape([102400]),
green: tf.gather(toTensor, indices[1], 2)
.sub(tf.scalar(meanImageNetRGB.green))
.reshape([102400]),
blue: tf.gather(toTensor, indices[2], 2)
.sub(tf.scalar(meanImageNetRGB.blue))
.reshape([102400])
};
let norm = tf.stack([centeredRGB.red.div(tf.scalar(stdImageNetRGB.red)).reshape([1,320,320]),
centeredRGB.green.div(tf.scalar(stdImageNetRGB.green)).reshape([1,320,320]),
centeredRGB.blue.div(tf.scalar(stdImageNetRGB.blue)).reshape([1,320,320])], 1);
let proc_image = tf.tensor4d(Array.from(norm.dataSync()),[1,3,320,320]);
// Return final pre-processed image tensor
return proc_image;
})
}
let im;
window.onload = function() {
im = $('#img_predicted')[0];
console.log(im)
test_grad(im);
};
async function test_grad(image) {
model = await tf.loadGraphModel("models/tfjsFromSaved/model.json");
// *Lines to confirm model works
// const warmupResult = await model.executeAsync(tf.zeros([1,3,320,320]), );
// warmupResult.dataSync();
// warmupResult.print();
// tf.dispose(warmupResult);
layer = tf.tidy(() => {
chestgrad = tf.grad(x =>model.executeAsync(x).reshape([-1]).gather(2))
const batched = preprocessImage(image);
const grad = chestgrad(batched);
grad.print();
const layer = grad.mean(0).abs().max(0)
return layer.div(layer.max())
});
layer.print(); // *IMPORTANT: Need this line working *
console.log(layer); // *IMPORTANT: Need this line working *
//////// display grad image
var myCanvas = document.getElementById("img_predicted");
await tf.browser.toPixels(layer, myCanvas);
console.log(myCanvas)
var myCanvasContext = myCanvas.getContext("2d");
d = myCanvasContext.getImageData(0, 0, myCanvas.width, myCanvas.height);
makeColor(d.data);
makeTransparent(d.data)
myCanvasContext.putImageData(d,0,0);
// *IMPORTANT: Display on browser canvas *
}
</script>
</body>
<html>
解决方案
正如方法名所指出的executeAsync
,它是一个异步方法,它返回一个需要等待的承诺。
chestgrad = tf.grad(async x => await model.executeAsync(x)).reshape([-1].gather(2))
tf.grad 似乎不接受异步函数。所以上面的行不通。一种选择是model.execute(x)
改用。
如果您更愿意使用 model.executeAsync,则需要限制tf.grad
仅计算梯度并将异步部分移到tf.tidy
.
const batched = preprocessImage(image);
const prediction = await model.executeAsync(batched);
layer = tf.tidy(() => {
chestgrad = tf.grad(x => x.reshape([-1]).gather(2));
const grad = chestgrad(prediction);
grad.print();
const layer = grad.mean(0).abs().max(0)
return layer.div(layer.max())
});
推荐阅读
- python - 我想知道是否有任何方法可以使这行代码更短:for x in letter
- python - 更改 URL 字符串中的单个值
- asp.net - 使用 dotnet ef database update 更新表不会创建表
- javascript - 为什么“点击”事件不会触发动态添加到表格的按钮?
- javascript - 将带有&符号的字符串转换为Javascript(节点js)中的键值映射
- sql - SQL Server 2014 中的 SUM
- mysql - 我的 Mysql 选择查询每次运行时运行速度较慢
- javascript - How can i resize an image in a block display? (javascript or react)
- reactjs - 如何在 React 中存储将在一小时内到期的日期?
- azure-active-directory - AAD - 用户密码到期更改通知