如何在Python中解决"total size of new array must be unchanged error"?



我正在实现以下模型:

def ConnectomeCNNAutoencoder(input_shape, keep_pr=0.65, n_filter=32, n_dense1=64, n_classes=2, 
mode="autoencoder", sign="neg"):
input_1 = Input(shape=input_shape)
# Convolutional Encoder 
bias_init = tf.constant_initializer(value=0.001)
conv1 = Conv2D(filters=n_filter , kernel_size=(1,input_shape[1]), strides=(1, 1),
padding= "valid", activation="selu", # "selu"
kernel_initializer="glorot_uniform",
bias_initializer=bias_init, name="conv1")(input_1)
dropout1 = Dropout(keep_pr, name="dropout1")(conv1)
conv2 = Conv2D(filters=n_filter*2 , kernel_size=(input_shape[1],1), strides=(1, 1),
padding= "valid", activation="selu", 
kernel_initializer="glorot_uniform",
bias_initializer=bias_init, name="conv2")(dropout1)
encoded = Dropout(keep_pr, name="dropout2")(conv2)
# Classification
reshape = Reshape((n_filter*2,), name="reshape1")(encoded)
dense1 = Dense(n_dense1, activation="selu", name="dense1", kernel_regularizer=keras.regularizers.l1_l2())(reshape) 
if n_classes == 1:
activation = "sigmoid"
else:
activation = "softmax"
output = Dense(n_classes, activation=activation, name="output")(dense1)
# Decoder
dense2 = Dense(n_dense1, activation="selu", name="dense2")(output) 
dim_reconstruct = tuple(encoded.get_shape().as_list())
reshape2 = Reshape(dim_reconstruct[1:], name="reshape2")(dense2)
conv3 = Conv2DTranspose(filters=n_filter*2 , kernel_size=(1,1), strides=(1, 1),
padding= "valid", activation="selu", # "selu"
kernel_initializer="glorot_uniform",
bias_initializer=bias_init, name="conv3")(reshape2)
conv4 = Conv2DTranspose(filters=n_filter , kernel_size=(input_shape[1],1), strides=(1, 1),
padding= "valid", activation="selu", # "selu"
kernel_initializer="glorot_uniform",
bias_initializer=bias_init, name="conv4")(conv3)
if sign == "pos":
reconstructed_activation = "sigmoid"
elif sign == "neg":
reconstructed_activation = "tanh"

reconstructed_input = Conv2DTranspose(filters=input_shape[-1], kernel_size=(1,input_shape[1]), strides=(1, 1),
padding= "valid", activation=reconstructed_activation, 
kernel_initializer="glorot_uniform",
bias_initializer=bias_init, name='autoencoder')(conv4)
if mode == "autoencoder":
model = keras.models.Model(inputs=input_1, outputs=[output, reconstructed_input])
elif mode =="encoder":
model = keras.models.Model(inputs=input_1, outputs=encoded)
elif mode == "decoder":
model = keras.models.Model(inputs=input_1, outputs=reconstructed_input)
return model

n_filter=32n_dense1=64时,模型工作良好,但当我将这些变量更改为其他值时,会弹出此错误:"ValueError: total size of new array must be unchanged"。我知道这与在reshape2中使用重塑有关,但我不知道如何解决这个问题。

我该如何解决这个问题?

谢谢!

问题出现在这一行:

reshape2 = Reshape(dim_reconstruct[1:], name="reshape2")(dense2)

张量dense2应该是可以"转换"成dim_reconstruct[1:]形状的张量。这意味着dim_reconstruct[1:]的值的乘积应该等于dense2的形状(不包括第零维-批大小,因为keras在导出张量的维数时不计算它)。

如果n_filters = 30,dim_reconstruct[1:]将是[1, 1, 60]-因为您将n_filters乘以2。但是密集过滤器的数量必须等于[1, 1, 60]中值的乘积,即60。

我找不到任何将1d转换为3d数组的图像。但是有一个2d数组的例子:一个人不能将数组[1,2,3,4,5]放入2x3 2d数组,但可以将[1,2,3,4,5,6]转换为[[1, 2, 3], [4, 5, 6]]之类的东西

所以,你可以在调用ConnectomeCNNAutoencoder时将n_units1设置为60,或者你可以自动派生它:

# Decoder
dim_reconstruct = tuple(encoded.get_shape().as_list())  # say, (1, 1, 60)
n_dense2 = np.product(dim_reconstruct[1:])  # will be 60
dense2 = Dense(n_dense2, activation="selu", name="dense2")(output)
reshape2 = Reshape(dim_reconstruct[1:], name="reshape2")(dense2)

完整的示例(我删除了一些等于默认值的参数):

import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import Input
from tensorflow.keras.layers import Conv2D, Dropout, Reshape, Dense, Conv2DTranspose

def ConnectomeCNNAutoencoder(input_shape,
keep_pr=0.65,
n_filter=32,
n_dense1=64,
n_classes=2,
mode="autoencoder",
sign="neg"):
input_1 = Input(shape=input_shape)
# Convolutional Encoder
bias_init = tf.constant_initializer(value=0.001)
conv1 = Conv2D(filters=n_filter,
kernel_size=(1, input_shape[1]),
strides=(1, 1),
activation="selu",  # "selu"
bias_initializer=bias_init,
name="conv1")(input_1)
dropout1 = Dropout(keep_pr, name="dropout1")(conv1)
conv2 = Conv2D(filters=n_filter * 2,
kernel_size=(input_shape[1], 1),
strides=(1, 1),
activation="selu",
bias_initializer=bias_init,
name="conv2")(dropout1)
encoded = Dropout(keep_pr, name="dropout2")(conv2)
# Classification
reshape = Reshape((n_filter * 2,), name="reshape1")(encoded)
dense1 = Dense(n_dense1,
activation="selu",
name="dense1",
kernel_regularizer=keras.regularizers.l1_l2())(reshape)
if n_classes == 1:
activation = "sigmoid"
else:
activation = "softmax"
output = Dense(n_classes, activation=activation, name="output")(dense1)
# Decoder - Changes here
dim_reconstruct = tuple(encoded.get_shape().as_list())
n_dense2 = np.product(dim_reconstruct[1:])
dense2 = Dense(n_dense2, activation="selu", name="dense2")(output)
reshape2 = Reshape(dim_reconstruct[1:], name="reshape2")(dense2)
conv3 = Conv2DTranspose(filters=n_filter * 2,
kernel_size=(1, 1),
strides=(1, 1),
activation="selu",  # "selu"
bias_initializer=bias_init,
name="conv3")(reshape2)
conv4 = Conv2DTranspose(filters=n_filter,
kernel_size=(input_shape[1], 1),
strides=(1, 1),
activation="selu",  # "selu"
bias_initializer=bias_init,
name="conv4")(conv3)
if sign == "pos":
reconstructed_activation = "sigmoid"
elif sign == "neg":
reconstructed_activation = "tanh"
reconstructed_input = Conv2DTranspose(filters=input_shape[-1],
kernel_size=(1, input_shape[1]),
strides=(1, 1),
activation=reconstructed_activation,
bias_initializer=bias_init,
name='autoencoder')(conv4)
if mode == "autoencoder":
model = keras.models.Model(inputs=input_1, outputs=[output, reconstructed_input])
elif mode == "encoder":
model = keras.models.Model(inputs=input_1, outputs=encoded)
elif mode == "decoder":
model = keras.models.Model(inputs=input_1, outputs=reconstructed_input)
else:
raise ValueError("Unexpected mode: %s" % mode)
return model

model = ConnectomeCNNAutoencoder((32, 32, 3), n_filter=30, n_dense1=65)

最新更新