如何在TensorFlow中存储AlexNet的5个无偏置中间卷积结果
问题描述
我需要将AlexNet中5个卷积层未加偏置的中间卷积结果保存为.npy文件,于是在conv函数中添加了np.save("conv_golden", conv)代码,执行时却报错:
NotImplementedError: Cannot convert a symbolic tf.Tensor (Conv2D: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.
我的conv函数代码如下:
def conv(input, kernel, biases, k_h, k_w, c_o, s_h, s_w, padding="VALID", group=1): '''From https://github.com/ethereon/caffe-tensorflow ''' c_i = input.get_shape()[-1] assert c_i%group==0 assert c_o%group==0 convolve = lambda i,k: tf.nn.conv2d(i,k,[1,s_h,s_w,1],padding=padding) if group==1: conv = convolve(input, kernel) else: input_groups = tf.split(input, group, 3) #tf.split(3, group, input) kernel_groups = tf.split(kernel, group, 3) #tf.split(3, group, kernel) output_groups = [convolve(i, k) for i,k in zip(input_groups, kernel_groups)] conv = tf.concat(output_groups, 3) #tf.concat(3, output_groups) np.save("conv_golden", conv) # <-------- added code print("conv input shape :", input.shape, ", filter shape :", kernel.shape, ", conv result(no bias) shape :", conv.shape) return tf.reshape(tf.nn.bias_add(conv,biases), [-1]+conv.get_shape().as_list()[1:])
解决方案
报错核心原因:TensorFlow中,你当前操作的conv是符号张量,仅定义了计算逻辑,还没有实际数值,无法直接转换为NumPy数组保存。必须等张量获得实际计算值后,再执行保存操作,以下是两种可行方案:
方案1:在函数内判断执行时机,按层保存
修改conv函数,添加层索引参数区分不同卷积层的结果文件,仅当张量有实际数值时执行保存:
def conv(input, kernel, biases, k_h, k_w, c_o, s_h, s_w, padding="VALID", group=1, layer_idx=0): '''From https://github.com/ethereon/caffe-tensorflow ''' c_i = input.get_shape()[-1] assert c_i%group==0 assert c_o%group==0 convolve = lambda i,k: tf.nn.conv2d(i,k,[1,s_h,s_w,1],padding=padding) if group==1: conv = convolve(input, kernel) else: input_groups = tf.split(input, group, 3) #tf.split(3, group, input) kernel_groups = tf.split(kernel, group, 3) #tf.split(3, group, kernel) output_groups = [convolve(i, k) for i,k in zip(input_groups, kernel_groups)] conv = tf.concat(output_groups, 3) #tf.concat(3, output_groups) # 仅当张量有实际数值时保存(即时执行模式下生效) if tf.executing_eagerly(): # 用layer_idx区分5个卷积层的结果文件,避免覆盖 np.save(f"conv_golden_layer_{layer_idx}.npy", conv.numpy()) print("conv input shape :", input.shape, ", filter shape :", kernel.shape, ", conv result(no bias) shape :", conv.shape) return tf.reshape(tf.nn.bias_add(conv,biases), [-1]+conv.get_shape().as_list()[1:])
调用卷积层时,给每个层传入唯一的layer_idx参数(比如第一个卷积层传layer_idx=0,第二个传layer_idx=1,以此类推),最终会生成conv_golden_layer_0.npy到conv_golden_layer_4.npy共5个文件。
方案2:推理时手动提取结果保存
如果你的代码是按推理流程运行,可以修改conv函数返回无偏置结果,再在外部手动保存:
- 修改
conv函数,增加无偏置张量的返回值:
def conv(input, kernel, biases, k_h, k_w, c_o, s_h, s_w, padding="VALID", group=1): # ... 原有代码逻辑不变 ... # 保留无偏置的卷积结果,作为额外返回值 return tf.reshape(tf.nn.bias_add(conv,biases), [-1]+conv.get_shape().as_list()[1:]), conv
- 在推理循环中逐个调用卷积层并保存:
# 假设已加载好输入数据input_data、各层权重kernels、偏置biases for layer_idx in range(5): # 替换为对应层的参数(比如kernel、biases、卷积核尺寸等) output, conv_no_bias = conv(input_data, kernels[layer_idx], biases[layer_idx], k_h=11, k_w=11, c_o=96, s_h=4, s_w=4, padding="VALID", group=1) # 保存当前层无偏置结果 np.save(f"conv_golden_layer_{layer_idx}.npy", conv_no_bias.numpy()) # 更新输入为当前层输出,作为下一层的输入 input_data = output
关键注意点
- TensorFlow 2.x默认启用即时执行模式,但如果代码用
@tf.function装饰(转为计算图模式),符号张量无法直接转NumPy,此时需要在装饰器外保存,或用tf.py_function包装保存逻辑。 - 必须确保传入实际输入数据后,张量有了具体数值,才能调用
.numpy()方法转换为NumPy数组,再执行np.save()。
内容的提问来源于stack exchange,提问作者Seil Lee
相关产品推荐
相关产品推荐

