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期