tf.keras.layers.Embedding实现共享embedding

本文介绍了如何在keras中实现共享embedding。通过核心代码展示如何构造和使用共享embedding层,并验证了其在不同输入长度情况下的正确性。

背景

使用feature_column可以非常方便的实现shared_embedding

tf.feature_column.shared_embedding_columns(shared_column_list, iembedding_size)

但是换成keras后,没有相应的接口。

查找资料,实现了共享embedding

核心代码

from keras.layers import Input, Embedding

first_input = Input(shape = (your_shape_tuple) )
second_input = Input(shape = (your_shape_tuple) )
...

embedding_layer = Embedding(embedding_size)

first_input_encoded = embedding_layer(first_input)
second_input_encoded = embedding_layer(second_input)

资料来源https://stackoverflow.com/questions/42122168/keras-how-to-construct-a-shared-embedding-layer-for-each-input-neuron

Embedding的实现

import tensorflow as tf
tf.enable_eager_execution()


import numpy 
<think>我们正在详细解释tf.keras.layers.Embedding层。根据引用内容,Embedding层是Keras中的一个常用层,主要用于将正整数(索引)转换为固定大小的密集向量。这在处理文本数据时特别有用,例如将单词索引转换为词向量。 引用[2]和引用[4]提供了Embedding层的参数和基本用法。我们将详细说明参数、工作原理以及使用示例。 1. 参数说明(根据引用[2]): - input_dim: 整数,词汇表大小,即最大整数索引+1。 - output_dim: 整数,表示密集嵌入的维度。 - embeddings_initializer: 嵌入矩阵的初始化方法(默认为'uniform')。 - embeddings_regularizer: 应用于嵌入矩阵的正则化函数(可选)。 - embeddings_constraint: 应用于嵌入矩阵的约束函数(可选)。 - mask_zero: 布尔值,是否将输入中的0看作应该被忽略的“填充”值。这在使用可变长度输入时很有用。如果为True,则后续的层必须支持masking。 - input_length: 输入序列的长度(当该层后面接Flatten层然后接Dense层时,需要此参数)。如果不指定,那么后续层必须能处理任意长度的序列。 2. 工作原理: Embedding层实际上是一个查找表,它将整数索引映射到密集向量。当我们创建一个Embedding层时,它会初始化一个形状为(input_dim, output_dim)的矩阵。当输入一个整数索引i时,Embedding层会返回矩阵的第i行(即第i个向量)。 3. 输入和输出: - 输入:形状为(batch_size, sequence_length)的2D张量。注意:该层只能作为模型的第一层时,直接接受输入。否则,需要先通过Input层。 - 输出:形状为(batch_size, sequence_length, output_dim)的3D张量。 4. 注意事项(引用[4]): - Embedding层通常作为模型的第一层。 - 如果需要在Embedding层之后添加其他层,可能需要使用Flatten或GlobalMaxPooling1D等层将嵌入向量转换为固定长度的向量。 5. 使用示例: 示例1:简单示例,用于文本分类模型的第一层。 ```python import tensorflow as tf from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Embedding, Flatten, Dense # 假设词汇表大小为1000,每个词用32维向量表示,输入序列长度为10 model = Sequential() model.add(Embedding(input_dim=1000, output_dim=32, input_length=10)) # 输出形状: (batch_size, 10, 32) # 将每个序列的10个向量展平为单个向量(10*32=320) model.add(Flatten()) # 然后添加全连接层 model.add(Dense(1, activation='sigmoid')) model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) model.summary() ``` 示例2:使用预训练嵌入(例如GloVe) ```python import numpy as np # 假设我们有一个预训练的嵌入矩阵(例如GloVe) # 假设词汇表大小为10000,嵌入维度为100 embedding_matrix = np.random.rand(10000, 100) # 这里用随机矩阵代替 # 构建模型 model = Sequential() # 使用预训练矩阵作为初始权重,并设置不可训练(trainable=False) model.add(Embedding(input_dim=10000, output_dim=100, input_length=50, weights=[embedding_matrix], trainable=False)) model.add(Flatten()) model.add(Dense(1, activation='sigmoid')) ``` 示例3:使用mask_zero处理可变长度序列 ```python model = Sequential() # 设置mask_zero=True,这样索引0将被视为掩码(通常用于填充值) model.add(Embedding(input_dim=100, output_dim=32, mask_zero=True, input_length=None)) # 注意:输入长度可以设为None,表示接受任意长度 # 然后添加一个LSTM层,它能够处理掩码 model.add(tf.keras.layers.LSTM(64)) model.add(Dense(1, activation='sigmoid')) ``` 6. 数学表示: 嵌入层本质上是一个从索引空间到向量空间的映射函数: $$ f: i \in \{0,1,...,\text{input\_dim}-1\} \mapsto \mathbf{v}_i \in \mathbb{R}^{\text{output\_dim}} $$ 其中,$\mathbf{v}_i$ 是嵌入矩阵的第$i$行。 7. 训练过程: 嵌入层的权重(即嵌入矩阵)在训练过程中通过反向传播进行更新。因此,它可以将索引映射到有意义的向量表示(例如,在自然语言处理中,相似的词会有相似的向量)。 8. 注意事项: - 当使用`mask_zero=True`时,请注意索引0不能用于词汇,因为它被用作特殊掩码值。 - 如果输入序列长度不固定,可以设置`input_length=None`,但后续层可能需要支持可变长度(如RNN、LSTM等)。 9. 与其他层的结合: - 嵌入层后面可以直接接RNN、LSTM、GRU等循环层,或者CNN层。 - 也可以使用池化层(GlobalMaxPooling1D, GlobalAveragePooling1D)来降维。 10. 性能考虑: - 嵌入层通常需要较大的内存,因为嵌入矩阵的大小为(input_dim, output_dim)。因此,对于非常大的词汇表,可能需要考虑其他技术(如子词嵌入)或分布式训练。 11. 引用总结: 根据引用[1][2][3][4],Embedding层是Keras中处理离散特征(如词索引)的重要工具,它可以将离散的符号映射到连续的向量空间,从而便于神经网络处理。 §§相关问题§§ 1. 在自然语言处理中,Embedding层的作用是什么? 2. 如何将预训练的词向量(如Word2Vec)加载到Embedding层? 3. 使用Embedding层时,如何处理变长输入序列? 4. Embedding层与One-Hot编码相比有什么优势? 5.Embedding层中,mask_zero参数的作用是什么?它如何影响后续层?</think>### TensorFlow `tf.keras.layers.Embedding` 层详解与用法示例 #### 1. **核心功能与数学原理** `Embedding` 层用于将正整数索引映射为密集向量,是处理离散特征(如文本、类别数据)的核心组件。其数学本质是: $$ \text{Embedding}(i) = W_i \quad \text{其中} \quad W \in \mathbb{R}^{\text{input\_dim} \times \text{output\_dim}} $$ 其中 $i$ 是输入索引,$W$ 是可训练的嵌入矩阵[^2][^4]。 #### 2. **参数详解** | 参数 | 类型 | 说明 | 默认值 | |------|------|------|--------| | `input_dim` | int | 词汇表大小(最大索引+1) | **必填** | | `output_dim` | int | 嵌入向量的维度 | **必填** | | `embeddings_initializer` | str/obj | 嵌入矩阵初始化方法 | `'uniform'` | | `embeddings_regularizer` | obj | 正则化函数 | `None` | | `mask_zero` | bool | 是否将索引0作为掩码 | `False` | | `input_length` | int | 输入序列长度 | `None` | **关键参数说明**: - `mask_zero=True` 时,索引0被视为填充值(不参与训练) - `input_length` 需在连接`Flatten`或`Dense`层时指定[^4] #### 3. **输入输出结构** ```python # 输入:2D张量 (batch_size, sequence_length) # 输出:3D张量 (batch_size, sequence_length, output_dim) ``` #### 4. **完整用法示例** ##### 示例1:文本分类基础模型 ```python import tensorflow as tf model = tf.keras.Sequential([ # 词汇表1000词,64维嵌入,序列长度50 tf.keras.layers.Embedding( input_dim=1000, output_dim=64, input_length=50, mask_zero=True # 处理填充值 ), tf.keras.layers.Flatten(), # 展平为2D tf.keras.layers.Dense(128, activation='relu'), tf.keras.layers.Dense(10, activation='softmax') ]) model.compile(optimizer='adam', loss='categorical_crossentropy') ``` ##### 示例2:预训练嵌入加载 ```python import numpy as np # 创建伪预训练矩阵 (1000个词,64维) pretrained_matrix = np.random.rand(1000, 64) model = tf.keras.Sequential([ tf.keras.layers.Embedding( input_dim=1000, output_dim=64, embeddings_initializer=tf.keras.initializers.Constant(pretrained_matrix), trainable=False # 冻结嵌入层 ), tf.keras.layers.GRU(128), tf.keras.layers.Dense(1, activation='sigmoid') ]) ``` ##### 示例3:结合LSTM处理变长序列 ```python inputs = tf.keras.Input(shape=(None,)) # 可变长度序列 x = tf.keras.layers.Embedding( input_dim=5000, output_dim=128, mask_zero=True # 关键:启用掩码 )(inputs) x = tf.keras.layers.LSTM(64)(x) outputs = tf.keras.layers.Dense(1)(x) model = tf.keras.Model(inputs=inputs, outputs=outputs) ``` #### 5. **最佳实践与注意事项** 1. **维度选择**: - 小数据集:$d_{emb} = \sqrt[4]{n_{vocab}}$(词汇量的四次方根) - 大数据集:$d_{emb} = 100 \sim 300$ 2. **初始化技巧**: ```python # 使用截断正态分布初始化 tf.keras.layers.Embedding( ..., embeddings_initializer=tf.keras.initializers.TruncatedNormal(stddev=0.02) ) ``` 3. **正则化应用**: ```python # 添加L2正则化防止过拟合 tf.keras.layers.Embedding( ..., embeddings_regularizer=tf.keras.regularizers.l2(1e-4) ) ``` 4. **性能优化**: - 使用`tf.keras.layers.Masking`替代`mask_zero`可提升GPU利用率 - 大词汇表场景优先使用`tf.nn.embedding_lookup` #### 6. **数学推导** 嵌入层本质是查表操作: $$ \text{Output}_{i,j,k} = W_{input_{i,j},k} $$ 其中: - $i$: batch索引 - $j$: 序列位置索引 - $k$: 嵌入维度索引 - $W$: 可训练权重矩阵[^2][^4] #### 7. **常见错误处理** 1. **形状不匹配**: ```python # 错误:未指定input_length时连接Dense层 # 正确:添加Flatten层或GlobalPooling model.add(tf.keras.layers.GlobalAveragePooling1D()) ``` 2. **掩码失效**: ```python # 需确保后续层支持掩码传播 tf.keras.layers.LSTM(64, return_sequences=False) # 正确 tf.keras.layers.Conv1D(64, 3) # 错误:不传播掩码 ``` 3. **OOM解决方案**: ```python # 梯度累积技术 optimizer = tf.keras.optimizers.Adam() model.compile(optimizer=optimizer, ...) ``` #### 8. **进阶应用** ```python # 多模态融合:文本+图像 text_input = tf.keras.Input(shape=(100,)) img_input = tf.keras.Input(shape=(224,224,3)) # 文本分支 text_emb = tf.keras.layers.Embedding(10000, 128)(text_input) text_feat = tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(64))(text_emb) # 图像分支 img_feat = tf.keras.applications.ResNet50(weights=None)(img_input) # 融合 merged = tf.keras.layers.concatenate([text_feat, img_feat]) outputs = tf.keras.layers.Dense(10)(merged) model = tf.keras.Model(inputs=[text_input, img_input], outputs=outputs) ```
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值