tf.model.predict() 在预测具有相同维度的数据时会产生值错误

Posted

技术标签:

【中文标题】tf.model.predict() 在预测具有相同维度的数据时会产生值错误【英文标题】:tf.model.predict() Produces Value Error when Predicting Data with the Same Dimensions 【发布时间】:2022-01-23 22:03:57 【问题描述】:

我在尝试使用成功训练/编译的变分自动编码器进行预测时遇到值错误。奇怪的是,我在与训练集具有相同维度的数据上使用 vae.predict()。事实上,在相同的训练数据上调用 predict 仍然会产生 Value Error。

我不明白发生了什么。值错误清楚地表明,输入预测方法的张量存在维度问题,但我不明白为什么数据在维度上都是相同的。我粘贴下面的代码——它基于代码linked here。

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
c:\Users\rzw3ch\Documents\logAnalyticsDFSS\testing.py in <module>
----> 1 reconstructions = vae.predict(normal_test_data,batch_size=128)

~\Anaconda3\lib\site-packages\keras\utils\traceback_utils.py in error_handler(*args, **kwargs)
     65     except Exception as e:  # pylint: disable=broad-except
     66       filtered_tb = _process_traceback_frames(e.__traceback__)
---> 67       raise e.with_traceback(filtered_tb) from None
     68     finally:
     69       del filtered_tb

~\Anaconda3\lib\site-packages\tensorflow\python\framework\func_graph.py in autograph_handler(*args, **kwargs)
   1127           except Exception as e:  # pylint:disable=broad-except
   1128             if hasattr(e, "ag_error_metadata"):
-> 1129               raise e.ag_error_metadata.to_exception(e)
   1130             else:
   1131               raise

ValueError: in user code:

    File "C:\Users\rzw3ch\Anaconda3\lib\site-packages\keras\engine\training.py", line 1621, in predict_function  *
        return step_function(self, iterator)
    File "C:\Users\rzw3ch\Anaconda3\lib\site-packages\keras\engine\training.py", line 1611, in step_function  **
        outputs = model.distribute_strategy.run(run_step, args=(data,))
    File "C:\Users\rzw3ch\Anaconda3\lib\site-packages\keras\engine\training.py", line 1604, in run_step  **
        outputs = model.predict_step(data)
    File "C:\Users\rzw3ch\Anaconda3\lib\site-packages\keras\engine\training.py", line 1572, in predict_step
        return self(x, training=False)
    File "C:\Users\rzw3ch\Anaconda3\lib\site-packages\keras\utils\traceback_utils.py", line 67, in error_handler
        raise e.with_traceback(filtered_tb) from None
    File "<ipython-input-12-0cad8c303831>", line 105, in call
        

    ValueError: Exception encountered when calling layer "vae_2" (type VAE).
    
    Layer "decoder" expects 1 input(s), but it received 3 input tensors. Inputs received: [<tf.Tensor 'vae_2/encoder/z_mean/BiasAdd:0' shape=(None, 8) dtype=float32>, <tf.Tensor 'vae_2/encoder/z_log_var/BiasAdd:0' shape=(None, 8) dtype=float32>, <tf.Tensor 'vae_2/encoder/sampling_2/add:0' shape=(None, 8) dtype=float32>]
    
    Call arguments received:
      • x=tf.Tensor(shape=(None, 100), dtype=float32)

代码如下:

#reassign the health labels
healthyVec['healthLabel'] = 1
unhealthyVec['healthLabel'] = 0
#recombine the healthy and unhealthy
combo = pd.concat([healthyVec,unhealthyVec])
data = combo.values
#define the x and y
y = data[:,-1]
x = data[:,0:-1]
#train, test split with sklearn
x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=.10,random_state=101)
#Need to Now define some transformers to move the distributions of the embeddings to a Guassian Distribution
from sklearn.preprocessing import QuantileTransformer, PowerTransformer
#Try different Transformations for the inputs--can just comment out the different transformers and leave only one active
#qt = QuantileTransformer(output_distribution='normal', random_state=101)
#pt = PowerTransformer(method='box-cox', standardize=True) 
#yeo-johnson can be used on any data without scaling
# pt = PowerTransformer(method='yeo-johnson', standardize=True)
#Perfornm the various transformations. Comment out the transformers as you see fit
# qt.fit(x_train)
# qt.transform(x_train)
# qt.transform(x_test)
# OR use the PowerTransformer
# pt.fit(x_train)
# pt.transform(x_train)
# pt.transform(x_test)
# Must scale data and make the inputs positive if using the box-cox transformation
# from sklearn.preprocessing import StandardScaler
# scaler = StandardScaler()
# scaler.fit(x_train)
# scaler.transform(x_train)
# scaler.transform(x_test)
#normalize the embeddings
min_val = tf.reduce_min(x_train)
max_val = tf.reduce_max(x_train)
x_train = (x_train - min_val) / (max_val-min_val)
x_test = (x_test - min_val) / (max_val-min_val)
#cast embeddings to float32
x_train = tf.cast(x_train,tf.float32)
x_test = tf.cast(x_test,tf.float32)
#make sure the labels are boolean type
y_train = y_train.astype(bool)
y_test = y_test.astype(bool)
#define the normal training / test and the anomalous training and test
normal_train_data = x_train[y_train]
normal_test_data = x_test[y_test]
anomalous_train_data = x_train[~y_train]
anomalous_test_data = x_test[~y_test]

class Sampling(layers.Layer):
    """Uses (z_mean, z_log_var) to sample z, the vector encoding a digit."""

    def call(self, inputs):
        z_mean, z_log_var = inputs
        batch = tf.shape(z_mean)[0]
        dim = tf.shape(z_mean)[1]
        epsilon = tf.keras.backend.random_normal(shape=(batch, dim))
        return z_mean + tf.exp(0.5 * z_log_var) * epsilon

def encoder_model(normal_train_data):
    encoder_inputs = tf.keras.Input(shape=(normal_train_data.shape[1]))
    x = layers.Dense(80, activation="relu")(encoder_inputs)
    x = layers.Dense(60, activation="relu")(x)
    x = layers.Dense(40, activation="relu")(x)
    x = layers.Dense(20, activation="relu")(x)
    x = layers.Dense(8, activation="relu")(x)
    
    # So far we just copied the network from above
    # Now we generate the latent space of mean and log-variance, in this case of dimension 30
    z_mean = layers.Dense(8, name="z_mean")(x)
    z_log_var = layers.Dense(8, name="z_log_var")(x)
    
    # Sample from these distributions
    z = Sampling()([z_mean, z_log_var])
    
    encoder = tf.keras.Model(encoder_inputs, [z_mean, z_log_var, z], name="encoder")
    return encoder

def decoder_model(normal_train_data):
    # Recreate the network we used for the 'normal' autoencoder
    latent_inputs = tf.keras.Input(shape=(8,))
    x = layers.Dense(20, activation="relu")(latent_inputs)
    x = layers.Dense(40, activation="relu")(x)
    x = layers.Dense(60, activation="relu")(x)
    x = layers.Dense(80, activation="relu")(x)
    decoder_outputs = layers.Dense(normal_train_data.shape[1], activation="relu")(x)
    decoder = tf.keras.Model(latent_inputs, decoder_outputs, name="decoder")
    return decoder

class VAE(tf.keras.Model):
    def __init__(self, encoder, decoder, **kwargs):
        super(VAE, self).__init__(**kwargs)
        self.encoder = encoder
        self.decoder = decoder

    def train_step(self, data):
        if isinstance(data, tuple):
            data = data[0]
        with tf.GradientTape() as tape:
            z_mean, z_log_var, z = self.encoder(data)
            reconstruction = self.decoder(z)
            reconstruction_loss = tf.reduce_mean(
                tf.keras.losses.binary_crossentropy(data, reconstruction)
            )
            kl_loss = 1 + z_log_var - tf.square(z_mean) - tf.exp(z_log_var)
            kl_loss = tf.reduce_mean(kl_loss)
            kl_loss *= -0.5
            total_loss = reconstruction_loss + kl_loss
        grads = tape.gradient(total_loss, self.trainable_weights)
        self.optimizer.apply_gradients(zip(grads, self.trainable_weights))
        return 
            "loss": total_loss,
            "reconstruction_loss": reconstruction_loss,
            "kl_loss": kl_loss,
        
    def test_step(self, data):
        if isinstance(data, tuple):
            data = data[0]
        with tf.GradientTape() as tape:
            z_mean, z_log_var, z = self.encoder(data)
            reconstruction = self.decoder(z)
            val_reconstruction_loss = tf.reduce_mean(
                tf.keras.losses.binary_crossentropy(data, reconstruction)
            )
            val_kl_loss = 1 + z_log_var - tf.square(z_mean) - tf.exp(z_log_var)
            val_kl_loss = tf.reduce_mean(val_kl_loss)
            val_kl_loss *= -0.5
            val_total_loss = val_reconstruction_loss + val_kl_loss
        grads = tape.gradient(val_total_loss, self.trainable_weights)
        self.optimizer.apply_gradients(zip(grads, self.trainable_weights))
        return 
            "val_loss": val_total_loss,
            "val_reconstruction_loss": val_reconstruction_loss,
            "val_kl_loss": val_kl_loss,
        
    def call(self, x):
        encoded = self.encoder(x)
        decoded = self.decoder(encoded)
        return decoded

# Get the encoder and decoder models
encoder = encoder_model(normal_train_data)
decoder = decoder_model(normal_train_data)

# Get the combined model
vae = VAE(encoder, decoder)

# Compile the model
vae.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.00001))

# Fit the model to the training set
# history = vae.fit(normal_train_data,normal_train_data,epochs=20,batch_size=128,validation_data=(x_test,x_test),shuffle=True)
history = vae.fit(normal_train_data,normal_train_data,epochs=20,batch_size=128,shuffle=True)

预测代码很简单

reconstructions = vae.predict(normal_test_data)

我可以确认所有张量都具有相同的维度:

<tf.Tensor: shape=(1515272, 100), dtype=float32, numpy=
<tf.Tensor: shape=(168320, 100), dtype=float32, numpy=
<tf.Tensor: shape=(546540, 100), dtype=float32, numpy=
<tf.Tensor: shape=(60771, 100), dtype=float32, numpy=

【问题讨论】:

该错误与数据的形状无关。问题是编码器返回 3 个输出 [z_mean, z_log_var, z],每个形状为 8,而解码器只需要 1 个形状为 8 (latent_inputs) 的输入,因此 call() 方法中的这一行 self.decoder(encoded) 会引发错误. 原谅我,我有点新,所以更清楚需要修复的内容会有所帮助。需要重构/考虑什么? 您需要将self.decoder(encoded)替换为self.decoder(encoded[-1]),因为解码器只需要编码器的最后一个输出(即z)。 这似乎有效!非常感谢:) 【参考方案1】:

您需要将 self.decoder(encoded) 替换为 self.decoder(encoded[-1]),因为解码器只需要编码器的最后一个输出(即 z)。 – 弗拉维亚·贾马里诺 9 分钟前

这似乎是答案

【讨论】:

如果您将工作脚本部分发布给未来的读者,那就太好了。

以上是关于tf.model.predict() 在预测具有相同维度的数据时会产生值错误的主要内容,如果未能解决你的问题,请参考以下文章

将 Pyspark Python k-means 模型预测插入具有原始 RDD 项和特征的 DF

技术基于负极主导区间的电池神经网络老化预测

BP回归预测基于matlab随机蛙跳算法SFLA优化神经网络数据回归预测含Matlab源码 2272期

如何绘制新数据的预测与 R 中的 gee、lme、glmer 和 gamm4 相匹配?

线性相关|回归分析|

无人机数字孪生算法研究