使用 BERT 进行多标签分类
Doing Multi-Label classification with BERT
我想使用 BERT model 通过 Tensorflow 进行多标签 class 化。
为此,我想改编 BERT github repository, which is an example on how to use BERT to do simple classification, using the pre-trained weights given by Google Research 中的示例 run_classifier.py
。 (例如 BERT-Base, Cased
)
我有 X
个不同的标签,它们的值为 0 或 1,所以我想向原始 BERT 模型添加一个新的大小为 X
的密集层并使用 sigmoid_cross_entropy_with_logits
激活函数.
所以,对于理论部分,我认为我还可以。
问题是我不知道如何使用现有的 BertModel
class.[=23= 附加一个新的输出层并用我的数据集重新训练这个新层]
这是来自 run_classifier.py
的原始 create_model()
函数,我想我必须在其中进行修改。但是我有点不知道该怎么做。
def create_model(bert_config, is_training, input_ids, input_mask, segment_ids,
labels, num_labels, use_one_hot_embeddings):
"""Creates a classification model."""
model = modeling.BertModel(
config=bert_config,
is_training=is_training,
input_ids=input_ids,
input_mask=input_mask,
token_type_ids=segment_ids,
use_one_hot_embeddings=use_one_hot_embeddings)
output_layer = model.get_pooled_output()
hidden_size = output_layer.shape[-1].value
output_weights = tf.get_variable(
"output_weights", [num_labels, hidden_size],
initializer=tf.truncated_normal_initializer(stddev=0.02))
output_bias = tf.get_variable(
"output_bias", [num_labels], initializer=tf.zeros_initializer())
with tf.variable_scope("loss"):
if is_training:
# I.e., 0.1 dropout
output_layer = tf.nn.dropout(output_layer, keep_prob=0.9)
logits = tf.matmul(output_layer, output_weights, transpose_b=True)
logits = tf.nn.bias_add(logits, output_bias)
probabilities = tf.nn.softmax(logits, axis=-1)
log_probs = tf.nn.log_softmax(logits, axis=-1)
one_hot_labels = tf.one_hot(labels, depth=num_labels, dtype=tf.float32)
per_example_loss = -tf.reduce_sum(one_hot_labels * log_probs, axis=-1)
loss = tf.reduce_mean(per_example_loss)
return (loss, per_example_loss, logits, probabilities)
这里是相同的功能,只是我做了一些修改,但是哪里有遗漏的地方(还有错误的地方?)
def create_model(bert_config, is_training, input_ids, input_mask, segment_ids, labels, num_labels):
"""Creates a classification model."""
model = modeling.BertModel(
config=bert_config,
is_training=is_training,
input_ids=input_ids,
input_mask=input_mask,
token_type_ids=segment_ids)
output_layer = model.get_pooled_output()
hidden_size = output_layer.shape[-1].value
output_weights = tf.get_variable("output_weights", [num_labels, hidden_size],initializer=tf.truncated_normal_initializer(stddev=0.02))
output_bias = tf.get_variable("output_bias", [num_labels], initializer=tf.zeros_initializer())
with tf.variable_scope("loss"):
if is_training:
# I.e., 0.1 dropout
output_layer = tf.nn.dropout(output_layer, keep_prob=0.9)
logits = tf.matmul(output_layer, output_weights, transpose_b=True)
logits = tf.nn.bias_add(logits, output_bias)
probabilities = tf.nn.softmax(logits, axis=-1)
log_probs = tf.nn.log_softmax(logits, axis=-1)
per_example_loss = tf.nn.sigmoid_cross_entropy_with_logits(labels=labels, logits=logits)
loss = tf.reduce_mean(per_example_loss)
return (loss, per_example_loss, logits, probabilities)
我在代码中修改的其他内容我没有问题:
- 用于加载和解析我的自定义数据集的数据处理器
- 在所有使用它的地方将标签变量的类型从数值更改为数组
所以,如果有人知道我应该如何解决我的问题,或者甚至指出我可能犯的一些明显错误,我会很高兴听到。
备注:
- 我发现 this article 与我正在尝试做的事情相当吻合,但它使用 PyTorch,我无法将其转换为 Tensorflow。
您想用 sigmoid 替换对可能输出(所有分数总和为 1)的单一分布建模的 softmax,它为每个 class(有 yes/no 分布建模独立分布对于每个输出)。
因此,您正确地更改了损失函数,但您还需要更改计算概率的方式。应该是:
probabilities = tf.sigmoid(logits)
在这种情况下,您不需要 log_probs
。
我想使用 BERT model 通过 Tensorflow 进行多标签 class 化。
为此,我想改编 BERT github repository, which is an example on how to use BERT to do simple classification, using the pre-trained weights given by Google Research 中的示例 run_classifier.py
。 (例如 BERT-Base, Cased
)
我有 X
个不同的标签,它们的值为 0 或 1,所以我想向原始 BERT 模型添加一个新的大小为 X
的密集层并使用 sigmoid_cross_entropy_with_logits
激活函数.
所以,对于理论部分,我认为我还可以。
问题是我不知道如何使用现有的 BertModel
class.[=23= 附加一个新的输出层并用我的数据集重新训练这个新层]
这是来自 run_classifier.py
的原始 create_model()
函数,我想我必须在其中进行修改。但是我有点不知道该怎么做。
def create_model(bert_config, is_training, input_ids, input_mask, segment_ids,
labels, num_labels, use_one_hot_embeddings):
"""Creates a classification model."""
model = modeling.BertModel(
config=bert_config,
is_training=is_training,
input_ids=input_ids,
input_mask=input_mask,
token_type_ids=segment_ids,
use_one_hot_embeddings=use_one_hot_embeddings)
output_layer = model.get_pooled_output()
hidden_size = output_layer.shape[-1].value
output_weights = tf.get_variable(
"output_weights", [num_labels, hidden_size],
initializer=tf.truncated_normal_initializer(stddev=0.02))
output_bias = tf.get_variable(
"output_bias", [num_labels], initializer=tf.zeros_initializer())
with tf.variable_scope("loss"):
if is_training:
# I.e., 0.1 dropout
output_layer = tf.nn.dropout(output_layer, keep_prob=0.9)
logits = tf.matmul(output_layer, output_weights, transpose_b=True)
logits = tf.nn.bias_add(logits, output_bias)
probabilities = tf.nn.softmax(logits, axis=-1)
log_probs = tf.nn.log_softmax(logits, axis=-1)
one_hot_labels = tf.one_hot(labels, depth=num_labels, dtype=tf.float32)
per_example_loss = -tf.reduce_sum(one_hot_labels * log_probs, axis=-1)
loss = tf.reduce_mean(per_example_loss)
return (loss, per_example_loss, logits, probabilities)
这里是相同的功能,只是我做了一些修改,但是哪里有遗漏的地方(还有错误的地方?)
def create_model(bert_config, is_training, input_ids, input_mask, segment_ids, labels, num_labels):
"""Creates a classification model."""
model = modeling.BertModel(
config=bert_config,
is_training=is_training,
input_ids=input_ids,
input_mask=input_mask,
token_type_ids=segment_ids)
output_layer = model.get_pooled_output()
hidden_size = output_layer.shape[-1].value
output_weights = tf.get_variable("output_weights", [num_labels, hidden_size],initializer=tf.truncated_normal_initializer(stddev=0.02))
output_bias = tf.get_variable("output_bias", [num_labels], initializer=tf.zeros_initializer())
with tf.variable_scope("loss"):
if is_training:
# I.e., 0.1 dropout
output_layer = tf.nn.dropout(output_layer, keep_prob=0.9)
logits = tf.matmul(output_layer, output_weights, transpose_b=True)
logits = tf.nn.bias_add(logits, output_bias)
probabilities = tf.nn.softmax(logits, axis=-1)
log_probs = tf.nn.log_softmax(logits, axis=-1)
per_example_loss = tf.nn.sigmoid_cross_entropy_with_logits(labels=labels, logits=logits)
loss = tf.reduce_mean(per_example_loss)
return (loss, per_example_loss, logits, probabilities)
我在代码中修改的其他内容我没有问题:
- 用于加载和解析我的自定义数据集的数据处理器
- 在所有使用它的地方将标签变量的类型从数值更改为数组
所以,如果有人知道我应该如何解决我的问题,或者甚至指出我可能犯的一些明显错误,我会很高兴听到。
备注:
- 我发现 this article 与我正在尝试做的事情相当吻合,但它使用 PyTorch,我无法将其转换为 Tensorflow。
您想用 sigmoid 替换对可能输出(所有分数总和为 1)的单一分布建模的 softmax,它为每个 class(有 yes/no 分布建模独立分布对于每个输出)。
因此,您正确地更改了损失函数,但您还需要更改计算概率的方式。应该是:
probabilities = tf.sigmoid(logits)
在这种情况下,您不需要 log_probs
。