Keras:跨训练示例共享一层权重(不在层之间)
Keras: Share a layer of weights across Training Examples (Not between layers)
问题如下。我有一个词汇量为 25K 的分类预测任务。在其中一个(输入词汇 10K,输出暗淡,即嵌入 50)上,我想引入一个可训练的权重矩阵,用于输入嵌入(形状 1,50)和权重(形状(50,128))之间的矩阵乘法(无偏差) 并且生成的向量分数与其他特征一起作为预测任务的输入。
关键是,我认为每个输入的可训练权重矩阵都不同,如果我简单地添加它的话。我希望这个权重矩阵在所有输入中都是通用的。
我应该澄清一下——这里的输入是指训练示例。所以所有的例子都会学习一些特定于例子的嵌入,并乘以一个共享的权重矩阵。
每隔这么多个epoch,我打算做一个batch update来学习这些共同的权重(或者使用其他目标变量做多输出预测)
LSTM?这是我应该在这里查看的内容吗?
除嵌入层外,层适用于批处理中的所有示例。
以一个非常简单的网络为例:
inp = Input(shape=(4,))
h1 = Dense(2, activation='relu', use_bias=False)(inp)
out = Dense(1)(h1)
model = Model(inp, out)
这是一个简单的网络,具有 1 个输入层、1 个隐藏层和一个输出层。如果我们以隐藏层为例;该层具有形状为 (4, 2,) 的权重矩阵。在每次迭代中,形状为 (batch_size, 4) 的矩阵的输入数据乘以隐藏层权重(前馈阶段)。因此 h1 激活依赖于所有样本。损失也是按 batch_size 计算的。输出层的形状为 (batch_size, 1)。鉴于在前向阶段,所有批次样本都会影响权重值,因此背景和梯度更新也是如此。
在处理文本时,通常会将问题指定为从一系列单词中预测特定标签。这被建模为 (batch_size、sequence_length、word_index) 的形状。让我们举一个非常基本的例子:
from tensorflow import keras
from tensorflow.keras.layers import *
from tensorflow.keras.models import Model
sequence_length = 80
emb_vec_size = 100
vocab_size = 10_000
def make_model():
inp = Input(shape=(sequence_length, 1))
emb = Embedding(vocab_size, emb_vec_size)(inp)
emb = Reshape((sequence_length, emb_vec_size))(emb)
h1 = Dense(64)(emb)
recurrent = LSTM(32)(h1)
output = Dense(1)(recurrent)
model = Model(inp, output)
model.compile('adam', 'mse')
return model
model = make_model()
model.summary()
您可以将其复制并粘贴到 colab 中并查看摘要。
这个例子所做的是:
- 将单词索引序列转换为单词嵌入向量序列。
- 将名为 h1 的密集层应用于所有批次(以及序列中的所有元素);该层减少了嵌入向量的维度。它不是处理文本(孤立地)的典型网络元素。但这似乎符合你的问题。
- 使用循环层将序列减少为每个示例的单个向量。
- 从 "sentence" 向量预测单个标签。
如果我正确地解决了问题,您可以在另一个模型中重复使用图层甚至模型。
具有密集层的示例。假设您有 10 个输入
import tensorflow as tf
from tensorflow.keras.layers import Input, Dense
from tensorflow.keras.models import Model
# defining 10 inputs in a List with (X,) shape
inputs = [Input(shape = (X,),name='input_{}'.format(k)) for k in
range(10)]
# defining a common Dense layer
D = Dense(64, name='one_layer_to_rule_them_all')
nets = [D(inp) for inp in inputs]
model = Model(inputs = inputs, outputs = nets)
model.compile(optimizer='adam', loss='categorical_crossentropy')
如果输入具有不同的形状,则此代码将不起作用。对 D 的第一次调用定义了它的属性。在此示例中,输出直接设置为网络。但当然你可以连接、堆叠或任何你想要的。
现在如果你有一些可训练的模型,你可以用它代替 D:
import tensorflow as tf
from tensorflow.keras.layers import Input, Dense
from tensorflow.keras.models import Model
# defining 10 inputs in a List with (X,) shape
inputs = [Input(shape = (X,),name='input_{}'.format(k)) for k in
range(10)]
# defining a shared model with the same weights for all inputs
nets = [special_model(inp) for inp in inputs]
model = Model(inputs = inputs, outputs = nets)
model.compile(optimizer='adam', loss='categorical_crossentropy')
此模型的权重在所有输入之间共享。
问题如下。我有一个词汇量为 25K 的分类预测任务。在其中一个(输入词汇 10K,输出暗淡,即嵌入 50)上,我想引入一个可训练的权重矩阵,用于输入嵌入(形状 1,50)和权重(形状(50,128))之间的矩阵乘法(无偏差) 并且生成的向量分数与其他特征一起作为预测任务的输入。
关键是,我认为每个输入的可训练权重矩阵都不同,如果我简单地添加它的话。我希望这个权重矩阵在所有输入中都是通用的。
我应该澄清一下——这里的输入是指训练示例。所以所有的例子都会学习一些特定于例子的嵌入,并乘以一个共享的权重矩阵。
每隔这么多个epoch,我打算做一个batch update来学习这些共同的权重(或者使用其他目标变量做多输出预测)
LSTM?这是我应该在这里查看的内容吗?
除嵌入层外,层适用于批处理中的所有示例。
以一个非常简单的网络为例:
inp = Input(shape=(4,))
h1 = Dense(2, activation='relu', use_bias=False)(inp)
out = Dense(1)(h1)
model = Model(inp, out)
这是一个简单的网络,具有 1 个输入层、1 个隐藏层和一个输出层。如果我们以隐藏层为例;该层具有形状为 (4, 2,) 的权重矩阵。在每次迭代中,形状为 (batch_size, 4) 的矩阵的输入数据乘以隐藏层权重(前馈阶段)。因此 h1 激活依赖于所有样本。损失也是按 batch_size 计算的。输出层的形状为 (batch_size, 1)。鉴于在前向阶段,所有批次样本都会影响权重值,因此背景和梯度更新也是如此。
在处理文本时,通常会将问题指定为从一系列单词中预测特定标签。这被建模为 (batch_size、sequence_length、word_index) 的形状。让我们举一个非常基本的例子:
from tensorflow import keras
from tensorflow.keras.layers import *
from tensorflow.keras.models import Model
sequence_length = 80
emb_vec_size = 100
vocab_size = 10_000
def make_model():
inp = Input(shape=(sequence_length, 1))
emb = Embedding(vocab_size, emb_vec_size)(inp)
emb = Reshape((sequence_length, emb_vec_size))(emb)
h1 = Dense(64)(emb)
recurrent = LSTM(32)(h1)
output = Dense(1)(recurrent)
model = Model(inp, output)
model.compile('adam', 'mse')
return model
model = make_model()
model.summary()
您可以将其复制并粘贴到 colab 中并查看摘要。
这个例子所做的是:
- 将单词索引序列转换为单词嵌入向量序列。
- 将名为 h1 的密集层应用于所有批次(以及序列中的所有元素);该层减少了嵌入向量的维度。它不是处理文本(孤立地)的典型网络元素。但这似乎符合你的问题。
- 使用循环层将序列减少为每个示例的单个向量。
- 从 "sentence" 向量预测单个标签。
如果我正确地解决了问题,您可以在另一个模型中重复使用图层甚至模型。
具有密集层的示例。假设您有 10 个输入
import tensorflow as tf
from tensorflow.keras.layers import Input, Dense
from tensorflow.keras.models import Model
# defining 10 inputs in a List with (X,) shape
inputs = [Input(shape = (X,),name='input_{}'.format(k)) for k in
range(10)]
# defining a common Dense layer
D = Dense(64, name='one_layer_to_rule_them_all')
nets = [D(inp) for inp in inputs]
model = Model(inputs = inputs, outputs = nets)
model.compile(optimizer='adam', loss='categorical_crossentropy')
如果输入具有不同的形状,则此代码将不起作用。对 D 的第一次调用定义了它的属性。在此示例中,输出直接设置为网络。但当然你可以连接、堆叠或任何你想要的。
现在如果你有一些可训练的模型,你可以用它代替 D:
import tensorflow as tf
from tensorflow.keras.layers import Input, Dense
from tensorflow.keras.models import Model
# defining 10 inputs in a List with (X,) shape
inputs = [Input(shape = (X,),name='input_{}'.format(k)) for k in
range(10)]
# defining a shared model with the same weights for all inputs
nets = [special_model(inp) for inp in inputs]
model = Model(inputs = inputs, outputs = nets)
model.compile(optimizer='adam', loss='categorical_crossentropy')
此模型的权重在所有输入之间共享。