Why do I receive the Error: Tensor is disposed, when using tf.grad() to implement FGSM?
Why do I receive the Error: Tensor is disposed, when using tf.grad() to implement FGSM?
我正在尝试使用 tensorflow.js 在 MobileNet 上实现快速梯度符号法 (FGSM),但是在使用 [= 计算梯度时我在最新版本 (1.0.1) 上遇到了问题38=]().
代码在 tfjs 0.13.0 及以下版本中运行良好,但是更新到任何更高版本都会导致以下错误:
core.js:15723 ERROR Error: Uncaught (in promise): Error: Tensor is disposed. Error: Tensor is disposed.
at e.throwIfDisposed (tf-core.esm.js:17)
at e.greaterEqual (tf-core.esm.js:17)
at Object.$x (tf-core.esm.js:17)
at n (tf-core.esm.js:17)
at backpropagateGradients (tf-core.esm.js:17)
at tf-core.esm.js:17
at tf-core.esm.js:17
at e.scopedRun (tf-core.esm.js:17)
at e.tidy (tf-core.esm.js:17)
at e.gradients (tf-core.esm.js:17)
at resolvePromise (zone.js:831)
at zone.js:896
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423)
at Object.onInvokeTask (core.js:17289)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:422)
at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:195)
at drainMicroTaskQueue (zone.js:601)
at push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask (zone.js:502)
at ZoneTask.invoke (zone.js:487)
at timer (zone.js:2281)
调用tf.grad(lossFunction)
时出现错误:
任何 help/insight 不胜感激!
完整代码:
let canvas = <HTMLCanvasElement> document.getElementById('canvas')
let img = tf.browser.fromPixels(canvas, 3) //let img = tf.fromPixels(canvas, 3)
let img4 = tf.browser.fromPixels(canvas, 4) //let img4 = tf.fromPixels(canvas, 4)
let model = mobilenet.load().then(model =>
{
var output = model.classify(img, 3).then(predictions =>
{
let tbuffer = tf.buffer([1000])
var labelClasses = IMAGENET_CLASSES
let targetClass = predictions[0].className
Object.keys(labelClasses).forEach(function(key)
{
if (labelClasses[key].valueOf() == targetClass.valueOf())
{
tbuffer.set(1, parseInt(key));
}
})
const oneHotLabels = tbuffer.toTensor()
const getModelLogits = x => model.infer(x)
const lossFunction = x => tf.losses.softmaxCrossEntropy(oneHotLabels, getModelLogits(x).as1D())
const gradientFunction = tf.grad(lossFunction)
var gradient = gradientFunction(img)
// scale the gradient and apply to original image
var perturbation = this.scaleGradient(gradient, 50)
const zeroes = new Uint8Array(224*224).fill(0)
let alphaChannel = tf.tensor3d(zeroes, [224, 224, 1])
let perturbationWithAlpha = tf.concat([perturbation, alphaChannel], 2)
var adversarialImage = tf.add(tf.cast(img4,'float32'), perturbationWithAlpha)
// Draw adversarial image to canvas
var context = canvas.getContext("2d")
let imgArray = Uint8ClampedArray.from(adversarialImage.dataSync());
let imgData = context.createImageData(this.imgHeight, this.imgWidth);
imgData.data.set(imgArray);
context.putImageData(imgData, 0, 0);
})
})
此处提供完整的回购协议:https://github.com/BenMcFadyen/tfjsFGSM
https://github.com/BenMcFadyen/tfjsFGSM/blob/master/src/app/app.component.ts
FGSM 代码最初来自:https://github.com/jaxball/advis.js
full trace
successful execution on tensorflow/tfjs@0.13.0, tensorflow-models/mobilenet@0.2.2
tensorflow-models/mobilenet@0.2.2 是一个 tf.LayersModel
,它提供梯度,因此可以重新训练。然而 tensorflow-models/mobilenet@1.0.0 在 https://github.com/tensorflow/tfjs-models/pull/161 中被更改为 tf.GraphModel
,以便从 TF-Hub 提供 MobileNet V2。 GraphModels 不提供渐变,因此您的代码不再有效。
我认为你有几条可能的前进道路:
- 如果它们满足您的需要,请坚持使用工作版本(tensorflow-models/mobilenet@0.2.2 应该可以与 tfjs 一起工作到 0.15.3,尽管这会产生弃用警告)。
- 在 PR #156 分支 tensorflow/tfjs-models 并在那里构建 mobilenet 包。
那和0.2.2是一样的,只是它可以和tfjs一起使用>1.0.0.
- 从 head 中分叉 tensorflow/tfjs-models,并将模型加载部分还原为使用
tf.loadLayersModel()
和在 #161 中删除的 BASE_PATH。 (这只会让你获得 V1)。
- 获取 Keras .h5 格式的 MobileNet V2(例如,从 here) and use the TF.js converter 获取
tf.LayersModel
.
我重现了错误并手动验证 https://github.com/tensorflow/tfjs-core/pull/1604 修复了它。修复将在下一个 TF.js 版本 (1.0.2
) 中发布,我们计划在本周末发布。
即使 MobileNet 现在是 tf.GraphModel
而不是 tf.LayersModel
,梯度仍然有效,因为该库很急切并且可以即时计算梯度。
我正在尝试使用 tensorflow.js 在 MobileNet 上实现快速梯度符号法 (FGSM),但是在使用 [= 计算梯度时我在最新版本 (1.0.1) 上遇到了问题38=]().
代码在 tfjs 0.13.0 及以下版本中运行良好,但是更新到任何更高版本都会导致以下错误:
core.js:15723 ERROR Error: Uncaught (in promise): Error: Tensor is disposed. Error: Tensor is disposed.
at e.throwIfDisposed (tf-core.esm.js:17)
at e.greaterEqual (tf-core.esm.js:17)
at Object.$x (tf-core.esm.js:17)
at n (tf-core.esm.js:17)
at backpropagateGradients (tf-core.esm.js:17)
at tf-core.esm.js:17
at tf-core.esm.js:17
at e.scopedRun (tf-core.esm.js:17)
at e.tidy (tf-core.esm.js:17)
at e.gradients (tf-core.esm.js:17)
at resolvePromise (zone.js:831)
at zone.js:896
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423)
at Object.onInvokeTask (core.js:17289)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:422)
at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:195)
at drainMicroTaskQueue (zone.js:601)
at push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask (zone.js:502)
at ZoneTask.invoke (zone.js:487)
at timer (zone.js:2281)
调用tf.grad(lossFunction)
时出现错误:
任何 help/insight 不胜感激!
完整代码:
let canvas = <HTMLCanvasElement> document.getElementById('canvas')
let img = tf.browser.fromPixels(canvas, 3) //let img = tf.fromPixels(canvas, 3)
let img4 = tf.browser.fromPixels(canvas, 4) //let img4 = tf.fromPixels(canvas, 4)
let model = mobilenet.load().then(model =>
{
var output = model.classify(img, 3).then(predictions =>
{
let tbuffer = tf.buffer([1000])
var labelClasses = IMAGENET_CLASSES
let targetClass = predictions[0].className
Object.keys(labelClasses).forEach(function(key)
{
if (labelClasses[key].valueOf() == targetClass.valueOf())
{
tbuffer.set(1, parseInt(key));
}
})
const oneHotLabels = tbuffer.toTensor()
const getModelLogits = x => model.infer(x)
const lossFunction = x => tf.losses.softmaxCrossEntropy(oneHotLabels, getModelLogits(x).as1D())
const gradientFunction = tf.grad(lossFunction)
var gradient = gradientFunction(img)
// scale the gradient and apply to original image
var perturbation = this.scaleGradient(gradient, 50)
const zeroes = new Uint8Array(224*224).fill(0)
let alphaChannel = tf.tensor3d(zeroes, [224, 224, 1])
let perturbationWithAlpha = tf.concat([perturbation, alphaChannel], 2)
var adversarialImage = tf.add(tf.cast(img4,'float32'), perturbationWithAlpha)
// Draw adversarial image to canvas
var context = canvas.getContext("2d")
let imgArray = Uint8ClampedArray.from(adversarialImage.dataSync());
let imgData = context.createImageData(this.imgHeight, this.imgWidth);
imgData.data.set(imgArray);
context.putImageData(imgData, 0, 0);
})
})
此处提供完整的回购协议:https://github.com/BenMcFadyen/tfjsFGSM https://github.com/BenMcFadyen/tfjsFGSM/blob/master/src/app/app.component.ts
FGSM 代码最初来自:https://github.com/jaxball/advis.js
full trace
successful execution on tensorflow/tfjs@0.13.0, tensorflow-models/mobilenet@0.2.2
tensorflow-models/mobilenet@0.2.2 是一个 tf.LayersModel
,它提供梯度,因此可以重新训练。然而 tensorflow-models/mobilenet@1.0.0 在 https://github.com/tensorflow/tfjs-models/pull/161 中被更改为 tf.GraphModel
,以便从 TF-Hub 提供 MobileNet V2。 GraphModels 不提供渐变,因此您的代码不再有效。
我认为你有几条可能的前进道路:
- 如果它们满足您的需要,请坚持使用工作版本(tensorflow-models/mobilenet@0.2.2 应该可以与 tfjs 一起工作到 0.15.3,尽管这会产生弃用警告)。
- 在 PR #156 分支 tensorflow/tfjs-models 并在那里构建 mobilenet 包。 那和0.2.2是一样的,只是它可以和tfjs一起使用>1.0.0.
- 从 head 中分叉 tensorflow/tfjs-models,并将模型加载部分还原为使用
tf.loadLayersModel()
和在 #161 中删除的 BASE_PATH。 (这只会让你获得 V1)。 - 获取 Keras .h5 格式的 MobileNet V2(例如,从 here) and use the TF.js converter 获取
tf.LayersModel
.
我重现了错误并手动验证 https://github.com/tensorflow/tfjs-core/pull/1604 修复了它。修复将在下一个 TF.js 版本 (1.0.2
) 中发布,我们计划在本周末发布。
即使 MobileNet 现在是 tf.GraphModel
而不是 tf.LayersModel
,梯度仍然有效,因为该库很急切并且可以即时计算梯度。