Bert做回归

1. 引言

我们在做句子相似度计算的时候需要的输出是一个0到1之间的实数值,用来表示句子的相似程度。BERT默认只提供了run_classifier.py,它可以用于Fine-Tuning文本分类、相似度分类、Entailment等任务。但是无法实现实数值的输出,因此我参照run_classifier.py实现了一个run_reg.py。

2. 应用场景

2.1 github代码

需要的读者可以代码fancyerii/bert

如果读者是其它的版本,也可以去add regression fine-tuning #503

2.2 用法

用法和run_classifier.py很像,它要求的输入是如下格式:

手机号码注销了,怎么换手机号吗? 如何修改手机号 1
支付宝怎么充值 微信怎么充值 0.5
也就是使用TAB分割的文件,每行三列,前两列是两个句子,最后一列是一个实数值。

使用的示例代码为:

python run_reg.py \
    --task_name=sim \
    --do_train=true \
    --do_eval=true \
    --data_dir=/path/to/your/data \
    --vocab_file=$BERT_BASE_DIR/vocab.txt \
    --bert_config_file=$BERT_BASE_DIR/bert_config.json \
    --init_checkpoint=$BERT_BASE_DIR/bert_model.ckpt \
    --max_seq_length=64 \
    --train_batch_size=8 \
    --learning_rate=5e-5 \
    --num_train_epochs=2 \
    --output_dir=/tmp/sim/

需要指定task_name为sim,如果回归的输出范围不是0和1之间,那么需要设置–use_sigmoid_act=false。

如果读者的输入格式不同,也可以自己参考SimProcessor类实现自己的数据处理。

3. 实现细节

代码基本是拷贝的run_classifier.py,然后把输入从label_ids(int32)变成了vals(float32),把loss从交叉熵改成了MSE,同时修改了相应的Metrics。不感兴趣的读者可以跳过,并不影响使用。

create_model函数的修改
原来的代码:

  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)

新的代码:

  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)

    if FLAGS.use_sigmoid_act:
      output = tf.nn.sigmoid(logits)
    else:
      output = logits

    output = tf.squeeze(output, [1])
    loss = tf.losses.mean_squared_error(vals, output)

    return (loss, output)
file_based_convert_examples_to_features的修改

原代码:

    features = collections.OrderedDict()
    features["input_ids"] = create_int_feature(feature.input_ids)
    features["input_mask"] = create_int_feature(feature.input_mask)
    features["segment_ids"] = create_int_feature(feature.segment_ids)
    features["label_ids"] = create_int_feature([feature.label_id])
    features["is_real_example"] = create_int_feature(
        [int(feature.is_real_example)])

修改后的:

    def create_float_feature(vals):
      return tf.train.Feature(float_list=tf.train.FloatList(value=vals))

    features = collections.OrderedDict()
    features["input_ids"] = create_int_feature(feature.input_ids)
    features["input_mask"] = create_int_feature(feature.input_mask)
    features["segment_ids"] = create_int_feature(feature.segment_ids)
    features["vals"] = create_float_feature([feature.val])

model_fn_builder的修改
原来是分类,因此有eval_accuracy和eval_loss等指标,现在是回归,因此只有eval_loss这一个指标。

原代码:

      def metric_fn(per_example_loss, label_ids, logits, is_real_example):
        predictions = tf.argmax(logits, axis=-1, output_type=tf.int32)
        accuracy = tf.metrics.accuracy(
            labels=label_ids, predictions=predictions, weights=is_real_example)
        loss = tf.metrics.mean(values=per_example_loss, weights=is_real_example)
        return {
            "eval_accuracy": accuracy,
            "eval_loss": loss,
        }

      eval_metrics = (metric_fn,
                      [per_example_loss, label_ids, logits, is_real_example])

修改后的:

      def metric_fn(preds, vals):
        return {
            "eval_loss": tf.metrics.mean_squared_error(vals, preds),
        }

      eval_metrics = (metric_fn, [pred_vals, vals])

file_based_input_fn_builder的修改
读取TFRecord文件时也有小的修改。
原始代码

  name_to_features = {
      "input_ids": tf.FixedLenFeature([seq_length], tf.int64),
      "input_mask": tf.FixedLenFeature([seq_length], tf.int64),
      "segment_ids": tf.FixedLenFeature([seq_length], tf.int64),
      "label_ids": tf.FixedLenFeature([], tf.int64),
      "is_real_example": tf.FixedLenFeature([], tf.int64),
  }

修改后代码

  name_to_features = {
      "input_ids": tf.FixedLenFeature([seq_length], tf.int64),
      "input_mask": tf.FixedLenFeature([seq_length], tf.int64),
      "segment_ids": tf.FixedLenFeature([seq_length], tf.int64),
      "vals": tf.FixedLenFeature([], tf.float32),
  }
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: BERT(Bidirectional Encoder Representations from Transformers)是一种用于自然语言处理任务的神经网络模型,它可以用于分类任务。 对于分类任务,BERT可以在输入文本之后添加一个分类层,然后训练模型来预测输入文本属于哪一类。 举个例子,假设我们要对一些新闻文本进行分类,分为“体育”、“娱乐”、“政治”三类。我们可以使用BERT将新闻文本编码为一个向量,然后再在其之后添加一个分类层,训练模型来预测输入文本属于哪一类。 因此,在使用BERT进行分类任务时,需要提供训练样本,其中包含文本和对应的分类标签,然后训练模型来预测新的输入文本属于哪一类。 ### 回答2: BERT是一种预训练的深度双向转换器模型,可用于各种自然语言处理任务,包括分类任务。下面是BERT如何进行分类任务的步骤: 1. 输入准备:将输入文本转化为适应BERT模型的格式。首先,将文本分割为一系列的词语或子词(subword)。然后,添加特殊的[CLS]标记在文本开始的位置,并用[SEP]标记来分隔不同句子或文本片段。最后,将文本转化为词嵌入或子词嵌入,用于输入到BERT模型。 2. Fine-tuning:将预训练的BERT模型和一个额外的分类层进行连接,并对连接的模型进行微调。在微调过程中,通过将一批输入文本输入到BERT模型中,并传递其输出到分类层,利用标签信息计算损失,然后使用反向传播优化模型参数。 3. Token级别分类:如果需要进行单个词语或子词的分类任务,可直接使用BERT模型的输出向量,对每个词语或子词进行分类。可以将输出向量输入到一个全连接层或逻辑回归层中,再通过softmax函数进行分类。 4. 句子级别分类:如果需要对整个句子或文本片段进行分类,可以使用[CLS]标记的输出向量进行句子级别的分类。将[CLS]标记的输出向量输入到一个全连接层或逻辑回归层中,再通过softmax函数进行分类。 在进行BERT分类任务时,还可以根据具体任务的需要对模型进行一些改进,例如添加更多的隐藏层或调整超参数。此外,还可以与其他技术结合使用,如注意力机制或添加附加特征。最终,经过训练和微调的BERT模型可以应用于各种分类任务,如情感分析、文本分类等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值