gpt4 book ai didi

python - 使用 Transformer 模型的多实例分类

转载 作者:行者123 更新时间:2023-12-05 05:36:45 31 4
gpt4 key购买 nike

我使用这个 Keras documentation example 的变压器用于多实例分类。每个实例的类别取决于同一个包中的其他实例。我使用变压器模型是因为:

It makes no assumptions about the temporal/spatial relationships across the data. This is ideal for processing a set of objects

例如,每个包最多可以有 5 个实例,每个实例有 3 个特征。

# Generate data
max_length = 5
x_lst = []
y_lst = []
for _ in range(10):
num_instances = np.random.randint(2, max_length + 1)
x_bag = np.random.randint(0, 9, size=(num_instances, 3))
y_bag = np.random.randint(0, 2, size=num_instances)

x_lst.append(x_bag)
y_lst.append(y_bag)

前 2 个包的特征和标签(5 个和 2 个实例):

x_lst[:2]

[array([[8, 0, 3],
[8, 1, 0],
[4, 6, 8],
[1, 6, 4],
[7, 4, 6]]),
array([[5, 8, 4],
[2, 1, 1]])]

y_lst[:2]

[array([0, 1, 1, 1, 0]), array([0, 0])]

接下来,我用零填充特征,用 -1 填充目标:

x_padded = []
y_padded = []

for x, y in zip(x_lst, y_lst):
x_p = np.zeros((max_length, 3))
x_p[:x.shape[0], :x.shape[1]] = x
x_padded.append(x_p)

y_p = np.negative(np.ones(max_length))
y_p[:y.shape[0]] = y
y_padded.append(y_p)

X = np.stack(x_padded)
y = np.stack(y_padded)

其中 X.shape 等于 (10, 5, 3)y.shape 等于 (10 , 5)

我对原始模型做了两处更改:添加了 Masking 层在输入层之后,将最后一个 Dense 层中的单元数设置为袋子的最大尺寸(加上“sigmoid”激活):

def transformer_encoder(inputs, head_size, num_heads, ff_dim, dropout=0):
# Attention and Normalization
x = layers.MultiHeadAttention(
key_dim=head_size, num_heads=num_heads, dropout=dropout
)(inputs, inputs)
x = layers.Dropout(dropout)(x)
x = layers.LayerNormalization(epsilon=1e-6)(x)
res = x + inputs

# Feed Forward Part
x = layers.Conv1D(filters=ff_dim, kernel_size=1, activation="relu")(res)
x = layers.Dropout(dropout)(x)
x = layers.Conv1D(filters=inputs.shape[-1], kernel_size=1)(x)
x = layers.LayerNormalization(epsilon=1e-6)(x)
return x + res

def build_model(
input_shape,
head_size,
num_heads,
ff_dim,
num_transformer_blocks,
mlp_units,
dropout=0,
mlp_dropout=0,
):
inputs = keras.Input(shape=input_shape)
inputs = keras.layers.Masking(mask_value=0)(inputs) # ADDED MASKING LAYER
x = inputs
for _ in range(num_transformer_blocks):
x = transformer_encoder(x, head_size, num_heads, ff_dim, dropout)

x = layers.GlobalAveragePooling1D(data_format="channels_first")(x)
for dim in mlp_units:
x = layers.Dense(dim, activation="relu")(x)
x = layers.Dropout(mlp_dropout)(x)
outputs = layers.Dense(5, activation='sigmoid')(x) # CHANGED ACCORDING TO MY OUTPUT
return keras.Model(inputs, outputs)

input_shape = (5, 3)

model = build_model(
input_shape,
head_size=256,
num_heads=4,
ff_dim=4,
num_transformer_blocks=4,
mlp_units=[128],
mlp_dropout=0.4,
dropout=0.25,
)

model.compile(
loss="binary_crossentropy",
optimizer=keras.optimizers.Adam(learning_rate=1e-4),
metrics=["binary_accuracy"],
)
model.summary()

看起来我的模型没有学到太多东西。如果我使用每个包的真值数量(y.sum(axis=1)Dense(1))作为目标而不是对每个实例进行分类,模型学得很好。我的错误在哪里?在这种情况下我应该如何构建输出层?我需要自定义丢失函数吗?

更新:我做了一个自定义损失函数:

def my_loss_fn(y_true, y_pred):
mask = tf.cast(tf.math.not_equal(y_true, tf.constant(-1.)), tf.float32)
y_true, y_pred = tf.expand_dims(y_true, axis=-1), tf.expand_dims(y_pred, axis=-1)
bce = tf.keras.losses.BinaryCrossentropy(reduction='none')
return tf.reduce_sum(tf.cast(bce(y_true, y_pred), tf.float32) * mask)

mask = (y_test != -1).astype(int)
pd.DataFrame({'n_labels': mask.sum(axis=1), 'preds': ((preds * mask) >= .5).sum(axis=1)}).plot(figsize=(20, 5))

看起来模型学习了: enter image description here

但它预测所有非屏蔽标签为 1。 enter image description here

@thushv89 这是my problem .我采用 2 个时间点:t1 和 t2,并查找在时间 t1 进行维护的所有车辆以及计划在时间 t2 进行维护的所有车辆。所以,这是我的元素袋。然后我计算一些特征,比如 t1 车辆已经花费了多少时间进行维护,从 t1 到 t2 车辆计划开始的时间等。如果我尝试预测在时间 t2 进行维护的车辆数量,我的模型会学得很好,但我想预测其中哪些会离开,哪些会进来(3 vs [True, False, True, True] 对于包中的 4 辆车)。

最佳答案

三个重要的改进:

  1. 删除 GlobalAveragePooling1D。如果您对每个项目进行预测,这是一种瓶颈(数据压缩)。如果没有这一层,您还会在输出中免费获得一个二维张量,该张量在第一维(在我的例子中是 5 个)中的项目数是最大的。因此,您可以将最后一个 Dense 层设置为类别数(在我的例子中为 1)。
  2. 添加自定义损失函数以从计算中排除目标填充(已添加到我的问题)和自定义度量函数(如果您想查看真实指标)。
  3. 将 attention_mask 添加到 MultiHeadAttention(而不是 Masking 层)以屏蔽填充。

关于python - 使用 Transformer 模型的多实例分类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73261021/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com