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 中并查看摘要。

这个例子所做的是:

  1. 将单词索引序列转换为单词嵌入向量序列。
  2. 将名为 h1 的密集层应用于所有批次(以及序列中的所有元素);该层减少了嵌入向量的维度。它不是处理文本(孤立地)的典型网络元素。但这似乎符合你的问题。
  3. 使用循环层将序列减少为每个示例的单个向量。
  4. 从 "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')

此模型的权重在所有输入之间共享。