Merge branch 'master' into add_models_special_tokens_to_specific_configs
This commit is contained in:
@@ -14,22 +14,6 @@ jobs:
|
|||||||
- run: sudo pip install codecov pytest-cov
|
- run: sudo pip install codecov pytest-cov
|
||||||
- run: python -m pytest -n 8 --dist=loadfile -s -v ./tests/ --cov
|
- run: python -m pytest -n 8 --dist=loadfile -s -v ./tests/ --cov
|
||||||
- run: codecov
|
- run: codecov
|
||||||
run_all_tests_torch_and_tf:
|
|
||||||
working_directory: ~/transformers
|
|
||||||
docker:
|
|
||||||
- image: circleci/python:3.5
|
|
||||||
environment:
|
|
||||||
OMP_NUM_THREADS: 1
|
|
||||||
RUN_SLOW: yes
|
|
||||||
RUN_CUSTOM_TOKENIZERS: yes
|
|
||||||
resource_class: xlarge
|
|
||||||
parallelism: 1
|
|
||||||
steps:
|
|
||||||
- checkout
|
|
||||||
- run: sudo pip install .[mecab,sklearn,tf-cpu,torch,testing]
|
|
||||||
- run:
|
|
||||||
command: python -m pytest -n 8 --dist=loadfile -s -v ./tests/
|
|
||||||
no_output_timeout: 4h
|
|
||||||
|
|
||||||
run_tests_torch:
|
run_tests_torch:
|
||||||
working_directory: ~/transformers
|
working_directory: ~/transformers
|
||||||
@@ -134,13 +118,3 @@ workflows:
|
|||||||
- run_tests_torch
|
- run_tests_torch
|
||||||
- run_tests_tf
|
- run_tests_tf
|
||||||
- deploy_doc: *workflow_filters
|
- deploy_doc: *workflow_filters
|
||||||
run_slow_tests:
|
|
||||||
triggers:
|
|
||||||
- schedule:
|
|
||||||
cron: "0 4 * * *"
|
|
||||||
filters:
|
|
||||||
branches:
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
jobs:
|
|
||||||
- run_all_tests_torch_and_tf
|
|
||||||
|
|||||||
19
.github/workflows/github-push.yml
vendored
Normal file
19
.github/workflows/github-push.yml
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
name: GitHub-hosted runner
|
||||||
|
|
||||||
|
on: push
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check_code_quality:
|
||||||
|
runs-on: ubuntu-18.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v1
|
||||||
|
with:
|
||||||
|
python-version: 3.7
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
pip install .[tf,torch,quality]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
49
.github/workflows/self-push.yml
vendored
Normal file
49
.github/workflows/self-push.yml
vendored
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
name: Self-hosted runner (push)
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
run_tests_torch_and_tf_gpu:
|
||||||
|
runs-on: self-hosted
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Python version
|
||||||
|
run: |
|
||||||
|
which python
|
||||||
|
python --version
|
||||||
|
pip --version
|
||||||
|
- name: Current dir
|
||||||
|
run: pwd
|
||||||
|
- run: nvidia-smi
|
||||||
|
- name: Create new python env (on self-hosted runners we have to handle isolation ourselves)
|
||||||
|
run: |
|
||||||
|
python -m venv .env
|
||||||
|
source .env/bin/activate
|
||||||
|
which python
|
||||||
|
python --version
|
||||||
|
pip --version
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
source .env/bin/activate
|
||||||
|
pip install .[sklearn,tf,torch,testing]
|
||||||
|
|
||||||
|
- name: Are GPUs recognized by our DL frameworks
|
||||||
|
run: |
|
||||||
|
source .env/bin/activate
|
||||||
|
python -c "import torch; print(torch.cuda.is_available())"
|
||||||
|
python -c "import tensorflow as tf; print(tf.test.is_built_with_cuda(), tf.config.list_physical_devices('GPU'))"
|
||||||
|
|
||||||
|
- name: Run all non-slow tests on GPU
|
||||||
|
env:
|
||||||
|
TF_FORCE_GPU_ALLOW_GROWTH: "true"
|
||||||
|
# TF_GPU_MEMORY_LIMIT: 4096
|
||||||
|
OMP_NUM_THREADS: 1
|
||||||
|
USE_CUDA: yes
|
||||||
|
run: |
|
||||||
|
source .env/bin/activate
|
||||||
|
python -m pytest -n 2 --dist=loadfile -s -v ./tests/
|
||||||
51
.github/workflows/self-scheduled.yml
vendored
Normal file
51
.github/workflows/self-scheduled.yml
vendored
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
name: Self-hosted runner (scheduled)
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- ci_*
|
||||||
|
repository_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: "0 0 * * *"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
run_all_tests_torch_and_tf_gpu:
|
||||||
|
runs-on: self-hosted
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Python version
|
||||||
|
run: |
|
||||||
|
which python
|
||||||
|
python --version
|
||||||
|
pip --version
|
||||||
|
- name: Current dir
|
||||||
|
run: pwd
|
||||||
|
- run: nvidia-smi
|
||||||
|
- name: Create new python env (on self-hosted runners we have to handle isolation ourselves)
|
||||||
|
run: |
|
||||||
|
python -m venv .env
|
||||||
|
source .env/bin/activate
|
||||||
|
which python
|
||||||
|
python --version
|
||||||
|
pip --version
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
source .env/bin/activate
|
||||||
|
pip install .[sklearn,tf,torch,testing]
|
||||||
|
|
||||||
|
- name: Are GPUs recognized by our DL frameworks
|
||||||
|
run: |
|
||||||
|
source .env/bin/activate
|
||||||
|
python -c "import torch; print(torch.cuda.is_available())"
|
||||||
|
python -c "import tensorflow as tf; print(tf.test.is_built_with_cuda(), tf.config.list_physical_devices('GPU'))"
|
||||||
|
|
||||||
|
- name: Run all tests on GPU
|
||||||
|
env:
|
||||||
|
TF_FORCE_GPU_ALLOW_GROWTH: "true"
|
||||||
|
OMP_NUM_THREADS: 1
|
||||||
|
RUN_SLOW: yes
|
||||||
|
USE_CUDA: yes
|
||||||
|
run: |
|
||||||
|
source .env/bin/activate
|
||||||
|
python -m pytest -n 1 --dist=loadfile -s -v ./tests/
|
||||||
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
FROM pytorch/pytorch:latest
|
|
||||||
|
|
||||||
RUN git clone https://github.com/NVIDIA/apex.git && cd apex && python setup.py install --cuda_ext --cpp_ext
|
|
||||||
|
|
||||||
RUN pip install transformers
|
|
||||||
|
|
||||||
WORKDIR /workspace
|
|
||||||
26
docker/transformers-cpu/Dockerfile
Normal file
26
docker/transformers-cpu/Dockerfile
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
FROM ubuntu:18.04
|
||||||
|
LABEL maintainer="Hugging Face"
|
||||||
|
LABEL repository="transformers"
|
||||||
|
|
||||||
|
RUN apt update && \
|
||||||
|
apt install -y bash \
|
||||||
|
build-essential \
|
||||||
|
git \
|
||||||
|
curl \
|
||||||
|
ca-certificates \
|
||||||
|
python3 \
|
||||||
|
python3-pip && \
|
||||||
|
rm -rf /var/lib/apt/lists
|
||||||
|
|
||||||
|
RUN python3 -m pip install --no-cache-dir --upgrade pip && \
|
||||||
|
python3 -m pip install --no-cache-dir \
|
||||||
|
jupyter \
|
||||||
|
tensorflow-cpu \
|
||||||
|
torch
|
||||||
|
|
||||||
|
WORKDIR /workspace
|
||||||
|
COPY . transformers/
|
||||||
|
RUN cd transformers/ && \
|
||||||
|
python3 -m pip install --no-cache-dir .
|
||||||
|
|
||||||
|
CMD ["/bin/bash"]
|
||||||
26
docker/transformers-gpu/Dockerfile
Normal file
26
docker/transformers-gpu/Dockerfile
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
FROM nvidia/cuda:10.1-cudnn7-runtime-ubuntu18.04
|
||||||
|
LABEL maintainer="Hugging Face"
|
||||||
|
LABEL repository="transformers"
|
||||||
|
|
||||||
|
RUN apt update && \
|
||||||
|
apt install -y bash \
|
||||||
|
build-essential \
|
||||||
|
git \
|
||||||
|
curl \
|
||||||
|
ca-certificates \
|
||||||
|
python3 \
|
||||||
|
python3-pip && \
|
||||||
|
rm -rf /var/lib/apt/lists
|
||||||
|
|
||||||
|
RUN python3 -m pip install --no-cache-dir --upgrade pip && \
|
||||||
|
python3 -m pip install --no-cache-dir \
|
||||||
|
jupyter \
|
||||||
|
tensorflow \
|
||||||
|
torch
|
||||||
|
|
||||||
|
WORKDIR /workspace
|
||||||
|
COPY . transformers/
|
||||||
|
RUN cd transformers/ && \
|
||||||
|
python3 -m pip install --no-cache-dir .
|
||||||
|
|
||||||
|
CMD ["/bin/bash"]
|
||||||
25
docker/transformers-pytorch-cpu/Dockerfile
Normal file
25
docker/transformers-pytorch-cpu/Dockerfile
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
FROM ubuntu:18.04
|
||||||
|
LABEL maintainer="Hugging Face"
|
||||||
|
LABEL repository="transformers"
|
||||||
|
|
||||||
|
RUN apt update && \
|
||||||
|
apt install -y bash \
|
||||||
|
build-essential \
|
||||||
|
git \
|
||||||
|
curl \
|
||||||
|
ca-certificates \
|
||||||
|
python3 \
|
||||||
|
python3-pip && \
|
||||||
|
rm -rf /var/lib/apt/lists
|
||||||
|
|
||||||
|
RUN python3 -m pip install --no-cache-dir --upgrade pip && \
|
||||||
|
python3 -m pip install --no-cache-dir \
|
||||||
|
jupyter \
|
||||||
|
torch
|
||||||
|
|
||||||
|
WORKDIR /workspace
|
||||||
|
COPY . transformers/
|
||||||
|
RUN cd transformers/ && \
|
||||||
|
python3 -m pip install --no-cache-dir .
|
||||||
|
|
||||||
|
CMD ["/bin/bash"]
|
||||||
25
docker/transformers-pytorch-gpu/Dockerfile
Normal file
25
docker/transformers-pytorch-gpu/Dockerfile
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
FROM nvidia/cuda:10.1-cudnn7-runtime-ubuntu18.04
|
||||||
|
LABEL maintainer="Hugging Face"
|
||||||
|
LABEL repository="transformers"
|
||||||
|
|
||||||
|
RUN apt update && \
|
||||||
|
apt install -y bash \
|
||||||
|
build-essential \
|
||||||
|
git \
|
||||||
|
curl \
|
||||||
|
ca-certificates \
|
||||||
|
python3 \
|
||||||
|
python3-pip && \
|
||||||
|
rm -rf /var/lib/apt/lists
|
||||||
|
|
||||||
|
RUN python3 -m pip install --no-cache-dir --upgrade pip && \
|
||||||
|
python3 -m pip install --no-cache-dir \
|
||||||
|
mkl \
|
||||||
|
torch
|
||||||
|
|
||||||
|
WORKDIR /workspace
|
||||||
|
COPY . transformers/
|
||||||
|
RUN cd transformers/ && \
|
||||||
|
python3 -m pip install --no-cache-dir .
|
||||||
|
|
||||||
|
CMD ["/bin/bash"]
|
||||||
25
docker/transformers-tensorflow-cpu/Dockerfile
Normal file
25
docker/transformers-tensorflow-cpu/Dockerfile
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
FROM ubuntu:18.04
|
||||||
|
LABEL maintainer="Hugging Face"
|
||||||
|
LABEL repository="transformers"
|
||||||
|
|
||||||
|
RUN apt update && \
|
||||||
|
apt install -y bash \
|
||||||
|
build-essential \
|
||||||
|
git \
|
||||||
|
curl \
|
||||||
|
ca-certificates \
|
||||||
|
python3 \
|
||||||
|
python3-pip && \
|
||||||
|
rm -rf /var/lib/apt/lists
|
||||||
|
|
||||||
|
RUN python3 -m pip install --no-cache-dir --upgrade pip && \
|
||||||
|
python3 -m pip install --no-cache-dir \
|
||||||
|
mkl \
|
||||||
|
tensorflow-cpu
|
||||||
|
|
||||||
|
WORKDIR /workspace
|
||||||
|
COPY . transformers/
|
||||||
|
RUN cd transformers/ && \
|
||||||
|
python3 -m pip install --no-cache-dir .
|
||||||
|
|
||||||
|
CMD ["/bin/bash"]
|
||||||
25
docker/transformers-tensorflow-gpu/Dockerfile
Normal file
25
docker/transformers-tensorflow-gpu/Dockerfile
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
FROM nvidia/cuda:10.1-cudnn7-runtime-ubuntu18.04
|
||||||
|
LABEL maintainer="Hugging Face"
|
||||||
|
LABEL repository="transformers"
|
||||||
|
|
||||||
|
RUN apt update && \
|
||||||
|
apt install -y bash \
|
||||||
|
build-essential \
|
||||||
|
git \
|
||||||
|
curl \
|
||||||
|
ca-certificates \
|
||||||
|
python3 \
|
||||||
|
python3-pip && \
|
||||||
|
rm -rf /var/lib/apt/lists
|
||||||
|
|
||||||
|
RUN python3 -m pip install --no-cache-dir --upgrade pip && \
|
||||||
|
python3 -m pip install --no-cache-dir \
|
||||||
|
mkl \
|
||||||
|
tensorflow
|
||||||
|
|
||||||
|
WORKDIR /workspace
|
||||||
|
COPY . transformers/
|
||||||
|
RUN cd transformers/ && \
|
||||||
|
python3 -m pip install --no-cache-dir .
|
||||||
|
|
||||||
|
CMD ["/bin/bash"]
|
||||||
@@ -1,3 +1,25 @@
|
|||||||
|
/* Our DOM objects */
|
||||||
|
|
||||||
|
.framework-selector {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.framework-selector > button {
|
||||||
|
background-color: white;
|
||||||
|
color: #6670FF;
|
||||||
|
border: 1px solid #6670FF;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.framework-selector > button.selected{
|
||||||
|
background-color: #6670FF;
|
||||||
|
color: white;
|
||||||
|
border: 1px solid #6670FF;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
/* The literal code blocks */
|
/* The literal code blocks */
|
||||||
.rst-content tt.literal, .rst-content tt.literal, .rst-content code.literal {
|
.rst-content tt.literal, .rst-content tt.literal, .rst-content code.literal {
|
||||||
color: #6670FF;
|
color: #6670FF;
|
||||||
|
|||||||
@@ -68,6 +68,74 @@ function addHfMenu() {
|
|||||||
document.body.insertAdjacentHTML('afterbegin', div);
|
document.body.insertAdjacentHTML('afterbegin', div);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function platformToggle() {
|
||||||
|
const codeBlocks = Array.from(document.getElementsByClassName("highlight"));
|
||||||
|
const pytorchIdentifier = "## PYTORCH CODE";
|
||||||
|
const tensorflowIdentifier = "## TENSORFLOW CODE";
|
||||||
|
const pytorchSpanIdentifier = `<span class="c1">${pytorchIdentifier}</span>`;
|
||||||
|
const tensorflowSpanIdentifier = `<span class="c1">${tensorflowIdentifier}</span>`;
|
||||||
|
|
||||||
|
const getFrameworkSpans = filteredCodeBlock => {
|
||||||
|
const spans = filteredCodeBlock.element.innerHTML;
|
||||||
|
const pytorchSpanPosition = spans.indexOf(pytorchSpanIdentifier);
|
||||||
|
const tensorflowSpanPosition = spans.indexOf(tensorflowSpanIdentifier);
|
||||||
|
|
||||||
|
let pytorchSpans;
|
||||||
|
let tensorflowSpans;
|
||||||
|
|
||||||
|
if(pytorchSpanPosition < tensorflowSpanPosition){
|
||||||
|
pytorchSpans = spans.slice(pytorchSpanPosition + pytorchSpanIdentifier.length + 1, tensorflowSpanPosition);
|
||||||
|
tensorflowSpans = spans.slice(tensorflowSpanPosition + tensorflowSpanIdentifier.length + 1, spans.length);
|
||||||
|
}else{
|
||||||
|
tensorflowSpans = spans.slice(tensorflowSpanPosition + tensorflowSpanIdentifier.length + 1, pytorchSpanPosition);
|
||||||
|
pytorchSpans = spans.slice(pytorchSpanPosition + pytorchSpanIdentifier.length + 1, spans.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...filteredCodeBlock,
|
||||||
|
pytorchSample: pytorchSpans ,
|
||||||
|
tensorflowSample: tensorflowSpans
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const createFrameworkButtons = sample => {
|
||||||
|
const pytorchButton = document.createElement("button");
|
||||||
|
pytorchButton.innerText = "PyTorch";
|
||||||
|
|
||||||
|
const tensorflowButton = document.createElement("button");
|
||||||
|
tensorflowButton.innerText = "TensorFlow";
|
||||||
|
|
||||||
|
const selectorDiv = document.createElement("div");
|
||||||
|
selectorDiv.classList.add("framework-selector");
|
||||||
|
selectorDiv.appendChild(pytorchButton);
|
||||||
|
selectorDiv.appendChild(tensorflowButton);
|
||||||
|
sample.element.parentElement.prepend(selectorDiv);
|
||||||
|
|
||||||
|
// Init on PyTorch
|
||||||
|
sample.element.innerHTML = sample.pytorchSample;
|
||||||
|
pytorchButton.classList.add("selected");
|
||||||
|
tensorflowButton.classList.remove("selected");
|
||||||
|
|
||||||
|
pytorchButton.addEventListener("click", () => {
|
||||||
|
sample.element.innerHTML = sample.pytorchSample;
|
||||||
|
pytorchButton.classList.add("selected");
|
||||||
|
tensorflowButton.classList.remove("selected");
|
||||||
|
});
|
||||||
|
tensorflowButton.addEventListener("click", () => {
|
||||||
|
sample.element.innerHTML = sample.tensorflowSample;
|
||||||
|
tensorflowButton.classList.add("selected");
|
||||||
|
pytorchButton.classList.remove("selected");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
codeBlocks
|
||||||
|
.map(element => {return {element: element.firstChild, innerText: element.innerText}})
|
||||||
|
.filter(codeBlock => codeBlock.innerText.includes(pytorchIdentifier) && codeBlock.innerText.includes(tensorflowIdentifier))
|
||||||
|
.map(getFrameworkSpans)
|
||||||
|
.forEach(createFrameworkButtons);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* github-buttons v2.2.10
|
* github-buttons v2.2.10
|
||||||
* (c) 2019 なつき
|
* (c) 2019 なつき
|
||||||
@@ -85,6 +153,7 @@ function onLoad() {
|
|||||||
addGithubButton();
|
addGithubButton();
|
||||||
parseGithubButtons();
|
parseGithubButtons();
|
||||||
addHfMenu();
|
addHfMenu();
|
||||||
|
platformToggle();
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener("load", onLoad);
|
window.addEventListener("load", onLoad);
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 7.6 KiB |
@@ -20,7 +20,7 @@ sys.path.insert(0, os.path.abspath('../../src'))
|
|||||||
# -- Project information -----------------------------------------------------
|
# -- Project information -----------------------------------------------------
|
||||||
|
|
||||||
project = u'transformers'
|
project = u'transformers'
|
||||||
copyright = u'2019, huggingface'
|
copyright = u'2020, huggingface'
|
||||||
author = u'huggingface'
|
author = u'huggingface'
|
||||||
|
|
||||||
# The short X.Y version
|
# The short X.Y version
|
||||||
@@ -105,6 +105,12 @@ html_static_path = ['_static']
|
|||||||
#
|
#
|
||||||
# html_sidebars = {}
|
# html_sidebars = {}
|
||||||
|
|
||||||
|
# This must be the name of an image file (path relative to the configuration
|
||||||
|
# directory) that is the favicon of the docs. Modern browsers use this as
|
||||||
|
# the icon for tabs, windows and bookmarks. It should be a Windows-style
|
||||||
|
# icon file (.ico).
|
||||||
|
html_favicon = 'favicon.ico'
|
||||||
|
|
||||||
|
|
||||||
# -- Options for HTMLHelp output ---------------------------------------------
|
# -- Options for HTMLHelp output ---------------------------------------------
|
||||||
|
|
||||||
|
|||||||
BIN
docs/source/favicon.ico
Normal file
BIN
docs/source/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 47 KiB |
@@ -61,6 +61,7 @@ The library currently contains PyTorch and Tensorflow implementations, pre-train
|
|||||||
quickstart
|
quickstart
|
||||||
glossary
|
glossary
|
||||||
pretrained_models
|
pretrained_models
|
||||||
|
usage
|
||||||
model_sharing
|
model_sharing
|
||||||
examples
|
examples
|
||||||
notebooks
|
notebooks
|
||||||
@@ -79,6 +80,7 @@ The library currently contains PyTorch and Tensorflow implementations, pre-train
|
|||||||
main_classes/configuration
|
main_classes/configuration
|
||||||
main_classes/model
|
main_classes/model
|
||||||
main_classes/tokenizer
|
main_classes/tokenizer
|
||||||
|
main_classes/pipelines
|
||||||
main_classes/optimizer_schedules
|
main_classes/optimizer_schedules
|
||||||
main_classes/processors
|
main_classes/processors
|
||||||
|
|
||||||
|
|||||||
63
docs/source/main_classes/pipelines.rst
Normal file
63
docs/source/main_classes/pipelines.rst
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
Pipelines
|
||||||
|
----------------------------------------------------
|
||||||
|
|
||||||
|
The pipelines are a great and easy way to use models for inference. These pipelines are objects that abstract most
|
||||||
|
of the complex code from the library, offering a simple API dedicated to several tasks, including Named Entity
|
||||||
|
Recognition, Masked Language Modeling, Sentiment Analysis, Feature Extraction and Question Answering.
|
||||||
|
|
||||||
|
There are two categories of pipeline abstractions to be aware about:
|
||||||
|
|
||||||
|
- The :class:`~transformers.pipeline` which is the most powerful object encapsulating all other pipelines
|
||||||
|
- The other task-specific pipelines, such as :class:`~transformers.NerPipeline`
|
||||||
|
or :class:`~transformers.QuestionAnsweringPipeline`
|
||||||
|
|
||||||
|
The pipeline abstraction
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The `pipeline` abstraction is a wrapper around all the other available pipelines. It is instantiated as any
|
||||||
|
other pipeline but requires an additional argument which is the `task`.
|
||||||
|
|
||||||
|
.. autoclass:: transformers.pipeline
|
||||||
|
:members:
|
||||||
|
|
||||||
|
|
||||||
|
The task specific pipelines
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Parent class: Pipeline
|
||||||
|
=========================================
|
||||||
|
|
||||||
|
.. autoclass:: transformers.Pipeline
|
||||||
|
:members: predict, transform, save_pretrained
|
||||||
|
|
||||||
|
NerPipeline
|
||||||
|
==========================================
|
||||||
|
|
||||||
|
.. autoclass:: transformers.NerPipeline
|
||||||
|
|
||||||
|
TokenClassificationPipeline
|
||||||
|
==========================================
|
||||||
|
|
||||||
|
This class is an alias of the :class:`~transformers.NerPipeline` defined above. Please refer to that pipeline for
|
||||||
|
documentation and usage examples.
|
||||||
|
|
||||||
|
FillMaskPipeline
|
||||||
|
==========================================
|
||||||
|
|
||||||
|
.. autoclass:: transformers.FillMaskPipeline
|
||||||
|
|
||||||
|
FeatureExtractionPipeline
|
||||||
|
==========================================
|
||||||
|
|
||||||
|
.. autoclass:: transformers.FeatureExtractionPipeline
|
||||||
|
|
||||||
|
TextClassificationPipeline
|
||||||
|
==========================================
|
||||||
|
|
||||||
|
.. autoclass:: transformers.TextClassificationPipeline
|
||||||
|
|
||||||
|
QuestionAnsweringPipeline
|
||||||
|
==========================================
|
||||||
|
|
||||||
|
.. autoclass:: transformers.QuestionAnsweringPipeline
|
||||||
|
|
||||||
@@ -41,7 +41,8 @@ AlbertTokenizer
|
|||||||
~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. autoclass:: transformers.AlbertTokenizer
|
.. autoclass:: transformers.AlbertTokenizer
|
||||||
:members:
|
:members: build_inputs_with_special_tokens, get_special_tokens_mask,
|
||||||
|
create_token_type_ids_from_sequences, save_vocabulary
|
||||||
|
|
||||||
|
|
||||||
AlbertModel
|
AlbertModel
|
||||||
|
|||||||
@@ -4,20 +4,27 @@ Bart
|
|||||||
file a `Github Issue <https://github.com/huggingface/transformers/issues/new?assignees=&labels=&template=bug-report.md&title>`__ and assign
|
file a `Github Issue <https://github.com/huggingface/transformers/issues/new?assignees=&labels=&template=bug-report.md&title>`__ and assign
|
||||||
@sshleifer
|
@sshleifer
|
||||||
|
|
||||||
The Bart model was `proposed <https://arxiv.org/abs/1910.13461>`_ by Mike Lewis, Yinhan Liu, Naman Goyal, Marjan Ghazvininejad, Abdelrahman Mohamed, Omer Levy, Ves Stoyanov, Luke Zettlemoyer on 29 Oct, 2019.
|
Paper
|
||||||
It is a sequence to sequence model where both encoder and decoder are transformers. The paper also introduces a novel pretraining objective, and demonstrates excellent summarization results.
|
~~~~~
|
||||||
The authors released their code `here <https://github.com/pytorch/fairseq/tree/master/examples/bart>`_
|
The Bart model was `proposed <https://arxiv.org/abs/1910.13461>`_ by Mike Lewis, Yinhan Liu, Naman Goyal, Marjan Ghazvininejad, Abdelrahman Mohamed, Omer Levy, Ves Stoyanov and Luke Zettlemoyer on 29 Oct, 2019.
|
||||||
|
According to the abstract:
|
||||||
|
|
||||||
**Abstract:**
|
- Bart uses a standard seq2seq/machine translation architecture with a bidirectional encoder (like BERT) and a left-to-right decoder (like GPT).
|
||||||
|
- The pretraining task involves randomly shuffling the order of the original sentences and a novel in-filling scheme, where spans of text are replaced with a single mask token.
|
||||||
|
- BART is particularly effective when fine tuned for text generation but also works well for comprehension tasks. It matches the performance of RoBERTa with comparable training resources on GLUE and SQuAD, achieves new state-of-the-art results on a range of abstractive dialogue, question answering, and summarization tasks, with gains of up to 6 ROUGE.
|
||||||
|
|
||||||
*We present BART, a denoising autoencoder for pretraining sequence-to-sequence models. BART is trained by (1) corrupting text with an arbitrary noising function, and (2) learning a model to reconstruct the original text. It uses a standard Tranformer-based neural machine translation architecture which, despite its simplicity, can be seen as generalizing BERT (due to the bidirectional encoder), GPT (with the left-to-right decoder), and many other more recent pretraining schemes. We evaluate a number of noising approaches, finding the best performance by both randomly shuffling the order of the original sentences and using a novel in-filling scheme, where spans of text are replaced with a single mask token. BART is particularly effective when fine tuned for text generation but also works well for comprehension tasks. It matches the performance of RoBERTa with comparable training resources on GLUE and SQuAD, achieves new state-of-the-art results on a range of abstractive dialogue, question answering, and summarization tasks, with gains of up to 6 ROUGE. BART also provides a 1.1 BLEU increase over a back-translation system for machine translation, with only target language pretraining. We also report ablation experiments that replicate other pretraining schemes within the BART framework, to better measure which factors most influence end-task performance.*
|
The Authors' code can be found `here <https://github.com/pytorch/fairseq/tree/master/examples/bart>`_
|
||||||
`BART: Denoising Sequence-to-Sequence Pre-training for Natural Language Generation, Translation, and Comprehension`
|
|
||||||
|
|
||||||
|
|
||||||
Notes:
|
Implementation Notes
|
||||||
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
- Bart doesn't use :obj:`token_type_ids`, for sequence classification just use BartTokenizer.encode to get the proper splitting.
|
- Bart doesn't use :obj:`token_type_ids`, for sequence classification just use BartTokenizer.encode to get the proper splitting.
|
||||||
- Inputs to the decoder are created by BartModel.forward if they are not passed. This is different than some other model APIs.
|
- Inputs to the decoder are created by BartModel.forward if they are not passed. This is different than some other model APIs.
|
||||||
- Model predictions are intended to be identical to the original implementation. This only works, however, if the string you pass to fairseq.encode starts with a space.
|
- Model predictions are intended to be identical to the original implementation. This only works, however, if the string you pass to fairseq.encode starts with a space.
|
||||||
|
- Decoder inputs are created automatically by the helper function ``transformers.modeling_bart._prepare_bart_decoder_inputs``
|
||||||
|
BartModel
|
||||||
|
- ``MaskedLM.generate`` should be used for summarization, see the example in that docstrings
|
||||||
|
|
||||||
|
|
||||||
BartModel
|
BartModel
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
@@ -30,7 +37,7 @@ BartForMaskedLM
|
|||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. autoclass:: transformers.BartForMaskedLM
|
.. autoclass:: transformers.BartForMaskedLM
|
||||||
:members: forward
|
:members: forward, generate
|
||||||
|
|
||||||
|
|
||||||
BartForSequenceClassification
|
BartForSequenceClassification
|
||||||
|
|||||||
@@ -46,7 +46,8 @@ BertTokenizer
|
|||||||
~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. autoclass:: transformers.BertTokenizer
|
.. autoclass:: transformers.BertTokenizer
|
||||||
:members:
|
:members: build_inputs_with_special_tokens, get_special_tokens_mask,
|
||||||
|
create_token_type_ids_from_sequences, save_vocabulary
|
||||||
|
|
||||||
|
|
||||||
BertModel
|
BertModel
|
||||||
|
|||||||
@@ -33,7 +33,8 @@ CamembertTokenizer
|
|||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. autoclass:: transformers.CamembertTokenizer
|
.. autoclass:: transformers.CamembertTokenizer
|
||||||
:members:
|
:members: build_inputs_with_special_tokens, get_special_tokens_mask,
|
||||||
|
create_token_type_ids_from_sequences, save_vocabulary
|
||||||
|
|
||||||
|
|
||||||
CamembertModel
|
CamembertModel
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ CTRLTokenizer
|
|||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. autoclass:: transformers.CTRLTokenizer
|
.. autoclass:: transformers.CTRLTokenizer
|
||||||
:members:
|
:members: save_vocabulary
|
||||||
|
|
||||||
|
|
||||||
CTRLModel
|
CTRLModel
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ OpenAIGPTTokenizer
|
|||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. autoclass:: transformers.OpenAIGPTTokenizer
|
.. autoclass:: transformers.OpenAIGPTTokenizer
|
||||||
:members:
|
:members: save_vocabulary
|
||||||
|
|
||||||
|
|
||||||
OpenAIGPTModel
|
OpenAIGPTModel
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ Overview
|
|||||||
~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
OpenAI GPT-2 model was proposed in
|
OpenAI GPT-2 model was proposed in
|
||||||
`Language Models are Unsupervised Multitask Learners`_
|
`Language Models are Unsupervised Multitask Learners <https://cdn.openai.com/better-language-models/language_models_are_unsupervised_multitask_learners.pdf>`_
|
||||||
by Alec Radford*, Jeffrey Wu*, Rewon Child, David Luan, Dario Amodei** and Ilya Sutskever**.
|
by Alec Radford*, Jeffrey Wu*, Rewon Child, David Luan, Dario Amodei** and Ilya Sutskever**.
|
||||||
It's a causal (unidirectional) transformer pre-trained using language modeling on a very large
|
It's a causal (unidirectional) transformer pre-trained using language modeling on a very large
|
||||||
corpus of ~40 GB of text data.
|
corpus of ~40 GB of text data.
|
||||||
@@ -46,7 +46,7 @@ GPT2Tokenizer
|
|||||||
~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. autoclass:: transformers.GPT2Tokenizer
|
.. autoclass:: transformers.GPT2Tokenizer
|
||||||
:members:
|
:members: save_vocabulary
|
||||||
|
|
||||||
|
|
||||||
GPT2Model
|
GPT2Model
|
||||||
|
|||||||
@@ -39,7 +39,8 @@ RobertaTokenizer
|
|||||||
~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. autoclass:: transformers.RobertaTokenizer
|
.. autoclass:: transformers.RobertaTokenizer
|
||||||
:members:
|
:members: build_inputs_with_special_tokens, get_special_tokens_mask,
|
||||||
|
create_token_type_ids_from_sequences, save_vocabulary
|
||||||
|
|
||||||
|
|
||||||
RobertaModel
|
RobertaModel
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ TransfoXLTokenizer
|
|||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. autoclass:: transformers.TransfoXLTokenizer
|
.. autoclass:: transformers.TransfoXLTokenizer
|
||||||
:members:
|
:members: save_vocabulary
|
||||||
|
|
||||||
|
|
||||||
TransfoXLModel
|
TransfoXLModel
|
||||||
|
|||||||
@@ -41,7 +41,8 @@ XLMTokenizer
|
|||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. autoclass:: transformers.XLMTokenizer
|
.. autoclass:: transformers.XLMTokenizer
|
||||||
:members:
|
:members: build_inputs_with_special_tokens, get_special_tokens_mask,
|
||||||
|
create_token_type_ids_from_sequences, save_vocabulary
|
||||||
|
|
||||||
XLMModel
|
XLMModel
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|||||||
@@ -39,7 +39,8 @@ XLMRobertaTokenizer
|
|||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. autoclass:: transformers.XLMRobertaTokenizer
|
.. autoclass:: transformers.XLMRobertaTokenizer
|
||||||
:members:
|
:members: build_inputs_with_special_tokens, get_special_tokens_mask,
|
||||||
|
create_token_type_ids_from_sequences, save_vocabulary
|
||||||
|
|
||||||
|
|
||||||
XLMRobertaModel
|
XLMRobertaModel
|
||||||
|
|||||||
@@ -44,7 +44,8 @@ XLNetTokenizer
|
|||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. autoclass:: transformers.XLNetTokenizer
|
.. autoclass:: transformers.XLNetTokenizer
|
||||||
:members:
|
:members: build_inputs_with_special_tokens, get_special_tokens_mask,
|
||||||
|
create_token_type_ids_from_sequences, save_vocabulary
|
||||||
|
|
||||||
|
|
||||||
XLNetModel
|
XLNetModel
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ The different languages this model/tokenizer handles, as well as the ids of thes
|
|||||||
|
|
||||||
.. code-block::
|
.. code-block::
|
||||||
|
|
||||||
|
# Continuation of the previous script
|
||||||
print(tokenizer.lang2id) # {'en': 0, 'fr': 1}
|
print(tokenizer.lang2id) # {'en': 0, 'fr': 1}
|
||||||
|
|
||||||
|
|
||||||
@@ -54,6 +55,7 @@ These ids should be used when passing a language parameter during a model pass.
|
|||||||
|
|
||||||
.. code-block::
|
.. code-block::
|
||||||
|
|
||||||
|
# Continuation of the previous script
|
||||||
input_ids = torch.tensor([tokenizer.encode("Wikipedia was used to")]) # batch size of 1
|
input_ids = torch.tensor([tokenizer.encode("Wikipedia was used to")]) # batch size of 1
|
||||||
|
|
||||||
|
|
||||||
@@ -62,6 +64,7 @@ filled with the appropriate language ids, of the same size as input_ids. For eng
|
|||||||
|
|
||||||
.. code-block::
|
.. code-block::
|
||||||
|
|
||||||
|
# Continuation of the previous script
|
||||||
language_id = tokenizer.lang2id['en'] # 0
|
language_id = tokenizer.lang2id['en'] # 0
|
||||||
langs = torch.tensor([language_id] * input_ids.shape[1]) # torch.tensor([0, 0, 0, ..., 0])
|
langs = torch.tensor([language_id] * input_ids.shape[1]) # torch.tensor([0, 0, 0, ..., 0])
|
||||||
|
|
||||||
@@ -73,6 +76,7 @@ You can then feed it all as input to your model:
|
|||||||
|
|
||||||
.. code-block::
|
.. code-block::
|
||||||
|
|
||||||
|
# Continuation of the previous script
|
||||||
outputs = model(input_ids, langs=langs)
|
outputs = model(input_ids, langs=langs)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -280,7 +280,10 @@ For a list that includes community-uploaded models, refer to `https://huggingfac
|
|||||||
| | | (see `details <https://github.com/pytorch/fairseq/tree/master/examples/bart>`_) |
|
| | | (see `details <https://github.com/pytorch/fairseq/tree/master/examples/bart>`_) |
|
||||||
| +------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------+
|
| +------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| | ``bart-large-mnli`` | | Adds a 2 layer classification head with 1 million parameters |
|
| | ``bart-large-mnli`` | | Adds a 2 layer classification head with 1 million parameters |
|
||||||
| | | | bart-large base architecture with a classification head |
|
| | | | bart-large base architecture with a classification head, finetuned on MNLI |
|
||||||
|
| +------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| | ``bart-large-cnn`` | | 12-layer, 1024-hidden, 16-heads, 406M parameters (same as base) |
|
||||||
|
| | | | bart-large base architecture finetuned on cnn summarization task |
|
||||||
+-------------------+------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------+
|
+-------------------+------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -220,96 +220,3 @@ print(sequence)
|
|||||||
```
|
```
|
||||||
|
|
||||||
The model only requires a single token as input as all the previous tokens' key/value pairs are contained in the `past`.
|
The model only requires a single token as input as all the previous tokens' key/value pairs are contained in the `past`.
|
||||||
|
|
||||||
### Model2Model example
|
|
||||||
|
|
||||||
Encoder-decoder architectures require two tokenized inputs: one for the encoder and the other one for the decoder. Let's assume that we want to use `Model2Model` for generative question answering, and start by tokenizing the question and answer that will be fed to the model.
|
|
||||||
|
|
||||||
```python
|
|
||||||
import torch
|
|
||||||
from transformers import BertTokenizer, Model2Model
|
|
||||||
|
|
||||||
# OPTIONAL: if you want to have more information on what's happening under the hood, activate the logger as follows
|
|
||||||
import logging
|
|
||||||
logging.basicConfig(level=logging.INFO)
|
|
||||||
|
|
||||||
# Load pre-trained model tokenizer (vocabulary)
|
|
||||||
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
|
|
||||||
|
|
||||||
# Encode the input to the encoder (the question)
|
|
||||||
question = "Who was Jim Henson?"
|
|
||||||
encoded_question = tokenizer.encode(question)
|
|
||||||
|
|
||||||
# Encode the input to the decoder (the answer)
|
|
||||||
answer = "Jim Henson was a puppeteer"
|
|
||||||
encoded_answer = tokenizer.encode(answer)
|
|
||||||
|
|
||||||
# Convert inputs to PyTorch tensors
|
|
||||||
question_tensor = torch.tensor([encoded_question])
|
|
||||||
answer_tensor = torch.tensor([encoded_answer])
|
|
||||||
```
|
|
||||||
|
|
||||||
Let's see how we can use `Model2Model` to get the value of the loss associated with this (question, answer) pair:
|
|
||||||
|
|
||||||
```python
|
|
||||||
# In order to compute the loss we need to provide language model
|
|
||||||
# labels (the token ids that the model should have produced) to
|
|
||||||
# the decoder.
|
|
||||||
lm_labels = encoded_answer
|
|
||||||
labels_tensor = torch.tensor([lm_labels])
|
|
||||||
|
|
||||||
# Load pre-trained model (weights)
|
|
||||||
model = Model2Model.from_pretrained('bert-base-uncased')
|
|
||||||
|
|
||||||
# Set the model in evaluation mode to deactivate the DropOut modules
|
|
||||||
# This is IMPORTANT to have reproducible results during evaluation!
|
|
||||||
model.eval()
|
|
||||||
|
|
||||||
# If you have a GPU, put everything on cuda
|
|
||||||
question_tensor = question_tensor.to('cuda')
|
|
||||||
answer_tensor = answer_tensor.to('cuda')
|
|
||||||
labels_tensor = labels_tensor.to('cuda')
|
|
||||||
model.to('cuda')
|
|
||||||
|
|
||||||
# Predict hidden states features for each layer
|
|
||||||
with torch.no_grad():
|
|
||||||
# See the models docstrings for the detail of the inputs
|
|
||||||
outputs = model(question_tensor, answer_tensor, decoder_lm_labels=labels_tensor)
|
|
||||||
# Transformers models always output tuples.
|
|
||||||
# See the models docstrings for the detail of all the outputs
|
|
||||||
# In our case, the first element is the value of the LM loss
|
|
||||||
lm_loss = outputs[0]
|
|
||||||
```
|
|
||||||
|
|
||||||
This loss can be used to fine-tune `Model2Model` on the question answering task. Assuming that we fine-tuned the model, let us now see how to generate an answer:
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Let's re-use the previous question
|
|
||||||
question = "Who was Jim Henson?"
|
|
||||||
encoded_question = tokenizer.encode(question)
|
|
||||||
question_tensor = torch.tensor([encoded_question])
|
|
||||||
|
|
||||||
# This time we try to generate the answer, so we start with an empty sequence
|
|
||||||
answer = "[CLS]"
|
|
||||||
encoded_answer = tokenizer.encode(answer, add_special_tokens=False)
|
|
||||||
answer_tensor = torch.tensor([encoded_answer])
|
|
||||||
|
|
||||||
# Load pre-trained model (weights)
|
|
||||||
model = Model2Model.from_pretrained('fine-tuned-weights')
|
|
||||||
model.eval()
|
|
||||||
|
|
||||||
# If you have a GPU, put everything on cuda
|
|
||||||
question_tensor = question_tensor.to('cuda')
|
|
||||||
answer_tensor = answer_tensor.to('cuda')
|
|
||||||
model.to('cuda')
|
|
||||||
|
|
||||||
# Predict all tokens
|
|
||||||
with torch.no_grad():
|
|
||||||
outputs = model(question_tensor, answer_tensor)
|
|
||||||
predictions = outputs[0]
|
|
||||||
|
|
||||||
# confirm we were able to predict 'jim'
|
|
||||||
predicted_index = torch.argmax(predictions[0, -1]).item()
|
|
||||||
predicted_token = tokenizer.convert_ids_to_tokens([predicted_index])[0]
|
|
||||||
assert predicted_token == 'jim'
|
|
||||||
```
|
|
||||||
|
|||||||
597
docs/source/usage.rst
Normal file
597
docs/source/usage.rst
Normal file
@@ -0,0 +1,597 @@
|
|||||||
|
Usage
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
This page shows the most frequent use-cases when using the library. The models available allow for many different
|
||||||
|
configurations and a great versatility in use-cases. The most simple ones are presented here, showcasing usage
|
||||||
|
for tasks such as question answering, sequence classification, named entity recognition and others.
|
||||||
|
|
||||||
|
These examples leverage auto-models, which are classes that will instantiate a model according to a given checkpoint,
|
||||||
|
automatically selecting the correct model architecture. Please check the :class:`~transformers.AutoModel` documentation
|
||||||
|
for more information.
|
||||||
|
Feel free to modify the code to be more specific and adapt it to your specific use-case.
|
||||||
|
|
||||||
|
In order for a model to perform well on a task, it must be loaded from a checkpoint corresponding to that task. These
|
||||||
|
checkpoints are usually pre-trained on a large corpus of data and fine-tuned on a specific task. This means the
|
||||||
|
following:
|
||||||
|
|
||||||
|
- Not all models were fine-tuned on all tasks. If you want to fine-tune a model on a specific task, you can leverage
|
||||||
|
one of the `run_$TASK.py` script in the
|
||||||
|
`examples <https://github.com/huggingface/transformers/tree/master/examples>`_ directory.
|
||||||
|
- Fine-tuned models were fine-tuned on a specific dataset. This dataset may or may not overlap with your use-case
|
||||||
|
and domain. As mentioned previously, you may leverage the
|
||||||
|
`examples <https://github.com/huggingface/transformers/tree/master/examples>`_ scripts to fine-tune your model, or you
|
||||||
|
may create your own training script.
|
||||||
|
|
||||||
|
In order to do an inference on a task, several mechanisms are made available by the library:
|
||||||
|
|
||||||
|
- Pipelines: very easy-to-use abstractions, which require as little as two lines of code.
|
||||||
|
- Using a model directly with a tokenizer (PyTorch/TensorFlow): the full inference using the model. Less abstraction,
|
||||||
|
but much more powerful.
|
||||||
|
|
||||||
|
Both approaches are showcased here.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
All tasks presented here leverage pre-trained checkpoints that were fine-tuned on specific tasks. Loading a
|
||||||
|
checkpoint that was not fine-tuned on a specific task would load only the base transformer layers and not the
|
||||||
|
additional head that is used for the task, initializing the weights of that head randomly.
|
||||||
|
|
||||||
|
This would produce random output.
|
||||||
|
|
||||||
|
Sequence Classification
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
Sequence classification is the task of classifying sequences according to a given number of classes. An example
|
||||||
|
of sequence classification is the GLUE dataset, which is entirely based on that task. If you would like to fine-tune
|
||||||
|
a model on a GLUE sequence classification task, you may leverage the
|
||||||
|
`run_glue.py <https://github.com/huggingface/transformers/tree/master/examples/run_glue.py>`_ or
|
||||||
|
`run_tf_glue.py <https://github.com/huggingface/transformers/tree/master/examples/run_tf_glue.py>`_ scripts.
|
||||||
|
|
||||||
|
Here is an example using the pipelines do to sentiment analysis: identifying if a sequence is positive or negative.
|
||||||
|
It leverages a fine-tuned model on sst2, which is a GLUE task.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
from transformers import pipeline
|
||||||
|
|
||||||
|
nlp = pipeline("sentiment-analysis")
|
||||||
|
|
||||||
|
print(nlp("I hate you"))
|
||||||
|
print(nlp("I love you"))
|
||||||
|
|
||||||
|
This returns a label ("POSITIVE" or "NEGATIVE") alongside a score, as follows:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
[{'label': 'NEGATIVE', 'score': 0.9991129}]
|
||||||
|
[{'label': 'POSITIVE', 'score': 0.99986565}]
|
||||||
|
|
||||||
|
|
||||||
|
Here is an example of doing a sequence classification using a model to determine if two sequences are paraphrases
|
||||||
|
of each other. The process is the following:
|
||||||
|
|
||||||
|
- Instantiate a tokenizer and a model from the checkpoint name. The model is identified as a BERT model and loads it
|
||||||
|
with the weights stored in the checkpoint.
|
||||||
|
- Build a sequence from the two sentences, with the correct model-specific separators token type ids
|
||||||
|
and attention masks (:func:`~transformers.PreTrainedTokenizer.encode` and
|
||||||
|
:func:`~transformers.PreTrainedTokenizer.encode_plus` take care of this)
|
||||||
|
- Pass this sequence through the model so that it is classified in one of the two available classes: 0
|
||||||
|
(not a paraphrase) and 1 (is a paraphrase)
|
||||||
|
- Compute the softmax of the result to get probabilities over the classes
|
||||||
|
- Print the results
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
## PYTORCH CODE
|
||||||
|
from transformers import AutoTokenizer, AutoModelForSequenceClassification
|
||||||
|
import torch
|
||||||
|
|
||||||
|
tokenizer = AutoTokenizer.from_pretrained("bert-base-cased-finetuned-mrpc")
|
||||||
|
model = AutoModelForSequenceClassification.from_pretrained("bert-base-cased-finetuned-mrpc")
|
||||||
|
|
||||||
|
classes = ["not paraphrase", "is paraphrase"]
|
||||||
|
|
||||||
|
sequence_0 = "The company HuggingFace is based in New York City"
|
||||||
|
sequence_1 = "Apples are especially bad for your health"
|
||||||
|
sequence_2 = "HuggingFace's headquarters are situated in Manhattan"
|
||||||
|
|
||||||
|
paraphrase = tokenizer.encode_plus(sequence_0, sequence_2, return_tensors="pt")
|
||||||
|
not_paraphrase = tokenizer.encode_plus(sequence_0, sequence_1, return_tensors="pt")
|
||||||
|
|
||||||
|
paraphrase_classification_logits = model(**paraphrase)[0]
|
||||||
|
not_paraphrase_classification_logits = model(**not_paraphrase)[0]
|
||||||
|
|
||||||
|
paraphrase_results = torch.softmax(paraphrase_classification_logits, dim=1).tolist()[0]
|
||||||
|
not_paraphrase_results = torch.softmax(not_paraphrase_classification_logits, dim=1).tolist()[0]
|
||||||
|
|
||||||
|
print("Should be paraphrase")
|
||||||
|
for i in range(len(classes)):
|
||||||
|
print(f"{classes[i]}: {round(paraphrase_results[i] * 100)}%")
|
||||||
|
|
||||||
|
print("\nShould not be paraphrase")
|
||||||
|
for i in range(len(classes)):
|
||||||
|
print(f"{classes[i]}: {round(not_paraphrase_results[i] * 100)}%")
|
||||||
|
## TENSORFLOW CODE
|
||||||
|
from transformers import AutoTokenizer, TFAutoModelForSequenceClassification
|
||||||
|
import tensorflow as tf
|
||||||
|
|
||||||
|
tokenizer = AutoTokenizer.from_pretrained("bert-base-cased-finetuned-mrpc")
|
||||||
|
model = TFAutoModelForSequenceClassification.from_pretrained("bert-base-cased-finetuned-mrpc")
|
||||||
|
|
||||||
|
classes = ["not paraphrase", "is paraphrase"]
|
||||||
|
|
||||||
|
sequence_0 = "The company HuggingFace is based in New York City"
|
||||||
|
sequence_1 = "Apples are especially bad for your health"
|
||||||
|
sequence_2 = "HuggingFace's headquarters are situated in Manhattan"
|
||||||
|
|
||||||
|
paraphrase = tokenizer.encode_plus(sequence_0, sequence_2, return_tensors="tf")
|
||||||
|
not_paraphrase = tokenizer.encode_plus(sequence_0, sequence_1, return_tensors="tf")
|
||||||
|
|
||||||
|
paraphrase_classification_logits = model(paraphrase)[0]
|
||||||
|
not_paraphrase_classification_logits = model(not_paraphrase)[0]
|
||||||
|
|
||||||
|
paraphrase_results = tf.nn.softmax(paraphrase_classification_logits, axis=1).numpy()[0]
|
||||||
|
not_paraphrase_results = tf.nn.softmax(not_paraphrase_classification_logits, axis=1).numpy()[0]
|
||||||
|
|
||||||
|
print("Should be paraphrase")
|
||||||
|
for i in range(len(classes)):
|
||||||
|
print(f"{classes[i]}: {round(paraphrase_results[i] * 100)}%")
|
||||||
|
|
||||||
|
print("\nShould not be paraphrase")
|
||||||
|
for i in range(len(classes)):
|
||||||
|
print(f"{classes[i]}: {round(not_paraphrase_results[i] * 100)}%")
|
||||||
|
|
||||||
|
This outputs the following results:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
Should be paraphrase
|
||||||
|
not paraphrase: 10%
|
||||||
|
is paraphrase: 90%
|
||||||
|
|
||||||
|
Should not be paraphrase
|
||||||
|
not paraphrase: 94%
|
||||||
|
is paraphrase: 6%
|
||||||
|
|
||||||
|
Extractive Question Answering
|
||||||
|
----------------------------------------------------
|
||||||
|
|
||||||
|
Extractive Question Answering is the task of extracting an answer from a text given a question. An example of a
|
||||||
|
question answering dataset is the SQuAD dataset, which is entirely based on that task. If you would like to fine-tune
|
||||||
|
a model on a SQuAD task, you may leverage the `run_squad.py`.
|
||||||
|
|
||||||
|
Here is an example using the pipelines do to question answering: extracting an answer from a text given a question.
|
||||||
|
It leverages a fine-tuned model on SQuAD.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
from transformers import pipeline
|
||||||
|
|
||||||
|
nlp = pipeline("question-answering")
|
||||||
|
|
||||||
|
context = r"""
|
||||||
|
Extractive Question Answering is the task of extracting an answer from a text given a question. An example of a
|
||||||
|
question answering dataset is the SQuAD dataset, which is entirely based on that task. If you would like to fine-tune
|
||||||
|
a model on a SQuAD task, you may leverage the `run_squad.py`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
print(nlp(question="What is extractive question answering?", context=context))
|
||||||
|
print(nlp(question="What is a good example of a question answering dataset?", context=context))
|
||||||
|
|
||||||
|
This returns an answer extracted from the text, a confidence score, alongside "start" and "end" values which
|
||||||
|
are the positions of the extracted answer in the text.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
{'score': 0.622232091629833, 'start': 34, 'end': 96, 'answer': 'the task of extracting an answer from a text given a question.'}
|
||||||
|
{'score': 0.5115299158662765, 'start': 147, 'end': 161, 'answer': 'SQuAD dataset,'}
|
||||||
|
|
||||||
|
|
||||||
|
Here is an example of question answering using a model and a tokenizer. The process is the following:
|
||||||
|
|
||||||
|
- Instantiate a tokenizer and a model from the checkpoint name. The model is identified as a BERT model and loads it
|
||||||
|
with the weights stored in the checkpoint.
|
||||||
|
- Define a text and a few questions.
|
||||||
|
- Iterate over the questions and build a sequence from the text and the current question, with the correct
|
||||||
|
model-specific separators token type ids and attention masks
|
||||||
|
- Pass this sequence through the model. This outputs a range of scores across the entire sequence tokens (question and
|
||||||
|
text), for both the start and end positions.
|
||||||
|
- Compute the softmax of the result to get probabilities over the tokens
|
||||||
|
- Fetch the tokens from the identified start and stop values, convert those tokens to a string.
|
||||||
|
- Print the results
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
## PYTORCH CODE
|
||||||
|
from transformers import AutoTokenizer, AutoModelForQuestionAnswering
|
||||||
|
import torch
|
||||||
|
|
||||||
|
tokenizer = AutoTokenizer.from_pretrained("bert-large-uncased-whole-word-masking-finetuned-squad")
|
||||||
|
model = AutoModelForQuestionAnswering.from_pretrained("bert-large-uncased-whole-word-masking-finetuned-squad")
|
||||||
|
|
||||||
|
text = r"""
|
||||||
|
🤗 Transformers (formerly known as pytorch-transformers and pytorch-pretrained-bert) provides general-purpose
|
||||||
|
architectures (BERT, GPT-2, RoBERTa, XLM, DistilBert, XLNet…) for Natural Language Understanding (NLU) and Natural
|
||||||
|
Language Generation (NLG) with over 32+ pretrained models in 100+ languages and deep interoperability between
|
||||||
|
TensorFlow 2.0 and PyTorch.
|
||||||
|
"""
|
||||||
|
|
||||||
|
questions = [
|
||||||
|
"How many pretrained models are available in Transformers?",
|
||||||
|
"What does Transformers provide?",
|
||||||
|
"Transformers provides interoperability between which frameworks?",
|
||||||
|
]
|
||||||
|
|
||||||
|
for question in questions:
|
||||||
|
inputs = tokenizer.encode_plus(question, text, add_special_tokens=True, return_tensors="pt")
|
||||||
|
input_ids = inputs["input_ids"].tolist()[0]
|
||||||
|
|
||||||
|
text_tokens = tokenizer.convert_ids_to_tokens(input_ids)
|
||||||
|
answer_start_scores, answer_end_scores = model(**inputs)
|
||||||
|
|
||||||
|
answer_start = torch.argmax(
|
||||||
|
answer_start_scores
|
||||||
|
) # Get the most likely beginning of answer with the argmax of the score
|
||||||
|
answer_end = torch.argmax(answer_end_scores) + 1 # Get the most likely end of answer with the argmax of the score
|
||||||
|
|
||||||
|
answer = tokenizer.convert_tokens_to_string(tokenizer.convert_ids_to_tokens(input_ids[answer_start:answer_end]))
|
||||||
|
|
||||||
|
print(f"Question: {question}")
|
||||||
|
print(f"Answer: {answer}\n")
|
||||||
|
## TENSORFLOW CODE
|
||||||
|
from transformers import AutoTokenizer, TFAutoModelForQuestionAnswering
|
||||||
|
import tensorflow as tf
|
||||||
|
|
||||||
|
tokenizer = AutoTokenizer.from_pretrained("bert-large-uncased-whole-word-masking-finetuned-squad")
|
||||||
|
model = TFAutoModelForQuestionAnswering.from_pretrained("bert-large-uncased-whole-word-masking-finetuned-squad")
|
||||||
|
|
||||||
|
text = r"""
|
||||||
|
🤗 Transformers (formerly known as pytorch-transformers and pytorch-pretrained-bert) provides general-purpose
|
||||||
|
architectures (BERT, GPT-2, RoBERTa, XLM, DistilBert, XLNet…) for Natural Language Understanding (NLU) and Natural
|
||||||
|
Language Generation (NLG) with over 32+ pretrained models in 100+ languages and deep interoperability between
|
||||||
|
TensorFlow 2.0 and PyTorch.
|
||||||
|
"""
|
||||||
|
|
||||||
|
questions = [
|
||||||
|
"How many pretrained models are available in Transformers?",
|
||||||
|
"What does Transformers provide?",
|
||||||
|
"Transformers provides interoperability between which frameworks?",
|
||||||
|
]
|
||||||
|
|
||||||
|
for question in questions:
|
||||||
|
inputs = tokenizer.encode_plus(question, text, add_special_tokens=True, return_tensors="tf")
|
||||||
|
input_ids = inputs["input_ids"].numpy()[0]
|
||||||
|
|
||||||
|
text_tokens = tokenizer.convert_ids_to_tokens(input_ids)
|
||||||
|
answer_start_scores, answer_end_scores = model(inputs)
|
||||||
|
|
||||||
|
answer_start = tf.argmax(
|
||||||
|
answer_start_scores, axis=1
|
||||||
|
).numpy()[0] # Get the most likely beginning of answer with the argmax of the score
|
||||||
|
answer_end = (
|
||||||
|
tf.argmax(answer_end_scores, axis=1) + 1
|
||||||
|
).numpy()[0] # Get the most likely end of answer with the argmax of the score
|
||||||
|
answer = tokenizer.convert_tokens_to_string(tokenizer.convert_ids_to_tokens(input_ids[answer_start:answer_end]))
|
||||||
|
|
||||||
|
print(f"Question: {question}")
|
||||||
|
print(f"Answer: {answer}\n")
|
||||||
|
|
||||||
|
This outputs the questions followed by the predicted answers:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
Question: How many pretrained models are available in Transformers?
|
||||||
|
Answer: over 32 +
|
||||||
|
|
||||||
|
Question: What does Transformers provide?
|
||||||
|
Answer: general - purpose architectures
|
||||||
|
|
||||||
|
Question: Transformers provides interoperability between which frameworks?
|
||||||
|
Answer: tensorflow 2 . 0 and pytorch
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Language Modeling
|
||||||
|
----------------------------------------------------
|
||||||
|
|
||||||
|
Language modeling is the task of fitting a model to a corpus, which can be domain specific. All popular transformer
|
||||||
|
based models are trained using a variant of language modeling, e.g. BERT with masked language modeling, GPT-2 with
|
||||||
|
causal language modeling.
|
||||||
|
|
||||||
|
Language modeling can be useful outside of pre-training as well, for example to shift the model distribution to be
|
||||||
|
domain-specific: using a language model trained over a very large corpus, and then fine-tuning it to a news dataset
|
||||||
|
or on scientific papers e.g. `LysandreJik/arxiv-nlp <https://huggingface.co/lysandre/arxiv-nlp>`__.
|
||||||
|
|
||||||
|
Masked Language Modeling
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Masked language modeling is the task of masking tokens in a sequence with a masking token, and prompting the model to
|
||||||
|
fill that mask with an appropriate token. This allows the model to attend to both the right context (tokens on the
|
||||||
|
right of the mask) and the left context (tokens on the left of the mask). Such a training creates a strong basis
|
||||||
|
for downstream tasks requiring bi-directional context such as SQuAD (question answering,
|
||||||
|
see `Lewis, Lui, Goyal et al. <https://arxiv.org/abs/1910.13461>`__, part 4.2).
|
||||||
|
|
||||||
|
Here is an example of using pipelines to replace a mask from a sequence:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
from transformers import pipeline
|
||||||
|
|
||||||
|
nlp = pipeline("fill-mask")
|
||||||
|
print(nlp(f"HuggingFace is creating a {nlp.tokenizer.mask_token} that the community uses to solve NLP tasks."))
|
||||||
|
|
||||||
|
This outputs the sequences with the mask filled, the confidence score as well as the token id in the tokenizer
|
||||||
|
vocabulary:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
[
|
||||||
|
{'sequence': '<s> HuggingFace is creating a tool that the community uses to solve NLP tasks.</s>', 'score': 0.15627853572368622, 'token': 3944},
|
||||||
|
{'sequence': '<s> HuggingFace is creating a framework that the community uses to solve NLP tasks.</s>', 'score': 0.11690319329500198, 'token': 7208},
|
||||||
|
{'sequence': '<s> HuggingFace is creating a library that the community uses to solve NLP tasks.</s>', 'score': 0.058063216507434845, 'token': 5560},
|
||||||
|
{'sequence': '<s> HuggingFace is creating a database that the community uses to solve NLP tasks.</s>', 'score': 0.04211743175983429, 'token': 8503},
|
||||||
|
{'sequence': '<s> HuggingFace is creating a prototype that the community uses to solve NLP tasks.</s>', 'score': 0.024718601256608963, 'token': 17715}
|
||||||
|
]
|
||||||
|
|
||||||
|
Here is an example doing masked language modeling using a model and a tokenizer. The process is the following:
|
||||||
|
|
||||||
|
- Instantiate a tokenizer and a model from the checkpoint name. The model is identified as a DistilBERT model and
|
||||||
|
loads it with the weights stored in the checkpoint.
|
||||||
|
- Define a sequence with a masked token, placing the :obj:`tokenizer.mask_token` instead of a word.
|
||||||
|
- Encode that sequence into IDs and find the position of the masked token in that list of IDs.
|
||||||
|
- Retrieve the predictions at the index of the mask token: this tensor has the same size as the vocabulary, and the
|
||||||
|
values are the scores attributed to each token. The model gives higher score to tokens he deems probable in that
|
||||||
|
context.
|
||||||
|
- Retrieve the top 5 tokens using the PyTorch :obj:`topk` or TensorFlow :obj:`top_k` methods.
|
||||||
|
- Replace the mask token by the tokens and print the results
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
## PYTORCH CODE
|
||||||
|
from transformers import AutoModelWithLMHead, AutoTokenizer
|
||||||
|
import torch
|
||||||
|
|
||||||
|
tokenizer = AutoTokenizer.from_pretrained("distilbert-base-cased")
|
||||||
|
model = AutoModelWithLMHead.from_pretrained("distilbert-base-cased")
|
||||||
|
|
||||||
|
sequence = f"Distilled models are smaller than the models they mimic. Using them instead of the large versions would help {tokenizer.mask_token} our carbon footprint."
|
||||||
|
|
||||||
|
input = tokenizer.encode(sequence, return_tensors="pt")
|
||||||
|
mask_token_index = torch.where(input == tokenizer.mask_token_id)[1]
|
||||||
|
|
||||||
|
token_logits = model(input)[0]
|
||||||
|
mask_token_logits = token_logits[0, mask_token_index, :]
|
||||||
|
|
||||||
|
top_5_tokens = torch.topk(mask_token_logits, 5, dim=1).indices[0].tolist()
|
||||||
|
|
||||||
|
for token in top_5_tokens:
|
||||||
|
print(sequence.replace(tokenizer.mask_token, tokenizer.decode([token])))
|
||||||
|
## TENSORFLOW CODE
|
||||||
|
from transformers import TFAutoModelWithLMHead, AutoTokenizer
|
||||||
|
import tensorflow as tf
|
||||||
|
|
||||||
|
tokenizer = AutoTokenizer.from_pretrained("distilbert-base-cased")
|
||||||
|
model = TFAutoModelWithLMHead.from_pretrained("distilbert-base-cased")
|
||||||
|
|
||||||
|
sequence = f"Distilled models are smaller than the models they mimic. Using them instead of the large versions would help {tokenizer.mask_token} our carbon footprint."
|
||||||
|
|
||||||
|
input = tokenizer.encode(sequence, return_tensors="tf")
|
||||||
|
mask_token_index = tf.where(input == tokenizer.mask_token_id)[0, 1]
|
||||||
|
|
||||||
|
token_logits = model(input)[0]
|
||||||
|
mask_token_logits = token_logits[0, mask_token_index, :]
|
||||||
|
|
||||||
|
top_5_tokens = tf.math.top_k(mask_token_logits, 5).indices.numpy()
|
||||||
|
|
||||||
|
for token in top_5_tokens:
|
||||||
|
print(sequence.replace(tokenizer.mask_token, tokenizer.decode([token])))
|
||||||
|
|
||||||
|
This prints five sequences, with the top 5 tokens predicted by the model:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
Distilled models are smaller than the models they mimic. Using them instead of the large versions would help reduce our carbon footprint.
|
||||||
|
Distilled models are smaller than the models they mimic. Using them instead of the large versions would help increase our carbon footprint.
|
||||||
|
Distilled models are smaller than the models they mimic. Using them instead of the large versions would help decrease our carbon footprint.
|
||||||
|
Distilled models are smaller than the models they mimic. Using them instead of the large versions would help offset our carbon footprint.
|
||||||
|
Distilled models are smaller than the models they mimic. Using them instead of the large versions would help improve our carbon footprint.
|
||||||
|
|
||||||
|
|
||||||
|
Causal Language Modeling
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Causal language modeling is the task of predicting the token following a sequence of tokens. In this situation, the
|
||||||
|
model only attends to the left context (tokens on the left of the mask). Such a training is particularly interesting
|
||||||
|
for generation tasks.
|
||||||
|
|
||||||
|
There is currently no pipeline to do causal language modeling/generation.
|
||||||
|
|
||||||
|
Here is an example using the tokenizer and model. leveraging the :func:`~transformers.PreTrainedModel.generate` method
|
||||||
|
to generate the tokens following the initial sequence in PyTorch, and creating a simple loop in TensorFlow.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
## PYTORCH CODE
|
||||||
|
from transformers import AutoModelWithLMHead, AutoTokenizer
|
||||||
|
|
||||||
|
tokenizer = AutoTokenizer.from_pretrained("gpt2")
|
||||||
|
model = AutoModelWithLMHead.from_pretrained("gpt2")
|
||||||
|
|
||||||
|
sequence = f"Hugging Face is based in DUMBO, New York City, and is"
|
||||||
|
|
||||||
|
input = tokenizer.encode(sequence, return_tensors="pt")
|
||||||
|
generated = model.generate(input, max_length=50)
|
||||||
|
|
||||||
|
resulting_string = tokenizer.decode(generated.tolist()[0])
|
||||||
|
print(resulting_string)
|
||||||
|
## TENSORFLOW CODE
|
||||||
|
from transformers import TFAutoModelWithLMHead, AutoTokenizer
|
||||||
|
import tensorflow as tf
|
||||||
|
|
||||||
|
tokenizer = AutoTokenizer.from_pretrained("gpt2")
|
||||||
|
model = TFAutoModelWithLMHead.from_pretrained("gpt2")
|
||||||
|
|
||||||
|
sequence = f"Hugging Face is based in DUMBO, New York City, and is"
|
||||||
|
generated = tokenizer.encode(sequence)
|
||||||
|
|
||||||
|
for i in range(50):
|
||||||
|
predictions = model(tf.constant([generated]))[0]
|
||||||
|
token = tf.argmax(predictions[0], axis=1)[-1].numpy()
|
||||||
|
generated += [token]
|
||||||
|
|
||||||
|
resulting_string = tokenizer.decode(generated)
|
||||||
|
print(resulting_string)
|
||||||
|
|
||||||
|
|
||||||
|
This outputs a (hopefully) coherent string from the original sequence, as the
|
||||||
|
:func:`~transformers.PreTrainedModel.generate` samples from a top_p/tok_k distribution:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
Hugging Face is based in DUMBO, New York City, and is a live-action TV series based on the novel by John
|
||||||
|
Carpenter, and its producers, David Kustlin and Steve Pichar. The film is directed by!
|
||||||
|
|
||||||
|
|
||||||
|
Named Entity Recognition
|
||||||
|
----------------------------------------------------
|
||||||
|
|
||||||
|
Named Entity Recognition (NER) is the task of classifying tokens according to a class, for example identifying a
|
||||||
|
token as a person, an organisation or a location.
|
||||||
|
An example of a named entity recognition dataset is the CoNLL-2003 dataset, which is entirely based on that task.
|
||||||
|
If you would like to fine-tune a model on an NER task, you may leverage the `ner/run_ner.py` (PyTorch),
|
||||||
|
`ner/run_pl_ner.py` (leveraging pytorch-lightning) or the `ner/run_tf_ner.py` (TensorFlow) scripts.
|
||||||
|
|
||||||
|
Here is an example using the pipelines do to named entity recognition, trying to identify tokens as belonging to one
|
||||||
|
of 9 classes:
|
||||||
|
|
||||||
|
- O, Outside of a named entity
|
||||||
|
- B-MIS, Beginning of a miscellaneous entity right after another miscellaneous entity
|
||||||
|
- I-MIS, Miscellaneous entity
|
||||||
|
- B-PER, Beginning of a person's name right after another person's name
|
||||||
|
- I-PER, Person's name
|
||||||
|
- B-ORG, Beginning of an organisation right after another organisation
|
||||||
|
- I-ORG, Organisation
|
||||||
|
- B-LOC, Beginning of a location right after another location
|
||||||
|
- I-LOC, Location
|
||||||
|
|
||||||
|
It leverages a fine-tuned model on CoNLL-2003, fine-tuned by `@stefan-it <https://github.com/stefan-it>`__ from
|
||||||
|
`dbmdz <https://github.com/dbmdz>`__.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
from transformers import pipeline
|
||||||
|
|
||||||
|
nlp = pipeline("ner")
|
||||||
|
|
||||||
|
sequence = "Hugging Face Inc. is a company based in New York City. Its headquarters are in DUMBO, therefore very" \
|
||||||
|
"close to the Manhattan Bridge which is visible from the window."
|
||||||
|
|
||||||
|
print(nlp(sequence))
|
||||||
|
|
||||||
|
This outputs a list of all words that have been identified as an entity from the 9 classes defined above. Here is the
|
||||||
|
expected results:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
[
|
||||||
|
{'word': 'Hu', 'score': 0.9995632767677307, 'entity': 'I-ORG'},
|
||||||
|
{'word': '##gging', 'score': 0.9915938973426819, 'entity': 'I-ORG'},
|
||||||
|
{'word': 'Face', 'score': 0.9982671737670898, 'entity': 'I-ORG'},
|
||||||
|
{'word': 'Inc', 'score': 0.9994403719902039, 'entity': 'I-ORG'},
|
||||||
|
{'word': 'New', 'score': 0.9994346499443054, 'entity': 'I-LOC'},
|
||||||
|
{'word': 'York', 'score': 0.9993270635604858, 'entity': 'I-LOC'},
|
||||||
|
{'word': 'City', 'score': 0.9993864893913269, 'entity': 'I-LOC'},
|
||||||
|
{'word': 'D', 'score': 0.9825621843338013, 'entity': 'I-LOC'},
|
||||||
|
{'word': '##UM', 'score': 0.936983048915863, 'entity': 'I-LOC'},
|
||||||
|
{'word': '##BO', 'score': 0.8987102508544922, 'entity': 'I-LOC'},
|
||||||
|
{'word': 'Manhattan', 'score': 0.9758241176605225, 'entity': 'I-LOC'},
|
||||||
|
{'word': 'Bridge', 'score': 0.990249514579773, 'entity': 'I-LOC'}
|
||||||
|
]
|
||||||
|
|
||||||
|
Note how the words "Hugging Face" have been identified as an organisation, and "New York City", "DUMBO" and
|
||||||
|
"Manhattan Bridge" have been identified as locations.
|
||||||
|
|
||||||
|
Here is an example doing named entity recognition using a model and a tokenizer. The process is the following:
|
||||||
|
|
||||||
|
- Instantiate a tokenizer and a model from the checkpoint name. The model is identified as a BERT model and
|
||||||
|
loads it with the weights stored in the checkpoint.
|
||||||
|
- Define the label list with which the model was trained on.
|
||||||
|
- Define a sequence with known entities, such as "Hugging Face" as an organisation and "New York City" as a location.
|
||||||
|
- Split words into tokens so that they can be mapped to the predictions. We use a small hack by firstly completely
|
||||||
|
encoding and decoding the sequence, so that we're left with a string that contains the special tokens.
|
||||||
|
- Encode that sequence into IDs (special tokens are added automatically).
|
||||||
|
- Retrieve the predictions by passing the input to the model and getting the first output. This results in a
|
||||||
|
distribution over the 9 possible classes for each token. We take the argmax to retrieve the most likely class
|
||||||
|
for each token.
|
||||||
|
- Zip together each token with its prediction and print it.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
## PYTORCH CODE
|
||||||
|
from transformers import AutoModelForTokenClassification, AutoTokenizer
|
||||||
|
import torch
|
||||||
|
|
||||||
|
model = AutoModelForTokenClassification.from_pretrained("dbmdz/bert-large-cased-finetuned-conll03-english")
|
||||||
|
tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")
|
||||||
|
|
||||||
|
label_list = [
|
||||||
|
"O", # Outside of a named entity
|
||||||
|
"B-MISC", # Beginning of a miscellaneous entity right after another miscellaneous entity
|
||||||
|
"I-MISC", # Miscellaneous entity
|
||||||
|
"B-PER", # Beginning of a person's name right after another person's name
|
||||||
|
"I-PER", # Person's name
|
||||||
|
"B-ORG", # Beginning of an organisation right after another organisation
|
||||||
|
"I-ORG", # Organisation
|
||||||
|
"B-LOC", # Beginning of a location right after another location
|
||||||
|
"I-LOC" # Location
|
||||||
|
]
|
||||||
|
|
||||||
|
sequence = "Hugging Face Inc. is a company based in New York City. Its headquarters are in DUMBO, therefore very" \
|
||||||
|
"close to the Manhattan Bridge."
|
||||||
|
|
||||||
|
# Bit of a hack to get the tokens with the special tokens
|
||||||
|
tokens = tokenizer.tokenize(tokenizer.decode(tokenizer.encode(sequence)))
|
||||||
|
inputs = tokenizer.encode(sequence, return_tensors="pt")
|
||||||
|
|
||||||
|
outputs = model(inputs)[0]
|
||||||
|
predictions = torch.argmax(outputs, dim=2)
|
||||||
|
|
||||||
|
print([(token, label_list[prediction]) for token, prediction in zip(tokens, predictions[0].tolist())])
|
||||||
|
## TENSORFLOW CODE
|
||||||
|
from transformers import TFAutoModelForTokenClassification, AutoTokenizer
|
||||||
|
import tensorflow as tf
|
||||||
|
|
||||||
|
model = TFAutoModelForTokenClassification.from_pretrained("dbmdz/bert-large-cased-finetuned-conll03-english")
|
||||||
|
tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")
|
||||||
|
|
||||||
|
label_list = [
|
||||||
|
"O", # Outside of a named entity
|
||||||
|
"B-MISC", # Beginning of a miscellaneous entity right after another miscellaneous entity
|
||||||
|
"I-MISC", # Miscellaneous entity
|
||||||
|
"B-PER", # Beginning of a person's name right after another person's name
|
||||||
|
"I-PER", # Person's name
|
||||||
|
"B-ORG", # Beginning of an organisation right after another organisation
|
||||||
|
"I-ORG", # Organisation
|
||||||
|
"B-LOC", # Beginning of a location right after another location
|
||||||
|
"I-LOC" # Location
|
||||||
|
]
|
||||||
|
|
||||||
|
sequence = "Hugging Face Inc. is a company based in New York City. Its headquarters are in DUMBO, therefore very" \
|
||||||
|
"close to the Manhattan Bridge."
|
||||||
|
|
||||||
|
# Bit of a hack to get the tokens with the special tokens
|
||||||
|
tokens = tokenizer.tokenize(tokenizer.decode(tokenizer.encode(sequence)))
|
||||||
|
inputs = tokenizer.encode(sequence, return_tensors="tf")
|
||||||
|
|
||||||
|
outputs = model(inputs)[0]
|
||||||
|
predictions = tf.argmax(outputs, axis=2)
|
||||||
|
|
||||||
|
print([(token, label_list[prediction]) for token, prediction in zip(tokens, predictions[0].numpy())])
|
||||||
|
|
||||||
|
This outputs a list of each token mapped to their prediction. Differently from the pipeline, here every token has
|
||||||
|
a prediction as we didn't remove the "0" class which means that no particular entity was found on that token. The
|
||||||
|
following array should be the output:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
[('[CLS]', 'O'), ('Hu', 'I-ORG'), ('##gging', 'I-ORG'), ('Face', 'I-ORG'), ('Inc', 'I-ORG'), ('.', 'O'), ('is', 'O'), ('a', 'O'), ('company', 'O'), ('based', 'O'), ('in', 'O'), ('New', 'I-LOC'), ('York', 'I-LOC'), ('City', 'I-LOC'), ('.', 'O'), ('Its', 'O'), ('headquarters', 'O'), ('are', 'O'), ('in', 'O'), ('D', 'I-LOC'), ('##UM', 'I-LOC'), ('##BO', 'I-LOC'), (',', 'O'), ('therefore', 'O'), ('very', 'O'), ('##c', 'O'), ('##lose', 'O'), ('to', 'O'), ('the', 'O'), ('Manhattan', 'I-LOC'), ('Bridge', 'I-LOC'), ('.', 'O'), ('[SEP]', 'O')]
|
||||||
@@ -22,7 +22,7 @@ pip install -r ./examples/requirements.txt
|
|||||||
| [GLUE](#glue) | Examples running BERT/XLM/XLNet/RoBERTa on the 9 GLUE tasks. Examples feature distributed training as well as half-precision. |
|
| [GLUE](#glue) | Examples running BERT/XLM/XLNet/RoBERTa on the 9 GLUE tasks. Examples feature distributed training as well as half-precision. |
|
||||||
| [SQuAD](#squad) | Using BERT/RoBERTa/XLNet/XLM for question answering, examples with distributed training. |
|
| [SQuAD](#squad) | Using BERT/RoBERTa/XLNet/XLM for question answering, examples with distributed training. |
|
||||||
| [Multiple Choice](#multiple-choice) | Examples running BERT/XLNet/RoBERTa on the SWAG/RACE/ARC tasks. |
|
| [Multiple Choice](#multiple-choice) | Examples running BERT/XLNet/RoBERTa on the SWAG/RACE/ARC tasks. |
|
||||||
| [Named Entity Recognition](#named-entity-recognition) | Using BERT for Named Entity Recognition (NER) on the CoNLL 2003 dataset, examples with distributed training. |
|
| [Named Entity Recognition](https://github.com/huggingface/transformers/tree/master/examples/ner) | Using BERT for Named Entity Recognition (NER) on the CoNLL 2003 dataset, examples with distributed training. |
|
||||||
| [XNLI](#xnli) | Examples running BERT/XLM on the XNLI benchmark. |
|
| [XNLI](#xnli) | Examples running BERT/XLM on the XNLI benchmark. |
|
||||||
| [Adversarial evaluation of model performances](#adversarial-evaluation-of-model-performances) | Testing a model with adversarial evaluation of natural language inference on the Heuristic Analysis for NLI Systems (HANS) dataset (McCoy et al., 2019.) |
|
| [Adversarial evaluation of model performances](#adversarial-evaluation-of-model-performances) | Testing a model with adversarial evaluation of natural language inference on the Heuristic Analysis for NLI Systems (HANS) dataset (McCoy et al., 2019.) |
|
||||||
|
|
||||||
|
|||||||
@@ -622,7 +622,7 @@ def main():
|
|||||||
# Setup CUDA, GPU & distributed training
|
# Setup CUDA, GPU & distributed training
|
||||||
if args.local_rank == -1 or args.no_cuda:
|
if args.local_rank == -1 or args.no_cuda:
|
||||||
device = torch.device("cuda" if torch.cuda.is_available() and not args.no_cuda else "cpu")
|
device = torch.device("cuda" if torch.cuda.is_available() and not args.no_cuda else "cpu")
|
||||||
args.n_gpu = torch.cuda.device_count()
|
args.n_gpu = 0 if args.no_cuda else torch.cuda.device_count()
|
||||||
else: # Initializes the distributed backend which will take care of sychronizing nodes/GPUs
|
else: # Initializes the distributed backend which will take care of sychronizing nodes/GPUs
|
||||||
torch.cuda.set_device(args.local_rank)
|
torch.cuda.set_device(args.local_rank)
|
||||||
device = torch.device("cuda", args.local_rank)
|
device = torch.device("cuda", args.local_rank)
|
||||||
|
|||||||
@@ -10,14 +10,14 @@ This folder contains the original code used to train Distil* as well as examples
|
|||||||
|
|
||||||
**October 23, 2019 - Update** We release **DistilRoBERTa**: 95% of `RoBERTa-base`'s performance on GLUE, twice as fast as RoBERTa while being 35% smaller.
|
**October 23, 2019 - Update** We release **DistilRoBERTa**: 95% of `RoBERTa-base`'s performance on GLUE, twice as fast as RoBERTa while being 35% smaller.
|
||||||
|
|
||||||
**October 3, 2019 - Update** We release our [NeurIPS workshop paper](https://arxiv.org/abs/1910.01108) explaining our approach on **DistilBERT**. It includes updated results and further experiments. We applied the same method to GPT2 and release the weights of **DistilGPT2**. DistilGPT2 is two times faster and 33% smaller than GPT2. **The paper superseeds our [previous blogpost](https://medium.com/huggingface/distilbert-8cf3380435b5) with a different distillation loss and better performances. Please use the paper as a reference when comparing/reporting results on DistilBERT.**
|
**October 3, 2019 - Update** We release our [NeurIPS workshop paper](https://arxiv.org/abs/1910.01108) explaining our approach on **DistilBERT**. It includes updated results and further experiments. We applied the same method to GPT2 and release the weights of **DistilGPT2**. DistilGPT2 is two times faster and 33% smaller than GPT2. **The paper supersedes our [previous blogpost](https://medium.com/huggingface/distilbert-8cf3380435b5) with a different distillation loss and better performances. Please use the paper as a reference when comparing/reporting results on DistilBERT.**
|
||||||
|
|
||||||
**September 19, 2019 - Update:** We fixed bugs in the code and released an upadted version of the weights trained with a modification of the distillation loss. DistilBERT now reaches 99% of `BERT-base`'s performance on GLUE, and 86.9 F1 score on SQuAD v1.1 dev set (compared to 88.5 for `BERT-base`). We will publish a formal write-up of our approach in the near future!
|
**September 19, 2019 - Update:** We fixed bugs in the code and released an upadted version of the weights trained with a modification of the distillation loss. DistilBERT now reaches 99% of `BERT-base`'s performance on GLUE, and 86.9 F1 score on SQuAD v1.1 dev set (compared to 88.5 for `BERT-base`). We will publish a formal write-up of our approach in the near future!
|
||||||
|
|
||||||
|
|
||||||
## What is Distil*
|
## What is Distil*
|
||||||
|
|
||||||
Distil* is a class of compressed models that started with DistilBERT. DistilBERT stands for Distillated-BERT. DistilBERT is a small, fast, cheap and light Transformer model based on Bert architecture. It has 40% less parameters than `bert-base-uncased`, runs 60% faster while preserving 99% of BERT's performances as measured on the GLUE language understanding benchmark. DistilBERT is trained using knowledge distillation, a technique to compress a large model called the teacher into a smaller model called the student. By distillating Bert, we obtain a smaller Transformer model that bears a lot of similarities with the original BERT model while being lighter, smaller and faster to run. DistilBERT is thus an interesting option to put large-scaled trained Transformer model into production.
|
Distil* is a class of compressed models that started with DistilBERT. DistilBERT stands for Distillated-BERT. DistilBERT is a small, fast, cheap and light Transformer model based on Bert architecture. It has 40% less parameters than `bert-base-uncased`, runs 60% faster while preserving 97% of BERT's performances as measured on the GLUE language understanding benchmark. DistilBERT is trained using knowledge distillation, a technique to compress a large model called the teacher into a smaller model called the student. By distillating Bert, we obtain a smaller Transformer model that bears a lot of similarities with the original BERT model while being lighter, smaller and faster to run. DistilBERT is thus an interesting option to put large-scaled trained Transformer model into production.
|
||||||
|
|
||||||
We have applied the same method to other Transformer architectures and released the weights:
|
We have applied the same method to other Transformer architectures and released the weights:
|
||||||
- GPT2: on the [WikiText-103](https://blog.einstein.ai/the-wikitext-long-term-dependency-language-modeling-dataset/) benchmark, GPT2 reaches a perplexity on the test set of 16.3 compared to 21.1 for **DistilGPT2** (after fine-tuning on the train set).
|
- GPT2: on the [WikiText-103](https://blog.einstein.ai/the-wikitext-long-term-dependency-language-modeling-dataset/) benchmark, GPT2 reaches a perplexity on the test set of 16.3 compared to 21.1 for **DistilGPT2** (after fine-tuning on the train set).
|
||||||
@@ -31,15 +31,15 @@ Here are the results on the dev sets of GLUE:
|
|||||||
|
|
||||||
| Model | Macro-score | CoLA | MNLI | MRPC | QNLI | QQP | RTE | SST-2| STS-B| WNLI |
|
| Model | Macro-score | CoLA | MNLI | MRPC | QNLI | QQP | RTE | SST-2| STS-B| WNLI |
|
||||||
| :---: | :---: | :---:| :---:| :---:| :---:| :---:| :---:| :---:| :---:| :---: |
|
| :---: | :---: | :---:| :---:| :---:| :---:| :---:| :---:| :---:| :---:| :---: |
|
||||||
| BERT-base-uncased | **74.9** | 49.2 | 80.8 | 87.4 | 87.5 | 86.4 | 61.7 | 92.0 | 83.8 | 45.1 |
|
| BERT-base-uncased | **79.5** | 56.3 | 84.7 | 88.6 | 91.8 | 89.6 | 69.3 | 92.7 | 89.0 | 53.5 |
|
||||||
| DistilBERT-base-uncased | **74.3** | 43.6 | 79.0 | 87.5 | 85.3 | 84.9 | 59.9 | 90.7 | 81.2 | 56.3 |
|
| DistilBERT-base-uncased | **77.0** | 51.3 | 82.1 | 87.5 | 89.2 | 88.5 | 59.9 | 91.3 | 86.9 | 56.3 |
|
||||||
| BERT-base-cased | **78.2** | 58.2 | 83.9 | 87.8 | 91.0 | 89.2 | 66.1 | 91.7 | 89.2 | 46.5 |
|
| BERT-base-cased | **78.2** | 58.2 | 83.9 | 87.8 | 91.0 | 89.2 | 66.1 | 91.7 | 89.2 | 46.5 |
|
||||||
| DistilBERT-base-cased | **75.9** | 47.2 | 81.5 | 85.6 | 88.2 | 87.8 | 60.6 | 90.4 | 85.5 | 56.3 |
|
| DistilBERT-base-cased | **75.9** | 47.2 | 81.5 | 85.6 | 88.2 | 87.8 | 60.6 | 90.4 | 85.5 | 56.3 |
|
||||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||||
| RoBERTa-base (reported) | **83.2**/**86.4**<sup>2</sup> | 63.6 | 87.6 | 90.2 | 92.8 | 91.9 | 78.7 | 94.8 | 91.2 | 57.7<sup>3</sup> |
|
| RoBERTa-base (reported) | **83.2**/**86.4**<sup>2</sup> | 63.6 | 87.6 | 90.2 | 92.8 | 91.9 | 78.7 | 94.8 | 91.2 | 57.7<sup>3</sup> |
|
||||||
| DistilRoBERTa<sup>1</sup> | **79.0**/**82.3**<sup>2</sup> | 59.3 | 84.0 | 86.6 | 90.8 | 89.4 | 67.9 | 92.5 | 88.3 | 52.1 |
|
| DistilRoBERTa<sup>1</sup> | **79.0**/**82.3**<sup>2</sup> | 59.3 | 84.0 | 86.6 | 90.8 | 89.4 | 67.9 | 92.5 | 88.3 | 52.1 |
|
||||||
|
|
||||||
<sup>1</sup> We did not use the MNLI checkpoint for fine-tuning but directy perform transfer learning on the pre-trained DistilRoBERTa.
|
<sup>1</sup> We did not use the MNLI checkpoint for fine-tuning but directly perform transfer learning on the pre-trained DistilRoBERTa.
|
||||||
|
|
||||||
<sup>2</sup> Macro-score computed without WNLI.
|
<sup>2</sup> Macro-score computed without WNLI.
|
||||||
|
|
||||||
@@ -65,9 +65,9 @@ This part of the library has only be tested with Python3.6+. There are few speci
|
|||||||
Transformers includes five pre-trained Distil* models, currently only provided for English and German (we are investigating the possibility to train and release a multilingual version of DistilBERT):
|
Transformers includes five pre-trained Distil* models, currently only provided for English and German (we are investigating the possibility to train and release a multilingual version of DistilBERT):
|
||||||
|
|
||||||
- `distilbert-base-uncased`: DistilBERT English language model pretrained on the same data used to pretrain Bert (concatenation of the Toronto Book Corpus and full English Wikipedia) using distillation with the supervision of the `bert-base-uncased` version of Bert. The model has 6 layers, 768 dimension and 12 heads, totalizing 66M parameters.
|
- `distilbert-base-uncased`: DistilBERT English language model pretrained on the same data used to pretrain Bert (concatenation of the Toronto Book Corpus and full English Wikipedia) using distillation with the supervision of the `bert-base-uncased` version of Bert. The model has 6 layers, 768 dimension and 12 heads, totalizing 66M parameters.
|
||||||
- `distilbert-base-uncased-distilled-squad`: A finetuned version of `distilbert-base-uncased` finetuned using (a second step of) knwoledge distillation on SQuAD 1.0. This model reaches a F1 score of 79.8 on the dev set (for comparison, Bert `bert-base-uncased` version reaches a 82.3 F1 score).
|
- `distilbert-base-uncased-distilled-squad`: A finetuned version of `distilbert-base-uncased` finetuned using (a second step of) knowledge distillation on SQuAD 1.0. This model reaches a F1 score of 86.9 on the dev set (for comparison, Bert `bert-base-uncased` version reaches a 88.5 F1 score).
|
||||||
- `distilbert-base-cased`: DistilBERT English language model pretrained on the same data used to pretrain Bert (concatenation of the Toronto Book Corpus and full English Wikipedia) using distillation with the supervision of the `bert-base-cased` version of Bert. The model has 6 layers, 768 dimension and 12 heads, totalizing 65M parameters.
|
- `distilbert-base-cased`: DistilBERT English language model pretrained on the same data used to pretrain Bert (concatenation of the Toronto Book Corpus and full English Wikipedia) using distillation with the supervision of the `bert-base-cased` version of Bert. The model has 6 layers, 768 dimension and 12 heads, totalizing 65M parameters.
|
||||||
- `distilbert-base-cased-distilled-squad`: A finetuned version of `distilbert-base-cased` finetuned using (a second step of) knwoledge distillation on SQuAD 1.0. This model reaches a F1 score of 87.1 on the dev set (for comparison, Bert `bert-base-cased` version reaches a 88.7 F1 score).
|
- `distilbert-base-cased-distilled-squad`: A finetuned version of `distilbert-base-cased` finetuned using (a second step of) knowledge distillation on SQuAD 1.0. This model reaches a F1 score of 87.1 on the dev set (for comparison, Bert `bert-base-cased` version reaches a 88.7 F1 score).
|
||||||
- `distilbert-base-german-cased`: DistilBERT German language model pretrained on 1/2 of the data used to pretrain Bert using distillation with the supervision of the `bert-base-german-dbmdz-cased` version of German DBMDZ Bert. For NER tasks the model reaches a F1 score of 83.49 on the CoNLL-2003 test set (for comparison, `bert-base-german-dbmdz-cased` reaches a 84.52 F1 score), and a F1 score of 85.23 on the GermEval 2014 test set (`bert-base-german-dbmdz-cased` reaches a 86.89 F1 score).
|
- `distilbert-base-german-cased`: DistilBERT German language model pretrained on 1/2 of the data used to pretrain Bert using distillation with the supervision of the `bert-base-german-dbmdz-cased` version of German DBMDZ Bert. For NER tasks the model reaches a F1 score of 83.49 on the CoNLL-2003 test set (for comparison, `bert-base-german-dbmdz-cased` reaches a 84.52 F1 score), and a F1 score of 85.23 on the GermEval 2014 test set (`bert-base-german-dbmdz-cased` reaches a 86.89 F1 score).
|
||||||
- `distilgpt2`: DistilGPT2 English language model pretrained with the supervision of `gpt2` (the smallest version of GPT2) on [OpenWebTextCorpus](https://skylion007.github.io/OpenWebTextCorpus/), a reproduction of OpenAI's WebText dataset. The model has 6 layers, 768 dimension and 12 heads, totalizing 82M parameters (compared to 124M parameters for GPT2). On average, DistilGPT2 is two times faster than GPT2.
|
- `distilgpt2`: DistilGPT2 English language model pretrained with the supervision of `gpt2` (the smallest version of GPT2) on [OpenWebTextCorpus](https://skylion007.github.io/OpenWebTextCorpus/), a reproduction of OpenAI's WebText dataset. The model has 6 layers, 768 dimension and 12 heads, totalizing 82M parameters (compared to 124M parameters for GPT2). On average, DistilGPT2 is two times faster than GPT2.
|
||||||
- `distilroberta-base`: DistilRoBERTa English language model pretrained with the supervision of `roberta-base` solely on [OpenWebTextCorpus](https://skylion007.github.io/OpenWebTextCorpus/), a reproduction of OpenAI's WebText dataset (it is ~4 times less training data than the teacher RoBERTa). The model has 6 layers, 768 dimension and 12 heads, totalizing 82M parameters (compared to 125M parameters for RoBERTa-base). On average DistilRoBERTa is twice as fast as Roberta-base.
|
- `distilroberta-base`: DistilRoBERTa English language model pretrained with the supervision of `roberta-base` solely on [OpenWebTextCorpus](https://skylion007.github.io/OpenWebTextCorpus/), a reproduction of OpenAI's WebText dataset (it is ~4 times less training data than the teacher RoBERTa). The model has 6 layers, 768 dimension and 12 heads, totalizing 82M parameters (compared to 125M parameters for RoBERTa-base). On average DistilRoBERTa is twice as fast as Roberta-base.
|
||||||
@@ -111,7 +111,7 @@ python scripts/binarized_data.py \
|
|||||||
--dump_file data/binarized_text
|
--dump_file data/binarized_text
|
||||||
```
|
```
|
||||||
|
|
||||||
Our implementation of masked language modeling loss follows [XLM](https://github.com/facebookresearch/XLM)'s one and smoothes the probability of masking with a factor that put more emphasis on rare words. Thus we count the occurences of each tokens in the data:
|
Our implementation of masked language modeling loss follows [XLM](https://github.com/facebookresearch/XLM)'s one and smoothes the probability of masking with a factor that put more emphasis on rare words. Thus we count the occurrences of each tokens in the data:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python scripts/token_counts.py \
|
python scripts/token_counts.py \
|
||||||
|
|||||||
@@ -39,6 +39,9 @@ from transformers import (
|
|||||||
DistilBertConfig,
|
DistilBertConfig,
|
||||||
DistilBertForQuestionAnswering,
|
DistilBertForQuestionAnswering,
|
||||||
DistilBertTokenizer,
|
DistilBertTokenizer,
|
||||||
|
RobertaConfig,
|
||||||
|
RobertaForQuestionAnswering,
|
||||||
|
RobertaTokenizer,
|
||||||
XLMConfig,
|
XLMConfig,
|
||||||
XLMForQuestionAnswering,
|
XLMForQuestionAnswering,
|
||||||
XLMTokenizer,
|
XLMTokenizer,
|
||||||
@@ -73,6 +76,7 @@ MODEL_CLASSES = {
|
|||||||
"xlnet": (XLNetConfig, XLNetForQuestionAnswering, XLNetTokenizer),
|
"xlnet": (XLNetConfig, XLNetForQuestionAnswering, XLNetTokenizer),
|
||||||
"xlm": (XLMConfig, XLMForQuestionAnswering, XLMTokenizer),
|
"xlm": (XLMConfig, XLMForQuestionAnswering, XLMTokenizer),
|
||||||
"distilbert": (DistilBertConfig, DistilBertForQuestionAnswering, DistilBertTokenizer),
|
"distilbert": (DistilBertConfig, DistilBertForQuestionAnswering, DistilBertTokenizer),
|
||||||
|
"roberta": (RobertaConfig, RobertaForQuestionAnswering, RobertaTokenizer),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -716,7 +720,7 @@ def main():
|
|||||||
# Setup CUDA, GPU & distributed training
|
# Setup CUDA, GPU & distributed training
|
||||||
if args.local_rank == -1 or args.no_cuda:
|
if args.local_rank == -1 or args.no_cuda:
|
||||||
device = torch.device("cuda" if torch.cuda.is_available() and not args.no_cuda else "cpu")
|
device = torch.device("cuda" if torch.cuda.is_available() and not args.no_cuda else "cpu")
|
||||||
args.n_gpu = torch.cuda.device_count()
|
args.n_gpu = 0 if args.no_cuda else torch.cuda.device_count()
|
||||||
else: # Initializes the distributed backend which will take care of sychronizing nodes/GPUs
|
else: # Initializes the distributed backend which will take care of sychronizing nodes/GPUs
|
||||||
torch.cuda.set_device(args.local_rank)
|
torch.cuda.set_device(args.local_rank)
|
||||||
device = torch.device("cuda", args.local_rank)
|
device = torch.device("cuda", args.local_rank)
|
||||||
|
|||||||
@@ -520,7 +520,7 @@ def main():
|
|||||||
# Setup CUDA, GPU & distributed training
|
# Setup CUDA, GPU & distributed training
|
||||||
if args.local_rank == -1 or args.no_cuda:
|
if args.local_rank == -1 or args.no_cuda:
|
||||||
device = torch.device("cuda" if torch.cuda.is_available() and not args.no_cuda else "cpu")
|
device = torch.device("cuda" if torch.cuda.is_available() and not args.no_cuda else "cpu")
|
||||||
args.n_gpu = torch.cuda.device_count()
|
args.n_gpu = 0 if args.no_cuda else torch.cuda.device_count()
|
||||||
else: # Initializes the distributed backend which will take care of sychronizing nodes/GPUs
|
else: # Initializes the distributed backend which will take care of sychronizing nodes/GPUs
|
||||||
torch.cuda.set_device(args.local_rank)
|
torch.cuda.set_device(args.local_rank)
|
||||||
device = torch.device("cuda", args.local_rank)
|
device = torch.device("cuda", args.local_rank)
|
||||||
|
|||||||
@@ -492,7 +492,7 @@ def main():
|
|||||||
# Setup CUDA, GPU & distributed training
|
# Setup CUDA, GPU & distributed training
|
||||||
if args.local_rank == -1 or args.no_cuda:
|
if args.local_rank == -1 or args.no_cuda:
|
||||||
device = torch.device("cuda" if torch.cuda.is_available() and not args.no_cuda else "cpu")
|
device = torch.device("cuda" if torch.cuda.is_available() and not args.no_cuda else "cpu")
|
||||||
args.n_gpu = torch.cuda.device_count()
|
args.n_gpu = 0 if args.no_cuda else torch.cuda.device_count()
|
||||||
else: # Initializes the distributed backend which will take care of sychronizing nodes/GPUs
|
else: # Initializes the distributed backend which will take care of sychronizing nodes/GPUs
|
||||||
torch.cuda.set_device(args.local_rank)
|
torch.cuda.set_device(args.local_rank)
|
||||||
device = torch.device("cuda", args.local_rank)
|
device = torch.device("cuda", args.local_rank)
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ from tqdm import tqdm, trange
|
|||||||
from transformers import (
|
from transformers import (
|
||||||
WEIGHTS_NAME,
|
WEIGHTS_NAME,
|
||||||
AdamW,
|
AdamW,
|
||||||
|
AlbertConfig,
|
||||||
|
AlbertForTokenClassification,
|
||||||
|
AlbertTokenizer,
|
||||||
BertConfig,
|
BertConfig,
|
||||||
BertForTokenClassification,
|
BertForTokenClassification,
|
||||||
BertTokenizer,
|
BertTokenizer,
|
||||||
@@ -70,6 +73,7 @@ ALL_MODELS = sum(
|
|||||||
)
|
)
|
||||||
|
|
||||||
MODEL_CLASSES = {
|
MODEL_CLASSES = {
|
||||||
|
"albert": (AlbertConfig, AlbertForTokenClassification, AlbertTokenizer),
|
||||||
"bert": (BertConfig, BertForTokenClassification, BertTokenizer),
|
"bert": (BertConfig, BertForTokenClassification, BertTokenizer),
|
||||||
"roberta": (RobertaConfig, RobertaForTokenClassification, RobertaTokenizer),
|
"roberta": (RobertaConfig, RobertaForTokenClassification, RobertaTokenizer),
|
||||||
"distilbert": (DistilBertConfig, DistilBertForTokenClassification, DistilBertTokenizer),
|
"distilbert": (DistilBertConfig, DistilBertForTokenClassification, DistilBertTokenizer),
|
||||||
@@ -77,6 +81,8 @@ MODEL_CLASSES = {
|
|||||||
"xlmroberta": (XLMRobertaConfig, XLMRobertaForTokenClassification, XLMRobertaTokenizer),
|
"xlmroberta": (XLMRobertaConfig, XLMRobertaForTokenClassification, XLMRobertaTokenizer),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TOKENIZER_ARGS = ["do_lower_case", "strip_accents", "keep_accents", "use_fast"]
|
||||||
|
|
||||||
|
|
||||||
def set_seed(args):
|
def set_seed(args):
|
||||||
random.seed(args.seed)
|
random.seed(args.seed)
|
||||||
@@ -462,7 +468,13 @@ def main():
|
|||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--do_lower_case", action="store_true", help="Set this flag if you are using an uncased model."
|
"--do_lower_case", action="store_true", help="Set this flag if you are using an uncased model."
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--keep_accents", action="store_const", const=True, help="Set this flag if model is trained with accents."
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--strip_accents", action="store_const", const=True, help="Set this flag if model is trained without accents."
|
||||||
|
)
|
||||||
|
parser.add_argument("--use_fast", action="store_const", const=True, help="Set this flag to use fast tokenization.")
|
||||||
parser.add_argument("--per_gpu_train_batch_size", default=8, type=int, help="Batch size per GPU/CPU for training.")
|
parser.add_argument("--per_gpu_train_batch_size", default=8, type=int, help="Batch size per GPU/CPU for training.")
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--per_gpu_eval_batch_size", default=8, type=int, help="Batch size per GPU/CPU for evaluation."
|
"--per_gpu_eval_batch_size", default=8, type=int, help="Batch size per GPU/CPU for evaluation."
|
||||||
@@ -545,7 +557,7 @@ def main():
|
|||||||
# Setup CUDA, GPU & distributed training
|
# Setup CUDA, GPU & distributed training
|
||||||
if args.local_rank == -1 or args.no_cuda:
|
if args.local_rank == -1 or args.no_cuda:
|
||||||
device = torch.device("cuda" if torch.cuda.is_available() and not args.no_cuda else "cpu")
|
device = torch.device("cuda" if torch.cuda.is_available() and not args.no_cuda else "cpu")
|
||||||
args.n_gpu = torch.cuda.device_count()
|
args.n_gpu = 0 if args.no_cuda else torch.cuda.device_count()
|
||||||
else: # Initializes the distributed backend which will take care of sychronizing nodes/GPUs
|
else: # Initializes the distributed backend which will take care of sychronizing nodes/GPUs
|
||||||
torch.cuda.set_device(args.local_rank)
|
torch.cuda.set_device(args.local_rank)
|
||||||
device = torch.device("cuda", args.local_rank)
|
device = torch.device("cuda", args.local_rank)
|
||||||
@@ -590,10 +602,12 @@ def main():
|
|||||||
label2id={label: i for i, label in enumerate(labels)},
|
label2id={label: i for i, label in enumerate(labels)},
|
||||||
cache_dir=args.cache_dir if args.cache_dir else None,
|
cache_dir=args.cache_dir if args.cache_dir else None,
|
||||||
)
|
)
|
||||||
|
tokenizer_args = {k: v for k, v in vars(args).items() if v is not None and k in TOKENIZER_ARGS}
|
||||||
|
logger.info("Tokenizer arguments: %s", tokenizer_args)
|
||||||
tokenizer = tokenizer_class.from_pretrained(
|
tokenizer = tokenizer_class.from_pretrained(
|
||||||
args.tokenizer_name if args.tokenizer_name else args.model_name_or_path,
|
args.tokenizer_name if args.tokenizer_name else args.model_name_or_path,
|
||||||
do_lower_case=args.do_lower_case,
|
|
||||||
cache_dir=args.cache_dir if args.cache_dir else None,
|
cache_dir=args.cache_dir if args.cache_dir else None,
|
||||||
|
**tokenizer_args,
|
||||||
)
|
)
|
||||||
model = model_class.from_pretrained(
|
model = model_class.from_pretrained(
|
||||||
args.model_name_or_path,
|
args.model_name_or_path,
|
||||||
@@ -636,7 +650,7 @@ def main():
|
|||||||
# Evaluation
|
# Evaluation
|
||||||
results = {}
|
results = {}
|
||||||
if args.do_eval and args.local_rank in [-1, 0]:
|
if args.do_eval and args.local_rank in [-1, 0]:
|
||||||
tokenizer = tokenizer_class.from_pretrained(args.output_dir, do_lower_case=args.do_lower_case)
|
tokenizer = tokenizer_class.from_pretrained(args.output_dir, **tokenizer_args)
|
||||||
checkpoints = [args.output_dir]
|
checkpoints = [args.output_dir]
|
||||||
if args.eval_all_checkpoints:
|
if args.eval_all_checkpoints:
|
||||||
checkpoints = list(
|
checkpoints = list(
|
||||||
@@ -658,7 +672,7 @@ def main():
|
|||||||
writer.write("{} = {}\n".format(key, str(results[key])))
|
writer.write("{} = {}\n".format(key, str(results[key])))
|
||||||
|
|
||||||
if args.do_predict and args.local_rank in [-1, 0]:
|
if args.do_predict and args.local_rank in [-1, 0]:
|
||||||
tokenizer = tokenizer_class.from_pretrained(args.output_dir, do_lower_case=args.do_lower_case)
|
tokenizer = tokenizer_class.from_pretrained(args.output_dir, **tokenizer_args)
|
||||||
model = model_class.from_pretrained(args.output_dir)
|
model = model_class.from_pretrained(args.output_dir)
|
||||||
model.to(args.device)
|
model.to(args.device)
|
||||||
result, predictions = evaluate(args, model, tokenizer, labels, pad_token_label_id, mode="test")
|
result, predictions = evaluate(args, model, tokenizer, labels, pad_token_label_id, mode="test")
|
||||||
|
|||||||
@@ -1,6 +1,20 @@
|
|||||||
# Require pytorch-lightning=0.6
|
# Install newest ptl.
|
||||||
|
pip install -U git+http://github.com/PyTorchLightning/pytorch-lightning/
|
||||||
|
|
||||||
|
|
||||||
|
curl -L 'https://sites.google.com/site/germeval2014ner/data/NER-de-train.tsv?attredirects=0&d=1' \
|
||||||
|
| grep -v "^#" | cut -f 2,3 | tr '\t' ' ' > train.txt.tmp
|
||||||
|
curl -L 'https://sites.google.com/site/germeval2014ner/data/NER-de-dev.tsv?attredirects=0&d=1' \
|
||||||
|
| grep -v "^#" | cut -f 2,3 | tr '\t' ' ' > dev.txt.tmp
|
||||||
|
curl -L 'https://sites.google.com/site/germeval2014ner/data/NER-de-test.tsv?attredirects=0&d=1' \
|
||||||
|
| grep -v "^#" | cut -f 2,3 | tr '\t' ' ' > test.txt.tmp
|
||||||
|
wget "https://raw.githubusercontent.com/stefan-it/fine-tuned-berts-seq/master/scripts/preprocess.py"
|
||||||
export MAX_LENGTH=128
|
export MAX_LENGTH=128
|
||||||
export BERT_MODEL=bert-base-multilingual-cased
|
export BERT_MODEL=bert-base-multilingual-cased
|
||||||
|
python3 preprocess.py train.txt.tmp $BERT_MODEL $MAX_LENGTH > train.txt
|
||||||
|
python3 preprocess.py dev.txt.tmp $BERT_MODEL $MAX_LENGTH > dev.txt
|
||||||
|
python3 preprocess.py test.txt.tmp $BERT_MODEL $MAX_LENGTH > test.txt
|
||||||
|
cat train.txt dev.txt test.txt | cut -d " " -f 2 | grep -v "^$"| sort | uniq > labels.txt
|
||||||
export OUTPUT_DIR=germeval-model
|
export OUTPUT_DIR=germeval-model
|
||||||
export BATCH_SIZE=32
|
export BATCH_SIZE=32
|
||||||
export NUM_EPOCHS=3
|
export NUM_EPOCHS=3
|
||||||
|
|||||||
@@ -7,8 +7,7 @@ import numpy as np
|
|||||||
import torch
|
import torch
|
||||||
from seqeval.metrics import f1_score, precision_score, recall_score
|
from seqeval.metrics import f1_score, precision_score, recall_score
|
||||||
from torch.nn import CrossEntropyLoss
|
from torch.nn import CrossEntropyLoss
|
||||||
from torch.utils.data import DataLoader, RandomSampler, SequentialSampler, TensorDataset
|
from torch.utils.data import DataLoader, TensorDataset
|
||||||
from torch.utils.data.distributed import DistributedSampler
|
|
||||||
|
|
||||||
from transformer_base import BaseTransformer, add_generic_args, generic_train
|
from transformer_base import BaseTransformer, add_generic_args, generic_train
|
||||||
from utils_ner import convert_examples_to_features, get_labels, read_examples_from_file
|
from utils_ner import convert_examples_to_features, get_labels, read_examples_from_file
|
||||||
@@ -25,13 +24,14 @@ class NERTransformer(BaseTransformer):
|
|||||||
def __init__(self, hparams):
|
def __init__(self, hparams):
|
||||||
self.labels = get_labels(hparams.labels)
|
self.labels = get_labels(hparams.labels)
|
||||||
num_labels = len(self.labels)
|
num_labels = len(self.labels)
|
||||||
|
self.pad_token_label_id = CrossEntropyLoss().ignore_index
|
||||||
super(NERTransformer, self).__init__(hparams, num_labels)
|
super(NERTransformer, self).__init__(hparams, num_labels)
|
||||||
|
|
||||||
def forward(self, **inputs):
|
def forward(self, **inputs):
|
||||||
return self.model(**inputs)
|
return self.model(**inputs)
|
||||||
|
|
||||||
def training_step(self, batch, batch_num):
|
def training_step(self, batch, batch_num):
|
||||||
"Compute loss"
|
"Compute loss and log."
|
||||||
inputs = {"input_ids": batch[0], "attention_mask": batch[1], "labels": batch[3]}
|
inputs = {"input_ids": batch[0], "attention_mask": batch[1], "labels": batch[3]}
|
||||||
if self.hparams.model_type != "distilbert":
|
if self.hparams.model_type != "distilbert":
|
||||||
inputs["token_type_ids"] = (
|
inputs["token_type_ids"] = (
|
||||||
@@ -40,25 +40,61 @@ class NERTransformer(BaseTransformer):
|
|||||||
|
|
||||||
outputs = self.forward(**inputs)
|
outputs = self.forward(**inputs)
|
||||||
loss = outputs[0]
|
loss = outputs[0]
|
||||||
|
|
||||||
tensorboard_logs = {"loss": loss, "rate": self.lr_scheduler.get_last_lr()[-1]}
|
tensorboard_logs = {"loss": loss, "rate": self.lr_scheduler.get_last_lr()[-1]}
|
||||||
return {"loss": loss, "log": tensorboard_logs}
|
return {"loss": loss, "log": tensorboard_logs}
|
||||||
|
|
||||||
|
def _feature_file(self, mode):
|
||||||
|
return os.path.join(
|
||||||
|
self.hparams.data_dir,
|
||||||
|
"cached_{}_{}_{}".format(
|
||||||
|
mode,
|
||||||
|
list(filter(None, self.hparams.model_name_or_path.split("/"))).pop(),
|
||||||
|
str(self.hparams.max_seq_length),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
def prepare_data(self):
|
||||||
|
"Called to initialize data. Use the call to construct features"
|
||||||
|
args = self.hparams
|
||||||
|
for mode in ["train", "dev", "test"]:
|
||||||
|
cached_features_file = self._feature_file(mode)
|
||||||
|
if not os.path.exists(cached_features_file):
|
||||||
|
logger.info("Creating features from dataset file at %s", args.data_dir)
|
||||||
|
examples = read_examples_from_file(args.data_dir, mode)
|
||||||
|
features = convert_examples_to_features(
|
||||||
|
examples,
|
||||||
|
self.labels,
|
||||||
|
args.max_seq_length,
|
||||||
|
self.tokenizer,
|
||||||
|
cls_token_at_end=bool(args.model_type in ["xlnet"]),
|
||||||
|
cls_token=self.tokenizer.cls_token,
|
||||||
|
cls_token_segment_id=2 if args.model_type in ["xlnet"] else 0,
|
||||||
|
sep_token=self.tokenizer.sep_token,
|
||||||
|
sep_token_extra=bool(args.model_type in ["roberta"]),
|
||||||
|
pad_on_left=bool(args.model_type in ["xlnet"]),
|
||||||
|
pad_token=self.tokenizer.convert_tokens_to_ids([self.tokenizer.pad_token])[0],
|
||||||
|
pad_token_segment_id=4 if args.model_type in ["xlnet"] else 0,
|
||||||
|
pad_token_label_id=self.pad_token_label_id,
|
||||||
|
)
|
||||||
|
logger.info("Saving features into cached file %s", cached_features_file)
|
||||||
|
torch.save(features, cached_features_file)
|
||||||
|
|
||||||
def load_dataset(self, mode, batch_size):
|
def load_dataset(self, mode, batch_size):
|
||||||
labels = get_labels(self.hparams.labels)
|
"Load datasets. Called after prepare data."
|
||||||
self.pad_token_label_id = CrossEntropyLoss().ignore_index
|
cached_features_file = self._feature_file(mode)
|
||||||
dataset = self.load_and_cache_examples(labels, self.pad_token_label_id, mode)
|
logger.info("Loading features from cached file %s", cached_features_file)
|
||||||
if mode == "train":
|
features = torch.load(cached_features_file)
|
||||||
if self.hparams.n_gpu > 1:
|
all_input_ids = torch.tensor([f.input_ids for f in features], dtype=torch.long)
|
||||||
sampler = DistributedSampler(dataset)
|
all_input_mask = torch.tensor([f.input_mask for f in features], dtype=torch.long)
|
||||||
else:
|
all_segment_ids = torch.tensor([f.segment_ids for f in features], dtype=torch.long)
|
||||||
sampler = RandomSampler(dataset)
|
all_label_ids = torch.tensor([f.label_ids for f in features], dtype=torch.long)
|
||||||
else:
|
return DataLoader(
|
||||||
sampler = SequentialSampler(dataset)
|
TensorDataset(all_input_ids, all_input_mask, all_segment_ids, all_label_ids), batch_size=batch_size
|
||||||
dataloader = DataLoader(dataset, sampler=sampler, batch_size=batch_size)
|
)
|
||||||
return dataloader
|
|
||||||
|
|
||||||
def validation_step(self, batch, batch_nb):
|
def validation_step(self, batch, batch_nb):
|
||||||
|
"Compute validation"
|
||||||
|
|
||||||
inputs = {"input_ids": batch[0], "attention_mask": batch[1], "labels": batch[3]}
|
inputs = {"input_ids": batch[0], "attention_mask": batch[1], "labels": batch[3]}
|
||||||
if self.hparams.model_type != "distilbert":
|
if self.hparams.model_type != "distilbert":
|
||||||
inputs["token_type_ids"] = (
|
inputs["token_type_ids"] = (
|
||||||
@@ -68,11 +104,10 @@ class NERTransformer(BaseTransformer):
|
|||||||
tmp_eval_loss, logits = outputs[:2]
|
tmp_eval_loss, logits = outputs[:2]
|
||||||
preds = logits.detach().cpu().numpy()
|
preds = logits.detach().cpu().numpy()
|
||||||
out_label_ids = inputs["labels"].detach().cpu().numpy()
|
out_label_ids = inputs["labels"].detach().cpu().numpy()
|
||||||
|
return {"val_loss": tmp_eval_loss.detach().cpu(), "pred": preds, "target": out_label_ids}
|
||||||
return {"val_loss": tmp_eval_loss, "pred": preds, "target": out_label_ids}
|
|
||||||
|
|
||||||
def _eval_end(self, outputs):
|
def _eval_end(self, outputs):
|
||||||
"Task specific validation"
|
"Evaluation called for both Val and Test"
|
||||||
val_loss_mean = torch.stack([x["val_loss"] for x in outputs]).mean()
|
val_loss_mean = torch.stack([x["val_loss"] for x in outputs]).mean()
|
||||||
preds = np.concatenate([x["pred"] for x in outputs], axis=0)
|
preds = np.concatenate([x["pred"] for x in outputs], axis=0)
|
||||||
preds = np.argmax(preds, axis=2)
|
preds = np.argmax(preds, axis=2)
|
||||||
@@ -96,7 +131,6 @@ class NERTransformer(BaseTransformer):
|
|||||||
}
|
}
|
||||||
|
|
||||||
if self.is_logger():
|
if self.is_logger():
|
||||||
logger.info(self.proc_rank)
|
|
||||||
logger.info("***** Eval results *****")
|
logger.info("***** Eval results *****")
|
||||||
for key in sorted(results.keys()):
|
for key in sorted(results.keys()):
|
||||||
logger.info(" %s = %s", key, str(results[key]))
|
logger.info(" %s = %s", key, str(results[key]))
|
||||||
@@ -140,56 +174,6 @@ class NERTransformer(BaseTransformer):
|
|||||||
)
|
)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def load_and_cache_examples(self, labels, pad_token_label_id, mode):
|
|
||||||
args = self.hparams
|
|
||||||
tokenizer = self.tokenizer
|
|
||||||
if self.proc_rank not in [-1, 0] and mode == "train":
|
|
||||||
torch.distributed.barrier() # Make sure only the first process in distributed training process the dataset, and the others will use the cache
|
|
||||||
|
|
||||||
# Load data features from cache or dataset file
|
|
||||||
cached_features_file = os.path.join(
|
|
||||||
args.data_dir,
|
|
||||||
"cached_{}_{}_{}".format(
|
|
||||||
mode, list(filter(None, args.model_name_or_path.split("/"))).pop(), str(args.max_seq_length)
|
|
||||||
),
|
|
||||||
)
|
|
||||||
if os.path.exists(cached_features_file) and not args.overwrite_cache:
|
|
||||||
logger.info("Loading features from cached file %s", cached_features_file)
|
|
||||||
features = torch.load(cached_features_file)
|
|
||||||
else:
|
|
||||||
logger.info("Creating features from dataset file at %s", args.data_dir)
|
|
||||||
examples = read_examples_from_file(args.data_dir, mode)
|
|
||||||
features = convert_examples_to_features(
|
|
||||||
examples,
|
|
||||||
labels,
|
|
||||||
args.max_seq_length,
|
|
||||||
tokenizer,
|
|
||||||
cls_token_at_end=bool(args.model_type in ["xlnet"]),
|
|
||||||
cls_token=tokenizer.cls_token,
|
|
||||||
cls_token_segment_id=2 if args.model_type in ["xlnet"] else 0,
|
|
||||||
sep_token=tokenizer.sep_token,
|
|
||||||
sep_token_extra=bool(args.model_type in ["roberta"]),
|
|
||||||
pad_on_left=bool(args.model_type in ["xlnet"]),
|
|
||||||
pad_token=tokenizer.convert_tokens_to_ids([tokenizer.pad_token])[0],
|
|
||||||
pad_token_segment_id=4 if args.model_type in ["xlnet"] else 0,
|
|
||||||
pad_token_label_id=pad_token_label_id,
|
|
||||||
)
|
|
||||||
if self.proc_rank in [-1, 0]:
|
|
||||||
logger.info("Saving features into cached file %s", cached_features_file)
|
|
||||||
torch.save(features, cached_features_file)
|
|
||||||
|
|
||||||
if self.proc_rank == 0 and mode == "train":
|
|
||||||
torch.distributed.barrier() # Make sure only the first process in distributed training process the dataset, and the others will use the cache
|
|
||||||
|
|
||||||
# Convert to Tensors and build dataset
|
|
||||||
all_input_ids = torch.tensor([f.input_ids for f in features], dtype=torch.long)
|
|
||||||
all_input_mask = torch.tensor([f.input_mask for f in features], dtype=torch.long)
|
|
||||||
all_segment_ids = torch.tensor([f.segment_ids for f in features], dtype=torch.long)
|
|
||||||
all_label_ids = torch.tensor([f.label_ids for f in features], dtype=torch.long)
|
|
||||||
|
|
||||||
dataset = TensorDataset(all_input_ids, all_input_mask, all_segment_ids, all_label_ids)
|
|
||||||
return dataset
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def add_model_specific_args(parser, root_dir):
|
def add_model_specific_args(parser, root_dir):
|
||||||
# Add NER specific options
|
# Add NER specific options
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
|
|
||||||
@@ -26,6 +27,9 @@ from transformers import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
ALL_MODELS = sum(
|
ALL_MODELS = sum(
|
||||||
(
|
(
|
||||||
tuple(conf.pretrained_config_archive_map.keys())
|
tuple(conf.pretrained_config_archive_map.keys())
|
||||||
@@ -77,20 +81,14 @@ class BaseTransformer(pl.LightningModule):
|
|||||||
cache_dir=self.hparams.cache_dir if self.hparams.cache_dir else None,
|
cache_dir=self.hparams.cache_dir if self.hparams.cache_dir else None,
|
||||||
)
|
)
|
||||||
self.config, self.tokenizer, self.model = config, tokenizer, model
|
self.config, self.tokenizer, self.model = config, tokenizer, model
|
||||||
self.proc_rank = -1
|
|
||||||
|
|
||||||
def is_logger(self):
|
def is_logger(self):
|
||||||
return self.proc_rank <= 0
|
return self.trainer.proc_rank <= 0
|
||||||
|
|
||||||
def configure_optimizers(self):
|
def configure_optimizers(self):
|
||||||
"Prepare optimizer and schedule (linear warmup and decay)"
|
"Prepare optimizer and schedule (linear warmup and decay)"
|
||||||
model = self.model
|
|
||||||
|
|
||||||
t_total = (
|
model = self.model
|
||||||
len(self.train_dataloader())
|
|
||||||
// self.hparams.gradient_accumulation_steps
|
|
||||||
* float(self.hparams.num_train_epochs)
|
|
||||||
)
|
|
||||||
no_decay = ["bias", "LayerNorm.weight"]
|
no_decay = ["bias", "LayerNorm.weight"]
|
||||||
optimizer_grouped_parameters = [
|
optimizer_grouped_parameters = [
|
||||||
{
|
{
|
||||||
@@ -103,18 +101,16 @@ class BaseTransformer(pl.LightningModule):
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
optimizer = AdamW(optimizer_grouped_parameters, lr=self.hparams.learning_rate, eps=self.hparams.adam_epsilon)
|
optimizer = AdamW(optimizer_grouped_parameters, lr=self.hparams.learning_rate, eps=self.hparams.adam_epsilon)
|
||||||
scheduler = get_linear_schedule_with_warmup(
|
self.opt = optimizer
|
||||||
optimizer, num_warmup_steps=self.hparams.warmup_steps, num_training_steps=t_total
|
|
||||||
)
|
|
||||||
self.lr_scheduler = scheduler
|
|
||||||
return [optimizer]
|
return [optimizer]
|
||||||
|
|
||||||
def optimizer_step(self, epoch, batch_idx, optimizer, optimizer_idx, second_order_closure=None):
|
def optimizer_step(self, epoch, batch_idx, optimizer, optimizer_idx, second_order_closure=None):
|
||||||
|
if self.trainer.use_tpu:
|
||||||
# Step each time.
|
xm.optimizer_step(optimizer)
|
||||||
optimizer.step()
|
else:
|
||||||
self.lr_scheduler.step()
|
optimizer.step()
|
||||||
optimizer.zero_grad()
|
optimizer.zero_grad()
|
||||||
|
self.lr_scheduler.step()
|
||||||
|
|
||||||
def get_tqdm_dict(self):
|
def get_tqdm_dict(self):
|
||||||
tqdm_dict = {"loss": "{:.3f}".format(self.trainer.avg_loss), "lr": self.lr_scheduler.get_last_lr()[-1]}
|
tqdm_dict = {"loss": "{:.3f}".format(self.trainer.avg_loss), "lr": self.lr_scheduler.get_last_lr()[-1]}
|
||||||
@@ -127,22 +123,27 @@ class BaseTransformer(pl.LightningModule):
|
|||||||
def test_end(self, outputs):
|
def test_end(self, outputs):
|
||||||
return self.validation_end(outputs)
|
return self.validation_end(outputs)
|
||||||
|
|
||||||
@pl.data_loader
|
|
||||||
def train_dataloader(self):
|
def train_dataloader(self):
|
||||||
return self.load_dataset("train", self.hparams.train_batch_size)
|
train_batch_size = self.hparams.train_batch_size
|
||||||
|
dataloader = self.load_dataset("train", train_batch_size)
|
||||||
|
|
||||||
|
t_total = (
|
||||||
|
(len(dataloader.dataset) // (train_batch_size * max(1, self.hparams.n_gpu)))
|
||||||
|
// self.hparams.gradient_accumulation_steps
|
||||||
|
* float(self.hparams.num_train_epochs)
|
||||||
|
)
|
||||||
|
scheduler = get_linear_schedule_with_warmup(
|
||||||
|
self.opt, num_warmup_steps=self.hparams.warmup_steps, num_training_steps=t_total
|
||||||
|
)
|
||||||
|
self.lr_scheduler = scheduler
|
||||||
|
return dataloader
|
||||||
|
|
||||||
@pl.data_loader
|
|
||||||
def val_dataloader(self):
|
def val_dataloader(self):
|
||||||
return self.load_dataset("dev", self.hparams.eval_batch_size)
|
return self.load_dataset("dev", self.hparams.eval_batch_size)
|
||||||
|
|
||||||
@pl.data_loader
|
|
||||||
def test_dataloader(self):
|
def test_dataloader(self):
|
||||||
return self.load_dataset("test", self.hparams.eval_batch_size)
|
return self.load_dataset("test", self.hparams.eval_batch_size)
|
||||||
|
|
||||||
def init_ddp_connection(self, proc_rank, world_size):
|
|
||||||
self.proc_rank = proc_rank
|
|
||||||
super(BaseTransformer, self).init_ddp_connection(proc_rank, world_size)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def add_model_specific_args(parser, root_dir):
|
def add_model_specific_args(parser, root_dir):
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
@@ -213,6 +214,7 @@ def add_generic_args(parser, root_dir):
|
|||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument("--n_gpu", type=int, default=1)
|
parser.add_argument("--n_gpu", type=int, default=1)
|
||||||
|
parser.add_argument("--n_tpu_cores", type=int, default=0)
|
||||||
parser.add_argument("--max_grad_norm", default=1.0, type=float, help="Max gradient norm.")
|
parser.add_argument("--max_grad_norm", default=1.0, type=float, help="Max gradient norm.")
|
||||||
parser.add_argument("--do_train", action="store_true", help="Whether to run training.")
|
parser.add_argument("--do_train", action="store_true", help="Whether to run training.")
|
||||||
parser.add_argument("--do_predict", action="store_true", help="Whether to run predictions on the test set.")
|
parser.add_argument("--do_predict", action="store_true", help="Whether to run predictions on the test set.")
|
||||||
@@ -252,13 +254,22 @@ def generic_train(model, args):
|
|||||||
accumulate_grad_batches=args.gradient_accumulation_steps,
|
accumulate_grad_batches=args.gradient_accumulation_steps,
|
||||||
gpus=args.n_gpu,
|
gpus=args.n_gpu,
|
||||||
max_epochs=args.num_train_epochs,
|
max_epochs=args.num_train_epochs,
|
||||||
|
early_stop_callback=False,
|
||||||
gradient_clip_val=args.max_grad_norm,
|
gradient_clip_val=args.max_grad_norm,
|
||||||
checkpoint_callback=checkpoint_callback,
|
checkpoint_callback=checkpoint_callback,
|
||||||
)
|
)
|
||||||
|
|
||||||
if args.fp16:
|
if args.fp16:
|
||||||
train_params["use_amp"] = args.fp16
|
train_params["use_amp"] = args.fp16
|
||||||
train_params["amp_level"] = args.fp16_opt_level
|
train_params["amp_level"] = args.fp16_opt_level
|
||||||
|
|
||||||
|
if args.n_tpu_cores > 0:
|
||||||
|
global xm
|
||||||
|
import torch_xla.core.xla_model as xm
|
||||||
|
|
||||||
|
train_params["num_tpu_cores"] = args.n_tpu_cores
|
||||||
|
train_params["gpus"] = 0
|
||||||
|
|
||||||
if args.n_gpu > 1:
|
if args.n_gpu > 1:
|
||||||
train_params["distributed_backend"] = "ddp"
|
train_params["distributed_backend"] = "ddp"
|
||||||
|
|
||||||
|
|||||||
@@ -338,7 +338,7 @@ def main():
|
|||||||
# Setup devices and distributed training
|
# Setup devices and distributed training
|
||||||
if args.local_rank == -1 or args.no_cuda:
|
if args.local_rank == -1 or args.no_cuda:
|
||||||
args.device = torch.device("cuda" if torch.cuda.is_available() and not args.no_cuda else "cpu")
|
args.device = torch.device("cuda" if torch.cuda.is_available() and not args.no_cuda else "cpu")
|
||||||
args.n_gpu = torch.cuda.device_count()
|
args.n_gpu = 0 if args.no_cuda else torch.cuda.device_count()
|
||||||
else:
|
else:
|
||||||
torch.cuda.set_device(args.local_rank)
|
torch.cuda.set_device(args.local_rank)
|
||||||
args.device = torch.device("cuda", args.local_rank)
|
args.device = torch.device("cuda", args.local_rank)
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ def main():
|
|||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
args.device = torch.device("cuda" if torch.cuda.is_available() and not args.no_cuda else "cpu")
|
args.device = torch.device("cuda" if torch.cuda.is_available() and not args.no_cuda else "cpu")
|
||||||
args.n_gpu = torch.cuda.device_count()
|
args.n_gpu = 0 if args.no_cuda else torch.cuda.device_count()
|
||||||
|
|
||||||
set_seed(args)
|
set_seed(args)
|
||||||
|
|
||||||
|
|||||||
@@ -183,8 +183,11 @@ def train(args, train_dataset, model, tokenizer):
|
|||||||
steps_trained_in_current_epoch = 0
|
steps_trained_in_current_epoch = 0
|
||||||
# Check if continuing training from a checkpoint
|
# Check if continuing training from a checkpoint
|
||||||
if os.path.exists(args.model_name_or_path):
|
if os.path.exists(args.model_name_or_path):
|
||||||
# set global_step to gobal_step of last saved checkpoint from model path
|
# set global_step to global_step of last saved checkpoint from model path
|
||||||
global_step = int(args.model_name_or_path.split("-")[-1].split("/")[0])
|
try:
|
||||||
|
global_step = int(args.model_name_or_path.split("-")[-1].split("/")[0])
|
||||||
|
except ValueError:
|
||||||
|
global_step = 0
|
||||||
epochs_trained = global_step // (len(train_dataloader) // args.gradient_accumulation_steps)
|
epochs_trained = global_step // (len(train_dataloader) // args.gradient_accumulation_steps)
|
||||||
steps_trained_in_current_epoch = global_step % (len(train_dataloader) // args.gradient_accumulation_steps)
|
steps_trained_in_current_epoch = global_step % (len(train_dataloader) // args.gradient_accumulation_steps)
|
||||||
|
|
||||||
@@ -575,7 +578,7 @@ def main():
|
|||||||
# Setup CUDA, GPU & distributed training
|
# Setup CUDA, GPU & distributed training
|
||||||
if args.local_rank == -1 or args.no_cuda:
|
if args.local_rank == -1 or args.no_cuda:
|
||||||
device = torch.device("cuda" if torch.cuda.is_available() and not args.no_cuda else "cpu")
|
device = torch.device("cuda" if torch.cuda.is_available() and not args.no_cuda else "cpu")
|
||||||
args.n_gpu = torch.cuda.device_count()
|
args.n_gpu = 0 if args.no_cuda else torch.cuda.device_count()
|
||||||
else: # Initializes the distributed backend which will take care of sychronizing nodes/GPUs
|
else: # Initializes the distributed backend which will take care of sychronizing nodes/GPUs
|
||||||
torch.cuda.set_device(args.local_rank)
|
torch.cuda.set_device(args.local_rank)
|
||||||
device = torch.device("cuda", args.local_rank)
|
device = torch.device("cuda", args.local_rank)
|
||||||
|
|||||||
@@ -663,7 +663,7 @@ def main():
|
|||||||
# Setup CUDA, GPU & distributed training
|
# Setup CUDA, GPU & distributed training
|
||||||
if args.local_rank == -1 or args.no_cuda:
|
if args.local_rank == -1 or args.no_cuda:
|
||||||
device = torch.device("cuda" if torch.cuda.is_available() and not args.no_cuda else "cpu")
|
device = torch.device("cuda" if torch.cuda.is_available() and not args.no_cuda else "cpu")
|
||||||
args.n_gpu = torch.cuda.device_count()
|
args.n_gpu = 0 if args.no_cuda else torch.cuda.device_count()
|
||||||
else: # Initializes the distributed backend which will take care of sychronizing nodes/GPUs
|
else: # Initializes the distributed backend which will take care of sychronizing nodes/GPUs
|
||||||
torch.cuda.set_device(args.local_rank)
|
torch.cuda.set_device(args.local_rank)
|
||||||
device = torch.device("cuda", args.local_rank)
|
device = torch.device("cuda", args.local_rank)
|
||||||
|
|||||||
@@ -535,7 +535,7 @@ def main():
|
|||||||
# Setup CUDA, GPU & distributed training
|
# Setup CUDA, GPU & distributed training
|
||||||
if args.local_rank == -1 or args.no_cuda:
|
if args.local_rank == -1 or args.no_cuda:
|
||||||
device = torch.device("cuda" if torch.cuda.is_available() and not args.no_cuda else "cpu")
|
device = torch.device("cuda" if torch.cuda.is_available() and not args.no_cuda else "cpu")
|
||||||
args.n_gpu = torch.cuda.device_count()
|
args.n_gpu = 0 if args.no_cuda else torch.cuda.device_count()
|
||||||
else: # Initializes the distributed backend which will take care of sychronizing nodes/GPUs
|
else: # Initializes the distributed backend which will take care of sychronizing nodes/GPUs
|
||||||
torch.cuda.set_device(args.local_rank)
|
torch.cuda.set_device(args.local_rank)
|
||||||
device = torch.device("cuda", args.local_rank)
|
device = torch.device("cuda", args.local_rank)
|
||||||
|
|||||||
@@ -725,7 +725,7 @@ def main():
|
|||||||
# Setup CUDA, GPU & distributed training
|
# Setup CUDA, GPU & distributed training
|
||||||
if args.local_rank == -1 or args.no_cuda:
|
if args.local_rank == -1 or args.no_cuda:
|
||||||
device = torch.device("cuda" if torch.cuda.is_available() and not args.no_cuda else "cpu")
|
device = torch.device("cuda" if torch.cuda.is_available() and not args.no_cuda else "cpu")
|
||||||
args.n_gpu = torch.cuda.device_count()
|
args.n_gpu = 0 if args.no_cuda else torch.cuda.device_count()
|
||||||
else: # Initializes the distributed backend which will take care of sychronizing nodes/GPUs
|
else: # Initializes the distributed backend which will take care of sychronizing nodes/GPUs
|
||||||
torch.cuda.set_device(args.local_rank)
|
torch.cuda.set_device(args.local_rank)
|
||||||
device = torch.device("cuda", args.local_rank)
|
device = torch.device("cuda", args.local_rank)
|
||||||
|
|||||||
@@ -530,7 +530,7 @@ def main():
|
|||||||
# Setup CUDA, GPU & distributed training
|
# Setup CUDA, GPU & distributed training
|
||||||
if args.local_rank == -1 or args.no_cuda:
|
if args.local_rank == -1 or args.no_cuda:
|
||||||
device = torch.device("cuda" if torch.cuda.is_available() and not args.no_cuda else "cpu")
|
device = torch.device("cuda" if torch.cuda.is_available() and not args.no_cuda else "cpu")
|
||||||
args.n_gpu = torch.cuda.device_count()
|
args.n_gpu = 0 if args.no_cuda else torch.cuda.device_count()
|
||||||
else: # Initializes the distributed backend which will take care of sychronizing nodes/GPUs
|
else: # Initializes the distributed backend which will take care of sychronizing nodes/GPUs
|
||||||
torch.cuda.set_device(args.local_rank)
|
torch.cuda.set_device(args.local_rank)
|
||||||
device = torch.device("cuda", args.local_rank)
|
device = torch.device("cuda", args.local_rank)
|
||||||
|
|||||||
0
examples/summarization/__init__.py
Normal file
0
examples/summarization/__init__.py
Normal file
45
examples/summarization/bart/README.md
Normal file
45
examples/summarization/bart/README.md
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
### Get the CNN/Daily Mail Data
|
||||||
|
To be able to reproduce the authors' results on the CNN/Daily Mail dataset you first need to download both CNN and Daily Mail datasets [from Kyunghyun Cho's website](https://cs.nyu.edu/~kcho/DMQA/) (the links next to "Stories") in the same folder. Then uncompress the archives by running:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
tar -xvf cnn_stories.tgz && tar -xvf dailymail_stories.tgz
|
||||||
|
```
|
||||||
|
this should make a directory called cnn_dm/ with files like `test.source`.
|
||||||
|
To use your own data, copy that files format. Each article to be summarized is on its own line.
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
To create summaries for each article in dataset, run:
|
||||||
|
```bash
|
||||||
|
python evaluate_cnn.py <path_to_test.source> cnn_test_summaries.txt
|
||||||
|
```
|
||||||
|
the default batch size, 8, fits in 16GB GPU memory, but may need to be adjusted to fit your system.
|
||||||
|
|
||||||
|
### Where is the code?
|
||||||
|
The core model is in `src/transformers/modeling_bart.py`. This directory only contains examples.
|
||||||
|
|
||||||
|
### (WIP) Rouge Scores
|
||||||
|
|
||||||
|
### Stanford CoreNLP Setup
|
||||||
|
```
|
||||||
|
ptb_tokenize () {
|
||||||
|
cat $1 | java edu.stanford.nlp.process.PTBTokenizer -ioFileList -preserveLines > $2
|
||||||
|
}
|
||||||
|
|
||||||
|
sudo apt install openjdk-8-jre-headless
|
||||||
|
sudo apt-get install ant
|
||||||
|
wget http://nlp.stanford.edu/software/stanford-corenlp-full-2018-10-05.zip
|
||||||
|
unzip stanford-corenlp-full-2018-10-05.zip
|
||||||
|
cd stanford-corenlp-full-2018-10-05
|
||||||
|
export CLASSPATH=stanford-corenlp-3.9.2.jar:stanford-corenlp-3.9.2-models.jar
|
||||||
|
```
|
||||||
|
### Rouge Setup
|
||||||
|
Install `files2rouge` following the instructions at [here](https://github.com/pltrdy/files2rouge).
|
||||||
|
I also needed to run `sudo apt-get install libxml-parser-perl`
|
||||||
|
|
||||||
|
```python
|
||||||
|
from files2rouge import files2rouge
|
||||||
|
from files2rouge import settings
|
||||||
|
files2rouge.run(<path_to_tokenized_hypo>,
|
||||||
|
<path_to_tokenized_target>,
|
||||||
|
saveto='rouge_output.txt')
|
||||||
|
```
|
||||||
0
examples/summarization/bart/__init__.py
Normal file
0
examples/summarization/bart/__init__.py
Normal file
60
examples/summarization/bart/evaluate_cnn.py
Normal file
60
examples/summarization/bart/evaluate_cnn.py
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
import argparse
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import torch
|
||||||
|
from tqdm import tqdm
|
||||||
|
|
||||||
|
from transformers import BartForMaskedLM, BartTokenizer
|
||||||
|
|
||||||
|
|
||||||
|
DEFAULT_DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
|
||||||
|
|
||||||
|
|
||||||
|
def chunks(lst, n):
|
||||||
|
"""Yield successive n-sized chunks from lst."""
|
||||||
|
for i in range(0, len(lst), n):
|
||||||
|
yield lst[i : i + n]
|
||||||
|
|
||||||
|
|
||||||
|
def generate_summaries(lns, out_file, batch_size=8, device=DEFAULT_DEVICE):
|
||||||
|
fout = Path(out_file).open("w")
|
||||||
|
model = BartForMaskedLM.from_pretrained("bart-large-cnn", output_past=True,)
|
||||||
|
tokenizer = BartTokenizer.from_pretrained("bart-large")
|
||||||
|
for batch in tqdm(list(chunks(lns, batch_size))):
|
||||||
|
dct = tokenizer.batch_encode_plus(batch, max_length=1024, return_tensors="pt", pad_to_max_length=True)
|
||||||
|
summaries = model.generate(
|
||||||
|
input_ids=dct["input_ids"].to(device),
|
||||||
|
attention_mask=dct["attention_mask"].to(device),
|
||||||
|
num_beams=4,
|
||||||
|
length_penalty=2.0,
|
||||||
|
max_length=140,
|
||||||
|
min_len=55,
|
||||||
|
no_repeat_ngram_size=3,
|
||||||
|
)
|
||||||
|
dec = [tokenizer.decode(g, skip_special_tokens=True, clean_up_tokenization_spaces=False) for g in summaries]
|
||||||
|
for hypothesis in dec:
|
||||||
|
fout.write(hypothesis + "\n")
|
||||||
|
fout.flush()
|
||||||
|
|
||||||
|
|
||||||
|
def _run_generate():
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument(
|
||||||
|
"source_path", type=str, help="like cnn_dm/test.source",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"output_path", type=str, help="where to save summaries",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--device", type=str, required=False, default=DEFAULT_DEVICE, help="cuda, cuda:1, cpu etc.",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--bs", type=int, default=8, required=False, help="batch size: how many to summarize at a time",
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
lns = [" " + x.rstrip() for x in open(args.source_path).readlines()]
|
||||||
|
generate_summaries(lns, args.output_path, batch_size=args.bs, device=args.device)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
_run_generate()
|
||||||
28
examples/summarization/bart/test_bart_examples.py
Normal file
28
examples/summarization/bart/test_bart_examples.py
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import logging
|
||||||
|
import sys
|
||||||
|
import tempfile
|
||||||
|
import unittest
|
||||||
|
from pathlib import Path
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from .evaluate_cnn import _run_generate
|
||||||
|
|
||||||
|
|
||||||
|
articles = [" New York (CNN)When Liana Barrientos was 23 years old, she got married in Westchester County."]
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
|
class TestBartExamples(unittest.TestCase):
|
||||||
|
def test_bart_cnn_cli(self):
|
||||||
|
stream_handler = logging.StreamHandler(sys.stdout)
|
||||||
|
logger.addHandler(stream_handler)
|
||||||
|
tmp = Path(tempfile.gettempdir()) / "utest_generations.hypo"
|
||||||
|
with tmp.open("w") as f:
|
||||||
|
f.write("\n".join(articles))
|
||||||
|
testargs = ["evaluate_cnn.py", str(tmp), "output.txt"]
|
||||||
|
with patch.object(sys, "argv", testargs):
|
||||||
|
_run_generate()
|
||||||
|
self.assertTrue(Path("output.txt").exists())
|
||||||
@@ -15,7 +15,7 @@ pip install nltk py-rouge
|
|||||||
cd examples/summarization
|
cd examples/summarization
|
||||||
```
|
```
|
||||||
|
|
||||||
## Reproduce the authors' results on ROUGE
|
## Reproduce the authors' ROUGE score
|
||||||
|
|
||||||
To be able to reproduce the authors' results on the CNN/Daily Mail dataset you first need to download both CNN and Daily Mail datasets [from Kyunghyun Cho's website](https://cs.nyu.edu/~kcho/DMQA/) (the links next to "Stories") in the same folder. Then uncompress the archives by running:
|
To be able to reproduce the authors' results on the CNN/Daily Mail dataset you first need to download both CNN and Daily Mail datasets [from Kyunghyun Cho's website](https://cs.nyu.edu/~kcho/DMQA/) (the links next to "Stories") in the same folder. Then uncompress the archives by running:
|
||||||
|
|
||||||
0
examples/summarization/bertabs/__init__.py
Normal file
0
examples/summarization/bertabs/__init__.py
Normal file
@@ -11,12 +11,13 @@ from tqdm import tqdm
|
|||||||
|
|
||||||
from modeling_bertabs import BertAbs, build_predictor
|
from modeling_bertabs import BertAbs, build_predictor
|
||||||
from transformers import BertTokenizer
|
from transformers import BertTokenizer
|
||||||
from utils_summarization import (
|
|
||||||
SummarizationDataset,
|
from .utils_summarization import (
|
||||||
|
CNNDMDataset,
|
||||||
build_mask,
|
build_mask,
|
||||||
compute_token_type_ids,
|
compute_token_type_ids,
|
||||||
encode_for_summarization,
|
encode_for_summarization,
|
||||||
fit_to_block_size,
|
truncate_or_pad,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -194,7 +195,7 @@ def build_data_iterator(args, tokenizer):
|
|||||||
|
|
||||||
|
|
||||||
def load_and_cache_examples(args, tokenizer):
|
def load_and_cache_examples(args, tokenizer):
|
||||||
dataset = SummarizationDataset(args.documents_dir)
|
dataset = CNNDMDataset(args.documents_dir)
|
||||||
return dataset
|
return dataset
|
||||||
|
|
||||||
|
|
||||||
@@ -211,7 +212,7 @@ def collate(data, tokenizer, block_size, device):
|
|||||||
|
|
||||||
encoded_text = [encode_for_summarization(story, summary, tokenizer) for _, story, summary in data]
|
encoded_text = [encode_for_summarization(story, summary, tokenizer) for _, story, summary in data]
|
||||||
encoded_stories = torch.tensor(
|
encoded_stories = torch.tensor(
|
||||||
[fit_to_block_size(story, block_size, tokenizer.pad_token_id) for story, _ in encoded_text]
|
[truncate_or_pad(story, block_size, tokenizer.pad_token_id) for story, _ in encoded_text]
|
||||||
)
|
)
|
||||||
encoder_token_type_ids = compute_token_type_ids(encoded_stories, tokenizer.cls_token_id)
|
encoder_token_type_ids = compute_token_type_ids(encoded_stories, tokenizer.cls_token_id)
|
||||||
encoder_mask = build_mask(encoded_stories, tokenizer.pad_token_id)
|
encoder_mask = build_mask(encoded_stories, tokenizer.pad_token_id)
|
||||||
@@ -17,7 +17,7 @@ import unittest
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import torch
|
import torch
|
||||||
|
|
||||||
from utils_summarization import build_mask, compute_token_type_ids, fit_to_block_size, process_story
|
from .utils_summarization import build_mask, compute_token_type_ids, process_story, truncate_or_pad
|
||||||
|
|
||||||
|
|
||||||
class SummarizationDataProcessingTest(unittest.TestCase):
|
class SummarizationDataProcessingTest(unittest.TestCase):
|
||||||
@@ -28,19 +28,19 @@ class SummarizationDataProcessingTest(unittest.TestCase):
|
|||||||
""" Pad the sequence with 0 if the sequence is smaller than the block size."""
|
""" Pad the sequence with 0 if the sequence is smaller than the block size."""
|
||||||
sequence = [1, 2, 3, 4]
|
sequence = [1, 2, 3, 4]
|
||||||
expected_output = [1, 2, 3, 4, 0, 0, 0, 0, 0, 0]
|
expected_output = [1, 2, 3, 4, 0, 0, 0, 0, 0, 0]
|
||||||
self.assertEqual(fit_to_block_size(sequence, self.block_size, 0), expected_output)
|
self.assertEqual(truncate_or_pad(sequence, self.block_size, 0), expected_output)
|
||||||
|
|
||||||
def test_fit_to_block_sequence_fit_exactly(self):
|
def test_fit_to_block_sequence_fit_exactly(self):
|
||||||
""" Do nothing if the sequence is the right size. """
|
""" Do nothing if the sequence is the right size. """
|
||||||
sequence = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
sequence = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||||
expected_output = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
expected_output = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||||
self.assertEqual(fit_to_block_size(sequence, self.block_size, 0), expected_output)
|
self.assertEqual(truncate_or_pad(sequence, self.block_size, 0), expected_output)
|
||||||
|
|
||||||
def test_fit_to_block_sequence_too_big(self):
|
def test_fit_to_block_sequence_too_big(self):
|
||||||
""" Truncate the sequence if it is too long. """
|
""" Truncate the sequence if it is too long. """
|
||||||
sequence = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
|
sequence = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
|
||||||
expected_output = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
expected_output = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||||
self.assertEqual(fit_to_block_size(sequence, self.block_size, 0), expected_output)
|
self.assertEqual(truncate_or_pad(sequence, self.block_size, 0), expected_output)
|
||||||
|
|
||||||
def test_process_story_no_highlights(self):
|
def test_process_story_no_highlights(self):
|
||||||
""" Processing a story with no highlights returns an empty list for the summary.
|
""" Processing a story with no highlights returns an empty list for the summary.
|
||||||
@@ -10,7 +10,7 @@ from torch.utils.data import Dataset
|
|||||||
# ------------
|
# ------------
|
||||||
|
|
||||||
|
|
||||||
class SummarizationDataset(Dataset):
|
class CNNDMDataset(Dataset):
|
||||||
""" Abstracts the dataset used to train seq2seq models.
|
""" Abstracts the dataset used to train seq2seq models.
|
||||||
|
|
||||||
The class will process the documents that are located in the specified
|
The class will process the documents that are located in the specified
|
||||||
@@ -62,11 +62,11 @@ class SummarizationDataset(Dataset):
|
|||||||
def process_story(raw_story):
|
def process_story(raw_story):
|
||||||
""" Extract the story and summary from a story file.
|
""" Extract the story and summary from a story file.
|
||||||
|
|
||||||
Attributes:
|
Arguments:
|
||||||
raw_story (str): content of the story file as an utf-8 encoded string.
|
raw_story (str): content of the story file as an utf-8 encoded string.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
IndexError: If the stoy is empty or contains no highlights.
|
IndexError: If the story is empty or contains no highlights.
|
||||||
"""
|
"""
|
||||||
nonempty_lines = list(filter(lambda x: len(x) != 0, [line.strip() for line in raw_story.split("\n")]))
|
nonempty_lines = list(filter(lambda x: len(x) != 0, [line.strip() for line in raw_story.split("\n")]))
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ def _add_missing_period(line):
|
|||||||
# --------------------------
|
# --------------------------
|
||||||
|
|
||||||
|
|
||||||
def fit_to_block_size(sequence, block_size, pad_token_id):
|
def truncate_or_pad(sequence, block_size, pad_token_id):
|
||||||
""" Adapt the source and target sequences' lengths to the block size.
|
""" Adapt the source and target sequences' lengths to the block size.
|
||||||
If the sequence is shorter we append padding token to the right of the sequence.
|
If the sequence is shorter we append padding token to the right of the sequence.
|
||||||
"""
|
"""
|
||||||
18
model_cards/DeepPavlov/bert-base-bg-cs-pl-ru-cased/README.md
Normal file
18
model_cards/DeepPavlov/bert-base-bg-cs-pl-ru-cased/README.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
language:
|
||||||
|
- bulgarian
|
||||||
|
- czech
|
||||||
|
- polish
|
||||||
|
- russian
|
||||||
|
---
|
||||||
|
|
||||||
|
# bert-base-bg-cs-pl-ru-cased
|
||||||
|
|
||||||
|
SlavicBERT\[1\] \(Slavic \(bg, cs, pl, ru\), cased, 12-layer, 768-hidden, 12-heads, 180M parameters\) was trained
|
||||||
|
on Russian News and four Wikipedias: Bulgarian, Czech, Polish, and Russian.
|
||||||
|
Subtoken vocabulary was built using this data. Multilingual BERT was used as an initialization for SlavicBERT.
|
||||||
|
|
||||||
|
|
||||||
|
\[1\]: Arkhipov M., Trofimova M., Kuratov Y., Sorokin A. \(2019\).
|
||||||
|
[Tuning Multilingual Transformers for Language-Specific Named Entity Recognition](https://www.aclweb.org/anthology/W19-3712/).
|
||||||
|
ACL anthology W19-3712.
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
---
|
||||||
|
language:
|
||||||
|
- english
|
||||||
|
---
|
||||||
|
|
||||||
|
# bert-base-cased-conversational
|
||||||
|
|
||||||
|
Conversational BERT \(English, cased, 12-layer, 768-hidden, 12-heads, 110M parameters\) was trained
|
||||||
|
on the English part of Twitter, Reddit, DailyDialogues\[1\], OpenSubtitles\[2\], Debates\[3\], Blogs\[4\],
|
||||||
|
Facebook News Comments. We used this training data to build the vocabulary of English subtokens and took
|
||||||
|
English cased version of BERT-base as an initialization for English Conversational BERT.
|
||||||
|
|
||||||
|
|
||||||
|
\[1\]: Yanran Li, Hui Su, Xiaoyu Shen, Wenjie Li, Ziqiang Cao, and Shuzi Niu. DailyDialog: A Manually Labelled
|
||||||
|
Multi-turn Dialogue Dataset. IJCNLP 2017.
|
||||||
|
|
||||||
|
\[2\]: P. Lison and J. Tiedemann, 2016, OpenSubtitles2016: Extracting Large Parallel Corpora from Movie and TV Subtitles.
|
||||||
|
In Proceedings of the 10th International Conference on Language Resources and Evaluation \(LREC 2016\)
|
||||||
|
|
||||||
|
\[3\]: Justine Zhang, Ravi Kumar, Sujith Ravi, Cristian Danescu-Niculescu-Mizil. Proceedings of NAACL, 2016.
|
||||||
|
|
||||||
|
\[4\]: J. Schler, M. Koppel, S. Argamon and J. Pennebaker \(2006\). Effects of Age and Gender on Blogging
|
||||||
|
in Proceedings of 2006 AAAI Spring Symposium on Computational Approaches for Analyzing Weblogs.
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
language:
|
||||||
|
- multilingual
|
||||||
|
---
|
||||||
|
|
||||||
|
# bert-base-multilingual-cased-sentence
|
||||||
|
|
||||||
|
Sentence Multilingual BERT \(101 languages, cased, 12-layer, 768-hidden, 12-heads, 180M parameters\)
|
||||||
|
is a representation-based sentence encoder for 101 languages of Multilingual BERT.
|
||||||
|
It is initialized with Multilingual BERT and then fine-tuned on english MultiNLI\[1\] and on dev set
|
||||||
|
of multilingual XNLI\[2\].
|
||||||
|
Sentence representations are mean pooled token embeddings in the same manner as in Sentence-BERT\[3\].
|
||||||
|
|
||||||
|
|
||||||
|
\[1\]: Williams A., Nangia N. & Bowman S. \(2017\) A Broad-Coverage Challenge Corpus for Sentence Understanding
|
||||||
|
through Inference. arXiv preprint [arXiv:1704.05426](https://arxiv.org/abs/1704.05426)
|
||||||
|
|
||||||
|
\[2\]: Williams A., Bowman S. \(2018\) XNLI: Evaluating Cross-lingual Sentence Representations.
|
||||||
|
arXiv preprint [arXiv:1809.05053](https://arxiv.org/abs/1809.05053)
|
||||||
|
|
||||||
|
\[3\]: N. Reimers, I. Gurevych \(2019\) Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks.
|
||||||
|
arXiv preprint [arXiv:1908.10084](https://arxiv.org/abs/1908.10084)
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
language:
|
||||||
|
- russian
|
||||||
|
---
|
||||||
|
|
||||||
|
# rubert-base-cased-conversational
|
||||||
|
|
||||||
|
Conversational RuBERT \(Russian, cased, 12-layer, 768-hidden, 12-heads, 180M parameters\) was trained
|
||||||
|
on OpenSubtitles\[1\], [Dirty](https://d3.ru/), [Pikabu](https://pikabu.ru/),
|
||||||
|
and a Social Media segment of Taiga corpus\[2\]. We assembled a new vocabulary for Conversational RuBERT model
|
||||||
|
on this data and initialized the model with [RuBERT](../rubert-base-cased).
|
||||||
|
|
||||||
|
|
||||||
|
\[1\]: P. Lison and J. Tiedemann, 2016, OpenSubtitles2016: Extracting Large Parallel Corpora from Movie and TV Subtitles.
|
||||||
|
In Proceedings of the 10th International Conference on Language Resources and Evaluation \(LREC 2016\)
|
||||||
|
|
||||||
|
\[2\]: Shavrina T., Shapovalova O. \(2017\) TO THE METHODOLOGY OF CORPUS CONSTRUCTION FOR MACHINE LEARNING:
|
||||||
|
«TAIGA» SYNTAX TREE CORPUS AND PARSER. in proc. of “CORPORA2017”, international conference , Saint-Petersbourg, 2017.
|
||||||
21
model_cards/DeepPavlov/rubert-base-cased-sentence/README.md
Normal file
21
model_cards/DeepPavlov/rubert-base-cased-sentence/README.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
language:
|
||||||
|
- russian
|
||||||
|
---
|
||||||
|
|
||||||
|
# rubert-base-cased-sentence
|
||||||
|
|
||||||
|
Sentence RuBERT \(Russian, cased, 12-layer, 768-hidden, 12-heads, 180M parameters\)
|
||||||
|
is a representation-based sentence encoder for Russian. It is initialized with RuBERT and fine-tuned on SNLI\[1\]
|
||||||
|
google-translated to russian and on russian part of XNLI dev set\[2\]. Sentence representations are mean pooled
|
||||||
|
token embeddings in the same manner as in Sentence-BERT\[3\].
|
||||||
|
|
||||||
|
|
||||||
|
\[1\]: S. R. Bowman, G. Angeli, C. Potts, and C. D. Manning. \(2015\) A large annotated corpus for learning
|
||||||
|
natural language inference. arXiv preprint [arXiv:1508.05326](https://arxiv.org/abs/1508.05326)
|
||||||
|
|
||||||
|
\[2\]: Williams A., Bowman S. \(2018\) XNLI: Evaluating Cross-lingual Sentence Representations.
|
||||||
|
arXiv preprint [arXiv:1809.05053](https://arxiv.org/abs/1809.05053)
|
||||||
|
|
||||||
|
\[3\]: N. Reimers, I. Gurevych \(2019\) Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks.
|
||||||
|
arXiv preprint [arXiv:1908.10084](https://arxiv.org/abs/1908.10084)
|
||||||
14
model_cards/DeepPavlov/rubert-base-cased/README.md
Normal file
14
model_cards/DeepPavlov/rubert-base-cased/README.md
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
language:
|
||||||
|
- russian
|
||||||
|
---
|
||||||
|
|
||||||
|
# rubert-base-cased
|
||||||
|
|
||||||
|
RuBERT \(Russian, cased, 12-layer, 768-hidden, 12-heads, 180M parameters\) was trained on the Russian part of Wikipedia
|
||||||
|
and news data. We used this training data to build a vocabulary of Russian subtokens and took a multilingual version
|
||||||
|
of BERT-base as an initialization for RuBERT\[1\].
|
||||||
|
|
||||||
|
|
||||||
|
\[1\]: Kuratov, Y., Arkhipov, M. \(2019\). Adaptation of Deep Bidirectional Multilingual Transformers for Russian Language.
|
||||||
|
arXiv preprint [arXiv:1905.07213](https://arxiv.org/abs/1905.07213).
|
||||||
48
model_cards/asafaya/bert-base-arabic/README.md
Normal file
48
model_cards/asafaya/bert-base-arabic/README.md
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
---
|
||||||
|
language: arabic
|
||||||
|
---
|
||||||
|
|
||||||
|
# Arabic BERT Model
|
||||||
|
|
||||||
|
Pretrained BERT base language model for Arabic
|
||||||
|
|
||||||
|
## Pretraining Corpus
|
||||||
|
|
||||||
|
`arabic-bert-base` model was pretrained on ~8.2 Billion words:
|
||||||
|
|
||||||
|
- Arabic version of [OSCAR](https://traces1.inria.fr/oscar/) - filtered from [Common Crawl](http://commoncrawl.org/)
|
||||||
|
- Recent dump of Arabic [Wikipedia](https://dumps.wikimedia.org/backup-index.html)
|
||||||
|
|
||||||
|
and other Arabic resources which sum up to ~95GB of text.
|
||||||
|
|
||||||
|
__Notes on training data:__
|
||||||
|
|
||||||
|
- Our final version of corpus contains some non-Arabic words inlines, which we did not remove from sentences since that would affect some tasks like NER.
|
||||||
|
- Although non-Arabic characters were lowered as a preprocessing step, since Arabic characters does not have upper or lower case, there is no cased and uncased version of the model.
|
||||||
|
- The corpus and vocabulary set are not restricted to Modern Standard Arabic, they contain some dialectical Arabic too.
|
||||||
|
|
||||||
|
## Pretraining details
|
||||||
|
|
||||||
|
- This model was trained using Google BERT's github [repository](https://github.com/google-research/bert) on a single TPU v3-8 provided for free from [TFRC](https://www.tensorflow.org/tfrc).
|
||||||
|
- Our pretraining procedure follows training settings of bert with some changes: trained for 3M training steps with batchsize of 128, instead of 1M with batchsize of 256.
|
||||||
|
|
||||||
|
## Load Pretrained Model
|
||||||
|
|
||||||
|
You can use this model by installing `torch` or `tensorflow` and Huggingface library `transformers`. And you can use it directly by initializing it like this:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from transformers import AutoTokenizer, AutoModel
|
||||||
|
|
||||||
|
tokenizer = AutoTokenizer.from_pretrained("asafaya/bert-base-arabic")
|
||||||
|
model = AutoModel.from_pretrained("asafaya/bert-base-arabic")
|
||||||
|
```
|
||||||
|
|
||||||
|
## Results
|
||||||
|
|
||||||
|
For further details on the models performance or any other queries, please refer to [Arabic-BERT](https://github.com/alisafaya/Arabic-BERT)
|
||||||
|
|
||||||
|
## Acknowledgement
|
||||||
|
|
||||||
|
Thanks to Google for providing free TPU for the training process and for Huggingface for hosting this model on their servers 😊
|
||||||
|
|
||||||
|
|
||||||
93
model_cards/aubmindlab/bert-base-arabert/README.md
Normal file
93
model_cards/aubmindlab/bert-base-arabert/README.md
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
---
|
||||||
|
language: arabic
|
||||||
|
---
|
||||||
|
|
||||||
|
# AraBERT : Pre-training BERT for Arabic Language Understanding
|
||||||
|
|
||||||
|
**AraBERT** is an Arabic pretrained lanaguage model based on [Google's BERT architechture](https://github.com/google-research/bert). AraBERT uses the same BERT-Base config.
|
||||||
|
|
||||||
|
There are two version off the model AraBERTv0.1 and AraBERTv1, with the difference being that AraBERTv1 uses pre-segmented text where prefixes and suffixes were splitted using the [Farasa Segmenter](http://alt.qcri.org/farasa/segmenter.html).
|
||||||
|
|
||||||
|
The model was trained on ~70M sentences or ~23GB of Arabic text with ~3B words. The training corpora are a collection of publically available large scale raw arabic text ([Arabic Wikidumps](https://archive.org/details/arwiki-20190201), [The 1.5B words Arabic Corpus](https://www.semanticscholar.org/paper/1.5-billion-words-Arabic-Corpus-El-Khair/f3eeef4afb81223df96575adadf808fe7fe440b4), [The OSIAN Corpus](https://www.aclweb.org/anthology/W19-4619), Assafir news articles, and 4 other manually crawled news websites (Al-Akhbar, Annahar, AL-Ahram, AL-Wafd) from [the Wayback Machine](http://web.archive.org/))
|
||||||
|
|
||||||
|
We evalaute both AraBERT models on different downstream tasks and compare it to [mBERT]((https://github.com/google-research/bert/blob/master/multilingual.md)), and other state of the art models (*To the extent of our knowledge*). The Tasks were Sentiment Analysis on 6 different datasets ([HARD](https://github.com/elnagara/HARD-Arabic-Dataset), [ASTD-Balanced](https://www.aclweb.org/anthology/D15-1299), [ArsenTD-Lev](https://staff.aub.edu.lb/~we07/Publications/ArSentD-LEV_Sentiment_Corpus.pdf), [LABR](https://github.com/mohamedadaly/LABR), [ArSaS](http://lrec-conf.org/workshops/lrec2018/W30/pdf/22_W30.pdf)), Named Entity Recognition with the [ANERcorp](http://curtis.ml.cmu.edu/w/courses/index.php/ANERcorp), and Arabic Question Answering on [Arabic-SQuAD and ARCD](https://github.com/husseinmozannar/SOQAL)
|
||||||
|
|
||||||
|
## Results (Acc.)
|
||||||
|
Task | prev. SOTA | mBERT | AraBERTv0.1 | AraBERTv1
|
||||||
|
---|:---:|:---:|:---:|:---:
|
||||||
|
HARD |95.7 [ElJundi et.al.](https://www.aclweb.org/anthology/W19-4608/)|95.7|96.2|96.1
|
||||||
|
ASTD |86.5 [ElJundi et.al.](https://www.aclweb.org/anthology/W19-4608/)| 80.1|92.2|92.6
|
||||||
|
ArsenTD-Lev|52.4 [ElJundi et.al.](https://www.aclweb.org/anthology/W19-4608/)|51|58.9|59.4
|
||||||
|
AJGT|93 [Dahou et.al.](https://dl.acm.org/doi/fullHtml/10.1145/3314941)| 83.6|94.1|93.8
|
||||||
|
LABR|87.5 [Dahou et.al.](https://dl.acm.org/doi/fullHtml/10.1145/3314941)|83|85.9|86.7
|
||||||
|
ANERcorp|81.7 (BiLSTM-CRF)|78.4|84.2|81.9
|
||||||
|
ARCD|mBERT|EM:34.2 F1: 61.3|EM:30.1 F1:61.2|EM:30.6 F1: 62.7
|
||||||
|
|
||||||
|
*We would be extremly thankful if everyone can contibute to the Results table by adding more scores on different datasets*
|
||||||
|
|
||||||
|
## How to use
|
||||||
|
|
||||||
|
You can easily use AraBERT since it is almost fully compatible with existing codebases (You can use this repo instead of the official BERT one, the only difference is in the ```tokenization.py``` file where we modify the _is_punctuation function to make it compatible with the "+" symbol and the "[" and "]" characters)
|
||||||
|
|
||||||
|
To use HuggingFace's Transformer repository you only need to provide a lost of token that forces the model to not split them, also make sure that the text is pre-segmented:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from transformers import AutoTokenizer
|
||||||
|
from preprocess_arabert import never_split_tokens
|
||||||
|
|
||||||
|
arabert_tokenizer = AutoTokenizer.from_pretrained(
|
||||||
|
"aubmindlab/bert-base-arabert",
|
||||||
|
do_lower_case=False,
|
||||||
|
do_basic_tokenize=True,
|
||||||
|
never_split=never_split_tokens)
|
||||||
|
arabert_model = AutoModel.from_pretrained("aubmindlab/bert-base-arabert")
|
||||||
|
|
||||||
|
arabert_tokenizer.tokenize("و+ لن نبالغ إذا قل +نا إن هاتف أو كمبيوتر ال+ مكتب في زمن +نا هذا ضروري")
|
||||||
|
|
||||||
|
>>> ['و+', 'لن', 'نبال', '##غ', 'إذا', 'قل', '+نا', 'إن', 'هاتف', 'أو', 'كمبيوتر', 'ال+', 'مكتب', 'في', 'زمن', '+نا', 'هذا', 'ضروري']
|
||||||
|
```
|
||||||
|
|
||||||
|
**AraBERTv0.1 is compatible with all existing libraries, since it needs no pre-segmentation.**
|
||||||
|
```python
|
||||||
|
from transformers import AutoTokenizer
|
||||||
|
from preprocess_arabert import never_split_tokens
|
||||||
|
|
||||||
|
arabert_tokenizer = AutoTokenizer.from_pretrained("aubmindlab/bert-base-arabertv01",do_lower_case=False)
|
||||||
|
arabert_model = AutoModel.from_pretrained("aubmindlab/bert-base-arabertv01")
|
||||||
|
|
||||||
|
arabert_tokenizer.tokenize("ولن نبالغ إذا قلنا إن هاتف أو كمبيوتر المكتب في زمننا هذا ضروري")
|
||||||
|
|
||||||
|
>>> ['ولن', 'ن', '##بالغ', 'إذا', 'قلنا', 'إن', 'هاتف', 'أو', 'كمبيوتر', 'المكتب', 'في', 'زمن', '##ن', '##ا', 'هذا', 'ضروري']
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
The ```araBERT_(initial_Demo_TF)_.ipynb``` Notebook is a small demo using the AJGT dataset using TensorFlow (GPU and TPU compatible).
|
||||||
|
|
||||||
|
## Model Weights and Vocab Download
|
||||||
|
Models | AraBERTv0.1 | AraBERTv1
|
||||||
|
---|:---:|:---:
|
||||||
|
TensorFlow|[Drive Link](https://drive.google.com/open?id=1-kVmTUZZ4DP2rzeHNjTPkY8OjnQCpomO) | [Drive Link](https://drive.google.com/open?id=1-d7-9ljKgDJP5mx73uBtio-TuUZCqZnt)
|
||||||
|
PyTorch| [Drive_Link](https://drive.google.com/open?id=1-_3te42mQCPD8SxwZ3l-VBL7yaJH-IOv)| [Drive_Link](https://drive.google.com/open?id=1-69s6Pxqbi63HOQ1M9wTcr-Ovc6PWLLo)
|
||||||
|
|
||||||
|
**You can find the PyTorch models in HuggingFace's Transformer Library under the ```aubmindlab``` username**
|
||||||
|
|
||||||
|
## If you used this model please cite us as:
|
||||||
|
```
|
||||||
|
@misc{antoun2020arabert,
|
||||||
|
title={AraBERT: Transformer-based Model for Arabic Language Understanding},
|
||||||
|
author={Wissam Antoun and Fady Baly and Hazem Hajj},
|
||||||
|
year={2020},
|
||||||
|
eprint={2003.00104},
|
||||||
|
archivePrefix={arXiv},
|
||||||
|
primaryClass={cs.CL}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
## Acknowledgments
|
||||||
|
Thanks to TensorFlow Research Cloud (TFRC) for the free access to Cloud TPUs, couldn't have done it without this program, and to the [AUB MIND Lab](https://sites.aub.edu.lb/mindlab/) Members for the continous support. Also thanks to [Yakshof](https://www.yakshof.com/#/) and Assafir for data and storage access.
|
||||||
|
|
||||||
|
## Contacts
|
||||||
|
**Wissam Antoun**: [Linkedin](https://www.linkedin.com/in/giulio-ravasio-3a81a9110/) | [Twitter](https://twitter.com/wissam_antoun) | [Github](https://github.com/WissamAntoun) | <wfa07@mail.aub.edu> | <wissam.antoun@gmail.com>
|
||||||
|
|
||||||
|
**Fady Baly**: [Linkedin](https://www.linkedin.com/in/fadybaly/) | [Twitter](https://twitter.com/BalyFady) | [Github](https://github.com/fadybaly) | <fgb06@mail.aub.edu> | <baly.fady@gmail.com>
|
||||||
|
|
||||||
|
***We are looking for sponsors to train BERT-Large and other Transformer models, the sponsor only needs to cover to data storage and compute cost of the generating the pretraining data***
|
||||||
93
model_cards/aubmindlab/bert-base-arabertv01/README.md
Normal file
93
model_cards/aubmindlab/bert-base-arabertv01/README.md
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
---
|
||||||
|
language: arabic
|
||||||
|
---
|
||||||
|
|
||||||
|
# AraBERT : Pre-training BERT for Arabic Language Understanding
|
||||||
|
|
||||||
|
**AraBERT** is an Arabic pretrained lanaguage model based on [Google's BERT architechture](https://github.com/google-research/bert). AraBERT uses the same BERT-Base config.
|
||||||
|
|
||||||
|
There are two version off the model AraBERTv0.1 and AraBERTv1, with the difference being that AraBERTv1 uses pre-segmented text where prefixes and suffixes were splitted using the [Farasa Segmenter](http://alt.qcri.org/farasa/segmenter.html).
|
||||||
|
|
||||||
|
The model was trained on ~70M sentences or ~23GB of Arabic text with ~3B words. The training corpora are a collection of publically available large scale raw arabic text ([Arabic Wikidumps](https://archive.org/details/arwiki-20190201), [The 1.5B words Arabic Corpus](https://www.semanticscholar.org/paper/1.5-billion-words-Arabic-Corpus-El-Khair/f3eeef4afb81223df96575adadf808fe7fe440b4), [The OSIAN Corpus](https://www.aclweb.org/anthology/W19-4619), Assafir news articles, and 4 other manually crawled news websites (Al-Akhbar, Annahar, AL-Ahram, AL-Wafd) from [the Wayback Machine](http://web.archive.org/))
|
||||||
|
|
||||||
|
We evalaute both AraBERT models on different downstream tasks and compare it to [mBERT]((https://github.com/google-research/bert/blob/master/multilingual.md)), and other state of the art models (*To the extent of our knowledge*). The Tasks were Sentiment Analysis on 6 different datasets ([HARD](https://github.com/elnagara/HARD-Arabic-Dataset), [ASTD-Balanced](https://www.aclweb.org/anthology/D15-1299), [ArsenTD-Lev](https://staff.aub.edu.lb/~we07/Publications/ArSentD-LEV_Sentiment_Corpus.pdf), [LABR](https://github.com/mohamedadaly/LABR), [ArSaS](http://lrec-conf.org/workshops/lrec2018/W30/pdf/22_W30.pdf)), Named Entity Recognition with the [ANERcorp](http://curtis.ml.cmu.edu/w/courses/index.php/ANERcorp), and Arabic Question Answering on [Arabic-SQuAD and ARCD](https://github.com/husseinmozannar/SOQAL)
|
||||||
|
|
||||||
|
## Results (Acc.)
|
||||||
|
Task | prev. SOTA | mBERT | AraBERTv0.1 | AraBERTv1
|
||||||
|
---|:---:|:---:|:---:|:---:
|
||||||
|
HARD |95.7 [ElJundi et.al.](https://www.aclweb.org/anthology/W19-4608/)|95.7|96.2|96.1
|
||||||
|
ASTD |86.5 [ElJundi et.al.](https://www.aclweb.org/anthology/W19-4608/)| 80.1|92.2|92.6
|
||||||
|
ArsenTD-Lev|52.4 [ElJundi et.al.](https://www.aclweb.org/anthology/W19-4608/)|51|58.9|59.4
|
||||||
|
AJGT|93 [Dahou et.al.](https://dl.acm.org/doi/fullHtml/10.1145/3314941)| 83.6|94.1|93.8
|
||||||
|
LABR|87.5 [Dahou et.al.](https://dl.acm.org/doi/fullHtml/10.1145/3314941)|83|85.9|86.7
|
||||||
|
ANERcorp|81.7 (BiLSTM-CRF)|78.4|84.2|81.9
|
||||||
|
ARCD|mBERT|EM:34.2 F1: 61.3|EM:30.1 F1:61.2|EM:30.6 F1: 62.7
|
||||||
|
|
||||||
|
*We would be extremly thankful if everyone can contibute to the Results table by adding more scores on different datasets*
|
||||||
|
|
||||||
|
## How to use
|
||||||
|
|
||||||
|
You can easily use AraBERT since it is almost fully compatible with existing codebases (You can use this repo instead of the official BERT one, the only difference is in the ```tokenization.py``` file where we modify the _is_punctuation function to make it compatible with the "+" symbol and the "[" and "]" characters)
|
||||||
|
|
||||||
|
To use HuggingFace's Transformer repository you only need to provide a lost of token that forces the model to not split them, also make sure that the text is pre-segmented:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from transformers import AutoTokenizer
|
||||||
|
from preprocess_arabert import never_split_tokens
|
||||||
|
|
||||||
|
arabert_tokenizer = AutoTokenizer.from_pretrained(
|
||||||
|
"aubmindlab/bert-base-arabert",
|
||||||
|
do_lower_case=False,
|
||||||
|
do_basic_tokenize=True,
|
||||||
|
never_split=never_split_tokens)
|
||||||
|
arabert_model = AutoModel.from_pretrained("aubmindlab/bert-base-arabert")
|
||||||
|
|
||||||
|
arabert_tokenizer.tokenize("و+ لن نبالغ إذا قل +نا إن هاتف أو كمبيوتر ال+ مكتب في زمن +نا هذا ضروري")
|
||||||
|
|
||||||
|
>>> ['و+', 'لن', 'نبال', '##غ', 'إذا', 'قل', '+نا', 'إن', 'هاتف', 'أو', 'كمبيوتر', 'ال+', 'مكتب', 'في', 'زمن', '+نا', 'هذا', 'ضروري']
|
||||||
|
```
|
||||||
|
|
||||||
|
**AraBERTv0.1 is compatible with all existing libraries, since it needs no pre-segmentation.**
|
||||||
|
```python
|
||||||
|
from transformers import AutoTokenizer
|
||||||
|
from preprocess_arabert import never_split_tokens
|
||||||
|
|
||||||
|
arabert_tokenizer = AutoTokenizer.from_pretrained("aubmindlab/bert-base-arabertv01",do_lower_case=False)
|
||||||
|
arabert_model = AutoModel.from_pretrained("aubmindlab/bert-base-arabertv01")
|
||||||
|
|
||||||
|
arabert_tokenizer.tokenize("ولن نبالغ إذا قلنا إن هاتف أو كمبيوتر المكتب في زمننا هذا ضروري")
|
||||||
|
|
||||||
|
>>> ['ولن', 'ن', '##بالغ', 'إذا', 'قلنا', 'إن', 'هاتف', 'أو', 'كمبيوتر', 'المكتب', 'في', 'زمن', '##ن', '##ا', 'هذا', 'ضروري']
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
The ```araBERT_(initial_Demo_TF)_.ipynb``` Notebook is a small demo using the AJGT dataset using TensorFlow (GPU and TPU compatible).
|
||||||
|
|
||||||
|
## Model Weights and Vocab Download
|
||||||
|
Models | AraBERTv0.1 | AraBERTv1
|
||||||
|
---|:---:|:---:
|
||||||
|
TensorFlow|[Drive Link](https://drive.google.com/open?id=1-kVmTUZZ4DP2rzeHNjTPkY8OjnQCpomO) | [Drive Link](https://drive.google.com/open?id=1-d7-9ljKgDJP5mx73uBtio-TuUZCqZnt)
|
||||||
|
PyTorch| [Drive_Link](https://drive.google.com/open?id=1-_3te42mQCPD8SxwZ3l-VBL7yaJH-IOv)| [Drive_Link](https://drive.google.com/open?id=1-69s6Pxqbi63HOQ1M9wTcr-Ovc6PWLLo)
|
||||||
|
|
||||||
|
**You can find the PyTorch models in HuggingFace's Transformer Library under the ```aubmindlab``` username**
|
||||||
|
|
||||||
|
## If you used this model please cite us as:
|
||||||
|
```
|
||||||
|
@misc{antoun2020arabert,
|
||||||
|
title={AraBERT: Transformer-based Model for Arabic Language Understanding},
|
||||||
|
author={Wissam Antoun and Fady Baly and Hazem Hajj},
|
||||||
|
year={2020},
|
||||||
|
eprint={2003.00104},
|
||||||
|
archivePrefix={arXiv},
|
||||||
|
primaryClass={cs.CL}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
## Acknowledgments
|
||||||
|
Thanks to TensorFlow Research Cloud (TFRC) for the free access to Cloud TPUs, couldn't have done it without this program, and to the [AUB MIND Lab](https://sites.aub.edu.lb/mindlab/) Members for the continous support. Also thanks to [Yakshof](https://www.yakshof.com/#/) and Assafir for data and storage access.
|
||||||
|
|
||||||
|
## Contacts
|
||||||
|
**Wissam Antoun**: [Linkedin](https://www.linkedin.com/in/giulio-ravasio-3a81a9110/) | [Twitter](https://twitter.com/wissam_antoun) | [Github](https://github.com/WissamAntoun) | <wfa07@mail.aub.edu> | <wissam.antoun@gmail.com>
|
||||||
|
|
||||||
|
**Fady Baly**: [Linkedin](https://www.linkedin.com/in/fadybaly/) | [Twitter](https://twitter.com/BalyFady) | [Github](https://github.com/fadybaly) | <fgb06@mail.aub.edu> | <baly.fady@gmail.com>
|
||||||
|
|
||||||
|
***We are looking for sponsors to train BERT-Large and other Transformer models, the sponsor only needs to cover to data storage and compute cost of the generating the pretraining data***
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Slavic BERT from https://github.com/deepmipt/Slavic-BERT-NER http://files.deeppavlov.ai/deeppavlov_data/bg_cs_pl_ru_cased_L-12_H-768_A-12.tar.gz
|
||||||
49
model_cards/fmikaelian/camembert-base-fquad/README.md
Normal file
49
model_cards/fmikaelian/camembert-base-fquad/README.md
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
---
|
||||||
|
language: french
|
||||||
|
---
|
||||||
|
|
||||||
|
# camembert-base-fquad
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
A baseline model for question-answering in french ([CamemBERT](https://camembert-model.fr/) model fine-tuned on [FQuAD](https://fquad.illuin.tech/))
|
||||||
|
|
||||||
|
## Training hyperparameters
|
||||||
|
|
||||||
|
```shell
|
||||||
|
python3 ./examples/run_squad.py \
|
||||||
|
--model_type camembert \
|
||||||
|
--model_name_or_path camembert-base \
|
||||||
|
--do_train \
|
||||||
|
--do_eval \
|
||||||
|
--do_lower_case \
|
||||||
|
--train_file train.json \
|
||||||
|
--predict_file valid.json \
|
||||||
|
--learning_rate 3e-5 \
|
||||||
|
--num_train_epochs 2 \
|
||||||
|
--max_seq_length 384 \
|
||||||
|
--doc_stride 128 \
|
||||||
|
--output_dir output \
|
||||||
|
--per_gpu_eval_batch_size=3 \
|
||||||
|
--per_gpu_train_batch_size=3 \
|
||||||
|
--save_steps 10000
|
||||||
|
```
|
||||||
|
|
||||||
|
## Evaluation results
|
||||||
|
|
||||||
|
```shell
|
||||||
|
{"f1": 77.24515316052342, "exact_match": 52.82308657465496}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```python
|
||||||
|
from transformers import pipeline
|
||||||
|
|
||||||
|
nlp = pipeline('question-answering', model='fmikaelian/camembert-base-fquad', tokenizer='fmikaelian/camembert-base-fquad')
|
||||||
|
|
||||||
|
nlp({
|
||||||
|
'question': "Qui est Claude Monet?",
|
||||||
|
'context': "Claude Monet, né le 14 novembre 1840 à Paris et mort le 5 décembre 1926 à Giverny, est un peintre français et l’un des fondateurs de l'impressionnisme."
|
||||||
|
})
|
||||||
|
```
|
||||||
49
model_cards/fmikaelian/camembert-base-squad/README.md
Normal file
49
model_cards/fmikaelian/camembert-base-squad/README.md
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
---
|
||||||
|
language: french
|
||||||
|
---
|
||||||
|
|
||||||
|
# camembert-base-squad
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
A baseline model for question-answering in french ([CamemBERT](https://camembert-model.fr/) model fine-tuned on [french-translated SQuAD 1.1 dataset](https://github.com/Alikabbadj/French-SQuAD))
|
||||||
|
|
||||||
|
## Training hyperparameters
|
||||||
|
|
||||||
|
```shell
|
||||||
|
python3 ./examples/run_squad.py \
|
||||||
|
--model_type camembert \
|
||||||
|
--model_name_or_path camembert-base \
|
||||||
|
--do_train \
|
||||||
|
--do_eval \
|
||||||
|
--do_lower_case \
|
||||||
|
--train_file SQuAD-v1.1-train_fr_ss999_awstart2_net.json \
|
||||||
|
--predict_file SQuAD-v1.1-dev_fr_ss999_awstart2_net.json \
|
||||||
|
--learning_rate 3e-5 \
|
||||||
|
--num_train_epochs 2 \
|
||||||
|
--max_seq_length 384 \
|
||||||
|
--doc_stride 128 \
|
||||||
|
--output_dir output3 \
|
||||||
|
--per_gpu_eval_batch_size=3 \
|
||||||
|
--per_gpu_train_batch_size=3 \
|
||||||
|
--save_steps 10000
|
||||||
|
```
|
||||||
|
|
||||||
|
## Evaluation results
|
||||||
|
|
||||||
|
```shell
|
||||||
|
{"f1": 79.8570684959745, "exact_match": 59.21327108373895}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```python
|
||||||
|
from transformers import pipeline
|
||||||
|
|
||||||
|
nlp = pipeline('question-answering', model='fmikaelian/camembert-base-squad', tokenizer='fmikaelian/camembert-base-squad')
|
||||||
|
|
||||||
|
nlp({
|
||||||
|
'question': "Qui est Claude Monet?",
|
||||||
|
'context': "Claude Monet, né le 14 novembre 1840 à Paris et mort le 5 décembre 1926 à Giverny, est un peintre français et l’un des fondateurs de l'impressionnisme."
|
||||||
|
})
|
||||||
|
```
|
||||||
12
model_cards/lvwerra/gpt2-medium-taboo/README.md
Normal file
12
model_cards/lvwerra/gpt2-medium-taboo/README.md
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# GPT-2 (medium) Taboo
|
||||||
|
|
||||||
|
## What is it?
|
||||||
|
A fine-tuned GPT-2 version for Taboo cards generation.
|
||||||
|
|
||||||
|
## Training setting
|
||||||
|
|
||||||
|
The model was trained on ~900 Taboo cards in the following format for 100 epochs:
|
||||||
|
```
|
||||||
|
Describe the word Glitch without using the words Problem, Unexpected, Technology, Minor, Outage.
|
||||||
|
````
|
||||||
|
|
||||||
137
model_cards/mrm8488/bert-multi-cased-finetuned-xquadv1/README.md
Normal file
137
model_cards/mrm8488/bert-multi-cased-finetuned-xquadv1/README.md
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
---
|
||||||
|
language: multilingual
|
||||||
|
thumbnail:
|
||||||
|
---
|
||||||
|
|
||||||
|
# BERT (base-multilingual-cased) fine-tuned on XQuAD
|
||||||
|
|
||||||
|
This model was created by [Google](https://github.com/google-research/bert/blob/master/multilingual.md) and fine-tuned on [XQuAD](https://github.com/deepmind/xquad) for multilingual (`11 different languages`) **Q&A** downstream task.
|
||||||
|
|
||||||
|
## Details of the language model('bert-base-multilingual-cased')
|
||||||
|
|
||||||
|
[Language model](https://github.com/google-research/bert/blob/master/multilingual.md)
|
||||||
|
|
||||||
|
| Languages | Heads | Layers | Hidden | Params |
|
||||||
|
| --------- | ----- | ------ | ------ | ------ |
|
||||||
|
| 104 | 12 | 12 | 768 | 100 M |
|
||||||
|
|
||||||
|
## Details of the downstream task (multilingual Q&A) - Dataset
|
||||||
|
|
||||||
|
Deepmind [XQuAD](https://github.com/deepmind/xquad)
|
||||||
|
|
||||||
|
Languages covered:
|
||||||
|
|
||||||
|
- Arabic: `ar`
|
||||||
|
- German: `de`
|
||||||
|
- Greek: `el`
|
||||||
|
- English: `en`
|
||||||
|
- Spanish: `es`
|
||||||
|
- Hindi: `hi`
|
||||||
|
- Russian: `ru`
|
||||||
|
- Thai: `th`
|
||||||
|
- Turkish: `tr`
|
||||||
|
- Vietnamese: `vi`
|
||||||
|
- Chinese: `zh`
|
||||||
|
|
||||||
|
As the dataset is based on SQuAD v1.1, there are no unanswerable questions in the data. We chose this
|
||||||
|
setting so that models can focus on cross-lingual transfer.
|
||||||
|
|
||||||
|
We show the average number of tokens per paragraph, question, and answer for each language in the
|
||||||
|
table below. The statistics were obtained using [Jieba](https://github.com/fxsjy/jieba) for Chinese
|
||||||
|
and the [Moses tokenizer](https://github.com/moses-smt/mosesdecoder/blob/master/scripts/tokenizer/tokenizer.perl)
|
||||||
|
for the other languages.
|
||||||
|
|
||||||
|
| | en | es | de | el | ru | tr | ar | vi | th | zh | hi |
|
||||||
|
| --------- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
|
||||||
|
| Paragraph | 142.4 | 160.7 | 139.5 | 149.6 | 133.9 | 126.5 | 128.2 | 191.2 | 158.7 | 147.6 | 232.4 |
|
||||||
|
| Question | 11.5 | 13.4 | 11.0 | 11.7 | 10.0 | 9.8 | 10.7 | 14.8 | 11.5 | 10.5 | 18.7 |
|
||||||
|
| Answer | 3.1 | 3.6 | 3.0 | 3.3 | 3.1 | 3.1 | 3.1 | 4.5 | 4.1 | 3.5 | 5.6 |
|
||||||
|
|
||||||
|
Citation:
|
||||||
|
|
||||||
|
<details>
|
||||||
|
```
|
||||||
|
@article{Artetxe:etal:2019,
|
||||||
|
author = {Mikel Artetxe and Sebastian Ruder and Dani Yogatama},
|
||||||
|
title = {On the cross-lingual transferability of monolingual representations},
|
||||||
|
journal = {CoRR},
|
||||||
|
volume = {abs/1910.11856},
|
||||||
|
year = {2019},
|
||||||
|
archivePrefix = {arXiv},
|
||||||
|
eprint = {1910.11856}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
</details>
|
||||||
|
|
||||||
|
I used `Data augmentation techniques` and splited the dataset in order to have a train and test set. The test set was created in a way that contains the same number of samples for each language. Finally, I got:
|
||||||
|
|
||||||
|
| Dataset | # samples |
|
||||||
|
| ----------- | --------- |
|
||||||
|
| XQUAD train | 50 K |
|
||||||
|
| XQUAD test | 8 K |
|
||||||
|
|
||||||
|
## Model training
|
||||||
|
|
||||||
|
The model was trained on a Tesla P100 GPU and 25GB of RAM.
|
||||||
|
The script for fine tuning can be found [here](https://github.com/huggingface/transformers/blob/master/examples/distillation/run_squad_w_distillation.py)
|
||||||
|
|
||||||
|
## Results:
|
||||||
|
|
||||||
|
| Metric | # Value |
|
||||||
|
| --------- | ----------- |
|
||||||
|
| **Exact** | **91.43** |
|
||||||
|
| **F1** | **94.14** |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Model in action
|
||||||
|
|
||||||
|
Fast usage with **pipelines**:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from transformers import pipeline
|
||||||
|
|
||||||
|
from transformers import pipeline
|
||||||
|
|
||||||
|
qa_pipeline = pipeline(
|
||||||
|
"question-answering",
|
||||||
|
model="mrm8488/bert-multi-cased-finetuned-xquadv1",
|
||||||
|
tokenizer="mrm8488/bert-multi-cased-finetuned-xquadv1"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# context: Coronavirus is seeding panic in the West because it expands so fast.
|
||||||
|
|
||||||
|
# question: Where is seeding panic Coronavirus?
|
||||||
|
qa_pipeline({
|
||||||
|
'context': "कोरोनावायरस पश्चिम में आतंक बो रहा है क्योंकि यह इतनी तेजी से फैलता है।",
|
||||||
|
'question': "कोरोनावायरस घबराहट कहां है?"
|
||||||
|
|
||||||
|
})
|
||||||
|
# output: {'answer': 'पश्चिम', 'end': 18, 'score': 0.7037217439689059, 'start': 12}
|
||||||
|
|
||||||
|
qa_pipeline({
|
||||||
|
'context': "Manuel Romero has been working hardly in the repository hugginface/transformers lately",
|
||||||
|
'question': "Who has been working hard for hugginface/transformers lately?"
|
||||||
|
|
||||||
|
})
|
||||||
|
# output: {'answer': 'Manuel Romero', 'end': 13, 'score': 0.7254485993702389, 'start': 0}
|
||||||
|
|
||||||
|
qa_pipeline({
|
||||||
|
'context': "Manuel Romero a travaillé à peine dans le référentiel hugginface / transformers ces derniers temps",
|
||||||
|
'question': "Pour quel référentiel a travaillé Manuel Romero récemment?"
|
||||||
|
|
||||||
|
})
|
||||||
|
#output: {'answer': 'hugginface / transformers', 'end': 79, 'score': 0.6482061613915384, 'start': 54}
|
||||||
|
```
|
||||||
|

|
||||||
|
|
||||||
|
Try it on a Colab:
|
||||||
|
|
||||||
|
<a href="https://colab.research.google.com/github/mrm8488/shared_colab_notebooks/blob/master/Try_mrm8488_xquad_finetuned_model.ipynb" target="_parent"><img src="https://camo.githubusercontent.com/52feade06f2fecbf006889a904d221e6a730c194/68747470733a2f2f636f6c61622e72657365617263682e676f6f676c652e636f6d2f6173736574732f636f6c61622d62616467652e737667" alt="Open In Colab" data-canonical-src="https://colab.research.google.com/assets/colab-badge.svg"></a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
> Created by [Manuel Romero/@mrm8488](https://twitter.com/mrm8488)
|
||||||
|
|
||||||
|
> Made with <span style="color: #e25555;">♥</span> in Spain
|
||||||
@@ -19,22 +19,29 @@ I preprocessed the dataset and splitted it as train / dev (80/20)
|
|||||||
| Dev | 2.2 K |
|
| Dev | 2.2 K |
|
||||||
|
|
||||||
|
|
||||||
- [Fine-tune on NER script](https://github.com/huggingface/transformers/blob/master/examples/run_ner.py)
|
- [Fine-tune on NER script provided by Huggingface](https://github.com/huggingface/transformers/blob/master/examples/run_ner.py)
|
||||||
|
|
||||||
```bash
|
- Labels covered:
|
||||||
!export NER_DIR='/content/ner_dataset'
|
|
||||||
!python /content/transformers/examples/run_ner.py \
|
|
||||||
--model_type bert \
|
|
||||||
--model_name_or_path dccuchile/bert-base-spanish-wwm-cased \
|
|
||||||
--do_train \
|
|
||||||
--do_eval \
|
|
||||||
--data_dir '/content/ner_dataset' \
|
|
||||||
--num_train_epochs 15.0 \
|
|
||||||
--max_seq_length 384 \
|
|
||||||
--output_dir /content/model_output \
|
|
||||||
--save_steps 5000 \
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
B-LOC
|
||||||
|
B-MISC
|
||||||
|
B-ORG
|
||||||
|
B-PER
|
||||||
|
I-LOC
|
||||||
|
I-MISC
|
||||||
|
I-ORG
|
||||||
|
I-PER
|
||||||
|
O
|
||||||
|
```
|
||||||
|
|
||||||
|
## Metrics on evaluation set:
|
||||||
|
|
||||||
|
| Metric | # score |
|
||||||
|
| :------------------------------------------------------------------------------------: | :-------: |
|
||||||
|
| F1 | **90.17**
|
||||||
|
| Precision | **89.86** |
|
||||||
|
| Recall | **90.47** |
|
||||||
|
|
||||||
## Comparison:
|
## Comparison:
|
||||||
|
|
||||||
@@ -44,13 +51,24 @@ I preprocessed the dataset and splitted it as train / dev (80/20)
|
|||||||
| [bert-spanish-cased-finetuned-ner (this one)](https://huggingface.co/mrm8488/bert-spanish-cased-finetuned-ner) | **89.65** |
|
| [bert-spanish-cased-finetuned-ner (this one)](https://huggingface.co/mrm8488/bert-spanish-cased-finetuned-ner) | **89.65** |
|
||||||
| Best Multilingual BERT | 87.38 |
|
| Best Multilingual BERT | 87.38 |
|
||||||
|
|
||||||
```
|
## Model in action
|
||||||
***** All metrics on Eval results *****
|
|
||||||
|
|
||||||
f1 = 0.8965040489828165
|
Fast usage with **pipelines**:
|
||||||
loss = 0.11504213575173258
|
|
||||||
precision = 0.893679858239811
|
```python
|
||||||
recall = 0.8993461462254805
|
from transformers import pipeline
|
||||||
|
|
||||||
|
nlp_ner = pipeline(
|
||||||
|
"ner",
|
||||||
|
model="mrm8488/bert-spanish-cased-finetuned-ner",
|
||||||
|
tokenizer=(
|
||||||
|
'mrm8488/bert-spanish-cased-finetuned-ner',
|
||||||
|
{"use_fast": False}
|
||||||
|
))
|
||||||
|
|
||||||
|
nlp_ner(text)
|
||||||
|
|
||||||
|
#Output: [{'entity': 'B-LOC', 'score': 0.9998720288276672, 'word': 'Londres'}]
|
||||||
```
|
```
|
||||||
|
|
||||||
> Created by [Manuel Romero/@mrm8488](https://twitter.com/mrm8488)
|
> Created by [Manuel Romero/@mrm8488](https://twitter.com/mrm8488)
|
||||||
|
|||||||
62
model_cards/mrm8488/bert-uncased-finetuned-qnli/README.md
Normal file
62
model_cards/mrm8488/bert-uncased-finetuned-qnli/README.md
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
---
|
||||||
|
language: english
|
||||||
|
thumbnail:
|
||||||
|
---
|
||||||
|
|
||||||
|
# [BERT](https://huggingface.co/deepset/bert-base-cased-squad2) fine tuned on [QNLI](https://github.com/rhythmcao/QNLI)+ compression ([BERT-of-Theseus](https://github.com/JetRunner/BERT-of-Theseus))
|
||||||
|
|
||||||
|
I used a [Bert model fine tuned on **SQUAD v2**](https://huggingface.co/deepset/bert-base-cased-squad2) and then I fine tuned it on **QNLI** using **compression** (with a constant replacing rate) as proposed in **BERT-of-Theseus**
|
||||||
|
|
||||||
|
## Details of the downstream task (QNLI):
|
||||||
|
|
||||||
|
### Getting the dataset
|
||||||
|
```bash
|
||||||
|
wget https://raw.githubusercontent.com/rhythmcao/QNLI/master/data/QNLI/train.tsv
|
||||||
|
wget https://raw.githubusercontent.com/rhythmcao/QNLI/master/data/QNLI/test.tsv
|
||||||
|
wget https://raw.githubusercontent.com/rhythmcao/QNLI/master/data/QNLI/dev.tsv
|
||||||
|
|
||||||
|
mkdir QNLI_dataset
|
||||||
|
mv *.tsv QNLI_dataset
|
||||||
|
```
|
||||||
|
|
||||||
|
### Model training
|
||||||
|
|
||||||
|
The model was trained on a Tesla P100 GPU and 25GB of RAM with the following command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
!python /content/BERT-of-Theseus/run_glue.py \
|
||||||
|
--model_name_or_path deepset/bert-base-cased-squad2 \
|
||||||
|
--task_name qnli \
|
||||||
|
--do_train \
|
||||||
|
--do_eval \
|
||||||
|
--do_lower_case \
|
||||||
|
--data_dir /content/QNLI_dataset \
|
||||||
|
--max_seq_length 128 \
|
||||||
|
--per_gpu_train_batch_size 32 \
|
||||||
|
--per_gpu_eval_batch_size 32 \
|
||||||
|
--learning_rate 2e-5 \
|
||||||
|
--save_steps 2000 \
|
||||||
|
--num_train_epochs 50 \
|
||||||
|
--output_dir /content/ouput_dir \
|
||||||
|
--evaluate_during_training \
|
||||||
|
--replacing_rate 0.7 \
|
||||||
|
--steps_for_replacing 2500
|
||||||
|
```
|
||||||
|
|
||||||
|
## Metrics:
|
||||||
|
|
||||||
|
| Model | Accuracy |
|
||||||
|
|-----------------|------|
|
||||||
|
| BERT-base | 91.2 |
|
||||||
|
| BERT-of-Theseus | 88.8 |
|
||||||
|
| [bert-uncased-finetuned-qnli](https://huggingface.co/mrm8488/bert-uncased-finetuned-qnli) | 87.2
|
||||||
|
| DistillBERT | 85.3 |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
> [See all my models](https://huggingface.co/models?search=mrm8488)
|
||||||
|
|
||||||
|
> Created by [Manuel Romero/@mrm8488](https://twitter.com/mrm8488)
|
||||||
|
|
||||||
|
> Made with <span style="color: #e25555;">♥</span> in Spain
|
||||||
370
notebooks/01-training-tokenizers.ipynb
Normal file
370
notebooks/01-training-tokenizers.ipynb
Normal file
@@ -0,0 +1,370 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"is_executing": false,
|
||||||
|
"name": "#%% md\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
"## Tokenization doesn't have to be slow !\n",
|
||||||
|
"\n",
|
||||||
|
"### Introduction\n",
|
||||||
|
"\n",
|
||||||
|
"Before going deep into any Machine Learning or Deep Learning Natural Language Processing models, every practitioner\n",
|
||||||
|
"should find a way to map raw input strings to a representation understandable by a trainable model.\n",
|
||||||
|
"\n",
|
||||||
|
"One very simple approach would be to split inputs over every space and assign an identifier to each word. This approach\n",
|
||||||
|
"would look similar to the code below in python\n",
|
||||||
|
"\n",
|
||||||
|
"```python\n",
|
||||||
|
"s = \"very long corpus...\"\n",
|
||||||
|
"words = s.split(\" \") # Split over space\n",
|
||||||
|
"vocabulary = dict(enumerate(set(words))) # Map storing the word to it's corresponding id\n",
|
||||||
|
"```\n",
|
||||||
|
"\n",
|
||||||
|
"This approach might work well if your vocabulary remains small as it would store every word (or **token**) present in your original\n",
|
||||||
|
"input. Moreover, word variations like \"cat\" and \"cats\" would not share the same identifiers even if their meaning is \n",
|
||||||
|
"quite close.\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"### Subtoken Tokenization\n",
|
||||||
|
"\n",
|
||||||
|
"To overcome the issues described above, recent works have been done on tokenization, leveraging \"subtoken\" tokenization.\n",
|
||||||
|
"**Subtokens** extends the previous splitting strategy to furthermore explode a word into grammatically logicial sub-components learned\n",
|
||||||
|
"from the data.\n",
|
||||||
|
"\n",
|
||||||
|
"Taking our previous example of the words __cat__ and __cats__, a sub-tokenization of the word __cats__ would be [cat, ##s]. Where the prefix _\"##\"_ indicates a subtoken of the initial input. \n",
|
||||||
|
"Such training algorithms might extract sub-tokens such as _\"##ing\"_, _\"##ed\"_ over English corpus.\n",
|
||||||
|
"\n",
|
||||||
|
"As you might think of, this kind of sub-tokens construction leveraging compositions of _\"pieces\"_ overall reduces the size\n",
|
||||||
|
"of the vocabulary you have to carry to train a Machine Learning model. On the other side, as one token might be exploded\n",
|
||||||
|
"into multiple subtokens, the input of your model might increase and become an issue on model with non-linear complexity over the input sequence's length. \n",
|
||||||
|
" \n",
|
||||||
|
"\n",
|
||||||
|
" \n",
|
||||||
|
"Among all the tokenization algorithms, we can highlight a few subtokens algorithms used in Transformers-based SoTA models : \n",
|
||||||
|
"\n",
|
||||||
|
"- [Byte Pair Encoding (BPE) - Neural Machine Translation of Rare Words with Subword Units (Sennrich et al., 2015)](https://arxiv.org/abs/1508.07909)\n",
|
||||||
|
"- [Word Piece - Japanese and Korean voice search (Schuster, M., and Nakajima, K., 2015)](https://research.google/pubs/pub37842/)\n",
|
||||||
|
"- [Unigram Language Model - Subword Regularization: Improving Neural Network Translation Models with Multiple Subword Candidates (Kudo, T., 2018)](https://arxiv.org/abs/1804.10959)\n",
|
||||||
|
"- [Sentence Piece - A simple and language independent subword tokenizer and detokenizer for Neural Text Processing (Taku Kudo and John Richardson, 2018)](https://arxiv.org/abs/1808.06226)\n",
|
||||||
|
"\n",
|
||||||
|
"Going through all of them is out of the scope of this notebook, so we will just highlight how you can use them.\n",
|
||||||
|
"\n",
|
||||||
|
"### @huggingface/tokenizers library \n",
|
||||||
|
"Along with the transformers library, we @huggingface provide a blazing fast tokenization library\n",
|
||||||
|
"able to train, tokenize and decode dozens of Gb/s of text on a common multi-core machine.\n",
|
||||||
|
"\n",
|
||||||
|
"The library is written in Rust allowing us to take full advantage of multi-core parallel computations in a native and memory-aware way, on-top of which \n",
|
||||||
|
"we provide bindings for Python and NodeJS (more bindings may be added in the future). \n",
|
||||||
|
"\n",
|
||||||
|
"We designed the library so that it provides all the required blocks to create end-to-end tokenizers in an interchangeable way. In that sense, we provide\n",
|
||||||
|
"these various components: \n",
|
||||||
|
"\n",
|
||||||
|
"- **Normalizer**: Executes all the initial transformations over the initial input string. For example when you need to\n",
|
||||||
|
"lowercase some text, maybe strip it, or even apply one of the common unicode normalization process, you will add a Normalizer. \n",
|
||||||
|
"- **PreTokenizer**: In charge of splitting the initial input string. That's the component that decides where and how to\n",
|
||||||
|
"pre-segment the origin string. The simplest example would be like we saw before, to simply split on spaces.\n",
|
||||||
|
"- **Model**: Handles all the sub-token discovery and generation, this part is trainable and really dependant\n",
|
||||||
|
" of your input data.\n",
|
||||||
|
"- **Post-Processor**: Provides advanced construction features to be compatible with some of the Transformers-based SoTA\n",
|
||||||
|
"models. For instance, for BERT it would wrap the tokenized sentence around [CLS] and [SEP] tokens.\n",
|
||||||
|
"- **Decoder**: In charge of mapping back a tokenized input to the original string. The decoder is usually chosen according\n",
|
||||||
|
"to the `PreTokenizer` we used previously.\n",
|
||||||
|
"- **Trainer**: Provides training capabilities to each model.\n",
|
||||||
|
"\n",
|
||||||
|
"For each of the components above we provide multiple implementations:\n",
|
||||||
|
"\n",
|
||||||
|
"- **Normalizer**: Lowercase, Unicode (NFD, NFKD, NFC, NFKC), Bert, Strip, ...\n",
|
||||||
|
"- **PreTokenizer**: ByteLevel, WhitespaceSplit, CharDelimiterSplit, Metaspace, ...\n",
|
||||||
|
"- **Model**: WordLevel, BPE, WordPiece\n",
|
||||||
|
"- **Post-Processor**: BertProcessor, ...\n",
|
||||||
|
"- **Decoder**: WordLevel, BPE, WordPiece, ...\n",
|
||||||
|
"\n",
|
||||||
|
"All of these building blocks can be combined to create working tokenization pipelines. \n",
|
||||||
|
"In the next section we will go over our first pipeline."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"name": "#%% md\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
"Alright, now we are ready to implement our first tokenization pipeline through `tokenizers`. \n",
|
||||||
|
"\n",
|
||||||
|
"For this, we will train a Byte-Pair Encoding (BPE) tokenizer on a quite small input for the purpose of this notebook.\n",
|
||||||
|
"We will work with [the file from Peter Norving](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=2ahUKEwjYp9Ppru_nAhUBzIUKHfbUAG8QFjAAegQIBhAB&url=https%3A%2F%2Fnorvig.com%2Fbig.txt&usg=AOvVaw2ed9iwhcP1RKUiEROs15Dz).\n",
|
||||||
|
"This file contains around 130.000 lines of raw text that will be processed by the library to generate a working tokenizer.\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"is_executing": false,
|
||||||
|
"name": "#%% code\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"!pip install tokenizers"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 2,
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"is_executing": false,
|
||||||
|
"name": "#%% code\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"BIG_FILE_URL = 'https://raw.githubusercontent.com/dscape/spell/master/test/resources/big.txt'\n",
|
||||||
|
"\n",
|
||||||
|
"# Let's download the file and save it somewhere\n",
|
||||||
|
"from requests import get\n",
|
||||||
|
"with open('big.txt', 'wb') as big_f:\n",
|
||||||
|
" response = get(BIG_FILE_URL, )\n",
|
||||||
|
" \n",
|
||||||
|
" if response.status_code == 200:\n",
|
||||||
|
" big_f.write(response.content)\n",
|
||||||
|
" else:\n",
|
||||||
|
" print(\"Unable to get the file: {}\".format(response.reason))\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"is_executing": false,
|
||||||
|
"name": "#%% md\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
" \n",
|
||||||
|
"Now that we have our training data we need to create the overall pipeline for the tokenizer\n",
|
||||||
|
" "
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 10,
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"is_executing": false,
|
||||||
|
"name": "#%% code\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# For the user's convenience `tokenizers` provides some very high-level classes encapsulating\n",
|
||||||
|
"# the overall pipeline for various well-known tokenization algorithm. \n",
|
||||||
|
"# Everything described below can be replaced by the ByteLevelBPETokenizer class. \n",
|
||||||
|
"\n",
|
||||||
|
"from tokenizers import Tokenizer\n",
|
||||||
|
"from tokenizers.decoders import ByteLevel as ByteLevelDecoder\n",
|
||||||
|
"from tokenizers.models import BPE\n",
|
||||||
|
"from tokenizers.normalizers import Lowercase, NFKC, Sequence\n",
|
||||||
|
"from tokenizers.pre_tokenizers import ByteLevel\n",
|
||||||
|
"\n",
|
||||||
|
"# First we create an empty Byte-Pair Encoding model (i.e. not trained model)\n",
|
||||||
|
"tokenizer = Tokenizer(BPE.empty())\n",
|
||||||
|
"\n",
|
||||||
|
"# Then we enable lower-casing and unicode-normalization\n",
|
||||||
|
"# The Sequence normalizer allows us to combine multiple Normalizer that will be\n",
|
||||||
|
"# executed in order.\n",
|
||||||
|
"tokenizer.normalizer = Sequence([\n",
|
||||||
|
" NFKC(),\n",
|
||||||
|
" Lowercase()\n",
|
||||||
|
"])\n",
|
||||||
|
"\n",
|
||||||
|
"# Our tokenizer also needs a pre-tokenizer responsible for converting the input to a ByteLevel representation.\n",
|
||||||
|
"tokenizer.pre_tokenizer = ByteLevel()\n",
|
||||||
|
"\n",
|
||||||
|
"# And finally, let's plug a decoder so we can recover from a tokenized input to the original one\n",
|
||||||
|
"tokenizer.decoder = ByteLevelDecoder()"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"name": "#%% md\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
"The overall pipeline is now ready to be trained on the corpus we downloaded earlier in this notebook."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 11,
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"is_executing": false,
|
||||||
|
"name": "#%% code\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"Trained vocab size: 25000\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"from tokenizers.trainers import BpeTrainer\n",
|
||||||
|
"\n",
|
||||||
|
"# We initialize our trainer, giving him the details about the vocabulary we want to generate\n",
|
||||||
|
"trainer = BpeTrainer(vocab_size=25000, show_progress=True, initial_alphabet=ByteLevel.alphabet())\n",
|
||||||
|
"tokenizer.train(trainer, [\"big.txt\"])\n",
|
||||||
|
"\n",
|
||||||
|
"print(\"Trained vocab size: {}\".format(tokenizer.get_vocab_size()))"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"name": "#%% md\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
"Et voilà ! You trained your very first tokenizer from scratch using `tokenizers`. Of course, this \n",
|
||||||
|
"covers only the basics, and you may want to have a look at the `add_special_tokens` or `special_tokens` parameters\n",
|
||||||
|
"on the `Trainer` class, but the overall process should be very similar.\n",
|
||||||
|
"\n",
|
||||||
|
"We can save the content of the model to reuse it later."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 12,
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"is_executing": false,
|
||||||
|
"name": "#%% code\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"['./vocab.json', './merges.txt']"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 12,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# You will see the generated files in the output.\n",
|
||||||
|
"tokenizer.model.save('.')"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"name": "#%% md\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
"Now, let load the trained model and start using out newly trained tokenizer"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 13,
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"is_executing": false,
|
||||||
|
"name": "#%% code\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"Encoded string: ['Ġthis', 'Ġis', 'Ġa', 'Ġsimple', 'Ġin', 'put', 'Ġto', 'Ġbe', 'Ġtoken', 'ized']\n",
|
||||||
|
"Decoded string: this is a simple input to be tokenized\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# Let's tokenizer a simple input\n",
|
||||||
|
"tokenizer.model = BPE.from_files('vocab.json', 'merges.txt')\n",
|
||||||
|
"encoding = tokenizer.encode(\"This is a simple input to be tokenized\")\n",
|
||||||
|
"\n",
|
||||||
|
"print(\"Encoded string: {}\".format(encoding.tokens))\n",
|
||||||
|
"\n",
|
||||||
|
"decoded = tokenizer.decode(encoding.ids)\n",
|
||||||
|
"print(\"Decoded string: {}\".format(decoded))"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"name": "#%% md\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
"The Encoding structure exposes multiple properties which are useful when working with transformers models\n",
|
||||||
|
"\n",
|
||||||
|
"- normalized_str: The input string after normalization (lower-casing, unicode, stripping, etc.)\n",
|
||||||
|
"- original_str: The input string as it was provided\n",
|
||||||
|
"- tokens: The generated tokens with their string representation\n",
|
||||||
|
"- input_ids: The generated tokens with their integer representation\n",
|
||||||
|
"- attention_mask: If your input has been padded by the tokenizer, then this would be a vector of 1 for any non padded token and 0 for padded ones.\n",
|
||||||
|
"- special_token_mask: If your input contains special tokens such as [CLS], [SEP], [MASK], [PAD], then this would be a vector with 1 in places where a special token has been added.\n",
|
||||||
|
"- type_ids: If your was made of multiple \"parts\" such as (question, context), then this would be a vector with for each token the segment it belongs to.\n",
|
||||||
|
"- overflowing: If your has been truncated into multiple subparts because of a length limit (for BERT for example the sequence length is limited to 512), this will contain all the remaining overflowing parts."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.7.6"
|
||||||
|
},
|
||||||
|
"pycharm": {
|
||||||
|
"stem_cell": {
|
||||||
|
"cell_type": "raw",
|
||||||
|
"metadata": {
|
||||||
|
"collapsed": false
|
||||||
|
},
|
||||||
|
"source": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 1
|
||||||
|
}
|
||||||
594
notebooks/02-transformers.ipynb
Normal file
594
notebooks/02-transformers.ipynb
Normal file
@@ -0,0 +1,594 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {
|
||||||
|
"collapsed": true,
|
||||||
|
"pycharm": {
|
||||||
|
"is_executing": false,
|
||||||
|
"name": "#%% md\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
"## Introduction\n",
|
||||||
|
"The transformers library is an open-source, community-based repository to train, use and share models based on \n",
|
||||||
|
"the Transformer architecture [(Vaswani & al., 2017)](https://arxiv.org/abs/1706.03762) such as Bert [(Devlin & al., 2018)](https://arxiv.org/abs/1810.04805),\n",
|
||||||
|
"Roberta [(Liu & al., 2019)](https://arxiv.org/abs/1907.11692), GPT2 [(Radford & al., 2019)](https://cdn.openai.com/better-language-models/language_models_are_unsupervised_multitask_learners.pdf),\n",
|
||||||
|
"XLNet [(Yang & al., 2019)](https://arxiv.org/abs/1906.08237), etc. \n",
|
||||||
|
"\n",
|
||||||
|
"Along with the models, the library contains multiple variations of each of them for a large variety of \n",
|
||||||
|
"downstream-tasks like **Named Entity Recognition (NER)**, **Sentiment Analysis**, \n",
|
||||||
|
"**Language Modeling**, **Question Answering** and so on.\n",
|
||||||
|
"\n",
|
||||||
|
"## Before Transformer\n",
|
||||||
|
"\n",
|
||||||
|
"Back to 2017, most of the people using Neural Networks when working on Natural Language Processing were relying on \n",
|
||||||
|
"sequential processing of the input through [Recurrent Neural Network (RNN)](https://en.wikipedia.org/wiki/Recurrent_neural_network).\n",
|
||||||
|
"\n",
|
||||||
|
" \n",
|
||||||
|
"\n",
|
||||||
|
"RNNs were performing well on large variety of tasks involving sequential dependency over the input sequence. \n",
|
||||||
|
"However, this sequentially-dependent process had issues modeling very long range dependencies and \n",
|
||||||
|
"was not well suited for the kind of hardware we're currently leveraging due to bad parallelization capabilities. \n",
|
||||||
|
"\n",
|
||||||
|
"Some extensions were provided by the academic community, such as Bidirectional RNN ([Schuster & Paliwal., 1997](https://www.researchgate.net/publication/3316656_Bidirectional_recurrent_neural_networks), [Graves & al., 2005](https://mediatum.ub.tum.de/doc/1290195/file.pdf)), \n",
|
||||||
|
"which can be seen as a concatenation of two sequential process, one going forward, the other one going backward over the sequence input.\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"And also, the Attention mechanism, which introduced a good improvement over \"raw\" RNNs by giving \n",
|
||||||
|
"a learned, weighted-importance to each element in the sequence, allowing the model to focus on important elements.\n",
|
||||||
|
"\n",
|
||||||
|
" \n",
|
||||||
|
"\n",
|
||||||
|
"## Then comes the Transformer \n",
|
||||||
|
"\n",
|
||||||
|
"The Transformers era originally started from the work of [(Vaswani & al., 2017)](https://arxiv.org/abs/1706.03762) who\n",
|
||||||
|
"demonstrated its superiority over [Recurrent Neural Network (RNN)](https://en.wikipedia.org/wiki/Recurrent_neural_network)\n",
|
||||||
|
"on translation tasks but it quickly extended to almost all the tasks RNNs were State-of-the-Art at that time.\n",
|
||||||
|
"\n",
|
||||||
|
"One advantage of Transformer over its RNN counterpart was its non sequential attention model. Remember, the RNNs had to\n",
|
||||||
|
"iterate over each element of the input sequence one-by-one and carry an \"updatable-state\" between each hop. With Transformer, the model is able to look at every position in the sequence, at the same time, in one operation.\n",
|
||||||
|
"\n",
|
||||||
|
"For a deep-dive into the Transformer architecture, [The Annotated Transformer](https://nlp.seas.harvard.edu/2018/04/03/attention.html#encoder-and-decoder-stacks) \n",
|
||||||
|
"will drive you along all the details of the paper.\n",
|
||||||
|
"\n",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"name": "#%% md\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
"## Getting started with transformers\n",
|
||||||
|
"\n",
|
||||||
|
"For the rest of this notebook, we will use the [BERT (Devlin & al., 2018)](https://arxiv.org/abs/1810.04805) architecture, as it's the most simple and there are plenty of content about it\n",
|
||||||
|
"over the internet, it will be easy to dig more over this architecture if you want to.\n",
|
||||||
|
"\n",
|
||||||
|
"The transformers library allows you to benefits from large, pretrained language models without requiring a huge and costly computational\n",
|
||||||
|
"infrastructure. Most of the State-of-the-Art models are provided directly by their author and made available in the library \n",
|
||||||
|
"in PyTorch and TensorFlow in a transparent and interchangeable way. "
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 1,
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"is_executing": false,
|
||||||
|
"name": "#%% code\n"
|
||||||
|
},
|
||||||
|
"scrolled": true
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"Requirement already satisfied: transformers in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (2.5.1)\n",
|
||||||
|
"Requirement already satisfied: filelock in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from transformers) (3.0.12)\n",
|
||||||
|
"Requirement already satisfied: sentencepiece in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from transformers) (0.1.83)\n",
|
||||||
|
"Requirement already satisfied: boto3 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from transformers) (1.12.0)\n",
|
||||||
|
"Requirement already satisfied: requests in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from transformers) (2.22.0)\n",
|
||||||
|
"Requirement already satisfied: numpy in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from transformers) (1.18.1)\n",
|
||||||
|
"Requirement already satisfied: sacremoses in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from transformers) (0.0.35)\n",
|
||||||
|
"Requirement already satisfied: tokenizers==0.5.2 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from transformers) (0.5.2)\n",
|
||||||
|
"Requirement already satisfied: regex!=2019.12.17 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from transformers) (2020.1.8)\n",
|
||||||
|
"Requirement already satisfied: tqdm>=4.27 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from transformers) (4.42.1)\n",
|
||||||
|
"Requirement already satisfied: s3transfer<0.4.0,>=0.3.0 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from boto3->transformers) (0.3.3)\n",
|
||||||
|
"Requirement already satisfied: botocore<1.16.0,>=1.15.0 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from boto3->transformers) (1.15.0)\n",
|
||||||
|
"Requirement already satisfied: jmespath<1.0.0,>=0.7.1 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from boto3->transformers) (0.9.4)\n",
|
||||||
|
"Requirement already satisfied: certifi>=2017.4.17 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from requests->transformers) (2019.11.28)\n",
|
||||||
|
"Requirement already satisfied: idna<2.9,>=2.5 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from requests->transformers) (2.8)\n",
|
||||||
|
"Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from requests->transformers) (1.25.8)\n",
|
||||||
|
"Requirement already satisfied: chardet<3.1.0,>=3.0.2 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from requests->transformers) (3.0.4)\n",
|
||||||
|
"Requirement already satisfied: joblib in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from sacremoses->transformers) (0.14.0)\n",
|
||||||
|
"Requirement already satisfied: click in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from sacremoses->transformers) (7.0)\n",
|
||||||
|
"Requirement already satisfied: six in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from sacremoses->transformers) (1.14.0)\n",
|
||||||
|
"Requirement already satisfied: docutils<0.16,>=0.10 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from botocore<1.16.0,>=1.15.0->boto3->transformers) (0.15.2)\n",
|
||||||
|
"Requirement already satisfied: python-dateutil<3.0.0,>=2.1 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from botocore<1.16.0,>=1.15.0->boto3->transformers) (2.8.1)\n",
|
||||||
|
"Requirement already satisfied: tensorflow==2.1.0 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (2.1.0)\n",
|
||||||
|
"Requirement already satisfied: termcolor>=1.1.0 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from tensorflow==2.1.0) (1.1.0)\n",
|
||||||
|
"Requirement already satisfied: keras-preprocessing>=1.1.0 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from tensorflow==2.1.0) (1.1.0)\n",
|
||||||
|
"Requirement already satisfied: opt-einsum>=2.3.2 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from tensorflow==2.1.0) (3.1.0)\n",
|
||||||
|
"Requirement already satisfied: protobuf>=3.8.0 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from tensorflow==2.1.0) (3.11.4)\n",
|
||||||
|
"Requirement already satisfied: numpy<2.0,>=1.16.0 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from tensorflow==2.1.0) (1.18.1)\n",
|
||||||
|
"Requirement already satisfied: tensorboard<2.2.0,>=2.1.0 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from tensorflow==2.1.0) (2.1.0)\n",
|
||||||
|
"Requirement already satisfied: keras-applications>=1.0.8 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from tensorflow==2.1.0) (1.0.8)\n",
|
||||||
|
"Requirement already satisfied: wrapt>=1.11.1 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from tensorflow==2.1.0) (1.11.2)\n",
|
||||||
|
"Requirement already satisfied: six>=1.12.0 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from tensorflow==2.1.0) (1.14.0)\n",
|
||||||
|
"Requirement already satisfied: tensorflow-estimator<2.2.0,>=2.1.0rc0 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from tensorflow==2.1.0) (2.1.0)\n",
|
||||||
|
"Requirement already satisfied: scipy==1.4.1; python_version >= \"3\" in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from tensorflow==2.1.0) (1.4.1)\n",
|
||||||
|
"Requirement already satisfied: google-pasta>=0.1.6 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from tensorflow==2.1.0) (0.1.8)\n",
|
||||||
|
"Requirement already satisfied: wheel>=0.26; python_version >= \"3\" in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from tensorflow==2.1.0) (0.34.2)\n",
|
||||||
|
"Requirement already satisfied: grpcio>=1.8.6 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from tensorflow==2.1.0) (1.16.1)\n",
|
||||||
|
"Requirement already satisfied: absl-py>=0.7.0 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from tensorflow==2.1.0) (0.9.0)\n",
|
||||||
|
"Requirement already satisfied: gast==0.2.2 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from tensorflow==2.1.0) (0.2.2)\n",
|
||||||
|
"Requirement already satisfied: astor>=0.6.0 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from tensorflow==2.1.0) (0.8.0)\n",
|
||||||
|
"Requirement already satisfied: setuptools in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from protobuf>=3.8.0->tensorflow==2.1.0) (45.2.0.post20200210)\n",
|
||||||
|
"Requirement already satisfied: google-auth<2,>=1.6.3 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from tensorboard<2.2.0,>=2.1.0->tensorflow==2.1.0) (1.11.2)\n",
|
||||||
|
"Requirement already satisfied: google-auth-oauthlib<0.5,>=0.4.1 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from tensorboard<2.2.0,>=2.1.0->tensorflow==2.1.0) (0.4.1)\n",
|
||||||
|
"Requirement already satisfied: markdown>=2.6.8 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from tensorboard<2.2.0,>=2.1.0->tensorflow==2.1.0) (3.1.1)\n",
|
||||||
|
"Requirement already satisfied: werkzeug>=0.11.15 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from tensorboard<2.2.0,>=2.1.0->tensorflow==2.1.0) (1.0.0)\n",
|
||||||
|
"Requirement already satisfied: requests<3,>=2.21.0 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from tensorboard<2.2.0,>=2.1.0->tensorflow==2.1.0) (2.22.0)\n",
|
||||||
|
"Requirement already satisfied: h5py in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from keras-applications>=1.0.8->tensorflow==2.1.0) (2.10.0)\n",
|
||||||
|
"Requirement already satisfied: rsa<4.1,>=3.1.4 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from google-auth<2,>=1.6.3->tensorboard<2.2.0,>=2.1.0->tensorflow==2.1.0) (4.0)\n",
|
||||||
|
"Requirement already satisfied: cachetools<5.0,>=2.0.0 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from google-auth<2,>=1.6.3->tensorboard<2.2.0,>=2.1.0->tensorflow==2.1.0) (4.0.0)\n",
|
||||||
|
"Requirement already satisfied: pyasn1-modules>=0.2.1 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from google-auth<2,>=1.6.3->tensorboard<2.2.0,>=2.1.0->tensorflow==2.1.0) (0.2.8)\n",
|
||||||
|
"Requirement already satisfied: requests-oauthlib>=0.7.0 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from google-auth-oauthlib<0.5,>=0.4.1->tensorboard<2.2.0,>=2.1.0->tensorflow==2.1.0) (1.3.0)\n",
|
||||||
|
"Requirement already satisfied: idna<2.9,>=2.5 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from requests<3,>=2.21.0->tensorboard<2.2.0,>=2.1.0->tensorflow==2.1.0) (2.8)\n",
|
||||||
|
"Requirement already satisfied: certifi>=2017.4.17 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from requests<3,>=2.21.0->tensorboard<2.2.0,>=2.1.0->tensorflow==2.1.0) (2019.11.28)\n",
|
||||||
|
"Requirement already satisfied: chardet<3.1.0,>=3.0.2 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from requests<3,>=2.21.0->tensorboard<2.2.0,>=2.1.0->tensorflow==2.1.0) (3.0.4)\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from requests<3,>=2.21.0->tensorboard<2.2.0,>=2.1.0->tensorflow==2.1.0) (1.25.8)\r\n",
|
||||||
|
"Requirement already satisfied: pyasn1>=0.1.3 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from rsa<4.1,>=3.1.4->google-auth<2,>=1.6.3->tensorboard<2.2.0,>=2.1.0->tensorflow==2.1.0) (0.4.8)\r\n",
|
||||||
|
"Requirement already satisfied: oauthlib>=3.0.0 in /usr/local/Caskroom/miniconda/base/envs/huggingface/lib/python3.7/site-packages (from requests-oauthlib>=0.7.0->google-auth-oauthlib<0.5,>=0.4.1->tensorboard<2.2.0,>=2.1.0->tensorflow==2.1.0) (3.1.0)\r\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"!pip install transformers\n",
|
||||||
|
"!pip install tensorflow==2.1.0"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 2,
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"is_executing": false,
|
||||||
|
"name": "#%% code\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"<torch.autograd.grad_mode.set_grad_enabled at 0x102c0ce10>"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 2,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"import torch\n",
|
||||||
|
"from transformers import AutoModel, AutoTokenizer, BertTokenizer\n",
|
||||||
|
"\n",
|
||||||
|
"torch.set_grad_enabled(False)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 3,
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"is_executing": false,
|
||||||
|
"name": "#%% code\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Store the model we want to use\n",
|
||||||
|
"MODEL_NAME = \"bert-base-cased\"\n",
|
||||||
|
"\n",
|
||||||
|
"# We need to create the model and tokenizer\n",
|
||||||
|
"model = AutoModel.from_pretrained(MODEL_NAME)\n",
|
||||||
|
"tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"name": "#%% md\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
"With only the above two lines of code, you're ready to use a BERT pre-trained model. \n",
|
||||||
|
"The tokenizers will allow us to map a raw textual input to a sequence of integers representing our textual input\n",
|
||||||
|
"in a way the model can manipulate."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 4,
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"is_executing": false,
|
||||||
|
"name": "#%% code\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"Tokens: ['This', 'is', 'an', 'input', 'example']\n",
|
||||||
|
"Tokens id: [1188, 1110, 1126, 7758, 1859]\n",
|
||||||
|
"Tokens PyTorch: tensor([[ 101, 1188, 1110, 1126, 7758, 1859, 102]])\n",
|
||||||
|
"Tokenw ise output: torch.Size([1, 7, 768]), Pooled output: torch.Size([1, 768])\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# Tokens comes from a process that splits the input into sub-entities with interesting linguistic properties. \n",
|
||||||
|
"tokens = tokenizer.tokenize(\"This is an input example\")\n",
|
||||||
|
"print(\"Tokens: {}\".format(tokens))\n",
|
||||||
|
"\n",
|
||||||
|
"# This is not sufficient for the model, as it requires integers as input, \n",
|
||||||
|
"# not a problem, let's convert tokens to ids.\n",
|
||||||
|
"tokens_ids = tokenizer.convert_tokens_to_ids(tokens)\n",
|
||||||
|
"print(\"Tokens id: {}\".format(tokens_ids))\n",
|
||||||
|
"\n",
|
||||||
|
"# Add the required special tokens\n",
|
||||||
|
"tokens_ids = tokenizer.build_inputs_with_special_tokens(tokens_ids)\n",
|
||||||
|
"\n",
|
||||||
|
"# We need to convert to a Deep Learning framework specific format, let's use PyTorch for now.\n",
|
||||||
|
"tokens_pt = torch.tensor([tokens_ids])\n",
|
||||||
|
"print(\"Tokens PyTorch: {}\".format(tokens_pt))\n",
|
||||||
|
"\n",
|
||||||
|
"# Now we're ready to go through BERT with out input\n",
|
||||||
|
"outputs, pooled = model(tokens_pt)\n",
|
||||||
|
"print(\"Tokenw ise output: {}, Pooled output: {}\".format(outputs.shape, pooled.shape))"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"name": "#%% md\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
"As you can see, BERT outputs two tensors:\n",
|
||||||
|
" - One with the generated representation for every token in the input `(1, NB_TOKENS, REPRESENTATION_SIZE)`\n",
|
||||||
|
" - One with an aggregated representation for the whole input `(1, REPRESENTATION_SIZE)`\n",
|
||||||
|
" \n",
|
||||||
|
"The first, token-based, representation can be leveraged if your task requires to keep the sequence representation and you\n",
|
||||||
|
"want to operate at a token-level. This is particularly useful for Named Entity Recognition and Question-Answering.\n",
|
||||||
|
"\n",
|
||||||
|
"The second, aggregated, representation is especially useful if you need to extract the overall context of the sequence and don't\n",
|
||||||
|
"require a fine-grained token-leven. This is the case for Sentiment-Analysis of the sequence or Information Retrieval."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"name": "#%% md\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
"The code you saw in the previous section introduced all the steps required to do simple model invocation.\n",
|
||||||
|
"For more day-to-day usage, transformers provides you higher-level methods which will makes your NLP journey easier\n",
|
||||||
|
"Let's improve our previous example"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 5,
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"is_executing": false,
|
||||||
|
"name": "#%% code\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"input_ids:\n",
|
||||||
|
"\ttensor([[ 101, 1188, 1110, 1126, 7758, 1859, 102]])\n",
|
||||||
|
"token_type_ids:\n",
|
||||||
|
"\ttensor([[0, 0, 0, 0, 0, 0, 0]])\n",
|
||||||
|
"attention_mask:\n",
|
||||||
|
"\ttensor([[1, 1, 1, 1, 1, 1, 1]])\n",
|
||||||
|
"Difference with previous code: (0.0, 0.0)\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# tokens = tokenizer.tokenize(\"This is an input example\")\n",
|
||||||
|
"# tokens_ids = tokenizer.convert_tokens_to_ids(tokens)\n",
|
||||||
|
"# tokens_pt = torch.tensor([tokens_ids])\n",
|
||||||
|
"\n",
|
||||||
|
"# This code can be factored into one-line as follow\n",
|
||||||
|
"tokens_pt2 = tokenizer.encode_plus(\"This is an input example\", return_tensors=\"pt\")\n",
|
||||||
|
"\n",
|
||||||
|
"for key, value in tokens_pt2.items():\n",
|
||||||
|
" print(\"{}:\\n\\t{}\".format(key, value))\n",
|
||||||
|
"\n",
|
||||||
|
"outputs2, pooled2 = model(**tokens_pt2)\n",
|
||||||
|
"print(\"Difference with previous code: ({}, {})\".format((outputs2 - outputs).sum(), (pooled2 - pooled).sum()))"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"As you can see above, the methode `encode_plus` provides a convenient way to generate all the required parameters\n",
|
||||||
|
"that will go through the model. \n",
|
||||||
|
"\n",
|
||||||
|
"Moreover, you might have noticed it generated some additional tensors: \n",
|
||||||
|
"\n",
|
||||||
|
"- token_type_ids: This tensor will map every tokens to their corresponding segment (see below).\n",
|
||||||
|
"- attention_mask: This tensor is used to \"mask\" padded values in a batch of sequence with different lengths (see below)."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 6,
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"is_executing": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"Single segment token (str): ['[CLS]', 'This', 'is', 'a', 'sample', 'input', '[SEP]']\n",
|
||||||
|
"Single segment token (int): [101, 1188, 1110, 170, 6876, 7758, 102]\n",
|
||||||
|
"Single segment type : [0, 0, 0, 0, 0, 0, 0]\n",
|
||||||
|
"\n",
|
||||||
|
"Multi segment token (str): ['[CLS]', 'This', 'is', 'segment', 'A', '[SEP]', 'This', 'is', 'segment', 'B', '[SEP]']\n",
|
||||||
|
"Multi segment token (int): [101, 1188, 1110, 6441, 138, 102, 1188, 1110, 6441, 139, 102]\n",
|
||||||
|
"Multi segment type : [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1]\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# Single segment input\n",
|
||||||
|
"single_seg_input = tokenizer.encode_plus(\"This is a sample input\")\n",
|
||||||
|
"\n",
|
||||||
|
"# Multiple segment input\n",
|
||||||
|
"multi_seg_input = tokenizer.encode_plus(\"This is segment A\", \"This is segment B\")\n",
|
||||||
|
"\n",
|
||||||
|
"print(\"Single segment token (str): {}\".format(tokenizer.convert_ids_to_tokens(single_seg_input['input_ids'])))\n",
|
||||||
|
"print(\"Single segment token (int): {}\".format(single_seg_input['input_ids']))\n",
|
||||||
|
"print(\"Single segment type : {}\".format(single_seg_input['token_type_ids']))\n",
|
||||||
|
"\n",
|
||||||
|
"# Segments are concatened in the input to the model, with \n",
|
||||||
|
"print()\n",
|
||||||
|
"print(\"Multi segment token (str): {}\".format(tokenizer.convert_ids_to_tokens(multi_seg_input['input_ids'])))\n",
|
||||||
|
"print(\"Multi segment token (int): {}\".format(multi_seg_input['input_ids']))\n",
|
||||||
|
"print(\"Multi segment type : {}\".format(multi_seg_input['token_type_ids']))"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 7,
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"is_executing": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"Tokens (int) : [101, 1188, 1110, 170, 6876, 102, 0, 0]\n",
|
||||||
|
"Tokens (str) : ['[CLS]', 'This', 'is', 'a', 'sample', '[SEP]', '[PAD]', '[PAD]']\n",
|
||||||
|
"Tokens (attn_mask): [1, 1, 1, 1, 1, 1, 0, 0]\n",
|
||||||
|
"\n",
|
||||||
|
"Tokens (int) : [101, 1188, 1110, 1330, 2039, 6876, 3087, 102]\n",
|
||||||
|
"Tokens (str) : ['[CLS]', 'This', 'is', 'another', 'longer', 'sample', 'text', '[SEP]']\n",
|
||||||
|
"Tokens (attn_mask): [1, 1, 1, 1, 1, 1, 1, 1]\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# Padding highlight\n",
|
||||||
|
"tokens = tokenizer.batch_encode_plus(\n",
|
||||||
|
" [\"This is a sample\", \"This is another longer sample text\"], \n",
|
||||||
|
" pad_to_max_length=True # First sentence will have some PADDED tokens to match second sequence length\n",
|
||||||
|
")\n",
|
||||||
|
"\n",
|
||||||
|
"for i in range(2):\n",
|
||||||
|
" print(\"Tokens (int) : {}\".format(tokens['input_ids'][i]))\n",
|
||||||
|
" print(\"Tokens (str) : {}\".format([tokenizer.convert_ids_to_tokens(s) for s in tokens['input_ids'][i]]))\n",
|
||||||
|
" print(\"Tokens (attn_mask): {}\".format(tokens['attention_mask'][i]))\n",
|
||||||
|
" print()"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Frameworks interoperability\n",
|
||||||
|
"\n",
|
||||||
|
"One of the most powerfull feature of transformers is its ability to seamlessly move from PyTorch to Tensorflow\n",
|
||||||
|
"without pain for the user.\n",
|
||||||
|
"\n",
|
||||||
|
"We provide some convenient methods to load TensorFlow pretrained weight insinde a PyTorch model and opposite."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"is_executing": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"from transformers import TFBertModel, BertModel\n",
|
||||||
|
"\n",
|
||||||
|
"# Let's load a BERT model for TensorFlow and PyTorch\n",
|
||||||
|
"model_tf = TFBertModel.from_pretrained('bert-base-cased')\n",
|
||||||
|
"model_pt = BertModel.from_pretrained('bert-base-cased')"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"is_executing": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# transformers generates a ready to use dictionary with all the required parameters for the specific framework.\n",
|
||||||
|
"input_tf = tokenizer.encode_plus(\"This is a sample input\", return_tensors=\"tf\")\n",
|
||||||
|
"input_pt = tokenizer.encode_plus(\"This is a sample input\", return_tensors=\"pt\")\n",
|
||||||
|
"\n",
|
||||||
|
"# Let's compare the outputs\n",
|
||||||
|
"output_tf, output_pt = model_tf(input_tf), model_pt(**input_pt)\n",
|
||||||
|
"\n",
|
||||||
|
"# Models outputs 2 values (The value for each tokens, the pooled representation of the input sentence)\n",
|
||||||
|
"# Here we compare the output differences between PyTorch and TensorFlow.\n",
|
||||||
|
"for name, o_tf, o_pt in zip([\"output\", \"pooled\"], output_tf, output_pt):\n",
|
||||||
|
" print(\"{} differences: {}\".format(name, (o_tf.numpy() - o_pt.numpy()).sum()))"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"name": "#%% md\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
"## Want it lighter? Faster? Let's talk distillation! \n",
|
||||||
|
"\n",
|
||||||
|
"One of the main concerns when using these Transformer based models is the computational power they require. All over this notebook we are using BERT model as it can be run on common machines but that's not the case for all of the models.\n",
|
||||||
|
"\n",
|
||||||
|
"For example, Google released a few months ago **T5** an Encoder/Decoder architecture based on Transformer and available in `transformers` with no more than 11 billions parameters. Microsoft also recently entered the game with **Turing-NLG** using 17 billions parameters. This kind of model requires tens of gigabytes to store the weights and a tremendous compute infrastructure to run such models which makes it impracticable for the common man !\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"With the goal of making Transformer-based NLP accessible to everyone we @huggingface developed models that take advantage of a training process called **Distillation** which allows us to drastically reduce the resources needed to run such models with almost zero drop in performances.\n",
|
||||||
|
"\n",
|
||||||
|
"Going over the whole Distillation process is out of the scope of this notebook, but if you want more information on the subject you may refer to [this Medium article written by my colleague Victor SANH, author of DistilBERT paper](https://medium.com/huggingface/distilbert-8cf3380435b5), you might also want to directly have a look at the paper [(Sanh & al., 2019)](https://arxiv.org/abs/1910.01108)\n",
|
||||||
|
"\n",
|
||||||
|
"Of course, in `transformers` we have distilled some models and made them available directly in the library ! "
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"is_executing": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"from transformers import DistilBertModel\n",
|
||||||
|
"\n",
|
||||||
|
"bert_distil = DistilBertModel.from_pretrained('distilbert-base-cased')\n",
|
||||||
|
"input_pt = tokenizer.encode_plus(\n",
|
||||||
|
" 'This is a sample input to demonstrate performance of distiled models especially inference time', \n",
|
||||||
|
" return_tensors=\"pt\"\n",
|
||||||
|
")\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"%time _ = bert_distil(input_pt['input_ids'])\n",
|
||||||
|
"%time _ = model_pt(input_pt['input_ids'])"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Community provided models\n",
|
||||||
|
"\n",
|
||||||
|
"Last but not least, earlier in this notebook we introduced Hugging Face `transformers` as a repository for the NLP community to exchange pretrained models. We wanted to highlight this features and all the possibilities it offers for the end-user.\n",
|
||||||
|
"\n",
|
||||||
|
"To leverage community pretrained models, just provide the organisation name and name of the model to `from_pretrained` and it will do all the magic for you ! \n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"We currently have more 50 models provided by the community and more are added every day, don't hesitate to give it a try !"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"is_executing": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Let's load German BERT from the Bavarian State Library\n",
|
||||||
|
"de_bert = BertModel.from_pretrained(\"dbmdz/bert-base-german-cased\")\n",
|
||||||
|
"de_tokenizer = BertTokenizer.from_pretrained(\"dbmdz/bert-base-german-cased\")\n",
|
||||||
|
"\n",
|
||||||
|
"de_input = de_tokenizer.encode_plus(\n",
|
||||||
|
" \"Hugging Face ist einen französische Firma Mitarbeitern in New-York.\",\n",
|
||||||
|
" return_tensors=\"pt\"\n",
|
||||||
|
")\n",
|
||||||
|
"output_de, pooled_de = de_bert(**de_input)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.7.6"
|
||||||
|
},
|
||||||
|
"pycharm": {
|
||||||
|
"stem_cell": {
|
||||||
|
"cell_type": "raw",
|
||||||
|
"metadata": {
|
||||||
|
"collapsed": false
|
||||||
|
},
|
||||||
|
"source": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 1
|
||||||
|
}
|
||||||
511
notebooks/03-pipelines.ipynb
Normal file
511
notebooks/03-pipelines.ipynb
Normal file
@@ -0,0 +1,511 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"name": "#%% md\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
"## How can I leverage State-of-the-Art Natural Language Models with only one line of code ?"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"name": "#%% md\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
"Newly introduced in transformers v2.3.0, **pipelines** provides a high-level, easy to use,\n",
|
||||||
|
"API for doing inference over a variety of downstream-tasks, including: \n",
|
||||||
|
"\n",
|
||||||
|
"- Sentence Classification (Sentiment Analysis): Indicate if the overall sentence is either positive or negative. _(Binary Classification task or Logitic Regression task)_\n",
|
||||||
|
"- Token Classification (Named Entity Recognition, Part-of-Speech tagging): For each sub-entities _(**tokens**)_ in the input, assign them a label _(Classification task)_.\n",
|
||||||
|
"- Question-Answering: Provided a tuple (question, context) the model should find the span of text in **content** answering the **question**.\n",
|
||||||
|
"- Mask-Filling: Suggests possible word(s) to fill the masked input with respect to the provided **context**.\n",
|
||||||
|
"- Feature Extraction: Maps the input to a higher, multi-dimensional space learned from the data.\n",
|
||||||
|
"\n",
|
||||||
|
"Pipelines encapsulate the overall process of every NLP process:\n",
|
||||||
|
" \n",
|
||||||
|
" 1. Tokenization: Split the initial input into multiple sub-entities with ... properties (i.e. tokens).\n",
|
||||||
|
" 2. Inference: Maps every tokens into a more meaningful representation. \n",
|
||||||
|
" 3. Decoding: Use the above representation to generate and/or extract the final output for the underlying task.\n",
|
||||||
|
"\n",
|
||||||
|
"The overall API is exposed to the end-user through the `pipeline()` method with the following \n",
|
||||||
|
"structure:\n",
|
||||||
|
"\n",
|
||||||
|
"```python\n",
|
||||||
|
"from transformers import pipeline\n",
|
||||||
|
"\n",
|
||||||
|
"# Using default model and tokenizer for the task\n",
|
||||||
|
"pipeline(\"<task-name>\")\n",
|
||||||
|
"\n",
|
||||||
|
"# Using a user-specified model\n",
|
||||||
|
"pipeline(\"<task-name>\", model=\"<model_name>\")\n",
|
||||||
|
"\n",
|
||||||
|
"# Using custom model/tokenizer as str\n",
|
||||||
|
"pipeline('<task-name>', model='<model name>', tokenizer='<tokenizer_name>')\n",
|
||||||
|
"```"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"!pip install transformers"
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"collapsed": false,
|
||||||
|
"pycharm": {
|
||||||
|
"name": "#%% code\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 6,
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"is_executing": false,
|
||||||
|
"name": "#%% code \n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"from __future__ import print_function\n",
|
||||||
|
"import ipywidgets as widgets\n",
|
||||||
|
"from transformers import pipeline"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"name": "#%% md\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
"## 1. Sentence Classification - Sentiment Analysis"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 8,
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"is_executing": false,
|
||||||
|
"name": "#%% code\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": "HBox(children=(FloatProgress(value=0.0, description='Downloading', max=230.0, style=ProgressStyle(description_…",
|
||||||
|
"application/vnd.jupyter.widget-view+json": {
|
||||||
|
"version_major": 2,
|
||||||
|
"version_minor": 0,
|
||||||
|
"model_id": "c9db53f30b9446c0af03268633a966c0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "display_data"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"text": [
|
||||||
|
"\n"
|
||||||
|
],
|
||||||
|
"output_type": "stream"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": "[{'label': 'POSITIVE', 'score': 0.9997656}]"
|
||||||
|
},
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result",
|
||||||
|
"execution_count": 8
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"nlp_sentence_classif = pipeline('sentiment-analysis')\n",
|
||||||
|
"nlp_sentence_classif('Such a nice weather outside !')"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"name": "#%% md\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
"## 2. Token Classification - Named Entity Recognition"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 9,
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"is_executing": false,
|
||||||
|
"name": "#%% code\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": "HBox(children=(FloatProgress(value=0.0, description='Downloading', max=230.0, style=ProgressStyle(description_…",
|
||||||
|
"application/vnd.jupyter.widget-view+json": {
|
||||||
|
"version_major": 2,
|
||||||
|
"version_minor": 0,
|
||||||
|
"model_id": "1e300789e22644f1aed66a5ed60e75c4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "display_data"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"text": [
|
||||||
|
"\n"
|
||||||
|
],
|
||||||
|
"output_type": "stream"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": "[{'word': 'Hu', 'score': 0.9970937967300415, 'entity': 'I-ORG'},\n {'word': '##gging', 'score': 0.9345750212669373, 'entity': 'I-ORG'},\n {'word': 'Face', 'score': 0.9787060022354126, 'entity': 'I-ORG'},\n {'word': 'French', 'score': 0.9981995820999146, 'entity': 'I-MISC'},\n {'word': 'New', 'score': 0.9983047246932983, 'entity': 'I-LOC'},\n {'word': '-', 'score': 0.8913455009460449, 'entity': 'I-LOC'},\n {'word': 'York', 'score': 0.9979523420333862, 'entity': 'I-LOC'}]"
|
||||||
|
},
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result",
|
||||||
|
"execution_count": 9
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"nlp_token_class = pipeline('ner')\n",
|
||||||
|
"nlp_token_class('Hugging Face is a French company based in New-York.')"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 3. Question Answering"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 10,
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"is_executing": false,
|
||||||
|
"name": "#%% code\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": "HBox(children=(FloatProgress(value=0.0, description='Downloading', max=230.0, style=ProgressStyle(description_…",
|
||||||
|
"application/vnd.jupyter.widget-view+json": {
|
||||||
|
"version_major": 2,
|
||||||
|
"version_minor": 0,
|
||||||
|
"model_id": "82aca58f1ea24b4cb37f16402e8a5923"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "display_data"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"text": [
|
||||||
|
"\n"
|
||||||
|
],
|
||||||
|
"output_type": "stream"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stderr",
|
||||||
|
"text": [
|
||||||
|
"convert squad examples to features: 100%|██████████| 1/1 [00:00<00:00, 225.51it/s]\n",
|
||||||
|
"add example index and unique id: 100%|██████████| 1/1 [00:00<00:00, 2158.67it/s]\n"
|
||||||
|
],
|
||||||
|
"output_type": "stream"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": "{'score': 0.9632966867654424, 'start': 42, 'end': 50, 'answer': 'New-York.'}"
|
||||||
|
},
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result",
|
||||||
|
"execution_count": 10
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"nlp_qa = pipeline('question-answering')\n",
|
||||||
|
"nlp_qa(context='Hugging Face is a French company based in New-York.', question='Where is based Hugging Face ?')"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 4. Text Generation - Mask Filling"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 11,
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"is_executing": false,
|
||||||
|
"name": "#%% code\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": "HBox(children=(FloatProgress(value=0.0, description='Downloading', max=230.0, style=ProgressStyle(description_…",
|
||||||
|
"application/vnd.jupyter.widget-view+json": {
|
||||||
|
"version_major": 2,
|
||||||
|
"version_minor": 0,
|
||||||
|
"model_id": "49df2227b4fa4eb28dcdcfc3d9261d0f"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "display_data"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"text": [
|
||||||
|
"\n"
|
||||||
|
],
|
||||||
|
"output_type": "stream"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": "[{'sequence': '<s> Hugging Face is a French company based in Paris</s>',\n 'score': 0.23106691241264343,\n 'token': 2201},\n {'sequence': '<s> Hugging Face is a French company based in Lyon</s>',\n 'score': 0.0819825753569603,\n 'token': 12790},\n {'sequence': '<s> Hugging Face is a French company based in Geneva</s>',\n 'score': 0.04769463092088699,\n 'token': 11559},\n {'sequence': '<s> Hugging Face is a French company based in Brussels</s>',\n 'score': 0.047622501850128174,\n 'token': 6497},\n {'sequence': '<s> Hugging Face is a French company based in France</s>',\n 'score': 0.04130595177412033,\n 'token': 1470}]"
|
||||||
|
},
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result",
|
||||||
|
"execution_count": 11
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"nlp_fill = pipeline('fill-mask')\n",
|
||||||
|
"nlp_fill('Hugging Face is a French company based in <mask>')"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 5. Projection - Features Extraction "
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 12,
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"is_executing": false,
|
||||||
|
"name": "#%% code\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": "HBox(children=(FloatProgress(value=0.0, description='Downloading', max=230.0, style=ProgressStyle(description_…",
|
||||||
|
"application/vnd.jupyter.widget-view+json": {
|
||||||
|
"version_major": 2,
|
||||||
|
"version_minor": 0,
|
||||||
|
"model_id": "2af4cfb19e3243dda014d0f56b48f4b2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "display_data"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"text": [
|
||||||
|
"\n"
|
||||||
|
],
|
||||||
|
"output_type": "stream"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": "(1, 12, 768)"
|
||||||
|
},
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result",
|
||||||
|
"execution_count": 12
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"import numpy as np\n",
|
||||||
|
"nlp_features = pipeline('feature-extraction')\n",
|
||||||
|
"output = nlp_features('Hugging Face is a French company based in Paris')\n",
|
||||||
|
"np.array(output).shape # (Samples, Tokens, Vector Size)\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"name": "#%% md\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
"Alright ! Now you have a nice picture of what is possible through transformers' pipelines, and there is more\n",
|
||||||
|
"to come in future releases. \n",
|
||||||
|
"\n",
|
||||||
|
"In the meantime, you can try the different pipelines with your own inputs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 13,
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"is_executing": false,
|
||||||
|
"name": "#%% code\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": "Dropdown(description='Task:', index=1, options=('sentiment-analysis', 'ner', 'fill_mask'), value='ner')",
|
||||||
|
"application/vnd.jupyter.widget-view+json": {
|
||||||
|
"version_major": 2,
|
||||||
|
"version_minor": 0,
|
||||||
|
"model_id": "10bac065d46f4e4d9a8498dcc8104ecd"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "display_data"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": "Text(value='', description='Your input:', placeholder='Enter something')",
|
||||||
|
"application/vnd.jupyter.widget-view+json": {
|
||||||
|
"version_major": 2,
|
||||||
|
"version_minor": 0,
|
||||||
|
"model_id": "2c5f1411f7a94714bc00f01b0e3b27b2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "display_data"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"task = widgets.Dropdown(\n",
|
||||||
|
" options=['sentiment-analysis', 'ner', 'fill_mask'],\n",
|
||||||
|
" value='ner',\n",
|
||||||
|
" description='Task:',\n",
|
||||||
|
" disabled=False\n",
|
||||||
|
")\n",
|
||||||
|
"\n",
|
||||||
|
"input = widgets.Text(\n",
|
||||||
|
" value='',\n",
|
||||||
|
" placeholder='Enter something',\n",
|
||||||
|
" description='Your input:',\n",
|
||||||
|
" disabled=False\n",
|
||||||
|
")\n",
|
||||||
|
"\n",
|
||||||
|
"def forward(_):\n",
|
||||||
|
" if len(input.value) > 0: \n",
|
||||||
|
" if task.value == 'ner':\n",
|
||||||
|
" output = nlp_token_class(input.value)\n",
|
||||||
|
" elif task.value == 'sentiment-analysis':\n",
|
||||||
|
" output = nlp_sentence_classif(input.value)\n",
|
||||||
|
" else:\n",
|
||||||
|
" if input.value.find('<mask>') == -1:\n",
|
||||||
|
" output = nlp_fill(input.value + ' <mask>')\n",
|
||||||
|
" else:\n",
|
||||||
|
" output = nlp_fill(input.value) \n",
|
||||||
|
" print(output)\n",
|
||||||
|
"\n",
|
||||||
|
"input.on_submit(forward)\n",
|
||||||
|
"display(task, input)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 14,
|
||||||
|
"metadata": {
|
||||||
|
"pycharm": {
|
||||||
|
"is_executing": false,
|
||||||
|
"name": "#%% Question Answering\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": "Textarea(value='Einstein is famous for the general theory of relativity', description='Context:', placeholder=…",
|
||||||
|
"application/vnd.jupyter.widget-view+json": {
|
||||||
|
"version_major": 2,
|
||||||
|
"version_minor": 0,
|
||||||
|
"model_id": "019fde2343634e94b6f32d04f6350ec1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "display_data"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"context = widgets.Textarea(\n",
|
||||||
|
" value='Einstein is famous for the general theory of relativity',\n",
|
||||||
|
" placeholder='Enter something',\n",
|
||||||
|
" description='Context:',\n",
|
||||||
|
" disabled=False\n",
|
||||||
|
")\n",
|
||||||
|
"\n",
|
||||||
|
"query = widgets.Text(\n",
|
||||||
|
" value='Why is Einstein famous for ?',\n",
|
||||||
|
" placeholder='Enter something',\n",
|
||||||
|
" description='Question:',\n",
|
||||||
|
" disabled=False\n",
|
||||||
|
")\n",
|
||||||
|
"\n",
|
||||||
|
"def forward(_):\n",
|
||||||
|
" if len(context.value) > 0 and len(query.value) > 0: \n",
|
||||||
|
" output = nlp_qa(question=query.value, context=context.value) \n",
|
||||||
|
" print(output)\n",
|
||||||
|
"\n",
|
||||||
|
"query.on_submit(forward)\n",
|
||||||
|
"display(context, query)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.7.6"
|
||||||
|
},
|
||||||
|
"pycharm": {
|
||||||
|
"stem_cell": {
|
||||||
|
"cell_type": "raw",
|
||||||
|
"source": [],
|
||||||
|
"metadata": {
|
||||||
|
"collapsed": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 1
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
17
notebooks/README.md
Normal file
17
notebooks/README.md
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# Transformers Notebooks
|
||||||
|
|
||||||
|
You can find here a list of the official notebooks provided by Hugging Face.
|
||||||
|
|
||||||
|
Also, we would like to list here interesting content created by the community.
|
||||||
|
If you wrote some notebook(s) leveraging transformers and would like be listed here, please open a
|
||||||
|
Pull Request and we'll review it so it can be included here.
|
||||||
|
|
||||||
|
|
||||||
|
## Hugging Face's notebooks :hugs:
|
||||||
|
|
||||||
|
| Notebook | Description | |
|
||||||
|
|:----------|:-------------:|------:|
|
||||||
|
| [Getting Started Tokenizers](01-training-tokenizers.ipynb) | How to train and use your very own tokenizer |[](https://colab.research.google.com/github/huggingface/transformers/blob/master/notebooks/01-training-tokenizers.ipynb) |
|
||||||
|
| [Getting Started Transformers](02-transformers.ipynb) | How to easily start using transformers | [](https://colab.research.google.com/github/huggingface/transformers/blob/master/notebooks/02-transformers.ipynb) |
|
||||||
|
| [How to use Pipelines](03-pipelines.ipynb) | Simple and efficient way to use State-of-the-Art models on downstream tasks through transformers | [](https://colab.research.google.com/github/huggingface/transformers/blob/master/notebooks/03-pipelines.ipynb) |
|
||||||
|
| [How to train a language model](https://github.com/huggingface/blog/blob/master/notebooks/01_how_to_train.ipynb)| Highlight all the steps to effectively train Transformer model on custom data | [](https://colab.research.google.com/github/huggingface/blog/blob/master/notebooks/01_how_to_train.ipynb)|
|
||||||
2
setup.py
2
setup.py
@@ -64,7 +64,7 @@ if stale_egg_info.exists():
|
|||||||
extras = {}
|
extras = {}
|
||||||
|
|
||||||
extras["mecab"] = ["mecab-python3"]
|
extras["mecab"] = ["mecab-python3"]
|
||||||
extras["sklearn"] = ["scikit-learn"]
|
extras["sklearn"] = ["scikit-learn==0.22.1"]
|
||||||
extras["tf"] = ["tensorflow"]
|
extras["tf"] = ["tensorflow"]
|
||||||
extras["tf-cpu"] = ["tensorflow-cpu"]
|
extras["tf-cpu"] = ["tensorflow-cpu"]
|
||||||
extras["torch"] = ["torch"]
|
extras["torch"] = ["torch"]
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ if is_sklearn_available():
|
|||||||
|
|
||||||
# Modeling
|
# Modeling
|
||||||
if is_torch_available():
|
if is_torch_available():
|
||||||
from .modeling_utils import PreTrainedModel, prune_layer, Conv1D
|
from .modeling_utils import PreTrainedModel, prune_layer, Conv1D, top_k_top_p_filtering
|
||||||
from .modeling_auto import (
|
from .modeling_auto import (
|
||||||
AutoModel,
|
AutoModel,
|
||||||
AutoModelForPreTraining,
|
AutoModelForPreTraining,
|
||||||
@@ -241,7 +241,7 @@ if is_torch_available():
|
|||||||
CamembertForTokenClassification,
|
CamembertForTokenClassification,
|
||||||
CAMEMBERT_PRETRAINED_MODEL_ARCHIVE_MAP,
|
CAMEMBERT_PRETRAINED_MODEL_ARCHIVE_MAP,
|
||||||
)
|
)
|
||||||
from .modeling_encoder_decoder import PreTrainedEncoderDecoder, Model2Model
|
from .modeling_encoder_decoder import PreTrainedEncoderDecoder
|
||||||
from .modeling_t5 import (
|
from .modeling_t5 import (
|
||||||
T5PreTrainedModel,
|
T5PreTrainedModel,
|
||||||
T5Model,
|
T5Model,
|
||||||
@@ -255,6 +255,7 @@ if is_torch_available():
|
|||||||
AlbertForMaskedLM,
|
AlbertForMaskedLM,
|
||||||
AlbertForSequenceClassification,
|
AlbertForSequenceClassification,
|
||||||
AlbertForQuestionAnswering,
|
AlbertForQuestionAnswering,
|
||||||
|
AlbertForTokenClassification,
|
||||||
load_tf_weights_in_albert,
|
load_tf_weights_in_albert,
|
||||||
ALBERT_PRETRAINED_MODEL_ARCHIVE_MAP,
|
ALBERT_PRETRAINED_MODEL_ARCHIVE_MAP,
|
||||||
)
|
)
|
||||||
@@ -290,7 +291,13 @@ if is_torch_available():
|
|||||||
|
|
||||||
# TensorFlow
|
# TensorFlow
|
||||||
if is_tf_available():
|
if is_tf_available():
|
||||||
from .modeling_tf_utils import TFPreTrainedModel, TFSharedEmbeddings, TFSequenceSummary, shape_list
|
from .modeling_tf_utils import (
|
||||||
|
TFPreTrainedModel,
|
||||||
|
TFSharedEmbeddings,
|
||||||
|
TFSequenceSummary,
|
||||||
|
shape_list,
|
||||||
|
tf_top_k_top_p_filtering,
|
||||||
|
)
|
||||||
from .modeling_tf_auto import (
|
from .modeling_tf_auto import (
|
||||||
TFAutoModel,
|
TFAutoModel,
|
||||||
TFAutoModelForPreTraining,
|
TFAutoModelForPreTraining,
|
||||||
|
|||||||
@@ -22,11 +22,10 @@ from .configuration_utils import PretrainedConfig
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
_bart_large_url = "https://s3.amazonaws.com/models.huggingface.co/bert/facebook/bart-large/config.json"
|
|
||||||
BART_PRETRAINED_CONFIG_ARCHIVE_MAP = {
|
BART_PRETRAINED_CONFIG_ARCHIVE_MAP = {
|
||||||
"bart-large": _bart_large_url,
|
"bart-large": "https://s3.amazonaws.com/models.huggingface.co/bert/facebook/bart-large/config.json",
|
||||||
"bart-large-mnli": _bart_large_url, # fine as same
|
"bart-large-mnli": "https://s3.amazonaws.com/models.huggingface.co/bert/facebook/bart-large-mnli/config.json",
|
||||||
"bart-cnn": None, # not done
|
"bart-large-cnn": "https://s3.amazonaws.com/models.huggingface.co/bert/facebook/bart-large-cnn/config.json",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -59,6 +58,7 @@ class BartConfig(PretrainedConfig):
|
|||||||
classifier_dropout=0.0,
|
classifier_dropout=0.0,
|
||||||
output_past=False,
|
output_past=False,
|
||||||
num_labels=3,
|
num_labels=3,
|
||||||
|
bos_token_id=0,
|
||||||
**common_kwargs
|
**common_kwargs
|
||||||
):
|
):
|
||||||
r"""
|
r"""
|
||||||
@@ -67,12 +67,16 @@ class BartConfig(PretrainedConfig):
|
|||||||
config = BartConfig.from_pretrained('bart-large')
|
config = BartConfig.from_pretrained('bart-large')
|
||||||
model = BartModel(config)
|
model = BartModel(config)
|
||||||
"""
|
"""
|
||||||
super().__init__(num_labels=num_labels, output_past=output_past, pad_token_id=pad_token_id, **common_kwargs)
|
super().__init__(
|
||||||
|
num_labels=num_labels,
|
||||||
|
output_past=output_past,
|
||||||
|
pad_token_id=pad_token_id,
|
||||||
|
bos_token_id=bos_token_id,
|
||||||
|
**common_kwargs,
|
||||||
|
)
|
||||||
self.vocab_size = vocab_size
|
self.vocab_size = vocab_size
|
||||||
self.d_model = d_model # encoder_embed_dim and decoder_embed_dim
|
self.d_model = d_model # encoder_embed_dim and decoder_embed_dim
|
||||||
self.eos_token_id = eos_token_id
|
self.eos_token_id = eos_token_id
|
||||||
|
|
||||||
self.encoder_ffn_dim = encoder_ffn_dim
|
self.encoder_ffn_dim = encoder_ffn_dim
|
||||||
self.encoder_layers = self.num_hidden_layers = encoder_layers
|
self.encoder_layers = self.num_hidden_layers = encoder_layers
|
||||||
self.encoder_attention_heads = encoder_attention_heads
|
self.encoder_attention_heads = encoder_attention_heads
|
||||||
|
|||||||
@@ -109,11 +109,12 @@ class FlaubertConfig(XLMConfig):
|
|||||||
Argument used when doing sequence summary. Used in for the multiple choice head in
|
Argument used when doing sequence summary. Used in for the multiple choice head in
|
||||||
:class:`~transformers.XLMForSequenceClassification`.
|
:class:`~transformers.XLMForSequenceClassification`.
|
||||||
Is one of the following options:
|
Is one of the following options:
|
||||||
- 'last' => take the last token hidden state (like XLNet)
|
|
||||||
- 'first' => take the first token hidden state (like Bert)
|
- 'last' => take the last token hidden state (like XLNet)
|
||||||
- 'mean' => take the mean of all tokens hidden states
|
- 'first' => take the first token hidden state (like Bert)
|
||||||
- 'cls_index' => supply a Tensor of classification token position (GPT/GPT-2)
|
- 'mean' => take the mean of all tokens hidden states
|
||||||
- 'attn' => Not implemented now, use multi-head attention
|
- 'cls_index' => supply a Tensor of classification token position (GPT/GPT-2)
|
||||||
|
- 'attn' => Not implemented now, use multi-head attention
|
||||||
summary_use_proj (:obj:`boolean`, optional, defaults to :obj:`True`):
|
summary_use_proj (:obj:`boolean`, optional, defaults to :obj:`True`):
|
||||||
Argument used when doing sequence summary. Used in for the multiple choice head in
|
Argument used when doing sequence summary. Used in for the multiple choice head in
|
||||||
:class:`~transformers.XLMForSequenceClassification`.
|
:class:`~transformers.XLMForSequenceClassification`.
|
||||||
|
|||||||
@@ -73,11 +73,12 @@ class GPT2Config(PretrainedConfig):
|
|||||||
Argument used when doing sequence summary. Used in for the multiple choice head in
|
Argument used when doing sequence summary. Used in for the multiple choice head in
|
||||||
:class:`~transformers.GPT2DoubleHeadsModel`.
|
:class:`~transformers.GPT2DoubleHeadsModel`.
|
||||||
Is one of the following options:
|
Is one of the following options:
|
||||||
- 'last' => take the last token hidden state (like XLNet)
|
|
||||||
- 'first' => take the first token hidden state (like Bert)
|
- 'last' => take the last token hidden state (like XLNet)
|
||||||
- 'mean' => take the mean of all tokens hidden states
|
- 'first' => take the first token hidden state (like Bert)
|
||||||
- 'cls_index' => supply a Tensor of classification token position (GPT/GPT-2)
|
- 'mean' => take the mean of all tokens hidden states
|
||||||
- 'attn' => Not implemented now, use multi-head attention
|
- 'cls_index' => supply a Tensor of classification token position (GPT/GPT-2)
|
||||||
|
- 'attn' => Not implemented now, use multi-head attention
|
||||||
summary_use_proj (:obj:`boolean`, optional, defaults to :obj:`True`):
|
summary_use_proj (:obj:`boolean`, optional, defaults to :obj:`True`):
|
||||||
Argument used when doing sequence summary. Used in for the multiple choice head in
|
Argument used when doing sequence summary. Used in for the multiple choice head in
|
||||||
:class:`~transformers.GPT2DoubleHeadsModel`.
|
:class:`~transformers.GPT2DoubleHeadsModel`.
|
||||||
|
|||||||
@@ -73,11 +73,12 @@ class OpenAIGPTConfig(PretrainedConfig):
|
|||||||
Argument used when doing sequence summary. Used in for the multiple choice head in
|
Argument used when doing sequence summary. Used in for the multiple choice head in
|
||||||
:class:`~transformers.OpenAIGPTDoubleHeadsModel`.
|
:class:`~transformers.OpenAIGPTDoubleHeadsModel`.
|
||||||
Is one of the following options:
|
Is one of the following options:
|
||||||
- 'last' => take the last token hidden state (like XLNet)
|
|
||||||
- 'first' => take the first token hidden state (like Bert)
|
- 'last' => take the last token hidden state (like XLNet)
|
||||||
- 'mean' => take the mean of all tokens hidden states
|
- 'first' => take the first token hidden state (like Bert)
|
||||||
- 'cls_index' => supply a Tensor of classification token position (GPT/GPT-2)
|
- 'mean' => take the mean of all tokens hidden states
|
||||||
- 'attn' => Not implemented now, use multi-head attention
|
- 'cls_index' => supply a Tensor of classification token position (GPT/GPT-2)
|
||||||
|
- 'attn' => Not implemented now, use multi-head attention
|
||||||
summary_use_proj (:obj:`boolean`, optional, defaults to :obj:`True`):
|
summary_use_proj (:obj:`boolean`, optional, defaults to :obj:`True`):
|
||||||
Argument used when doing sequence summary. Used in for the multiple choice head in
|
Argument used when doing sequence summary. Used in for the multiple choice head in
|
||||||
:class:`~transformers.OpenAIGPTDoubleHeadsModel`.
|
:class:`~transformers.OpenAIGPTDoubleHeadsModel`.
|
||||||
|
|||||||
@@ -98,6 +98,18 @@ class PretrainedConfig(object):
|
|||||||
logger.error("Can't set {} with value {} for {}".format(key, value, self))
|
logger.error("Can't set {} with value {} for {}".format(key, value, self))
|
||||||
raise err
|
raise err
|
||||||
|
|
||||||
|
@property
|
||||||
|
def num_labels(self):
|
||||||
|
return self._num_labels
|
||||||
|
|
||||||
|
@num_labels.setter
|
||||||
|
def num_labels(self, num_labels):
|
||||||
|
self._num_labels = num_labels
|
||||||
|
self.id2label = {i: "LABEL_{}".format(i) for i in range(self.num_labels)}
|
||||||
|
self.id2label = dict((int(key), value) for key, value in self.id2label.items())
|
||||||
|
self.label2id = dict(zip(self.id2label.values(), self.id2label.keys()))
|
||||||
|
self.label2id = dict((key, int(value)) for key, value in self.label2id.items())
|
||||||
|
|
||||||
def save_pretrained(self, save_directory):
|
def save_pretrained(self, save_directory):
|
||||||
"""
|
"""
|
||||||
Save a configuration object to the directory `save_directory`, so that it
|
Save a configuration object to the directory `save_directory`, so that it
|
||||||
|
|||||||
@@ -108,11 +108,12 @@ class XLMConfig(PretrainedConfig):
|
|||||||
Argument used when doing sequence summary. Used in for the multiple choice head in
|
Argument used when doing sequence summary. Used in for the multiple choice head in
|
||||||
:class:`~transformers.XLMForSequenceClassification`.
|
:class:`~transformers.XLMForSequenceClassification`.
|
||||||
Is one of the following options:
|
Is one of the following options:
|
||||||
- 'last' => take the last token hidden state (like XLNet)
|
|
||||||
- 'first' => take the first token hidden state (like Bert)
|
- 'last' => take the last token hidden state (like XLNet)
|
||||||
- 'mean' => take the mean of all tokens hidden states
|
- 'first' => take the first token hidden state (like Bert)
|
||||||
- 'cls_index' => supply a Tensor of classification token position (GPT/GPT-2)
|
- 'mean' => take the mean of all tokens hidden states
|
||||||
- 'attn' => Not implemented now, use multi-head attention
|
- 'cls_index' => supply a Tensor of classification token position (GPT/GPT-2)
|
||||||
|
- 'attn' => Not implemented now, use multi-head attention
|
||||||
summary_use_proj (:obj:`boolean`, optional, defaults to :obj:`True`):
|
summary_use_proj (:obj:`boolean`, optional, defaults to :obj:`True`):
|
||||||
Argument used when doing sequence summary. Used in for the multiple choice head in
|
Argument used when doing sequence summary. Used in for the multiple choice head in
|
||||||
:class:`~transformers.XLMForSequenceClassification`.
|
:class:`~transformers.XLMForSequenceClassification`.
|
||||||
|
|||||||
@@ -23,9 +23,11 @@ import fairseq
|
|||||||
import torch
|
import torch
|
||||||
from packaging import version
|
from packaging import version
|
||||||
|
|
||||||
from transformers import BartConfig, BartForSequenceClassification, BartModel, BartTokenizer
|
from transformers import BartConfig, BartForMaskedLM, BartForSequenceClassification, BartModel, BartTokenizer
|
||||||
|
|
||||||
|
|
||||||
|
FAIRSEQ_MODELS = ["bart.large", "bart.large.mnli", "bart.large.cnn"]
|
||||||
|
|
||||||
if version.parse(fairseq.__version__) < version.parse("0.9.0"):
|
if version.parse(fairseq.__version__) < version.parse("0.9.0"):
|
||||||
raise Exception("requires fairseq >= 0.9.0")
|
raise Exception("requires fairseq >= 0.9.0")
|
||||||
|
|
||||||
@@ -33,7 +35,7 @@ if version.parse(fairseq.__version__) < version.parse("0.9.0"):
|
|||||||
logging.basicConfig(level=logging.INFO)
|
logging.basicConfig(level=logging.INFO)
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
SAMPLE_TEXT = "Hello world! cécé herlolip"
|
SAMPLE_TEXT = " Hello world! cécé herlolip"
|
||||||
|
|
||||||
rename_keys = [
|
rename_keys = [
|
||||||
("model.classification_heads.mnli.dense.weight", "classification_head.dense.weight"),
|
("model.classification_heads.mnli.dense.weight", "classification_head.dense.weight"),
|
||||||
@@ -41,7 +43,7 @@ rename_keys = [
|
|||||||
("model.classification_heads.mnli.out_proj.weight", "classification_head.out_proj.weight"),
|
("model.classification_heads.mnli.out_proj.weight", "classification_head.out_proj.weight"),
|
||||||
("model.classification_heads.mnli.out_proj.bias", "classification_head.out_proj.bias"),
|
("model.classification_heads.mnli.out_proj.bias", "classification_head.out_proj.bias"),
|
||||||
]
|
]
|
||||||
IGNORE_KEYS = ["encoder.version", "decoder.version", "model.encoder.version", "model.decoder.version"]
|
IGNORE_KEYS = ["encoder.version", "decoder.version", "model.encoder.version", "model.decoder.version", "_float_tensor"]
|
||||||
|
|
||||||
|
|
||||||
def rename_key(dct, old, new):
|
def rename_key(dct, old, new):
|
||||||
@@ -53,36 +55,45 @@ def convert_bart_checkpoint(checkpoint_path, pytorch_dump_folder_path):
|
|||||||
"""
|
"""
|
||||||
Copy/paste/tweak model's weights to our BERT structure.
|
Copy/paste/tweak model's weights to our BERT structure.
|
||||||
"""
|
"""
|
||||||
b2 = torch.hub.load("pytorch/fairseq", checkpoint_path)
|
bart = torch.hub.load("pytorch/fairseq", checkpoint_path)
|
||||||
b2.eval() # disable dropout
|
bart.eval() # disable dropout
|
||||||
b2.model.upgrade_state_dict(b2.model.state_dict())
|
bart.model.upgrade_state_dict(bart.model.state_dict())
|
||||||
config = BartConfig()
|
hf_model_name = checkpoint_path.replace(".", "-")
|
||||||
tokens = b2.encode(SAMPLE_TEXT).unsqueeze(0)
|
config = BartConfig.from_pretrained(hf_model_name)
|
||||||
tokens2 = BartTokenizer.from_pretrained("bart-large").encode(SAMPLE_TEXT).unsqueeze(0)
|
tokens = bart.encode(SAMPLE_TEXT).unsqueeze(0)
|
||||||
|
tokens2 = BartTokenizer.from_pretrained(hf_model_name).encode(SAMPLE_TEXT, return_tensors="pt").unsqueeze(0)
|
||||||
assert torch.eq(tokens, tokens2).all()
|
assert torch.eq(tokens, tokens2).all()
|
||||||
|
|
||||||
# assert their_output.size() == (1, 11, 1024)
|
if checkpoint_path in ["bart.large", "bart.large.cnn"]:
|
||||||
|
state_dict = bart.model.state_dict()
|
||||||
if checkpoint_path == "bart.large":
|
for k in IGNORE_KEYS:
|
||||||
state_dict = b2.model.state_dict()
|
state_dict.pop(k, None)
|
||||||
state_dict["shared.weight"] = state_dict["decoder.embed_tokens.weight"]
|
state_dict["shared.weight"] = state_dict["decoder.embed_tokens.weight"]
|
||||||
model = BartModel(config)
|
model = BartModel(config)
|
||||||
their_output = b2.extract_features(tokens)
|
their_output = bart.extract_features(tokens)
|
||||||
|
|
||||||
else: # MNLI Case
|
else: # MNLI Case
|
||||||
state_dict = b2.state_dict()
|
state_dict = bart.state_dict()
|
||||||
|
for k in IGNORE_KEYS:
|
||||||
|
state_dict.pop(k, None)
|
||||||
state_dict["model.shared.weight"] = state_dict["model.decoder.embed_tokens.weight"]
|
state_dict["model.shared.weight"] = state_dict["model.decoder.embed_tokens.weight"]
|
||||||
for src, dest in rename_keys:
|
for src, dest in rename_keys:
|
||||||
rename_key(state_dict, src, dest)
|
rename_key(state_dict, src, dest)
|
||||||
state_dict.pop("_float_tensor", None)
|
|
||||||
model = BartForSequenceClassification(config)
|
model = BartForSequenceClassification(config)
|
||||||
their_output = b2.predict("mnli", tokens, return_logits=True)
|
their_output = bart.predict("mnli", tokens, return_logits=True)
|
||||||
for k in IGNORE_KEYS:
|
|
||||||
state_dict.pop(k, None)
|
# Load state dict
|
||||||
model.load_state_dict(state_dict)
|
model.load_state_dict(state_dict)
|
||||||
model.eval()
|
model.eval()
|
||||||
our_outputs = model.forward(tokens)[0]
|
# Check results
|
||||||
|
|
||||||
|
if checkpoint_path == "bart.large.cnn": # generate doesnt work yet
|
||||||
|
model = BartForMaskedLM(config, base_model=model)
|
||||||
|
assert "lm_head.weight" in model.state_dict()
|
||||||
|
assert model.lm_head.out_features == config.max_position_embeddings
|
||||||
|
model.eval()
|
||||||
|
our_outputs = model.model.forward(tokens)[0]
|
||||||
|
else:
|
||||||
|
our_outputs = model.forward(tokens)[0]
|
||||||
assert their_output.shape == our_outputs.shape
|
assert their_output.shape == our_outputs.shape
|
||||||
assert (their_output == our_outputs).all().item()
|
assert (their_output == our_outputs).all().item()
|
||||||
Path(pytorch_dump_folder_path).mkdir(exist_ok=True)
|
Path(pytorch_dump_folder_path).mkdir(exist_ok=True)
|
||||||
@@ -92,7 +103,8 @@ def convert_bart_checkpoint(checkpoint_path, pytorch_dump_folder_path):
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
# Required parameters
|
# Required parameters
|
||||||
parser.add_argument("fairseq_path", choices=["bart.large", "bart.large.mnli"], type=str, help="")
|
parser.add_argument("fairseq_path", choices=FAIRSEQ_MODELS, type=str, help="")
|
||||||
|
|
||||||
parser.add_argument("pytorch_dump_folder_path", default=None, type=str, help="Path to the output PyTorch model.")
|
parser.add_argument("pytorch_dump_folder_path", default=None, type=str, help="Path to the output PyTorch model.")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
convert_bart_checkpoint(
|
convert_bart_checkpoint(
|
||||||
|
|||||||
@@ -46,7 +46,9 @@ logger = logging.getLogger(__name__)
|
|||||||
SAMPLE_TEXT = "Hello world! cécé herlolip"
|
SAMPLE_TEXT = "Hello world! cécé herlolip"
|
||||||
|
|
||||||
|
|
||||||
def convert_roberta_checkpoint_to_pytorch(roberta_checkpoint_path, pytorch_dump_folder_path, classification_head):
|
def convert_roberta_checkpoint_to_pytorch(
|
||||||
|
roberta_checkpoint_path: str, pytorch_dump_folder_path: str, classification_head: bool
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
Copy/paste/tweak roberta's weights to our BERT structure.
|
Copy/paste/tweak roberta's weights to our BERT structure.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -788,6 +788,103 @@ class AlbertForSequenceClassification(AlbertPreTrainedModel):
|
|||||||
return outputs # (loss), logits, (hidden_states), (attentions)
|
return outputs # (loss), logits, (hidden_states), (attentions)
|
||||||
|
|
||||||
|
|
||||||
|
@add_start_docstrings(
|
||||||
|
"""Albert Model with a token classification head on top (a linear layer on top of
|
||||||
|
the hidden-states output) e.g. for Named-Entity-Recognition (NER) tasks. """,
|
||||||
|
ALBERT_START_DOCSTRING,
|
||||||
|
)
|
||||||
|
class AlbertForTokenClassification(AlbertPreTrainedModel):
|
||||||
|
def __init__(self, config):
|
||||||
|
super().__init__(config)
|
||||||
|
self.num_labels = config.num_labels
|
||||||
|
|
||||||
|
self.albert = AlbertModel(config)
|
||||||
|
self.dropout = nn.Dropout(config.hidden_dropout_prob)
|
||||||
|
self.classifier = nn.Linear(config.hidden_size, self.config.num_labels)
|
||||||
|
|
||||||
|
self.init_weights()
|
||||||
|
|
||||||
|
@add_start_docstrings_to_callable(ALBERT_INPUTS_DOCSTRING)
|
||||||
|
def forward(
|
||||||
|
self,
|
||||||
|
input_ids=None,
|
||||||
|
attention_mask=None,
|
||||||
|
token_type_ids=None,
|
||||||
|
position_ids=None,
|
||||||
|
head_mask=None,
|
||||||
|
inputs_embeds=None,
|
||||||
|
labels=None,
|
||||||
|
):
|
||||||
|
r"""
|
||||||
|
labels (:obj:`torch.LongTensor` of shape :obj:`(batch_size, sequence_length)`, `optional`, defaults to :obj:`None`):
|
||||||
|
Labels for computing the token classification loss.
|
||||||
|
Indices should be in ``[0, ..., config.num_labels - 1]``.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
:obj:`tuple(torch.FloatTensor)` comprising various elements depending on the configuration (:class:`~transformers.AlbertConfig`) and inputs:
|
||||||
|
loss (:obj:`torch.FloatTensor` of shape :obj:`(1,)`, `optional`, returned when ``labels`` is provided) :
|
||||||
|
Classification loss.
|
||||||
|
scores (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, sequence_length, config.num_labels)`)
|
||||||
|
Classification scores (before SoftMax).
|
||||||
|
hidden_states (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_hidden_states=True``):
|
||||||
|
Tuple of :obj:`torch.FloatTensor` (one for the output of the embeddings + one for the output of each layer)
|
||||||
|
of shape :obj:`(batch_size, sequence_length, hidden_size)`.
|
||||||
|
|
||||||
|
Hidden-states of the model at the output of each layer plus the initial embedding outputs.
|
||||||
|
attentions (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_attentions=True``):
|
||||||
|
Tuple of :obj:`torch.FloatTensor` (one for each layer) of shape
|
||||||
|
:obj:`(batch_size, num_heads, sequence_length, sequence_length)`.
|
||||||
|
|
||||||
|
Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
|
||||||
|
heads.
|
||||||
|
|
||||||
|
Examples::
|
||||||
|
|
||||||
|
from transformers import AlbertTokenizer, AlbertForTokenClassification
|
||||||
|
import torch
|
||||||
|
|
||||||
|
tokenizer = AlbertTokenizer.from_pretrained('albert-base-v2')
|
||||||
|
model = AlbertForTokenClassification.from_pretrained('albert-base-v2')
|
||||||
|
|
||||||
|
input_ids = torch.tensor(tokenizer.encode("Hello, my dog is cute", add_special_tokens=True)).unsqueeze(0) # Batch size 1
|
||||||
|
labels = torch.tensor([1] * input_ids.size(1)).unsqueeze(0) # Batch size 1
|
||||||
|
outputs = model(input_ids, labels=labels)
|
||||||
|
|
||||||
|
loss, scores = outputs[:2]
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
outputs = self.albert(
|
||||||
|
input_ids,
|
||||||
|
attention_mask=attention_mask,
|
||||||
|
token_type_ids=token_type_ids,
|
||||||
|
position_ids=position_ids,
|
||||||
|
head_mask=head_mask,
|
||||||
|
inputs_embeds=inputs_embeds,
|
||||||
|
)
|
||||||
|
|
||||||
|
sequence_output = outputs[0]
|
||||||
|
|
||||||
|
sequence_output = self.dropout(sequence_output)
|
||||||
|
logits = self.classifier(sequence_output)
|
||||||
|
|
||||||
|
outputs = (logits,) + outputs[2:] # add hidden states and attention if they are here
|
||||||
|
|
||||||
|
if labels is not None:
|
||||||
|
loss_fct = CrossEntropyLoss()
|
||||||
|
# Only keep active parts of the loss
|
||||||
|
if attention_mask is not None:
|
||||||
|
active_loss = attention_mask.view(-1) == 1
|
||||||
|
active_logits = logits.view(-1, self.num_labels)[active_loss]
|
||||||
|
active_labels = labels.view(-1)[active_loss]
|
||||||
|
loss = loss_fct(active_logits, active_labels)
|
||||||
|
else:
|
||||||
|
loss = loss_fct(logits.view(-1, self.num_labels), labels.view(-1))
|
||||||
|
outputs = (loss,) + outputs
|
||||||
|
|
||||||
|
return outputs # (loss), logits, (hidden_states), (attentions)
|
||||||
|
|
||||||
|
|
||||||
@add_start_docstrings(
|
@add_start_docstrings(
|
||||||
"""Albert Model with a span classification head on top for extractive question-answering tasks like SQuAD (a linear layers on top of
|
"""Albert Model with a span classification head on top for extractive question-answering tasks like SQuAD (a linear layers on top of
|
||||||
the hidden-states output to compute `span start logits` and `span end logits`). """,
|
the hidden-states output to compute `span start logits` and `span end logits`). """,
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user