TensorFlow中DeepDream代码报错:无法转换符号tf.Tensor为NumPy数组
DeepDream代码运行报错:NotImplementedError
错误信息
NotImplementedError: Cannot convert a symbolictf.Tensor(Mean:0) to a numpy array.
This error may indicate that you're trying to pass a Tensor to a NumPy call, which is not supported.
运行代码
import tensorflow as tf import pandas as pd import numpy as np import seaborn as sns import matplotlib.pyplot as plt import random base_model = tf.keras.applications.InceptionV3(include_top=False, weights='imagenet') base_model.summary() names = ['mixed3','mixed5'] layers = [base_model.get_layer(name).output for name in names] deepdream_model = tf.keras.Model(inputs=base_model.input, outputs=layers) Sample_Image = tf.keras.preprocessing.image.load_img(r'apple.jpg', target_size =(225, 375)) np.shape(Sample_Image) Sample_Image = np.array(Sample_Image)/255.0 Sample_Image.shape plt.imshow(Sample_Image) Sample_Image.max() Sample_Image.min() Sample_Image = tf.keras.preprocessing.image.img_to_array(Sample_Image) Sample_Image.shape Sample_Image = tf.Variable(tf.keras.applications.inception_v3.preprocess_input(Sample_Image)) Sample_Image = tf.expand_dims(Sample_Image, axis = 0) np.shape(Sample_Image) activations = deepdream_model(Sample_Image) def calc_loss(image, model): img_batch = tf.expand_dims(image, axis=0) layer_activations = model(img_batch) print('VALORES DE ACTIVACION (LAYER OUTPUT) =\n', layer_activations) losses = [] for act in layer_activations: loss = tf.math.reduce_mean(act) losses.append(loss) print('PERDIDAS (DE MULTIPLES CAPAS DE ACTIVACION) = ', losses) print('FORMA DE PERDIDA (DE MULTIPLES CAPAS DE ACTIVACION) =', np.shape(losses)) print('SUMA DE TODAS LAS CAPAS PERDIDAS (DE TODAS LAS CAPAS SELECCIONADAS) =', tf.reduce_sum(losses)) return tf.reduce_sum(losses) Sample_Image = tf.keras.preprocessing.image.load_img(r'apple.jpg', target_size =(225, 375)) Sample_Image = np.array(Sample_Image)/255.0 Sample_Image = tf.keras.preprocessing.image.img_to_array(Sample_Image) Sample_Image = tf.Variable(tf.keras.applications.inception_v3.preprocess_input(Sample_Image)) loss = calc_loss(Sample_Image, deepdream_model) loss @tf.function def deepdream(model, image, step_size): with tf.GradientTape() as tape: tape.watch(image) loss = calc_loss(image, model) gradients = tape.gradient(loss, image) print('GRADIENTES = \n', gradients) print('FORMA DE GRADIENTES =\n', np.shape(gradients)) gradients /= tf.math.reduce_std(gradients) image = image + gradients * step_size image = tf.clip_by_value(image, -1, 1) return loss, image def run_deep_dream_simple(model, image, steps=100, step_size=0.01): image = tf.keras.applications.inception_v3.preprocess_input(image) for step in range(steps): loss, image = deepdream(model, image, step_size) if step % 100 == 0: plt.figure(figsize=(12, 12)) plt.imshow(deprocess(image)) plt.show() print("Step {}, loss{}".format(step, loss)) plt.figure(figsize=(12, 12)) plt.imshow(deprocess(image)) plt.show() return deprocess(image) def deprocess(image): image = 255 * (image + 1.0) / 2.0 return tf.cast(image, tf.uint8) Sample_Image= tf.keras.preprocessing.image.load_img(r'apple.jpg', target_size = (225, 375)) Sample_Image = np.array(Sample_Image) dream_img = run_deep_dream_simple(model=deepdream_model, image=Sample_Image, steps=2000, step_size=0.001)
问题分析与修复方案
核心错误原因
报错根源是在@tf.function装饰的图模式函数中,调用了numpy的API处理符号张量:
calc_loss里的np.shape(losses)试图将符号张量列表转换为numpy数组,图模式下不支持这种操作deepdream函数里的np.shape(gradients)存在同样问题- 最后一段运行代码错误缩进在
deprocess函数内部,导致逻辑无法正常执行
修复步骤
1. 替换numpy操作为TensorFlow原生方法
把所有np.shape()替换为TensorFlow的tf.shape()或张量自身的.shape属性,同时将普通print改为tf.print适配图模式:
# 修改calc_loss中的打印逻辑 def calc_loss(image, model): img_batch = tf.expand_dims(image, axis=0) layer_activations = model(img_batch) tf.print('VALORES DE ACTIVACION (LAYER OUTPUT) =\n', layer_activations) losses = [tf.math.reduce_mean(act) for act in layer_activations] tf.print('PERDIDAS (DE MULTIPLES CAPAS DE ACTIVACION) = ', losses) tf.print('FORMA DE PERDIDA (DE MULTIPLES CAPAS DE ACTIVACION) =', [tf.shape(l) for l in losses]) total_loss = tf.reduce_sum(losses) tf.print('SUMA DE TODAS LAS CAPAS PERDIDAS (DE TODAS LAS CAPAS SELECCIONADAS) =', total_loss) return total_loss # 修改deepdream中的打印逻辑 @tf.function def deepdream(model, image, step_size): with tf.GradientTape() as tape: tape.watch(image) loss = calc_loss(image, model) gradients = tape.gradient(loss, image) tf.print('GRADIENTES = \n', gradients) tf.print('FORMA DE GRADIENTES =\n', tf.shape(gradients)) gradients /= tf.math.reduce_std(gradients) image = image + gradients * step_size image = tf.clip_by_value(image, -1, 1) return loss, image
2. 修复代码缩进错误
将最后一段加载图片并运行DeepDream的代码移到deprocess函数外部:
def deprocess(image): image = 255 * (image + 1.0) / 2.0 return tf.cast(image, tf.uint8) # 移到函数外部,保证正常执行 Sample_Image= tf.keras.preprocessing.image.load_img(r'apple.jpg', target_size = (225, 375)) Sample_Image = np.array(Sample_Image) dream_img = run_deep_dream_simple(model=deepdream_model, image=Sample_Image, steps=2000, step_size=0.001)
3. (可选)移除调试打印
如果不需要调试信息,可以直接删除所有打印语句,进一步避免图模式下的张量交互问题。
内容的提问来源于stack exchange,提问作者ROMERO VISOSO
相关产品推荐
相关产品推荐

