复现SkimLit论文时Bidirectional层初始化及特征拼接报错求助
复现SkimLit论文时的模型构建错误与特征拼接问题
问题背景
正在复现SkimLit论文,尝试拼接token级、字符级嵌入以及行号、总行号特征时遇到错误,参考相关issue后问题仍未解决。
数据预处理代码
# Combine chars and tokens into a dataset train_token_char_data = tf.data.Dataset.from_tensor_slices((train_sentences, train_chars)) train_char_token_labels = tf.data.Dataset.from_tensor_slices(train_labels_one_hot) train_char_token_dataset = tf.data.Dataset.zip((train_token_char_data, train_char_token_labels)) # Prefetch and batch train data train_char_token_dataset = train_char_token_dataset.batch(32).prefetch(tf.data.AUTOTUNE) # Combine chars and tokens into a dataset val_token_char_data = tf.data.Dataset.from_tensor_slices((val_sentences, val_chars)) val_char_token_labels = tf.data.Dataset.from_tensor_slices(val_labels_one_hot) val_char_token_dataset = tf.data.Dataset.zip((val_token_char_data, val_char_token_labels)) # Prefetch and batch train data val_char_token_dataset = val_char_token_dataset.batch(32).prefetch(tf.data.AUTOTUNE) # Use tensorflow to create one-hot-encoded tensors of our "line_number" column train_line_numbers_one_hot = tf.one_hot(train_df["line_number"].to_numpy(), depth=20) val_line_numbers_one_hot = tf.one_hot(val_df["line_number"].to_numpy(), depth=20) test_line_numbers_one_hot = tf.one_hot(test_df["line_number"].to_numpy(), depth=20) train_line_numbers_one_hot[:5], train_line_numbers_one_hot.shape # Use tensorflow to create one-hot encoded tensors of our "total_lines" feature train_total_lines_one_hot = tf.one_hot(train_df["total_lines"].to_numpy(), depth=20) val_total_lines_one_hot = tf.one_hot(val_df["total_lines"].to_numpy(), depth=20) test_total_lines_one_hot = tf.one_hot(test_df["total_lines"].to_numpy(), depth=20) train_total_lines_one_hot[:2], train_total_lines_one_hot.shape
模型构建代码
# 1. Token inputs token_inputs = layers.Input(shape=[], dtype=tf.string, name="token_inputs") token_embeddings = tf_hub_embedding_layer(token_inputs) token_outputs = layers.Dense(128, activation="relu")(token_embeddings) token_model = tf.keras.Model(token_inputs,token_outputs) # 2. Char inputs char_inputs = layers.Input(shape=(1,), dtype=tf.string, name="char_inputs") char_vectors = char_vectorizer(char_inputs) char_embedding = char_embed(char_vectors) char_bi_lstm = layers.Bidirectional(layers.LSTM(24)(char_embeddings)) char_model = tf.keras.Model(char_inputs, char_bi_lstm) # 3. Line number feature line_number_inputs = layers.Input(shape=[], dtype=tf.float32, name="line_number_inputs") x = layers.Dense(32, activation="relu")(line_numbers_inputs) line_number_model = tf.keras.Model(line_numbers_inputs, x) # 4. Total line number feature total_lines_inputs = layers.Input(shape=(20,), dtype=tf.float32, name="total_lines_inputs") y = layers.Dense(32, activation="relu")(total_lines_inputs) total_lines_model = tf.keras.Model(total_lines_inputs, y) # 5. Combine token and char embeddings into a hybrid embedding combined_embeddings = layers.Concatenate(name="char_token_hybrid_embedding")([token_model.output, char_model.output]) z = layers.Dense(256, activation="relu")(combined_embeddings) z = layers.Dropout(0.5)(z) # 6. Combine positional embedding with combined token and char embeddings tribrid_embeddings = layers.Concatenate(name="char_token_tribrid_embedding")([line_number_model.output, total_lines_model.ouput, z]) # 7. Create output layer output_layer = layers.Dense(5, activation="softmax", name="output_layer")(tribrid_embeddings) # 8. Put together model with all kinds of inputs model_5 = tf.keras.Model(inputs=[line_number_model.input, total_line_model.input, token_model.input, char_model.input], outputs=output_layer)
报错信息
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) Cell In[123], line 11 9 char_vectors = char_vectorizer(char_inputs) 10 char_embedding = char_embed(char_vectors) ---> 11 char_bi_lstm = layers.Bidirectional(layers.LSTM(24)(char_embeddings)) 12 char_model = tf.keras.Model(char_inputs, char_bi_lstm) 14 # 3. Line number feature File ~/Desktop/skimLit/env/lib/python3.10/site-packages/keras/src/layers/rnn/bidirectional.py:118, in Bidirectional.__init__(self, layer, merge_mode, weights, backward_layer, **kwargs) 109 def __init__( 110 self, 111 layer, (...) 115 **kwargs, 116 ): 117 if not isinstance(layer, Layer): --> 118 raise ValueError( 119 "Please initialize `Bidirectional` layer with a " 120 f"`tf.keras.layers.Layer` instance. Received: {layer}" 121 ) 122 if backward_layer is not None and not isinstance(backward_layer, Layer): 123 raise ValueError( 124 "`backward_layer` need to be a `tf.keras.layers.Layer` " 125 f"instance. Received: {backward_layer}" 126 ) ValueError: Please initialize `Bidirectional` layer with a `tf.keras.layers.Layer` instance. Received: KerasTensor(type_spec=TensorSpec(shape=(None, 24), dtype=tf.float32, name=None), name='lstm_19/PartitionedCall:0', description="created by layer 'lstm_19'")
解决方案
1. 修复Bidirectional层初始化错误
报错核心是把LSTM层的输出张量传给了Bidirectional,而Bidirectional需要接收Layer实例,同时存在变量名拼写错误:char_embeddings应为char_embedding。修正后的字符分支代码:
# 2. Char inputs char_inputs = layers.Input(shape=(1,), dtype=tf.string, name="char_inputs") char_vectors = char_vectorizer(char_inputs) char_embedding = char_embed(char_vectors) # 先实例化LSTM层传入Bidirectional,再调用处理输入张量 char_bi_lstm = layers.Bidirectional(layers.LSTM(24))(char_embedding) char_model = tf.keras.Model(char_inputs, char_bi_lstm)
2. 修正变量名拼写与输入维度错误
- 行号分支:
line_numbers_inputs应为line_number_inputs,且输入维度需匹配one-hot后的20维,修改为shape=(20,) - 特征拼接:
total_lines_model.ouput拼写错误,改为total_lines_model.output - 最终模型输入:
total_line_model.input改为total_lines_model.input
3. 整合所有特征到数据集
当前数据集仅包含token和char数据,缺少行号、总行号特征,需整合后才能匹配模型输入:
# 训练集整合所有特征:(token, char, line_num, total_lines) train_all_data = tf.data.Dataset.from_tensor_slices((train_sentences, train_chars, train_line_numbers_one_hot, train_total_lines_one_hot)) train_all_labels = tf.data.Dataset.from_tensor_slices(train_labels_one_hot) train_dataset = tf.data.Dataset.zip((train_all_data, train_all_labels)) train_dataset = train_dataset.batch(32).prefetch(tf.data.AUTOTUNE) # 验证集同理 val_all_data = tf.data.Dataset.from_tensor_slices((val_sentences, val_chars, val_line_numbers_one_hot, val_total_lines_one_hot)) val_all_labels = tf.data.Dataset.from_tensor_slices(val_labels_one_hot) val_dataset = tf.data.Dataset.zip((val_all_data, val_all_labels)) val_dataset = val_dataset.batch(32).prefetch(tf.data.AUTOTUNE)
4. 完整修正后的模型代码
# 1. Token inputs token_inputs = layers.Input(shape=[], dtype=tf.string, name="token_inputs") token_embeddings = tf_hub_embedding_layer(token_inputs) token_outputs = layers.Dense(128, activation="relu")(token_embeddings) token_model = tf.keras.Model(token_inputs, token_outputs) # 2. Char inputs char_inputs = layers.Input(shape=(1,), dtype=tf.string, name="char_inputs") char_vectors = char_vectorizer(char_inputs) char_embedding = char_embed(char_vectors) char_bi_lstm = layers.Bidirectional(layers.LSTM(24))(char_embedding) char_model = tf.keras.Model(char_inputs, char_bi_lstm) # 3. Line number feature line_number_inputs = layers.Input(shape=(20,), dtype=tf.float32, name="line_number_inputs") x = layers.Dense(32, activation="relu")(line_number_inputs) line_number_model = tf.keras.Model(line_number_inputs, x) # 4. Total line number feature total_lines_inputs = layers.Input(shape=(20,), dtype=tf.float32, name="total_lines_inputs") y = layers.Dense(32, activation="relu")(total_lines_inputs) total_lines_model = tf.keras.Model(total_lines_inputs, y) # 5. Combine token and char embeddings into a hybrid embedding combined_embeddings = layers.Concatenate(name="char_token_hybrid_embedding")([token_model.output, char_model.output]) z = layers.Dense(256, activation="relu")(combined_embeddings) z = layers.Dropout(0.5)(z) # 6. Combine positional embedding with combined token and char embeddings tribrid_embeddings = layers.Concatenate(name="char_token_tribrid_embedding")([line_number_model.output, total_lines_model.output, z]) # 7. Create output layer output_layer = layers.Dense(5, activation="softmax", name="output_layer")(tribrid_embeddings) # 8. Put together model with all kinds of inputs model_5 = tf.keras.Model(inputs=[token_model.input, char_model.input, line_number_model.input, total_lines_model.input], outputs=output_layer)
内容的提问来源于stack exchange,提问作者Frederic Strand
相关产品推荐
相关产品推荐

