From b4ce4adb77dca8836b13bad980a68fe8b8751c2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=95=B7=E6=BE=A4=E6=98=A5=E5=B8=8C?= Date: Fri, 25 Nov 2022 00:32:11 +0900 Subject: [PATCH] removed original English lines --- chapters/ja/chapter2/4.mdx | 86 +---- chapters/ja/chapter2/5.mdx | 744 ++----------------------------------- 2 files changed, 52 insertions(+), 778 deletions(-) diff --git a/chapters/ja/chapter2/4.mdx b/chapters/ja/chapter2/4.mdx index 1823ba774..0c2fa5c53 100644 --- a/chapters/ja/chapter2/4.mdx +++ b/chapters/ja/chapter2/4.mdx @@ -1,6 +1,6 @@ -# Tokenizers(トークナイザ) +# トークナイザ {#if fw === 'pt'} @@ -24,36 +24,30 @@ -Tokenizers are one of the core components of the NLP pipeline. They serve one purpose: to translate text into data that can be processed by the model. Models can only process numbers, so tokenizers need to convert our text inputs to numerical data. In this section, we'll explore exactly what happens in the tokenization pipeline. -トークナイザはNLPパイプラインの重要な構成要素の1つです。トークナイザの目的は1つで、テキストをモデルが処理できるデータに変換することです。モデルが処理できるのは数値のみなので、トークナイザはテキストの入力を数値データに変換する必要があります。このセクションでは、トークン化パイプラインで何が起きているのかを具体的に説明します。 +トークナイザはNLPパイプラインの重要な構成要素の1つです。トークナイザの目的は1つで、テキストをモデルが処理できるデータに変換することです。モデルが処理できるのは数値のみなので、トークナイザは入力されたテキストを数値データに変換する必要があります。このセクションでは、トークン化パイプラインで何が起きているのかを具体的に説明します。 -In NLP tasks, the data that is generally processed is raw text. Here's an example of such text: -NLPのタスクでは、一般的に処理されるデータは生文です。以下はその例です。 +NLPのタスクにおいて、一般的に処理されるデータは生文で、以下はその例です。 ``` Jim Henson was a puppeteer (Jim Hensonは人形師でした) ``` -However, models can only process numbers, so we need to find a way to convert the raw text to numbers. That's what the tokenizers do, and there are a lot of ways to go about this. The goal is to find the most meaningful representation — that is, the one that makes the most sense to the model — and, if possible, the smallest representation. -しかしながらモデルが処理できるのは数値のみなので、生文を数値に変換する方法を見つける必要があります。トークナイザはまさにこの役割を担っているものであり、変換にはさまざまな方法があります。目的はモデルにとって最も意味のある表現を見つけることです。そして可能であれば、最小な表現を見つけることも目的としています。 +しかしながらモデルが処理できるのは数値のみなので、生文を数値に変換する方法を考える必要があります。トークナイザはまさにこの役割を担っているものであり、変換にはさまざまな方法があります。目的はモデルにとって最も意味のある表現を見つけることです。そして可能な限り、最小な表現を見つけることも目的としています。 -Let's take a look at some examples of tokenization algorithms, and try to answer some of the questions you may have about tokenization. ここではトークン化アルゴリズムの例をいくつか見ながら、トークン化に関する疑問を解消していきます。 ## 単語ベース -The first type of tokenizer that comes to mind is _word-based_. It's generally very easy to set up and use with only a few rules, and it often yields decent results. For example, in the image below, the goal is to split the raw text into words and find a numerical representation for each of them: -最初に思い浮かぶトークナイズ方法は、_単語ベース_ です。一般に、いくつかのルールを設定するだけで非常に簡単に使用でき、そして多くの場合において適切な結果を得ることができます。例えば以下の画像では、生のテキストを単語に分割し、それぞれの数値表現を見つけることが目的です。 +最初に思い浮かぶトークナイズ方法は、_単語ベース_ のものです。一般に、いくつかのルールを設定するだけで非常に簡単に使用でき、そして多くの場合において適切な結果を得ることができます。例えば以下の画像のように、生のテキストを単語に分割し、それぞれの数値表現を見つけることが目的です。
An example of word-based tokenization.
-There are different ways to split the text. For example, we could could use whitespace to tokenize the text into words by applying Python's `split()` function: -テキストの分け方にはさまざまな種類があります。例えば、Pythonの `split()` 関数を適用して、テキストを空白区切ることで単語に分割することができます。 +テキストの分け方にはさまざまな種類があります。例えば、Pythonの `split()` 関数を適用して、テキストを空白で区切ることで単語に分割することができます。 ```py tokenized_text = "Jim Henson was a puppeteer".split() @@ -64,35 +58,25 @@ print(tokenized_text) ['Jim', 'Henson', 'was', 'a', 'puppeteer'] ``` -There are also variations of word tokenizers that have extra rules for punctuation. With this kind of tokenizer, we can end up with some pretty large "vocabularies," where a vocabulary is defined by the total number of independent tokens that we have in our corpus. -また、単語トークン化には、句読点に関する特別なルールを持つものもあります。この種のトークナイザを使用すると、かなり大きな「語彙」を作成することができます。語彙は、コーパスに含まれるトークンの総数で定義されます。 +また、単語トークン化には句読点に関する特別なルールを持つものもあります。この種のトークナイザを使用すると、かなり大きな「語彙」が作成されることになります。語彙は、コーパスに含まれるトークンの総数で定義されます。 -Each word gets assigned an ID, starting from 0 and going up to the size of the vocabulary. The model uses these IDs to identify each word. -各単語には個別のID(0〜語彙のサイズ)が割り当てられます。モデルはこれらのIDを使用して各単語を識別します。 +各単語には個別のID(0〜語彙のサイズの数値)が割り当てられます。モデルはこれらのIDを使用して各単語を識別します。 -If we want to completely cover a language with a word-based tokenizer, we'll need to have an identifier for each word in the language, which will generate a huge amount of tokens. For example, there are over 500,000 words in the English language, so to build a map from each word to an input ID we'd need to keep track of that many IDs. Furthermore, words like "dog" are represented differently from words like "dogs", and the model will initially have no way of knowing that "dog" and "dogs" are similar: it will identify the two words as unrelated. The same applies to other similar words, like "run" and "running", which the model will not see as being similar initially. -単語ベースのトークナイザで言語を完全にカバーしようとすると、その言語の各単語に対応する識別子(ID)が必要になり、膨大な量のトークンが生成されることになります。例えば、英語には50万語以上の単語があるので、各単語から入力IDへのマップ(対応表)を作るには、それだけのIDを記録しておく必要があります。また、「dog」のような単語と「dogs」のような単語は表現が異なるため、モデルは最初 "dog" と "dogs" が似ていることを知ることができず、無関係な単語として認識してしまいます。また、"run" と "running" のような類似した単語についても同様で、モデルは初期状態では類似しているとは認識できません。 +単語ベースのトークナイザで言語を完全にカバーしようとすると、その言語の各単語に対応する識別子(ID)が必要になり、膨大な量のトークンが生成されることになります。例えば、英語には50万語以上の単語があるので、各単語から入力IDへのマップ(対応表)を作るには、それだけのIDを記録しておく必要があります。また、「dog」のような単語と「dogs」のような単語は表現が異なるため、モデルは初め "dog" と "dogs" が似ていることを知ることができず、無関係な単語として認識してしまいます。また、"run" と "running" のような類似した単語についても同様で、モデルは初期状態では類似しているとは認識できません。 -Finally, we need a custom token to represent words that are not in our vocabulary. This is known as the "unknown" token, often represented as "[UNK]" or "<unk>". It's generally a bad sign if you see that the tokenizer is producing a lot of these tokens, as it wasn't able to retrieve a sensible representation of a word and you're losing information along the way. The goal when crafting the vocabulary is to do it in such a way that the tokenizer tokenizes as few words as possible into the unknown token. 最後に、語彙にない単語 (未知語)を表すためのトークンが必要です。これは "unknown" トークンと呼ばれ、"[UNK]" や "<unk>" として表されます。トークナイザが多くの unknown トークンを生成している場合、単語の適切な表現を取得できず、情報が失われていると解釈できます。語彙を作成する際の目標は、unknownトークンにトークン化されてしまう単語(未知語)がより少なくなるようにすることです。 -One way to reduce the amount of unknown tokens is to go one level deeper, using a _character-based_ tokenizer. unknown トークンの総数を減らす方法の1つは、_文字ベース_ のトークナイザを使用することです。 ## 文字ベース -Character-based tokenizers split the text into characters, rather than words. This has two primary benefits: _文字ベース_ トークナイザはテキストを単語単位ではなく文字単位で分割します。これには2つの主な利点があります。 -- The vocabulary is much smaller. -- There are much fewer out-of-vocabulary (unknown) tokens, since every word can be built from characters. +- 語彙サイズがはるかに小さくなります +- すべての単語は文字で構成されるため、語彙外のトークン(未知語)がはるかに少なくなります -- 語彙サイズがはるかに小さくなります。 -- すべての単語は文字で構成されるため、語彙外の (unknown) トークンがはるかに少なくなります。 - -But here too some questions arise concerning spaces and punctuation: しかし、ここでも空白と句読点に関する問題が発生します。
@@ -100,26 +84,20 @@ But here too some questions arise concerning spaces and punctuation:
-This approach isn't perfect either. Since the representation is now based on characters rather than words, one could argue that, intuitively, it's less meaningful: each character doesn't mean a lot on its own, whereas that is the case with words. However, this again differs according to the language; in Chinese, for example, each character carries more information than a character in a Latin language. このアプローチも先と同様、完璧なものではありません。ここでは、表現が単語ではなく文字に基づいているので、直感的にはテキストの意味をうまく汲み取れないとも考えられます。各文字は単独ではあまり意味を持たないのに対し、単語はそのようなことはありません。しかし、言語によってはここでも違いがあります。例えば中国語の各文字は、ラテン語の文字よりも情報を持っています。(漢字1文字とアルファベット1文字では、表現している情報量が異なる場合がありますね。) -Another thing to consider is that we'll end up with a very large amount of tokens to be processed by our model: whereas a word would only be a single token with a word-based tokenizer, it can easily turn into 10 or more tokens when converted into characters. 考慮すべきもう1つの点としては、モデルが処理する必要があるトークンの数が非常に多くなってしまうことです。単語ベースのトークナイザでは、単語は1つのトークンになりますが、文字ベースのトークナイザでは、単語は10個以上のトークンに変換される可能性があります。 -To get the best of both worlds, we can use a third technique that combines the two approaches: *subword tokenization*. 両者のいいとこ取りをするために、これらのアプローチを組み合わせた第3の手法を使用することができます。それが *サブワードトークン化* です。 ## サブワードトークン化 -Subword tokenization algorithms rely on the principle that frequently used words should not be split into smaller subwords, but rare words should be decomposed into meaningful subwords. -サーブワードトークン化アルゴリズムは、「出現頻度の高い単語は小さなサブワードに分割されるべきではないが、出現頻度の低い単語は意味のあるサブワードに分割されるべきである」という原理に基づいています。 +サーブワードトークン化アルゴリズムは、「出現頻度の高い単語は小さなサブワードに分割されるべきではないが、出現頻度の低い単語は、意味を持ったサブワードに分割されるべきである」という原理に基づいています。 -For instance, "annoyingly" might be considered a rare word and could be decomposed into "annoying" and "ly". These are both likely to appear more frequently as standalone subwords, while at the same time the meaning of "annoyingly" is kept by the composite meaning of "annoying" and "ly". 例えば "annoyingly" は出現頻度の低い単語として扱われ、"annoying" と "ly" に分割されることがあります。これら2つのサブワードは、それぞれ単独で頻繁に出現する可能性がありますが、一方で "annoyingly" は稀な単語なので、その意味を "annoying" と "ly" の合成語として表現しようという考え方になります。 -Here is an example showing how a subword tokenization algorithm would tokenize the sequence "Let's do tokenization!": それではここで、サブワードトークン化アルゴリズムが "Let's do tokenization!" という系列をトークン化する様子を見てみましょう。
@@ -127,35 +105,25 @@ Here is an example showing how a subword tokenization algorithm would tokenize t
-These subwords end up providing a lot of semantic meaning: for instance, in the example above "tokenization" was split into "token" and "ization", two tokens that have a semantic meaning while being space-efficient (only two tokens are needed to represent a long word). This allows us to have relatively good coverage with small vocabularies, and close to no unknown tokens. これらのサブワードは最終的に、うまく意味を表現したものとして機能します。例えば上の例では "tokenization" は "token" と "ization" に分割されていましたが、これら2つのトークンは、空間効率が良く(2つのトークンだけで長い単語を表現できている)、意味論的にも有意なものとなっています。これにより、比較的小さな語彙で多くの単語をカバーすることができ、未知語がほとんど出ないようになります。 -This approach is especially useful in agglutinative languages such as Turkish, where you can form (almost) arbitrarily long complex words by stringing together subwords. このアプローチはトルコ語などの膠着語(機能語が自立語にくっついて文が構成される言語)において特に有効です。トルコ語では、サブワードを繋げることで(ほぼ)任意の長さの合成語を作ることができます。 ### さらなるトークン化手法! -Unsurprisingly, there are many more techniques out there. To name a few: 実は他にも多くのトークン化手法が存在し、例えば以下のようなものがあります。 -- Byte-level BPE, as used in GPT-2 -- WordPiece, as used in BERT -- SentencePiece or Unigram, as used in several multilingual models - - Byte-level BPE: GPT-2で使用される手法 - WordPiece: BERTで使用される手法 - SentencePiece もしくは Unigram: いくつかの多言語モデルで使用される手法 -You should now have sufficient knowledge of how tokenizers work to get started with the API. ここまで読めば、APIを使ってトークナイザを使い始めるために必要な知識は十分に身についていると思います! ## 読み込みと保存 -Loading and saving tokenizers is as simple as it is with models. Actually, it's based on the same two methods: `from_pretrained()` and `save_pretrained()`. These methods will load or save the algorithm used by the tokenizer (a bit like the *architecture* of the model) as well as its vocabulary (a bit like the *weights* of the model). トークナイザの読み込みと保存は、モデルと同様に簡単です。実際、これらは同じ2つのメソッド `from_pretrained()` と `save_pretrained()` に基づいています。これらのメソッドは、トークナイザが使用するアルゴリズム(モデルでいう *アーキテクチャ*)と、語彙(モデルでいう *重み*)を読み込むか保存するかを決定します。 -Loading the BERT tokenizer trained with the same checkpoint as BERT is done the same way as loading the model, except we use the `BertTokenizer` class: -BERTとなじチェックポイントで学習されたBERTトークナイザを読み込む方法は、モデルでの読み込み方法と同じです。ただし、`BertTokenizer` クラスを使う点だけが異なります。 +BERTと同じチェックポイントで学習されたBERTトークナイザを読み込む方法は、モデルでの読み込み方法と同じです。ただし、`BertTokenizer` クラスを使う点だけが異なります。 ```py from transformers import BertTokenizer @@ -164,11 +132,9 @@ tokenizer = BertTokenizer.from_pretrained("bert-base-cased") ``` {#if fw === 'pt'} -Similar to `AutoModel`, the `AutoTokenizer` class will grab the proper tokenizer class in the library based on the checkpoint name, and can be used directly with any checkpoint: `AutoModel` と同様に、`AutoTokenizer` クラスはチェックポイント名に基づいてライブラリ内の適切なトークナイザクラスを取得し、任意のチェックポイントを直接使用することができます。 {:else} -Similar to `TFAutoModel`, the `AutoTokenizer` class will grab the proper tokenizer class in the library based on the checkpoint name, and can be used directly with any checkpoint: `TFAutoModel` と同様に、`AutoTokenizer` クラスはチェックポイント名に基づいてライブラリ内の適切なトークナイザクラスを取得し、任意のチェックポイントを直接使用することができます。 {/if} @@ -179,7 +145,6 @@ from transformers import AutoTokenizer tokenizer = AutoTokenizer.from_pretrained("bert-base-cased") ``` -We can now use the tokenizer as shown in the previous section: そして、前のセクションで見たようにトークナイザを使用することができます。 ```python @@ -192,35 +157,28 @@ tokenizer("Using a Transformer network is simple") 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1]} ``` -Saving a tokenizer is identical to saving a model: トークナイザの保存は、モデルの保存と同じ方法でできます。 ```py tokenizer.save_pretrained("directory_on_my_computer") ``` -We'll talk more about `token_type_ids` in [Chapter 3](/course/chapter3), and we'll explain the `attention_mask` key a little later. First, let's see how the `input_ids` are generated. To do this, we'll need to look at the intermediate methods of the tokenizer. `token_type_ids` については[Chapter3](/course/chapter3)で詳しく説明し、`attention_mask` についても後ほど説明します。まずは `input_ids` がどのように生成されるかを見てみましょう。 ## エンコーディング -Translating text to numbers is known as _encoding_. Encoding is done in a two-step process: the tokenization, followed by the conversion to input IDs. テキストを数値に変換することを _エンコード_ と呼びます。エンコードはトークン化とその後の入力IDへの変換の2段階のプロセスで行われます。 -As we've seen, the first step is to split the text into words (or parts of words, punctuation symbols, etc.), usually called *tokens*. There are multiple rules that can govern that process, which is why we need to instantiate the tokenizer using the name of the model, to make sure we use the same rules that were used when the model was pretrained. -ここまで見てきたように、最初のステップはテキストをトークン(単語や単語の一部、句読点など)に分割することです。このプロセスを管理するためには、いくつかのルールがあります。そのため、モデルの名前を使ってトークナイザをインスタンス化する必要があります。これにより、モデルが事前学習されたときに使用されたものと同じルールを使用することができます。 +ここまで見てきたように、最初のステップはテキストをトークン(単語や単語の一部、句読点など)に分割することです。このプロセスを管理するためのルールがいくつか存在します。まずは、モデルの名前を使ってトークナイザをインスタンス化する必要があります。これにより、モデルが事前学習されたときに使用されたものと同じルールを使用することができます。 -The second step is to convert those tokens into numbers, so we can build a tensor out of them and feed them to the model. To do this, the tokenizer has a *vocabulary*, which is the part we download when we instantiate it with the `from_pretrained()` method. Again, we need to use the same vocabulary used when the model was pretrained. 2番目のステップはトークンを数値に変換することです。これにより、テンソルを構築し、モデルに入力することができます。これを行うために、トークナイザは *語彙* を有しています。これは、`from_pretrained()` メソッドでインスタンス化するときにダウンロードされる部分です。繰り返しになりますが、モデルの事前学習で使用された語彙と同じものを使用する必要があることに注意してください。 -To get a better understanding of the two steps, we'll explore them separately. Note that we will use some methods that perform parts of the tokenization pipeline separately to show you the intermediate results of those steps, but in practice, you should call the tokenizer directly on your inputs (as shown in the section 2). この2つの理解を深めるために、それぞれのステップを別々に見ていきます。ステップの中間結果を表示するために、トークン化パイプラインの一部を別々に実行するメソッドを使用しますが、実際には(セクション2で見たように)入力に対して直接トークナイザを呼び出す必要があります。 ### トークン化 -The tokenization process is done by the `tokenize()` method of the tokenizer: トークン化のプロセスは `tokenize()` メソッドによって行われます。 ```py @@ -234,20 +192,17 @@ tokens = tokenizer.tokenize(sequence) print(tokens) ``` -The output of this method is a list of strings, or tokens: このメソッドの出力はトークンもしくは文字のリストです。 ```python out ['Using', 'a', 'transform', '##er', 'network', 'is', 'simple'] ``` -This tokenizer is a subword tokenizer: it splits the words until it obtains tokens that can be represented by its vocabulary. That's the case here with `transformer`, which is split into two tokens: `transform` and `##er`. -これはサブワードトークナイザとなっているため、語彙に含まれるトークンになるまで単語を分割します。ここでは `transformer` が `transform` と `##er` に分割されているのがわかります。 +ここではサブワードトークナイザを使用しているので、単語を語彙に含まれるトークンになるまで分割していきます。具体的には `transformer` が `transform` と `##er` に分割されているのがわかります。 ### トークンからIDへの変換 -The conversion to input IDs is handled by the `convert_tokens_to_ids()` tokenizer method: -トークンからIDへの変換は `convert_tokens_to_ids()` トークナイザメソッドによって行われます。 +トークンからIDへの変換は `convert_tokens_to_ids()` のトークナイザメソッドによって行われます。 ```py ids = tokenizer.convert_tokens_to_ids(tokens) @@ -259,19 +214,16 @@ print(ids) [7993, 170, 11303, 1200, 2443, 1110, 3014] ``` -These outputs, once converted to the appropriate framework tensor, can then be used as inputs to a model as seen earlier in this chapter. これらの出力は、適切なフレームワークのテンソルに変換された後、前述のようにモデルの入力として使用できます。 -✏️ **Try it out!** Replicate the two last steps (tokenization and conversion to input IDs) on the input sentences we used in section 2 ("I've been waiting for a HuggingFace course my whole life." and "I hate this so much!"). Check that you get the same input IDs we got earlier! ✏️ **試してみよう!** 最後の2つのステップ(トークン化と入力IDへの変換)を、セクション2で使った入力文("I've been waiting for a HuggingFace course my whole life." と "I hate this so much!")に対して再現してみましょう。先ほどと同じ入力IDが得られるかどうかを確認してみてください。 ## デコーディング -*Decoding* is going the other way around: from vocabulary indices, we want to get a string. This can be done with the `decode()` method as follows: *デコーディング* はエンコーディングとは逆の処理になります。`decode()` メソッドを使うことで、語彙のインデックスから文字列を取得することができます。 ```py @@ -283,8 +235,6 @@ print(decoded_string) 'Using a Transformer network is simple' ``` -Note that the `decode` method not only converts the indices back to tokens, but also groups together the tokens that were part of the same words to produce a readable sentence. This behavior will be extremely useful when we use models that predict new text (either text generated from a prompt, or for sequence-to-sequence problems like translation or summarization). -`decode` メソッドは語彙のインデックスをトークンに戻すだけでなく、同じ単語の一部であったトークンをまとめて、読みやすい文章に変換してくれることに注意してください。この挙動は、プロンプトから生成されたテキストや、翻訳や要約などの系列から系列への変換などの問題を解くモデルを使うときに非常に役に立ちます。 +`decode` メソッドは語彙のインデックスをトークンに戻すだけでなく、同じ単語の一部であったトークンをまとめて、読みやすい文章に変換するところも担っています。この挙動は、プロンプトから生成されたテキストや、翻訳や要約などの系列から系列への変換などの問題を解くモデルを使うときに非常に役に立ちます。 -By now you should understand the atomic operations a tokenizer can handle: tokenization, conversion to IDs, and converting IDs back to a string. However, we've just scraped the tip of the iceberg. In the following section, we'll take our approach to its limits and take a look at how to overcome them. -ここまでで、トークナイザでできる基本的な処理(トークン化、IDへの変換、IDから文字列への変換)を理解できたのではないでしょうか。しかし、これは氷山の一角にすぎません。次のセクションでは、これらの処理を限界まで拡張していき、その限界を超える方法を見ていきましょう。 +ここまでで、トークナイザでできる基本的な処理(トークン化、IDへの変換、IDから文字列への変換)を理解できたのではないでしょうか。しかし、これは氷山の一角に過ぎません。次のセクションでは、これらの処理を限界まで拡張していき、その限界を超える方法を見ていきましょう。 diff --git a/chapters/ja/chapter2/5.mdx b/chapters/ja/chapter2/5.mdx index 3d84c5099..7866e0128 100644 --- a/chapters/ja/chapter2/5.mdx +++ b/chapters/ja/chapter2/5.mdx @@ -28,430 +28,18 @@ {/if} -In the previous section, we explored the simplest of use cases: doing inference on a single sequence of a small length. However, some questions emerge already: -前のセクションでは、最も単純な使用例である、小さな長さの単一のシーケンスに対する推論を調べました。 しかし、すでにいくつかの質問が生じています。 +前のセクションでは、最も単純な使用例である、単一の短い系列(テキスト)に対して推論を行う方法を見てきました。しかし、これについて以下のような疑問をお持ちの方もいるかもしれません。 -- How do we handle multiple sequences? -- How do we handle multiple sequences *of different lengths*? -- Are vocabulary indices the only inputs that allow a model to work well? -- Is there such a thing as too long a sequence? +- 複数の系列をどのように処理するのか? +- *異なる長さ*の複数の系列をどのように処理するのか? +- モデルがうまく機能するためには、単語のインデックスだけが入力として必要なのか? +- 系列が長すぎてしまうということはあるのか? -Let's see what kinds of problems these questions pose, and how we can solve them using the 🤗 Transformers API. +これらの疑問について、実際はどのような問題があるのか、そして🤗 Transformers APIを使ってどのように解決できるのかを見ていきましょう。 -## Models expect a batch of inputs +## モデルへのバッチ入力 -In the previous exercise you saw how sequences get translated into lists of numbers. Let's convert this list of numbers to a tensor and send it to the model: - -{#if fw === 'pt'} -```py -import torch -from transformers import AutoTokenizer, AutoModelForSequenceClassification - -checkpoint = "distilbert-base-uncased-finetuned-sst-2-english" -tokenizer = AutoTokenizer.from_pretrained(checkpoint) -model = AutoModelForSequenceClassification.from_pretrained(checkpoint) - -sequence = "I've been waiting for a HuggingFace course my whole life." - -tokens = tokenizer.tokenize(sequence) -ids = tokenizer.convert_tokens_to_ids(tokens) -input_ids = torch.tensor(ids) -# This line will fail. -model(input_ids) - -# Handling multiple sequences - -{#if fw === 'pt'} - - - -{:else} - - - -{/if} - -{#if fw === 'pt'} - -{:else} - -{/if} - -In the previous section, we explored the simplest of use cases: doing inference on a single sequence of a small length. However, some questions emerge already: - -- How do we handle multiple sequences? -- How do we handle multiple sequences *of different lengths*? -- Are vocabulary indices the only inputs that allow a model to work well? -- Is there such a thing as too long a sequence? - -Let's see what kinds of problems these questions pose, and how we can solve them using the 🤗 Transformers API. - -## Models expect a batch of inputs - -In the previous exercise you saw how sequences get translated into lists of numbers. Let's convert this list of numbers to a tensor and send it to the model: - -{#if fw === 'pt'} -```py -import torch -from transformers import AutoTokenizer, AutoModelForSequenceClassification - -checkpoint = "distilbert-base-uncased-finetuned-sst-2-english" -tokenizer = AutoTokenizer.from_pretrained(checkpoint) -model = AutoModelForSequenceClassification.from_pretrained(checkpoint) - -sequence = "I've been waiting for a HuggingFace course my whole life." - -tokens = tokenizer.tokenize(sequence) -ids = tokenizer.convert_tokens_to_ids(tokens) -input_ids = torch.tensor(ids) -# This line will fail. -model(input_ids) -``` - -```python out -IndexError: Dimension out of range (expected to be in range of [-1, 0], but got 1) -``` -{:else} -```py -import tensorflow as tf -from transformers import AutoTokenizer, TFAutoModelForSequenceClassification - -checkpoint = "distilbert-base-uncased-finetuned-sst-2-english" -tokenizer = AutoTokenizer.from_pretrained(checkpoint) -model = TFAutoModelForSequenceClassification.from_pretrained(checkpoint) - -sequence = "I've been waiting for a HuggingFace course my whole life." - -tokens = tokenizer.tokenize(sequence) -ids = tokenizer.convert_tokens_to_ids(tokens) -input_ids = tf.constant(ids) -# This line will fail. -model(input_ids) -``` - -```py out -InvalidArgumentError: Input to reshape is a tensor with 14 values, but the requested shape has 196 [Op:Reshape] -``` -{/if} - -Oh no! Why did this fail? "We followed the steps from the pipeline in section 2. - -The problem is that we sent a single sequence to the model, whereas 🤗 Transformers models expect multiple sentences by default. Here we tried to do everything the tokenizer did behind the scenes when we applied it to a `sequence`. But if you look closely, you'll see that the tokenizer didn't just convert the list of input IDs into a tensor, it added a dimension on top of it: - -{#if fw === 'pt'} -```py -tokenized_inputs = tokenizer(sequence, return_tensors="pt") -print(tokenized_inputs["input_ids"]) -``` - -```python out -tensor([[ 101, 1045, 1005, 2310, 2042, 3403, 2005, 1037, 17662, 12172, - 2607, 2026, 2878, 2166, 1012, 102]]) -``` -{:else} -```py -tokenized_inputs = tokenizer(sequence, return_tensors="tf") -print(tokenized_inputs["input_ids"]) -``` - -```py out - -``` -{/if} - -Let's try again and add a new dimension: - -{#if fw === 'pt'} -```py -import torch -from transformers import AutoTokenizer, AutoModelForSequenceClassification - -checkpoint = "distilbert-base-uncased-finetuned-sst-2-english" -tokenizer = AutoTokenizer.from_pretrained(checkpoint) -model = AutoModelForSequenceClassification.from_pretrained(checkpoint) - -sequence = "I've been waiting for a HuggingFace course my whole life." - -tokens = tokenizer.tokenize(sequence) -ids = tokenizer.convert_tokens_to_ids(tokens) - -input_ids = torch.tensor([ids]) -print("Input IDs:", input_ids) - -output = model(input_ids) -print("Logits:", output.logits) -``` -{:else} -```py -import tensorflow as tf -from transformers import AutoTokenizer, TFAutoModelForSequenceClassification - -checkpoint = "distilbert-base-uncased-finetuned-sst-2-english" -tokenizer = AutoTokenizer.from_pretrained(checkpoint) -model = TFAutoModelForSequenceClassification.from_pretrained(checkpoint) - -sequence = "I've been waiting for a HuggingFace course my whole life." - -tokens = tokenizer.tokenize(sequence) -ids = tokenizer.convert_tokens_to_ids(tokens) - -input_ids = tf.constant([ids]) -print("Input IDs:", input_ids) - -output = model(input_ids) -print("Logits:", output.logits) -``` -{/if} - -We print the input IDs as well as the resulting logits — here's the output: - -{#if fw === 'pt'} -```python out -Input IDs: [[ 1045, 1005, 2310, 2042, 3403, 2005, 1037, 17662, 12172, 2607, 2026, 2878, 2166, 1012]] -Logits: [[-2.7276, 2.8789]] -``` -{:else} -```py out -Input IDs: tf.Tensor( -[[ 1045 1005 2310 2042 3403 2005 1037 17662 12172 2607 2026 2878 - 2166 1012]], shape=(1, 14), dtype=int32) -Logits: tf.Tensor([[-2.7276208 2.8789377]], shape=(1, 2), dtype=float32) -``` -{/if} - -*Batching* is the act of sending multiple sentences through the model, all at once. If you only have one sentence, you can just build a batch with a single sequence: - -``` -batched_ids = [ids, ids] -``` - -This is a batch of two identical sequences! - - - -✏️ **Try it out!** Convert this `batched_ids` list into a tensor and pass it through your model. Check that you obtain the same logits as before (but twice)! - - - -Batching allows the model to work when you feed it multiple sentences. Using multiple sequences is just as simple as building a batch with a single sequence. There's a second issue, though. When you're trying to batch together two (or more) sentences, they might be of different lengths. If you've ever worked with tensors before, you know that they need to be of rectangular shape, so you won't be able to convert the list of input IDs into a tensor directly. To work around this problem, we usually *pad* the inputs. - -## Padding the inputs - -The following list of lists cannot be converted to a tensor: - -```py no-format -batched_ids = [ - [200, 200, 200], - [200, 200] -] -``` - -In order to work around this, we'll use *padding* to make our tensors have a rectangular shape. Padding makes sure all our sentences have the same length by adding a special word called the *padding token* to the sentences with fewer values. For example, if you have 10 sentences with 10 words and 1 sentence with 20 words, padding will ensure all the sentences have 20 words. In our example, the resulting tensor looks like this: - -```py no-format -padding_id = 100 - -batched_ids = [ - [200, 200, 200], - [200, 200, padding_id], -] -``` - -The padding token ID can be found in `tokenizer.pad_token_id`. Let's use it and send our two sentences through the model individually and batched together: - -{#if fw === 'pt'} -```py no-format -model = AutoModelForSequenceClassification.from_pretrained(checkpoint) - -sequence1_ids = [[200, 200, 200]] -sequence2_ids = [[200, 200]] -batched_ids = [ - [200, 200, 200], - [200, 200, tokenizer.pad_token_id], -] - -print(model(torch.tensor(sequence1_ids)).logits) -print(model(torch.tensor(sequence2_ids)).logits) -print(model(torch.tensor(batched_ids)).logits) -``` - -```python out -tensor([[ 1.5694, -1.3895]], grad_fn=) -tensor([[ 0.5803, -0.4125]], grad_fn=) -tensor([[ 1.5694, -1.3895], - [ 1.3373, -1.2163]], grad_fn=) -``` -{:else} -```py no-format -model = TFAutoModelForSequenceClassification.from_pretrained(checkpoint) - -sequence1_ids = [[200, 200, 200]] -sequence2_ids = [[200, 200]] -batched_ids = [ - [200, 200, 200], - [200, 200, tokenizer.pad_token_id], -] - -print(model(tf.constant(sequence1_ids)).logits) -print(model(tf.constant(sequence2_ids)).logits) -print(model(tf.constant(batched_ids)).logits) -``` - -```py out -tf.Tensor([[ 1.5693678 -1.3894581]], shape=(1, 2), dtype=float32) -tf.Tensor([[ 0.5803005 -0.41252428]], shape=(1, 2), dtype=float32) -tf.Tensor( -[[ 1.5693681 -1.3894582] - [ 1.3373486 -1.2163193]], shape=(2, 2), dtype=float32) -``` -{/if} - -There's something wrong with the logits in our batched predictions: the second row should be the same as the logits for the second sentence, but we've got completely different values! - -This is because the key feature of Transformer models is attention layers that *contextualize* each token. These will take into account the padding tokens since they attend to all of the tokens of a sequence. To get the same result when passing individual sentences of different lengths through the model or when passing a batch with the same sentences and padding applied, we need to tell those attention layers to ignore the padding tokens. This is done by using an attention mask. - -## Attention masks - -*Attention masks* are tensors with the exact same shape as the input IDs tensor, filled with 0s and 1s: 1s indicate the corresponding tokens should be attended to, and 0s indicate the corresponding tokens should not be attended to (i.e., they should be ignored by the attention layers of the model). - -Let's complete the previous example with an attention mask: - -{#if fw === 'pt'} -```py no-format -batched_ids = [ - [200, 200, 200], - [200, 200, tokenizer.pad_token_id], -] - -attention_mask = [ - [1, 1, 1], - [1, 1, 0], -] - -outputs = model(torch.tensor(batched_ids), attention_mask=torch.tensor(attention_mask)) -print(outputs.logits) -``` - -```python out -tensor([[ 1.5694, -1.3895], - [ 0.5803, -0.4125]], grad_fn=) -``` -{:else} -```py no-format -batched_ids = [ - [200, 200, 200], - [200, 200, tokenizer.pad_token_id], -] - -attention_mask = [ - [1, 1, 1], - [1, 1, 0], -] - -outputs = model(tf.constant(batched_ids), attention_mask=tf.constant(attention_mask)) -print(outputs.logits) -``` - -```py out -tf.Tensor( -[[ 1.5693681 -1.3894582 ] - [ 0.5803021 -0.41252586]], shape=(2, 2), dtype=float32) -``` -{/if} - -Now we get the same logits for the second sentence in the batch. - -Notice how the last value of the second sequence is a padding ID, which is a 0 value in the attention mask. - - - -✏️ **Try it out!** Apply the tokenization manually on the two sentences used in section 2 ("I've been waiting for a HuggingFace course my whole life." and "I hate this so much!"). Pass them through the model and check that you get the same logits as in section 2. Now batch them together using the padding token, then create the proper attention mask. Check that you obtain the same results when going through the model! - - - -## Longer sequences - -With Transformer models, there is a limit to the lengths of the sequences we can pass the models. Most models handle sequences of up to 512 or 1024 tokens, and will crash when asked to process longer sequences. There are two solutions to this problem: - -- Use a model with a longer supported sequence length. -- Truncate your sequences. - -Models have different supported sequence lengths, and some specialize in handling very long sequences. [Longformer](https://huggingface.co/transformers/model_doc/longformer.html) is one example, and another is [LED](https://huggingface.co/transformers/model_doc/led.html). If you're working on a task that requires very long sequences, we recommend you take a look at those models. - -Otherwise, we recommend you truncate your sequences by specifying the `max_sequence_length` parameter: - -```py -sequence = sequence[:max_sequence_length] -``` - -``` - -```python out -IndexError: Dimension out of range (expected to be in range of [-1, 0], but got 1) -``` -{:else} -```py -import tensorflow as tf -from transformers import AutoTokenizer, TFAutoModelForSequenceClassification - -checkpoint = "distilbert-base-uncased-finetuned-sst-2-english" -tokenizer = AutoTokenizer.from_pretrained(checkpoint) -model = TFAutoModelForSequenceClassification.from_pretrained(checkpoint) - -sequence = "I've been waiting for a HuggingFace course my wh - -# Handling multiple sequences - -{#if fw === 'pt'} - - - -{:else} - - - -{/if} - -{#if fw === 'pt'} - -{:else} - -{/if} - -In the previous section, we explored the simplest of use cases: doing inference on a single sequence of a small length. However, some questions emerge already: - -- How do we handle multiple sequences? -- How do we handle multiple sequences *of different lengths*? -- Are vocabulary indices the only inputs that allow a model to work well? -- Is there such a thing as too long a sequence? - -Let's see what kinds of problems these questions pose, and how we can solve them using the 🤗 Transformers API. - -## Models expect a batch of inputs - -In the previous exercise you saw how sequences get translated into lists of numbers. Let's convert this list of numbers to a tensor and send it to the model: +以前のエクササイズで、系列が数値のリストに変換される方法を見てきました。この数値列をテンソルに変換し、モデルに入力してみましょう。 {#if fw === 'pt'} ```py @@ -497,274 +85,10 @@ InvalidArgumentError: Input to reshape is a tensor with 14 values, but the reque ``` {/if} -Oh no! Why did this fail? "We followed the steps from the pipeline in section 2. - -The problem is that we sent a single sequence to the model, whereas 🤗 Transformers models expect multiple sentences by default. Here we tried to do everything the tokenizer did behind the scenes when we applied it to a `sequence`. But if you look closely, you'll see that the tokenizer didn't just convert the list of input IDs into a tensor, it added a dimension on top of it: - -{#if fw === 'pt'} -```py -tokenized_inputs = tokenizer(sequence, return_tensors="pt") -print(tokenized_inputs["input_ids"]) -``` - -```python out -tensor([[ 101, 1045, 1005, 2310, 2042, 3403, 2005, 1037, 17662, 12172, - 2607, 2026, 2878, 2166, 1012, 102]]) -``` -{:else} -```py -tokenized_inputs = tokenizer(sequence, return_tensors="tf") -print(tokenized_inputs["input_ids"]) -``` - -```py out - -``` -{/if} - -Let's try again and add a new dimension: - -{#if fw === 'pt'} -```py -import torch -from transformers import AutoTokenizer, AutoModelForSequenceClassification - -checkpoint = "distilbert-base-uncased-finetuned-sst-2-english" -tokenizer = AutoTokenizer.from_pretrained(checkpoint) -model = AutoModelForSequenceClassification.from_pretrained(checkpoint) - -sequence = "I've been waiting for a HuggingFace course my whole life." - -tokens = tokenizer.tokenize(sequence) -ids = tokenizer.convert_tokens_to_ids(tokens) - -input_ids = torch.tensor([ids]) -print("Input IDs:", input_ids) - -output = model(input_ids) -print("Logits:", output.logits) -``` -{:else} -```py -import tensorflow as tf -from transformers import AutoTokenizer, TFAutoModelForSequenceClassification - -checkpoint = "distilbert-base-uncased-finetuned-sst-2-english" -tokenizer = AutoTokenizer.from_pretrained(checkpoint) -model = TFAutoModelForSequenceClassification.from_pretrained(checkpoint) - -sequence = "I've been waiting for a HuggingFace course my whole life." - -tokens = tokenizer.tokenize(sequence) -ids = tokenizer.convert_tokens_to_ids(tokens) - -input_ids = tf.constant([ids]) -print("Input IDs:", input_ids) - -output = model(input_ids) -print("Logits:", output.logits) -``` -{/if} - -We print the input IDs as well as the resulting logits — here's the output: - -{#if fw === 'pt'} -```python out -Input IDs: [[ 1045, 1005, 2310, 2042, 3403, 2005, 1037, 17662, 12172, 2607, 2026, 2878, 2166, 1012]] -Logits: [[-2.7276, 2.8789]] -``` -{:else} -```py out -Input IDs: tf.Tensor( -[[ 1045 1005 2310 2042 3403 2005 1037 17662 12172 2607 2026 2878 - 2166 1012]], shape=(1, 14), dtype=int32) -Logits: tf.Tensor([[-2.7276208 2.8789377]], shape=(1, 2), dtype=float32) -``` -{/if} - -*Batching* is the act of sending multiple sentences through the model, all at once. If you only have one sentence, you can just build a batch with a single sequence: - -``` -batched_ids = [ids, ids] -``` - -This is a batch of two identical sequences! - - - -✏️ **Try it out!** Convert this `batched_ids` list into a tensor and pass it through your model. Check that you obtain the same logits as before (but twice)! - - - -Batching allows the model to work when you feed it multiple sentences. Using multiple sequences is just as simple as building a batch with a single sequence. There's a second issue, though. When you're trying to batch together two (or more) sentences, they might be of different lengths. If you've ever worked with tensors before, you know that they need to be of rectangular shape, so you won't be able to convert the list of input IDs into a tensor directly. To work around this problem, we usually *pad* the inputs. - -## Padding the inputs - -The following list of lists cannot be converted to a tensor: - -```py no-format -batched_ids = [ - [200, 200, 200], - [200, 200] -] -``` - -In order to work around this, we'll use *padding* to make our tensors have a rectangular shape. Padding makes sure all our sentences have the same length by adding a special word called the *padding token* to the sentences with fewer values. For example, if you have 10 sentences with 10 words and 1 sentence with 20 words, padding will ensure all the sentences have 20 words. In our example, the resulting tensor looks like this: - -```py no-format -padding_id = 100 - -batched_ids = [ - [200, 200, 200], - [200, 200, padding_id], -] -``` - -The padding token ID can be found in `tokenizer.pad_token_id`. Let's use it and send our two sentences through the model individually and batched together: - -{#if fw === 'pt'} -```py no-format -model = AutoModelForSequenceClassification.from_pretrained(checkpoint) - -sequence1_ids = [[200, 200, 200]] -sequence2_ids = [[200, 200]] -batched_ids = [ - [200, 200, 200], - [200, 200, tokenizer.pad_token_id], -] - -print(model(torch.tensor(sequence1_ids)).logits) -print(model(torch.tensor(sequence2_ids)).logits) -print(model(torch.tensor(batched_ids)).logits) -``` - -```python out -tensor([[ 1.5694, -1.3895]], grad_fn=) -tensor([[ 0.5803, -0.4125]], grad_fn=) -tensor([[ 1.5694, -1.3895], - [ 1.3373, -1.2163]], grad_fn=) -``` -{:else} -```py no-format -model = TFAutoModelForSequenceClassification.from_pretrained(checkpoint) - -sequence1_ids = [[200, 200, 200]] -sequence2_ids = [[200, 200]] -batched_ids = [ - [200, 200, 200], - [200, 200, tokenizer.pad_token_id], -] - -print(model(tf.constant(sequence1_ids)).logits) -print(model(tf.constant(sequence2_ids)).logits) -print(model(tf.constant(batched_ids)).logits) -``` - -```py out -tf.Tensor([[ 1.5693678 -1.3894581]], shape=(1, 2), dtype=float32) -tf.Tensor([[ 0.5803005 -0.41252428]], shape=(1, 2), dtype=float32) -tf.Tensor( -[[ 1.5693681 -1.3894582] - [ 1.3373486 -1.2163193]], shape=(2, 2), dtype=float32) -``` -{/if} - -There's something wrong with the logits in our batched predictions: the second row should be the same as the logits for the second sentence, but we've got completely different values! - -This is because the key feature of Transformer models is attention layers that *contextualize* each token. These will take into account the padding tokens since they attend to all of the tokens of a sequence. To get the same result when passing individual sentences of different lengths through the model or when passing a batch with the same sentences and padding applied, we need to tell those attention layers to ignore the padding tokens. This is done by using an attention mask. - -## Attention masks - -*Attention masks* are tensors with the exact same shape as the input IDs tensor, filled with 0s and 1s: 1s indicate the corresponding tokens should be attended to, and 0s indicate the corresponding tokens should not be attended to (i.e., they should be ignored by the attention layers of the model). - -Let's complete the previous example with an attention mask: - -{#if fw === 'pt'} -```py no-format -batched_ids = [ - [200, 200, 200], - [200, 200, tokenizer.pad_token_id], -] - -attention_mask = [ - [1, 1, 1], - [1, 1, 0], -] - -outputs = model(torch.tensor(batched_ids), attention_mask=torch.tensor(attention_mask)) -print(outputs.logits) -``` - -```python out -tensor([[ 1.5694, -1.3895], - [ 0.5803, -0.4125]], grad_fn=) -``` -{:else} -```py no-format -batched_ids = [ - [200, 200, 200], - [200, 200, tokenizer.pad_token_id], -] - -attention_mask = [ - [1, 1, 1], - [1, 1, 0], -] - -outputs = model(tf.constant(batched_ids), attention_mask=tf.constant(attention_mask)) -print(outputs.logits) -``` - -```py out -tf.Tensor( -[[ 1.5693681 -1.3894582 ] - [ 0.5803021 -0.41252586]], shape=(2, 2), dtype=float32) -``` -{/if} - -Now we get the same logits for the second sentence in the batch. - -Notice how the last value of the second sequence is a padding ID, which is a 0 value in the attention mask. - - - -✏️ **Try it out!** Apply the tokenization manually on the two sentences used in section 2 ("I've been waiting for a HuggingFace course my whole life." and "I hate this so much!"). Pass them through the model and check that you get the same logits as in section 2. Now batch them together using the padding token, then create the proper attention mask. Check that you obtain the same results when going through the model! - - - -## Longer sequences - -With Transformer models, there is a limit to the lengths of the sequences we can pass the models. Most models handle sequences of up to 512 or 1024 tokens, and will crash when asked to process longer sequences. There are two solutions to this problem: - -- Use a model with a longer supported sequence length. -- Truncate your sequences. - -Models have different supported sequence lengths, and some specialize in handling very long sequences. [Longformer](https://huggingface.co/transformers/model_doc/longformer.html) is one example, and another is [LED](https://huggingface.co/transformers/model_doc/led.html). If you're working on a task that requires very long sequences, we recommend you take a look at those models. - -Otherwise, we recommend you truncate your sequences by specifying the `max_sequence_length` parameter: - -```py -sequence = sequence[:max_sequence_length] -``` -ole life." - -tokens = tokenizer.tokenize(sequence) -ids = tokenizer.convert_tokens_to_ids(tokens) -input_ids = tf.constant(ids) -# This line will fail. -model(input_ids) -``` - -```py out -InvalidArgumentError: Input to reshape is a tensor with 14 values, but the requested shape has 196 [Op:Reshape] -``` -{/if} +おっと!「セクション2のパイプラインの手順に従ったのに、なぜ失敗したのか?」と思われるかもしれません。 -Oh no! Why did this fail? "We followed the steps from the pipeline in section 2. +この問題はモデルに単一の系列を入力しようとしたために発生しました。🤗 Transformersモデルは、デフォルトでは複数の系列を入力として受け付けます。ここでは、`sequence`に対してトークナイザを適用したときに、トークナイザがその背後で行ったすべての処理を行おうとしました。しかし、もう少し詳しく見てみると、トークナイザは入力IDのリストをテンソルに変換するだけでなく、それに対して次元を追加していることがわかります。 -The problem is that we sent a single sequence to the model, whereas 🤗 Transformers models expect multiple sentences by default. Here we tried to do everything the tokenizer did behind the scenes when we applied it to a `sequence`. But if you look closely, you'll see that the tokenizer didn't just convert the list of input IDs into a tensor, it added a dimension on top of it: {#if fw === 'pt'} ```py @@ -789,7 +113,7 @@ array([[ 101, 1045, 1005, 2310, 2042, 3403, 2005, 1037, 17662, ``` {/if} -Let's try again and add a new dimension: +それでは次元を追加して再度試してみましょう。 {#if fw === 'pt'} ```py @@ -833,7 +157,7 @@ print("Logits:", output.logits) ``` {/if} -We print the input IDs as well as the resulting logits — here's the output: +ここで入力IDと結果のロジット(モデルの出力)を見てみましょう。 {#if fw === 'pt'} ```python out @@ -849,25 +173,25 @@ Logits: tf.Tensor([[-2.7276208 2.8789377]], shape=(1, 2), dtype=float32) ``` {/if} -*Batching* is the act of sending multiple sentences through the model, all at once. If you only have one sentence, you can just build a batch with a single sequence: +*バッチ処理*とは、複数の系列をまとめてモデルに入力することです。系列が1つしかない場合でも、バッチを構築することができます。 ``` batched_ids = [ids, ids] ``` -This is a batch of two identical sequences! +これは2つの同じ系列からなるバッチとなっています。 -✏️ **Try it out!** Convert this `batched_ids` list into a tensor and pass it through your model. Check that you obtain the same logits as before (but twice)! +✏️ **試してみよう!** この `batch_ids` をテンソルに変換し、モデルに入力してみましょう。前と同じロジット(モデル出力)が得られることを確認してください(ただし、二重になっていることに注意してください)。 -Batching allows the model to work when you feed it multiple sentences. Using multiple sequences is just as simple as building a batch with a single sequence. There's a second issue, though. When you're trying to batch together two (or more) sentences, they might be of different lengths. If you've ever worked with tensors before, you know that they need to be of rectangular shape, so you won't be able to convert the list of input IDs into a tensor directly. To work around this problem, we usually *pad* the inputs. +バッチ処理により、複数の系列をモデルに入力できるようになります。単一の系列でバッチを構築するのと同じように、簡単に複数の系列を使用することができます。ただし、ここで1つ問題があります。2つ以上の系列をバッチ処理する場合、系列の長さがそれぞれ異なる場合があります。これまでテンソルを扱ったことがある場合は、テンソルの形状は長方形である必要があることをご存知なのではないでしょうか。従って、異なる長さの系列の入力IDリストを直接テンソルに変換することはできません。この問題を回避するための方法として、入力を*パディング*することが一般的です。 -## Padding the inputs +## 入力のパディング -The following list of lists cannot be converted to a tensor: +以下の二重のリストはテンソルには変換できません。 ```py no-format batched_ids = [ @@ -876,7 +200,7 @@ batched_ids = [ ] ``` -In order to work around this, we'll use *padding* to make our tensors have a rectangular shape. Padding makes sure all our sentences have the same length by adding a special word called the *padding token* to the sentences with fewer values. For example, if you have 10 sentences with 10 words and 1 sentence with 20 words, padding will ensure all the sentences have 20 words. In our example, the resulting tensor looks like this: +この問題を回避するために、*パディング*を使用して、テンソルの形状を長方形にしてみましょう。パディングは、*パディングトークン*と呼ばれる特別な単語を短い系列に対して追加することで、すべての系列の長さを同じにします。例えば、10語の系列が10個、20語の系列が1個ある場合、パディングにより、すべての系列の長さが20語になります。上記の例では、結果として得られるテンソルは次のようになります。 ```py no-format padding_id = 100 @@ -887,7 +211,7 @@ batched_ids = [ ] ``` -The padding token ID can be found in `tokenizer.pad_token_id`. Let's use it and send our two sentences through the model individually and batched together: +パティングトークンのIDは `tokenizer.pad_token_id` で見つけることができます。それでは、これを使って2つの系列を個別にモデルに入力する場合と、バッチ処理した場合の結果を比較してみましょう。 {#if fw === 'pt'} ```py no-format @@ -936,15 +260,15 @@ tf.Tensor( ``` {/if} -There's something wrong with the logits in our batched predictions: the second row should be the same as the logits for the second sentence, but we've got completely different values! +バッチ処理した予測のロジットについて何か違いがあるようです。2行目は2つ目の系列のロジットと同じであるべきですが、完全に異なる値となってしまっています! -This is because the key feature of Transformer models is attention layers that *contextualize* each token. These will take into account the padding tokens since they attend to all of the tokens of a sequence. To get the same result when passing individual sentences of different lengths through the model or when passing a batch with the same sentences and padding applied, we need to tell those attention layers to ignore the padding tokens. This is done by using an attention mask. +これは、Transformerモデルの代表的な特徴であるアテンション層が、それぞれのトークンに対して*コンテクスト化*を行っていることに起因します。アテンション層は、系列のすべてのトークンに注意(アテンション)を向けるため、パディングトークンも考慮の対象として扱います。異なる長さの系列を個別にモデルに入力する場合と、同じ系列をバッチ処理した場合の両方で同じ結果を得るためには、アテンション層にパディングトークンを無視するように指示する必要があります。これは、アテンションマスクを使用することで実現できます。 -## Attention masks +## アテンションマスク -*Attention masks* are tensors with the exact same shape as the input IDs tensor, filled with 0s and 1s: 1s indicate the corresponding tokens should be attended to, and 0s indicate the corresponding tokens should not be attended to (i.e., they should be ignored by the attention layers of the model). +*アテンションマスク*とは入力IDのテンソルと全く同じ形をしたテンソルのことで、0と1で構成されています。1は対応するトークンに注意を向けることを示し、0は対応するトークンに注意を向けないこと(つまり、アテンション層に無視されること)を示します。 -Let's complete the previous example with an attention mask: +前の例に対して、アテンションマスクを追加してみましょう。 {#if fw === 'pt'} ```py no-format @@ -989,26 +313,26 @@ tf.Tensor( ``` {/if} -Now we get the same logits for the second sentence in the batch. +これで、バッチ内の2つ目の系列について同じロジットが得られました。 -Notice how the last value of the second sequence is a padding ID, which is a 0 value in the attention mask. +2つ目の系列の最後の値がパディングIDであることに注目してください。これは、アテンションマスクの0の値となっています。 -✏️ **Try it out!** Apply the tokenization manually on the two sentences used in section 2 ("I've been waiting for a HuggingFace course my whole life." and "I hate this so much!"). Pass them through the model and check that you get the same logits as in section 2. Now batch them together using the padding token, then create the proper attention mask. Check that you obtain the same results when going through the model! +✏️ **試してみよう!** セクション2で使用した2つの文 ("I've been waiting for a HuggingFace course my whole life." と "I hate this so much!") を手動でトークン化してみましょう。そしてこれらをモデルに入力し、セクション2で得られたロジットと同じ結果となることを確認してみましょう。次に、パディングトークンを使用してこれらをバッチ処理し、適切なアテンションマスクを作成してみましょう。また同様にモデルに入力した際、セクション2で得られた結果と同じものになることを確認してみましょう。 -## Longer sequences +## より長い系列 -With Transformer models, there is a limit to the lengths of the sequences we can pass the models. Most models handle sequences of up to 512 or 1024 tokens, and will crash when asked to process longer sequences. There are two solutions to this problem: +トランスフォーマーモデルでは、モデルに入力できる系列の長さに制限があります。ほとんどのモデルは512トークンまたは1024トークンの系列を処理できますが、これより長い系列を処理しようとするとクラッシュしてしまいます。この問題に対しては、2つの解決策があります。 -- Use a model with a longer supported sequence length. -- Truncate your sequences. +- 長い系列を処理できるモデルを使用する +- 系列を途中で区切って短くする -Models have different supported sequence lengths, and some specialize in handling very long sequences. [Longformer](https://huggingface.co/transformers/model_doc/longformer.html) is one example, and another is [LED](https://huggingface.co/transformers/model_doc/led.html). If you're working on a task that requires very long sequences, we recommend you take a look at those models. +処理できる系列長はモデルによって異なり、非常に長い系列の処理に特化したモデルも存在します。[Longformer](https://huggingface.co/transformers/model_doc/longformer.html) はその一例です。また、[LED](https://huggingface.co/transformers/model_doc/led.html) も長い系列を処理できるモデルです。非常に長い系列を処理する必要があるタスクに取り組んでいる場合は、これらのモデルを見てみて下さい。 -Otherwise, we recommend you truncate your sequences by specifying the `max_sequence_length` parameter: +もう1つの手法として、`max_sequence_length` パラメータを指定して系列を途中で区切ることをお勧めします。 ```py sequence = sequence[:max_sequence_length]