如何在TensorFlow线性回归模型中结合词嵌入与多特征训练?
解决方案
一、整合词嵌入与数值特征构建多输入回归模型
你的模型需要同时处理文本特征和数值特征,Sequential模型无法满足多输入需求,必须使用Keras Functional API 实现。具体步骤如下:
1. 将文本预处理转为Keras内置层(避免训练/推理不一致)
推荐用tf.keras.layers.TextVectorization替代原生Tokenizer,它可以直接嵌入模型,自动完成分词、转序列、截断/补全操作,比Tokenizer更适配TF生态:
import tensorflow as tf from tensorflow import keras from tensorflow.keras import layers # 从数据集提取字符串特征列(假设列名为'string_feature') sentences = dataset['string_feature'].tolist() # 定义文本向量化层 maxlen = 20 # 根据你的文本实际长度调整 num_words = 10000 # 词汇表最大容量 text_vectorizer = layers.TextVectorization( max_tokens=num_words, output_mode='int', output_sequence_length=maxlen, standardize='lower_and_strip_punctuation' ) # 用文本数据适配层 text_vectorizer.adapt(sentences)
2. 构建多输入融合模型
分别搭建文本特征分支和数值特征分支,将两者输出拼接后接入回归网络:
# 1. 数值特征分支(复用你已定义的normalizer) num_numeric_features = 16 # 总17个特征:1个文本+16个数值 numeric_input = layers.Input(shape=(num_numeric_features,), dtype=tf.float32) normalized_numeric = normalizer(numeric_input) # 2. 文本特征分支 text_input = layers.Input(shape=(1,), dtype=tf.string) vectorized_text = text_vectorizer(text_input) embedding = layers.Embedding( input_dim=num_words, output_dim=64, # 嵌入维度,可根据效果调整 input_length=maxlen )(vectorized_text) text_features = layers.GlobalAveragePooling1D()(embedding) # 压缩为固定维度向量 # 3. 拼接两个分支的特征 concatenated_features = layers.concatenate([normalized_numeric, text_features]) # 4. 回归网络主体 x = layers.Dense(64, activation='relu')(concatenated_features) x = layers.Dense(64, activation='relu')(x) output = layers.Dense(2)(x) # 输出2个目标特征 # 构建并编译模型 model = keras.Model(inputs=[numeric_input, text_input], outputs=output) model.compile( loss='mean_absolute_error', optimizer=tf.keras.optimizers.Adam(0.001) )
3. 模型训练
训练时需传入两个输入数据:数值特征数组和文本特征数组:
# 提取训练集的文本特征和标签 train_texts = train_dataset['string_feature'].tolist() train_y = train_dataset[['output_col1', 'output_col2']].values # 替换为你的输出列名 model.fit( x=[train_x_inputs, train_texts], y=train_y, epochs=50, validation_split=0.2 )
二、是否需要词嵌入?替代方案选择
要不要用词嵌入?
- 需要的场景:如果字符串特征是长文本/序列文本(比如用户描述、段落语句),词嵌入能捕捉文本语义信息,比简单编码效果更好。
- 不需要的场景:如果字符串是离散类别型特征(比如"男/女"、"北京/上海"、"A/B/C类"),词嵌入属于过度设计,用类别编码更高效。
适合TensorFlow的字符串转数值方案
如果不用词嵌入,优先选择Keras内置类别编码层,可以直接嵌入模型,避免离线预处理带来的不一致问题:
方案1:StringLookup + CategoryEncoding(适合类别数较多的场景)
# 提取类别型字符串特征 string_feature = dataset['string_feature'].tolist() # 1. 字符串转整数索引 string_lookup = layers.StringLookup(vocabulary=list(set(string_feature))) # 2. 整数索引转独热编码(可选'multi_hot'/'count'/'tf_idf') category_encoding = layers.CategoryEncoding( num_tokens=string_lookup.vocabulary_size(), output_mode='one_hot' ) # 嵌入模型的示例分支 cat_input = layers.Input(shape=(1,), dtype=tf.string) x = string_lookup(cat_input) cat_features = category_encoding(x) # 后续可直接和数值特征拼接,逻辑同多输入模型
方案2:LabelEncoder + 嵌入层(适合类别数较少的场景)
如果用sklearn的LabelEncoder,需将编码结果转为TF兼容格式,最好封装成Lambda层嵌入模型:
from sklearn.preprocessing import LabelEncoder le = LabelEncoder() encoded_cats = le.fit_transform(dataset['string_feature']) # 模型中处理编码后的类别特征 cat_input = layers.Input(shape=(1,), dtype=tf.int32) # 类别数少的话,也可以用Dense层替代嵌入 cat_features = layers.Embedding(input_dim=len(le.classes_), output_dim=4)(cat_input) cat_features = layers.Flatten()(cat_features)
注意:优先使用Keras内置层(TextVectorization、StringLookup),它们支持TF分布式训练、模型序列化保存,比sklearn工具更适配TF生态。
内容的提问来源于stack exchange,提问作者Shawn Hunter
相关产品推荐
相关产品推荐

