详细内容请见:
huggingface的github:https://github.com/huggingface/transformers
官方文档:https://huggingface.co/transformers/

目录结构

image.png
注:原始的目录结构可参照huggingface的github的项目。

核心文件夹:
data:数据集,生成的cache文件也会存放在data_dir的同级文件夹下。
examples:入口文件,包含各类任务的入口文件,如分类回归任务的run_glud.py、多模态任务的mm-imdb、命名实体识别的run_ner.py、问答任务的run_squad.py、多项选择的run_multiple_choice.py、文本生成任务的run_generation.py。详细内容可查看官方github的examples下的README。
models:非官方,自己下载的model,如中文等预训练模型huggingface并未提供,自己下载后可存放在该文件夹下。
output:非官方,模型输出。
scripts:非官方,运行脚本。
src:源包,包含transformers的各个模型的文件,以及读取和评估文件。

如何使用自己的数据集?

以LIAR数据集为例进行流程介绍。

配置环境

根据官方提供的requirements.txt安装python虚拟环境。

数据集

将数据集存放在data文件夹下,自行划分文件结构即可。
image.png

入口文件

选择对应任务入口文件,如run_glue.py,可复制并修改为自己需要使用的文件(如run_classifier.py),以便后续增添自己需要的内容。
image.png

运行脚本

可按照如下结构划分各个任务的运行脚本结构,也可自己设计目录结构。
image.png

  1. #!/usr/bin/env bash
  2. set -eux
  3. export TASK=FakeNews # 任务名
  4. export TASK_NAME=LIAR # 子任务名
  5. export DATA_DIR=data/${TASK}/${TASK_NAME} # 数据集目录
  6. export OUTPUT_NAME=output # 模型输出目录
  7. export MODEL=roberta # 模型总称
  8. export MODEL_NAME=roberta-base # 模型名称
  9. export TRAIN_BATCH_SIZE=4 # 训练批次大小
  10. export EVAL_BATCH_SIZE=256 # 评估批次大小
  11. export SAVE_STEPS=1000 # 模型输出间隔
  12. export MAX_SEQ_LENGTH=64 # 句子最大长度
  13. # 用于在前一个输出模型上继续训练
  14. export STAGE_NUM=1 # 子模型阶段(可无)
  15. export NEXT_STAGE_NUM=3 # 下一个子模型阶段(可无)
  16. python ./examples/run_classifier.py \ # 入口文件
  17. --model_type ${MODEL} \
  18. --model_name_or_path ${MODEL_NAME} \
  19. --task_name ${TASK_NAME} \
  20. --do_lower_case \
  21. --data_dir ${DATA_DIR} \
  22. --max_seq_length ${MAX_SEQ_LENGTH} \
  23. --per_gpu_train_batch_size ${TRAIN_BATCH_SIZE} \
  24. --per_gpu_eval_batch_size ${EVAL_BATCH_SIZE} \
  25. --per_gpu_test_batch_size ${EVAL_BATCH_SIZE} \
  26. --per_gpu_pred_batch_size ${EVAL_BATCH_SIZE} \
  27. --learning_rate 1e-5 \ # 学习率
  28. --weight_decay 0.0001 \ # 权重衰减
  29. --num_train_epochs 1.0 \ # 轮次输目
  30. --output_dir ${OUTPUT_NAME}/${TASK}/${TASK_NAME}-${MODEL_NAME}/stage_${NEXT_STAGE_NUM} \
  31. --save_steps ${SAVE_STEPS} \
  32. --overwrite_cache \ # 是否覆盖cache,标记则为覆盖,默认读取cache
  33. --eval_all_checkpoints \ # 验证所有输出模型
  34. --do_test \
  35. --do_eval \
  36. --do_train \

读取数据

src/transformers/data/processors/glue.py
可复制一份作为自己的读取文件。
包含五个部分,

convert_examples_to_features

转化函数,可不用修改。

XXXXProcessor

各个任务的读取类,以LIAR任务举例。
  1. class LIARProcessor(DataProcessor):
  2. """Processor for the LIAR data set (My version)."""
  3. def get_example_from_tensor_dict(self, tensor_dict):
  4. """See base class."""
  5. return InputExample(tensor_dict['idx'].numpy(),
  6. tensor_dict['sentence'].numpy().decode('utf-8'),
  7. None,
  8. str(tensor_dict['label'].numpy()))
  9. def get_train_examples(self, data_dir):
  10. """See base class."""
  11. logger.info("LOOKING AT {}".format(os.path.join(data_dir, "train.tsv")))
  12. return self._create_examples(
  13. self._read_tsv(os.path.join(data_dir, "train.tsv")), "train")
  14. def get_dev_examples(self, data_dir):
  15. """See base class."""
  16. return self._create_examples(
  17. self._read_tsv(os.path.join(data_dir, "dev.tsv")), "dev")
  18. def get_test_examples(self, data_dir):
  19. """See base class."""
  20. return self._create_examples(
  21. self._read_tsv(os.path.join(data_dir, "test.tsv")), "dev")
  22. def get_pred_examples(self, data_dir):
  23. """See base class."""
  24. return self._create_examples(
  25. self._read_tsv(os.path.join(data_dir, "test.tsv")), "pred")
  26. def get_labels(self):
  27. """See base class."""
  28. return ["pants-fire", "false", "barely-true", "half-true", "mostly-true", "true"]
  29. def _create_examples(self, lines, set_type):
  30. """Creates examples for the training and dev sets."""
  31. examples = []
  32. for (i, line) in enumerate(lines):
  33. if i == 0:
  34. continue
  35. guid = line[0]
  36. label = line[1]
  37. if set_type in ["train", "dev", "test"]:
  38. text_a = line[2]
  39. text_a = self.preprocess(text_a)
  40. examples.append(InputExample(guid=guid, text_a=text_a, text_b=None, label=label))
  41. elif set_type == "pred":
  42. text_a = line[2]
  43. text_a = self.preprocess(text_a)
  44. examples.append(InputExample(guid=guid, text_a=text_a, text_b=None, label=None))
  45. return examples

tasks_num_labels

类别数。

  1. tasks_num_labels = {
  2. "liar": 6,
  3. }

processors

指定对应的processor类。

  1. processors = {
  2. "liar": LIARProcessor,
  3. }

output_modes

任务类型,分类任务(classification)/回归任务(regression)。


评估任务

src/transformers/data/metrics/init.py

评估函数
  1. # micro-F1
  2. def acc_and_f1_micro(preds, labels):
  3. acc = simple_accuracy(preds, labels)
  4. precision = metrics.precision_score(y_true=labels, y_pred=preds, average='micro')
  5. recall = metrics.recall_score(y_true=labels, y_pred=preds, average='micro')
  6. f1 = metrics.f1_score(y_true=labels, y_pred=preds, average='micro')
  7. return {
  8. "acc": acc,
  9. "precision": precision,
  10. "recall": recall,
  11. "micro-f1": f1,
  12. "acc_and_f1": (acc + f1) / 2,
  13. }
  14. # macro-F1
  15. def acc_and_f1_macro(preds, labels):
  16. acc = simple_accuracy(preds, labels)
  17. precision = metrics.precision_score(y_true=labels, y_pred=preds, average='macro')
  18. recall = metrics.recall_score(y_true=labels, y_pred=preds, average='macro')
  19. f1 = metrics.f1_score(y_true=labels, y_pred=preds, average='macro')
  20. return {
  21. "acc": acc,
  22. "precision": precision,
  23. "recall": recall,
  24. "macro-f1": f1,
  25. "acc_and_f1": (acc + f1) / 2,
  26. }
  27. # classification-report
  28. def classification_report(preds, labels, target_names=None):
  29. f1 = metrics.f1_score(y_true=labels, y_pred=preds, average='macro')
  30. report = metrics.classification_report(y_true=labels, y_pred=preds, target_names=target_names, digits=4)
  31. return {
  32. "report": report,
  33. "score_name": "macro-f1",
  34. "macro-f1": f1,
  35. }
  36. # 回归任务
  37. def pearson_and_spearman(preds, labels):
  38. pearson_corr = pearsonr(preds, labels)[0]
  39. spearman_corr = spearmanr(preds, labels)[0]
  40. return {
  41. "pearson": pearson_corr,
  42. "spearmanr": spearman_corr,
  43. "corr": (pearson_corr + spearman_corr) / 2,
  44. "score_name": "spearmanr",
  45. }

指定对应任务的评估方法

可自己写一个函数,以替换glue的。

  1. def my_compute_metrics(task_name, preds, labels, target_names=None):
  2. assert len(preds) == len(labels)
  3. if task_name == "fnews":
  4. return {"acc": simple_accuracy(preds, labels)}
  5. elif task_name == "liar":
  6. return classification_report(preds, labels, target_names)
  7. else:
  8. raise KeyError(task_name)

运行任务

windows下可进入git bash执行sh脚本。

进入虚拟环境

source activate xxxxxx

运行脚本

bash xxxxxxx