Keras前后尺寸一致却依然报错'ValueError: total size of new array must be unchanged'的原因

本文介绍了解决TensorFlow中Reshape操作时遇到的'ValueError: totalsize of new array must be unchanged'错误的方法。重点在于正确设置Lambda层的output_shape属性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    某些情况下我们需要对张量进行维度变换,一般可以通过调用以下两种方法实现:

# 1. TensorFlow自带
tf.reshape(tensor, target_shape)  


# 2. (推荐)Keras中的Reshape层。如果用第一种方法的话,最后构建Model的时候可能会报错:
#     AttributeError: 'NoneType' object has no attribute '_inbound_nodes'
Reshape(target_shape)(tensor)  

    一般来说Reshape操作必须要满足变换前后总Elements数量不变。例如某维度为[2,4,8]的张量可以变换为[2,8,4]、[8,8]、[64]的形式。在Keras中可能显示为[?,2,4,8]的形式,其中‘?’代表输入尺寸,不影响结果。

    但有时候即使前后尺寸完全一致,但依然报错'ValueError: total size of new array must be unchanged'就很让人怀疑人生了(如下):

print(z.get_shape())  # 查看张量z的shape
z_reshape = Reshape([4498, 2])(z)  # 变换为同一shape
z尺寸也为[?,4998,2]
明明尺寸一样!!

因为这个报错百思不得其解,看了中外无数个帖子、博客,快被逼疯!!经过多轮调试终于知道问题出在哪儿了:

 

产生原因:

    问题出现在张量z是怎么得到上:是不是通过Lambda包装了自定义的操作?其output_shapes属性至关重要。本文的Z的产生过程如下:

def sampling(args):
    mean, log = args
    epsilon = K.random_normal(shape=K.shape(mean))
    return tf.math.sqrt(log) * epsilon + mean

# 通过sampling函数获得的结果. z_mean/z_log的shape均为[?,4498,2]
z = Lambda(sampling, output_shape=(2,), name='output_z')([z_mean, z_log])

通过output_shapes产生的维度是可操作的,而其它维度将被锁定。拿本例来说,正常情况下张量z [?,4498,2]只要符合尺寸乘积等于4498*2=8996即可。但由于我指定了output_shapes=(2,),它所产生的[?, 4498, 2]张量中我们只能对最后的2进行Reshape操作。比如:

z_reshape = Reshape([1, 2])(z) 
# 结果为[?, 4498, 1, 2]

z_reshape = Reshape([2, 1])(z) 
# 结果为[?, 4498, 2, 1]

z_reshape = Reshape([1, 1, 2])(z) 
# 结果为[?, 4498, 1, 1, 2]

 

解决办法

    准确指定output_shapes!!!不要只写最后一维就完了。

#  这是原先sampling的函数体,放一起了
epsilon = K.random_normal(shape=K.shape(mean))
return tf.math.sqrt(log) * epsilon + mean

# 获得的结果
z = Lambda(sampling, output_shape=(4498, 2), name='output_z')([z_mean, z_log])

# 再进行转换成功!
z_reshape = Reshape([2249, 4])(z)

此时通过Lambda产生的张量z [?, 4498, 2]中44982都是output_shapes已经声明过的,接下来只要target_shape之积等于4498*2=8996就能成功啦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值