[翻訳] Hugging Face transformersにおける前処理

[Preprocess](https://huggingface.co/docs/transformers/preprocessing)の翻訳です。

:::note warn
本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。
:::

データセットでモデルをトレーニングする前に、期待されるモデル入力フォーマットに前処理を行う必要があります。データがテキスト、画像、音声であろうが、これらはtensorのバッチに変換、組み立てられる必要があります。🤗 Transformersは、モデルのデータの準備に役立つ一連の前処理クラスを提供しています。このチュートリアルでは以下を学びます:

- テキストでは、テキストをトークンのシーケンスに変換するために[Tokenizer](https://huggingface.co/docs/transformers/main_classes/tokenizer)を使用し、トークンの数値表現を作成し、tensorを組み立てます。
- スピーチや音声では、音声波形からシーケンスの特徴量を抽出するために[Feature extractor](https://huggingface.co/docs/transformers/main_classes/feature_extractor)を使用し、tensorに変換します。
- 画像入力では、画像をtensorに変換するために[ImageProcessor](https://huggingface.co/docs/transformers/main_classes/image)を使用します。
- マルチモーダルの入力では、トークナイザーと特徴量抽出器や画像プロセッサーを組み合わせるために[Processor](https://huggingface.co/docs/transformers/main_classes/processors)を使用します。

:::note
AutoProcessorは、あなたがトークナイザー、画像プロセッサー、特徴量抽出器やプロセッサーを使用していたとしても、**常に**動作し、使用しているモデルに適切なクラスを自動で選択します。
:::

始める前に、実験するデータセットをロードできるように🤗 Datasetsをインストールします:

```
pip install datasets
```

# 自然言語処理

<iframe width="560" height="315" src="https://www.youtube.com/embed/Yffk5aydLzg" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

テキストデータを前処理する主要なツールが[tokenizer](https://huggingface.co/docs/transformers/main_classes/tokenizer)です。トークナイザーは一連のルールに沿ってテキストを`トークン`に分割します。トークンは数値、そしてtensorに変換され、これがモデルの入力となります。モデルに必要となる追加の入力はトークナイザーによって追加されます。

:::note
事前学習済みモデルを使用しようとしているのであれば、関連づけられている事前学習済みトークナイザーを使用することが重要です。これによって、テキストは事前学習されたコーパスと同じ方法で分割されるようになり、事前学習で用いられたトークンのインデックスを使用するようになります。
:::

[AutoTokenizer\.from\_pretrained\(\)](https://huggingface.co/docs/transformers/v4.29.1/en/model_doc/auto#transformers.AutoTokenizer.from_pretrained)メソッドで事前トレーニング済みトークナイザーをロードするところからスタートします。これは、モデルが事前学習で用いた`vocab`をダウンロードします:

```py:Python
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")
```

そして、トークナイザーにテキストを渡します:

```py:Python
encoded_input = tokenizer("Do not meddle in the affairs of wizards, for they are subtle and quick to anger.")
print(encoded_input)
```

```
{'input_ids': [101, 2079, 2025, 19960, 10362, 1999, 1996, 3821, 1997, 16657, 1010, 2005, 2027, 2024, 11259, 1998, 4248, 2000, 4963, 1012, 102], 
 'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]}
```

トークナイザーは3つの重要なアイテムを持つディクショナリーを返却します:

- [input\_ids](https://huggingface.co/docs/transformers/glossary#input-ids)は、センテンスにおけるそれぞれのトークンに対応するインデックスです。
- [attention\_mask](https://huggingface.co/docs/transformers/glossary#attention-mask)は、トークンがアテンションされるかどうかを示します。
- [token\_type\_ids](https://huggingface.co/docs/transformers/glossary#token-type-ids)は、センテンスが複数ある場合、トークンがどのセンテンスに属するのかを示します。

`input_ids`をデコードすることで入力に戻します:

```py:Python
tokenizer.decode(encoded_input["input_ids"])
```

```
'[CLS] Do not meddle in the affairs of wizards, for they are subtle and quick to anger. [SEP]'
```

見てわかるように、トークナイザーは2つの特殊トークン、`CLS`と`SEP`(classifierとseparator)をセンテンスに追加しています。全てのモデルで特殊トークンは必要ではありませんが、モデルが必要とする際にはトークナイザーは自動でそれらを追加します。

前処理したいセンテンスが複数ある場合には、トークナイザーにリストを渡します:

```py:Python
batch_sentences = [
    "But what about second breakfast?",
    "Don't think he knows about second breakfast, Pip.",
    "What about elevensies?",
]
encoded_inputs = tokenizer(batch_sentences)
print(encoded_inputs)
```

```
{'input_ids': [[101, 1252, 1184, 1164, 1248, 6462, 136, 102], 
               [101, 1790, 112, 189, 1341, 1119, 3520, 1164, 1248, 6462, 117, 21902, 1643, 119, 102], 
               [101, 1327, 1164, 5450, 23434, 136, 102]], 
 'token_type_ids': [[0, 0, 0, 0, 0, 0, 0, 0], 
                    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
                    [0, 0, 0, 0, 0, 0, 0]], 
 'attention_mask': [[1, 1, 1, 1, 1, 1, 1, 1], 
                    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 
                    [1, 1, 1, 1, 1, 1, 1]]}
```

## パディング

センテンスは常に同じ長さというわけではなく、これはモデル入力のtensorが同じ形状を持つ必要があるため問題となることがあります。短いセンテンスに特殊な`パディングトークン`を追加することで、tensorが長方形になるようにするための戦略がパディングです。

最長のシーケンスにマッチするようにバッチの短いシーケンスにパディングするように、`padding`パラメーターを`True`に設定します。

```py:Python
batch_sentences = [
    "But what about second breakfast?",
    "Don't think he knows about second breakfast, Pip.",
    "What about elevensies?",
]
encoded_input = tokenizer(batch_sentences, padding=True)
print(encoded_input)
```

```
{'input_ids': [[101, 1252, 1184, 1164, 1248, 6462, 136, 102, 0, 0, 0, 0, 0, 0, 0], 
               [101, 1790, 112, 189, 1341, 1119, 3520, 1164, 1248, 6462, 117, 21902, 1643, 119, 102], 
               [101, 1327, 1164, 5450, 23434, 136, 102, 0, 0, 0, 0, 0, 0, 0, 0]], 
 'token_type_ids': [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
                    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
                    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], 
 'attention_mask': [[1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0], 
                    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 
                    [1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]}
```

これで、短い最初と三番目のセンテンスに0のパディングが追加されます。

## 切り取り

逆の観点では、時にはあるシーケンスがモデルがハンドリングするには長すぎることがあります。この場合、シーケンスを短い長さで切り取る必要があります。

モデルで受け付ける最大長にシーケンスを切り取るために、`truncation`パラメーターを`True`に設定します:

```py:Python
batch_sentences = [
    "But what about second breakfast?",
    "Don't think he knows about second breakfast, Pip.",
    "What about elevensies?",
]
encoded_input = tokenizer(batch_sentences, padding=True, truncation=True)
print(encoded_input)
```

```
{'input_ids': [[101, 1252, 1184, 1164, 1248, 6462, 136, 102, 0, 0, 0, 0, 0, 0, 0], 
               [101, 1790, 112, 189, 1341, 1119, 3520, 1164, 1248, 6462, 117, 21902, 1643, 119, 102], 
               [101, 1327, 1164, 5450, 23434, 136, 102, 0, 0, 0, 0, 0, 0, 0, 0]], 
 'token_type_ids': [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
                    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
                    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], 
 'attention_mask': [[1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0], 
                    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 
                    [1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]}
```

:::note
より多くのパディングや切り取りの引数の詳細については、[Padding and truncation](https://huggingface.co/docs/transformers/pad_truncation)のコンセプトガイドをご覧ください。
:::

## tensorの構築

最後に、モデルに入力される実際のtensorを返却するようにトークナイザーに指示します。

`return_tensors`パラメーターに、PyTorchなら`pt`、TensorFlowなら`tf`を指定します:

### PyTorch

```py:Python
batch_sentences = [
    "But what about second breakfast?",
    "Don't think he knows about second breakfast, Pip.",
    "What about elevensies?",
]
encoded_input = tokenizer(batch_sentences, padding=True, truncation=True, return_tensors="pt")
print(encoded_input)
```

```
{'input_ids': tensor([[101, 1252, 1184, 1164, 1248, 6462, 136, 102, 0, 0, 0, 0, 0, 0, 0],
                      [101, 1790, 112, 189, 1341, 1119, 3520, 1164, 1248, 6462, 117, 21902, 1643, 119, 102],
                      [101, 1327, 1164, 5450, 23434, 136, 102, 0, 0, 0, 0, 0, 0, 0, 0]]), 
 'token_type_ids': tensor([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                           [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                           [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]), 
 'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
                           [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
                           [1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]])}
```

### TensorFlow

```py:Python
batch_sentences = [
    "But what about second breakfast?",
    "Don't think he knows about second breakfast, Pip.",
    "What about elevensies?",
]
encoded_input = tokenizer(batch_sentences, padding=True, truncation=True, return_tensors="tf")
print(encoded_input)
```

```
{'input_ids': <tf.Tensor: shape=(2, 9), dtype=int32, numpy=
array([[101, 1252, 1184, 1164, 1248, 6462, 136, 102, 0, 0, 0, 0, 0, 0, 0],
       [101, 1790, 112, 189, 1341, 1119, 3520, 1164, 1248, 6462, 117, 21902, 1643, 119, 102],
       [101, 1327, 1164, 5450, 23434, 136, 102, 0, 0, 0, 0, 0, 0, 0, 0]],
      dtype=int32)>, 
 'token_type_ids': <tf.Tensor: shape=(2, 9), dtype=int32, numpy=
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=int32)>, 
 'attention_mask': <tf.Tensor: shape=(2, 9), dtype=int32, numpy=
array([[1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
       [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=int32)>}
```

# 音声

音声タスクでは、モデルにデータセットを準備するために[feature extractor](https://huggingface.co/docs/transformers/main_classes/feature_extractor)が必要となります。特徴量抽出器は、生の音声データから特徴量を抽出し、tensorに変換するように設計されています。

音声データセットに対してどのように特徴量抽出器を活用できるのかを見るために、[MInDS\-14](https://huggingface.co/datasets/PolyAI/minds14)データセットをロードします(どのようにデータセットをロードするのかの詳細については🤗 [Datasets tutorial](https://huggingface.co/docs/datasets/load_hub.html)をご覧ください):

```py:Python
from datasets import load_dataset, Audio

dataset = load_dataset("PolyAI/minds14", name="en-US", split="train")
```

入力を確認するために`audio`カラムの最初の要素にアクセスします。`audio`カラムを呼び出すことで、自動で音声ファイルをロードし、再サンプルします:

```py:Python
dataset[0]["audio"]
```

```
{'array': array([ 0.        ,  0.00024414, -0.00024414, ..., -0.00024414,
         0.        ,  0.        ], dtype=float32),
 'path': '/root/.cache/huggingface/datasets/downloads/extracted/f14948e0e84be638dd7943ac36518a4cf3324e8b7aa331c5ab11541518e9368c/en-US~JOINT_ACCOUNT/602ba55abb1e6d0fbce92065.wav',
 'sampling_rate': 8000}
```

これは3つのアイテムを返却します:

- `array`は、ロードされたスピーチの信号であり、場合によっては再サンプリングされる1Dの配列です。
- `path`は、音声ファイルへのパスです。
- `sampling_rate`は、スピーチ信号で秒間いくつのデータポイントを計測しているのかを示します。

このチュートリアルでは、[Wav2Vec2](https://huggingface.co/facebook/wav2vec2-base)モデルを使用します。モデルカードを参照すると、Wav2Vec2は16kHzでサンプリングされたスピーチオーディオであることがわかります。ご自身の音声データのサンプリングレートが、モデルの事前学習で使用されたデータセットのサンプリングレートと一致することが重要です。データのサンプリングレートが同じでない場合には、データの再サンプリングが必要です。

1. サンプリングレートを16kHzにアップサンプルするために、🤗 Datasetsの[cast\_column](https://huggingface.co/docs/datasets/v2.12.0/en/package_reference/main_classes#datasets.Dataset.cast_column)メソッドを使用します:

    ```py:Python
    dataset = dataset.cast_column("audio", Audio(sampling_rate=16_000))
    ```

1. 音声ファイルを再サンプリングするために再度`audio`カラムを呼び出します:

    ```py:Python
    dataset[0]["audio"]
    ```

    ```
    {'array': array([ 2.3443763e-05,  2.1729663e-04,  2.2145823e-04, ...,
         3.8356509e-05, -7.3497440e-06, -2.1754686e-05], dtype=float32),
     'path': '/root/.cache/huggingface/datasets/downloads/extracted/f14948e0e84be638dd7943ac36518a4cf3324e8b7aa331c5ab11541518e9368c/en-US~JOINT_ACCOUNT/602ba55abb1e6d0fbce92065.wav',
     'sampling_rate': 16000}
    ```

次に、入力を正規化、パディングするために特徴量抽出器をロードします。テキストデータをパディングする際、短いシーケンスには`0`が追加されます。同じ考え方が音声データにも適用されます。特徴量抽出器は、沈黙を意味する`0`を`array`に追加します。

[AutoFeatureExtractor\.from\_pretrained\(\)](https://huggingface.co/docs/transformers/v4.29.1/en/model_doc/auto#transformers.AutoFeatureExtractor.from_pretrained)で特徴量抽出器をロードします:

```py:Python
from transformers import AutoFeatureExtractor

feature_extractor = AutoFeatureExtractor.from_pretrained("facebook/wav2vec2-base")
```

特徴量抽出器に音声の`array`を渡します。また、発生する可能性のあるサイレントエラーをよりデバックしやすくするために、特徴量抽出器に`sampling_rate`引数を追加することをお勧めします。

```py:Python
audio_input = [dataset[0]["audio"]["array"]]
feature_extractor(audio_input, sampling_rate=16000)
```

```
{'input_values': [array([ 3.8106556e-04,  2.7506407e-03,  2.8015103e-03, ...,
        5.6335266e-04,  4.6588284e-06, -1.7142107e-04], dtype=float32)]}
```

トークナイザーと同じように、バッチに対してばらつきのあるシーケンスを取り扱えるようにパディングや切り取りを適用することができます。二つの音声サンプルのシーケンス長を見てみましょう:

```py:Python
dataset[0]["audio"]["array"].shape
(173398,)
dataset[1]["audio"]["array"].shape
(106496,)
```

音声サンプルが同じ長さになるようにデータセットを前処理する関数を作成します。最大サンプル長を指定すると、特徴量抽出器はマッチするようにシーケンスに対してパディング、切り取りを行います:

```py:Python
def preprocess_function(examples):
    audio_arrays = [x["array"] for x in examples["audio"]]
    inputs = feature_extractor(
        audio_arrays,
        sampling_rate=16000,
        padding=True,
        max_length=100000,
        truncation=True,
    )
    return inputs
```

データセットの最初の数サンプルに`preprocess_function`を適用します:

```py:Python
processed_dataset = preprocess_function(dataset[:5])
```

これで、サンプルの長さは指定された最大長にマッチするようになりました。これで、処理されたデータセットをモデルに与えられるようになります！

```py:Python
processed_dataset["input_values"][0].shape
(100000,)
processed_dataset["input_values"][1].shape
(100000,)
```

# コンピュータービジョン

コンピュータービジョンタスクでは、モデルにデータセットを準備するために[image processor](https://huggingface.co/docs/transformers/main_classes/image_processor)が必要となります。画像処理は、モデルによって期待される入力に画像を変換する数ステップから構成されます。これらのステップには、リサイズ、正規化、カラーチャネル修正、画像からtensorへの変換などが含まれます。

:::note
画像処理は、多くの場合ある種の画像拡張を伴います。画像の前処理と画像拡張の両方は画像データを変換しますが、いくつかの目的が異なります:

- 画像拡張はモデルの過学習を避け、堅牢性を高めるための方法で画像を変更します。明度や色の調整、切り取り、改訂ん、リサイズ、ズームなど、画像をどのように拡張するのかに関してクリエイティブになることができます。しかし、ご自身の拡張処理で画像の意味を変更しないことに気をつけてください。
- 画像の前処理は画像がモデルの期待する入力にマッチすることを確実にします。コンピュータービジョンモデルをファインチューニングする際、画像は最初にモデルがトレーニングされた際と全く同じように前処理される必要があります。

画像拡張にはお好きなライブラリを活用することができます。画像の前処理では、モデルに関連づけられている`ImageProcessor`を使ってください。
:::

コンピュータービジョンデータセットにどのように画像プロセッサーを使えるのかを見るために、[food101](https://huggingface.co/datasets/food101)データセットをロードします(どのようにデータセットをロードするのかの詳細については🤗 [Datasets tutorial](https://huggingface.co/docs/datasets/load_hub.html)をご覧ください):

:::note
このデータセットは非常に大きいので、トレーニングスプリットから小規模なサンプルのみをロードするには🤗 Datasetsの`split`パラメーターを使ってください！
:::

```py:Python
from datasets import load_dataset

dataset = load_dataset("food101", split="train[:100]")
```

次に、🤗 Datasetsの[Image](https://huggingface.co/docs/datasets/package_reference/main_classes.html?highlight=image#datasets.Image)機能を用いて画像を見てみます:

```py:Python
dataset[0]["image"]
```

![](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/vision-preprocess-tutorial.png)

[AutoImageProcessor\.from\_pretrained\(\)](https://huggingface.co/docs/transformers/v4.29.1/en/model_doc/auto#transformers.AutoImageProcessor.from_pretrained)で画像プロセッサーをロードします:

```py:Python
from transformers import AutoImageProcessor

image_processor = AutoImageProcessor.from_pretrained("google/vit-base-patch16-224")
```

最初に、いくつかの画像拡張処理を追加しましょう。好きなライブラリを活用することができますが、このチュートリアルでは、torchvisionの[transforms](https://pytorch.org/vision/stable/transforms.html)モジュールを使用します。他のデータ拡張ライブラリに興味があるのであれば、[Albumentations](https://colab.research.google.com/github/huggingface/notebooks/blob/main/examples/image_classification_albumentations.ipynb)や[Kornia notebooks](https://colab.research.google.com/github/huggingface/notebooks/blob/main/examples/image_classification_kornia.ipynb)をご覧ください。

1. ここでは、いくつかの変換処理、[RandomResizedCrop](https://pytorch.org/vision/main/generated/torchvision.transforms.RandomResizedCrop.html)や[ColorJitter](https://pytorch.org/vision/main/generated/torchvision.transforms.ColorJitter.html)をチェーンするために[Compose](https://pytorch.org/vision/master/generated/torchvision.transforms.Compose.html)を使用します。リサイズでは`image_processor`の画像サイズ要件を取得できることに注意してください。いくつかのモデルでは、正確な高さ、幅が期待され、他のモデルでは`shortest_edge`のみが定義されます。

    ```py:Python
    from torchvision.transforms import RandomResizedCrop, ColorJitter, Compose

    size = (
        image_processor.size["shortest_edge"]
        if "shortest_edge" in image_processor.size
        else (image_processor.size["height"], image_processor.size["width"])
    )

    _transforms = Compose([RandomResizedCrop(size), ColorJitter(brightness=0.5, hue=0.5)])
    ```

1. このモデルは入力として[pixel\_values](https://huggingface.co/docs/transformers/model_doc/visionencoderdecoder#transformers.VisionEncoderDecoderModel.forward.pixel_values)を受け付けます。`ImageProcessor`は画像の正規化と適切なtensorの作成をケアすることができます。画像のバッチに対して画像拡張と前処理を組み合わせ、`pixel_values`を生成する関数を作成します:

    ```py:Python
    def transforms(examples):
        images = [_transforms(img.convert("RGB")) for img in examples["image"]]
        examples["pixel_values"] = image_processor(images, do_resize=False, return_tensors="pt")["pixel_values"]
        return examples
    ```

    :::note
    上の例では、画像拡張変換処理ですでに画像をリサイズしており、適切な`image_processor`からの`size`属性を活用するために、`do_resize=False`を設定しています。画像拡張で画像のリサイズを行っていない場合、このパラメーターはそのままにしてください。デフォルトで`ImageProcessor`はリサイズをハンドリングします。

    拡張変換処理の一部で画像を正規化したいのであれば、`image_processor.image_mean`や`image_processor.image_std`の値を活用してください。
   :::

1. そして、オンザフライで変換処理を適用するために、🤗 Datasetsの[set\_transform](https://huggingface.co/docs/datasets/process.html#format-transform)を使用します:

    ```py:Python
    dataset.set_transform(transforms)
    ```

1. これで、画像にアクセスすると画像プロセッサが`pixel_values`を追加していることに気づくことでしょう。これで、モデルに処理したデータセットを渡せるようになります！

    ```py:Python
    dataset[0].keys()
    ```

変換処理を適用した後の画像がどのようになるのかを以下に示します。画像はランダムに切り取られ、色のプロパティが異なっています。

```py:Python
import numpy as np
import matplotlib.pyplot as plt

img = dataset[0]["pixel_values"]
plt.imshow(img.permute(1, 2, 0))
```

![](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/preprocessed_image.png)

:::note
物体検知、セマンティックセグメンテーション、インスタンスセグメンテーション、パノプティックセグメンテーションのようなタスクにおいて、`ImageProcessor`は後処理のメソッドを提供します。これらのメソッドは、モデルの生のアウトプットを、領域ボックスやセグメンテーションマップのように意味のある予測結果に変換します。
:::

## パディング

あるケースでは、例えば、[DETR](https://huggingface.co/docs/transformers/model_doc/detr)をファインチューニングする際、モデルはトレーニング時にスケール拡張を適用します。これによって、バッチにおける画像サイズが異なる場合があります。[DetrImageProcessor](https://huggingface.co/docs/transformers/v4.29.1/en/model_doc/detr#transformers.DetrImageProcessor)の[DetrImageProcessor\.pad\_and\_create\_pixel\_mask\(\)](https://huggingface.co/docs/transformers/v4.29.1/en/model_doc/detr#transformers.DetrFeatureExtractor.pad_and_create_pixel_mask)を使用し、バッチ画像を一緒にするためにカスタムの`collate_fn`を定義することができます。

```py:Python
def collate_fn(batch):
    pixel_values = [item["pixel_values"] for item in batch]
    encoding = image_processor.pad_and_create_pixel_mask(pixel_values, return_tensors="pt")
    labels = [item["labels"] for item in batch]
    batch = {}
    batch["pixel_values"] = encoding["pixel_values"]
    batch["pixel_mask"] = encoding["pixel_mask"]
    batch["labels"] = labels
    return batch
```

# マルチモーダル

マルチモーダルの入力を含むタスクにおいては、モデルのデータセットを準備するために[processor](https://huggingface.co/docs/transformers/main_classes/processors)が必要となります。プロセッサーは、トークナイザーや特徴量抽出器のような2つの処理オブジェクトを一緒にまとめることができます。

自動スピーチ認識(ASR)のために、どのようにプロセッサーを活用できるのかを見るために、[LJ Speech](https://huggingface.co/datasets/lj_speech)データセットをロードします(どのようにデータセットをロードするのかの詳細については🤗 [Datasets tutorial](https://huggingface.co/docs/datasets/load_hub.html)をご覧ください):

```py:Python
from datasets import load_dataset

lj_speech = load_dataset("lj_speech", split="train")
```

ASRでは、主に`audio`と`text`にフォーカスするので他のカラムを削除することができます:

```py:Python
lj_speech = lj_speech.map(remove_columns=["file", "id", "normalized_text"])
```

それでは、`audio`と`text`カラムを見てみましょう:

```py:Python
lj_speech[0]["audio"]
{'array': array([-7.3242188e-04, -7.6293945e-04, -6.4086914e-04, ...,
         7.3242188e-04,  2.1362305e-04,  6.1035156e-05], dtype=float32),
 'path': '/root/.cache/huggingface/datasets/downloads/extracted/917ece08c95cf0c4115e45294e3cd0dee724a1165b7fc11798369308a465bd26/LJSpeech-1.1/wavs/LJ001-0001.wav',
 'sampling_rate': 22050}

lj_speech[0]["text"]
'Printing, in the only sense with which we are at present concerned, differs from most if not from all the arts and crafts represented in the Exhibition'
```

モデルの事前学習で使用されたデータセットのサンプリングレートとご自身の音声データセットのサンプリングレートが一致するように、常に[再サンプル](https://huggingface.co/docs/transformers/preprocessing#audio)を行うことを覚えておいてください！

```py:Python
lj_speech = lj_speech.cast_column("audio", Audio(sampling_rate=16_000))
```

[AutoProcessor\.from\_pretrained\(\)](https://huggingface.co/docs/transformers/v4.29.1/en/model_doc/auto#transformers.AutoProcessor.from_pretrained)でプロセッサーをロードします:

```py:Python
from transformers import AutoProcessor

processor = AutoProcessor.from_pretrained("facebook/wav2vec2-base-960h")
```

1. `array`に含まれる音声データを`input_values`に処理し、`text`を`labels`にトークナイズする関数を作成します。これらはモデルの入力になります:

    ```py:Python
    def prepare_dataset(example):
    audio = example["audio"]

        example.update(processor(audio=audio["array"], text=example["text"], sampling_rate=16000))

        return example
    ```

1. サンプルに`prepare_dataset`関数を適用します:

    ```py:Python
    prepare_dataset(lj_speech[0])
    ```

プロセッサーは`input_values`と`labels`を追加し、サンプリングレートは適切に16kHzにダウンサンプルします。これで、処理されたデータセットをモデルに与えられるようになりました！