TensorFlow 2.x: Cannot load trained model in h5 format when using embedding columns (ValueError: Shapes (101, 15) and (57218, 15) are incompatible)
TensorFlow 2.x: Cannot load trained model in h5 format when using embedding columns (ValueError: Shapes (101, 15) and (57218, 15) are incompatible)
来回折腾了很久,我终于保存了我的模型(见我的问题)。但是现在我在加载保存的模型时遇到问题。首先我通过加载模型得到以下错误:
ValueError: You are trying to load a weight file containing 1 layers into a model with 0 layers.
将顺序更改为函数后 API 我收到以下错误:
ValueError: Cannot assign to variable dense_features/NAME1W1_embedding/embedding_weights:0 due to variable shape (101, 15) and value shape (57218, 15) are incompatible
我尝试了不同版本的 TensorFlow。我在版本 tf-nightly 中遇到了描述的错误。在 2.1 版中我得到了一个非常相似的错误:
ValueError: Shapes (101, 15) and (57218, 15) are incompatible.
在 2.2 和 2.3 版本中,我什至无法保存我的模型(如我之前的问题所述)。
这里是函数的相关代码API:
def __loadModel(args):
filepath = args.loadModel
model = tf.keras.models.load_model(filepath)
print("start preprocessing...")
(_, _, test_ds) = preprocessing.getPreProcessedDatasets(args.data, args.batchSize)
print("preprocessing completed")
_, accuracy = model.evaluate(test_ds)
print("Accuracy", accuracy)
def __trainModel(args):
(train_ds, val_ds, test_ds) = preprocessing.getPreProcessedDatasets(args.data, args.batchSize)
for bucketSizeGEO in args.bucketSizeGEO:
print("start preprocessing...")
feature_columns = preprocessing.getFutureColumns(args.data, args.zip, bucketSizeGEO, True)
#Todo: compare trainable=False to trainable=True
feature_layer = tf.keras.layers.DenseFeatures(feature_columns, trainable=False)
print("preprocessing completed")
feature_layer_inputs = preprocessing.getFeatureLayerInputs()
feature_layer_outputs = feature_layer(feature_layer_inputs)
output_layer = tf.keras.layers.Dense(1, activation=tf.nn.sigmoid)(feature_layer_outputs)
model = tf.keras.Model(inputs=[v for v in feature_layer_inputs.values()], outputs=output_layer)
model.compile(optimizer='sgd',
loss='binary_crossentropy',
metrics=['accuracy'])
paramString = "Arg-e{}-b{}-z{}".format(args.epoch, args.batchSize, bucketSizeGEO)
log_dir = "logs\logR\" + paramString + datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=1)
model.fit(train_ds,
validation_data=val_ds,
epochs=args.epoch,
callbacks=[tensorboard_callback])
model.summary()
loss, accuracy = model.evaluate(test_ds)
print("Accuracy", accuracy)
paramString = paramString + "-a{:.4f}".format(accuracy)
outputName = "logReg" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S") + paramString
if args.saveModel:
for i, w in enumerate(model.weights): print(i, w.name)
path = './saved_models/' + outputName + '.h5'
model.save(path, save_format='h5')
相关预处理部分见本题开头提到的问题。 for i, w in enumerate(model.weights): print(i, w.name)
returns 以下内容:
0 dense_features/NAME1W1_embedding/embedding_weights:0
1 dense_features/NAME1W2_embedding/embedding_weights:0
2 dense_features/STREETW_embedding/embedding_weights:0
3 dense_features/ZIP_embedding/embedding_weights:0
4 dense/kernel:0
5 dense/bias:0
这个问题是由于训练和预测中embedding矩阵的维数不一致造成的
通常我们在使用嵌入矩阵之前,会形成一个字典。这里我们暂且称这个字典为word_index。如果代码作者考虑不周,会导致训练和预测出现两个不同的words_index(因为训练和预测使用的数据不同),嵌入矩阵的维数发生变化。
从你的bug可以看出你训练时得到len(word_index)+1是57218,预测时得到len(word_index)+1是101
如果我们想要运行代码正确,当我们需要使用word_index的预测时,我们不能在预测期间重新生成一个word_index。所以这个问题最简单的解决办法就是把你训练的时候得到的word_index保存下来,在预测的时候调用,这样我们就可以正确的加载我们训练的时候得到的权重
我能够解决我相当愚蠢的错误:
我正在使用 feature_column 库来预处理我的数据。不幸的是,我在函数 categorical_column_with_identity 的参数 num_buckets 中指定了一个固定的而非实际大小的词汇列表。
错误的版本:
street_voc = tf.feature_column.categorical_column_with_identity(
key='STREETW', num_buckets=100)
正确版本:
street_voc = tf.feature_column.categorical_column_with_identity(
key='STREETW', num_buckets= __getNumberOfWords(data, 'STREETPRO') + 1)
函数 __getNumberOfWords(data, 'STREETPRO')
returns pandas 数据帧的 'STREETPRO' 列中不同单词的数量。
来回折腾了很久,我终于保存了我的模型(见我的问题
ValueError: You are trying to load a weight file containing 1 layers into a model with 0 layers.
将顺序更改为函数后 API 我收到以下错误:
ValueError: Cannot assign to variable dense_features/NAME1W1_embedding/embedding_weights:0 due to variable shape (101, 15) and value shape (57218, 15) are incompatible
我尝试了不同版本的 TensorFlow。我在版本 tf-nightly 中遇到了描述的错误。在 2.1 版中我得到了一个非常相似的错误:
ValueError: Shapes (101, 15) and (57218, 15) are incompatible.
在 2.2 和 2.3 版本中,我什至无法保存我的模型(如我之前的问题所述)。
这里是函数的相关代码API:
def __loadModel(args):
filepath = args.loadModel
model = tf.keras.models.load_model(filepath)
print("start preprocessing...")
(_, _, test_ds) = preprocessing.getPreProcessedDatasets(args.data, args.batchSize)
print("preprocessing completed")
_, accuracy = model.evaluate(test_ds)
print("Accuracy", accuracy)
def __trainModel(args):
(train_ds, val_ds, test_ds) = preprocessing.getPreProcessedDatasets(args.data, args.batchSize)
for bucketSizeGEO in args.bucketSizeGEO:
print("start preprocessing...")
feature_columns = preprocessing.getFutureColumns(args.data, args.zip, bucketSizeGEO, True)
#Todo: compare trainable=False to trainable=True
feature_layer = tf.keras.layers.DenseFeatures(feature_columns, trainable=False)
print("preprocessing completed")
feature_layer_inputs = preprocessing.getFeatureLayerInputs()
feature_layer_outputs = feature_layer(feature_layer_inputs)
output_layer = tf.keras.layers.Dense(1, activation=tf.nn.sigmoid)(feature_layer_outputs)
model = tf.keras.Model(inputs=[v for v in feature_layer_inputs.values()], outputs=output_layer)
model.compile(optimizer='sgd',
loss='binary_crossentropy',
metrics=['accuracy'])
paramString = "Arg-e{}-b{}-z{}".format(args.epoch, args.batchSize, bucketSizeGEO)
log_dir = "logs\logR\" + paramString + datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=1)
model.fit(train_ds,
validation_data=val_ds,
epochs=args.epoch,
callbacks=[tensorboard_callback])
model.summary()
loss, accuracy = model.evaluate(test_ds)
print("Accuracy", accuracy)
paramString = paramString + "-a{:.4f}".format(accuracy)
outputName = "logReg" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S") + paramString
if args.saveModel:
for i, w in enumerate(model.weights): print(i, w.name)
path = './saved_models/' + outputName + '.h5'
model.save(path, save_format='h5')
相关预处理部分见本题开头提到的问题。 for i, w in enumerate(model.weights): print(i, w.name)
returns 以下内容:
0 dense_features/NAME1W1_embedding/embedding_weights:0
1 dense_features/NAME1W2_embedding/embedding_weights:0
2 dense_features/STREETW_embedding/embedding_weights:0
3 dense_features/ZIP_embedding/embedding_weights:0
4 dense/kernel:0
5 dense/bias:0
这个问题是由于训练和预测中embedding矩阵的维数不一致造成的
通常我们在使用嵌入矩阵之前,会形成一个字典。这里我们暂且称这个字典为word_index。如果代码作者考虑不周,会导致训练和预测出现两个不同的words_index(因为训练和预测使用的数据不同),嵌入矩阵的维数发生变化。
从你的bug可以看出你训练时得到len(word_index)+1是57218,预测时得到len(word_index)+1是101
如果我们想要运行代码正确,当我们需要使用word_index的预测时,我们不能在预测期间重新生成一个word_index。所以这个问题最简单的解决办法就是把你训练的时候得到的word_index保存下来,在预测的时候调用,这样我们就可以正确的加载我们训练的时候得到的权重
我能够解决我相当愚蠢的错误:
我正在使用 feature_column 库来预处理我的数据。不幸的是,我在函数 categorical_column_with_identity 的参数 num_buckets 中指定了一个固定的而非实际大小的词汇列表。 错误的版本:
street_voc = tf.feature_column.categorical_column_with_identity(
key='STREETW', num_buckets=100)
正确版本:
street_voc = tf.feature_column.categorical_column_with_identity(
key='STREETW', num_buckets= __getNumberOfWords(data, 'STREETPRO') + 1)
函数 __getNumberOfWords(data, 'STREETPRO')
returns pandas 数据帧的 'STREETPRO' 列中不同单词的数量。