8
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

[翻訳] Hugging Face transformersの推論パイプライン

Last updated at Posted at 2023-05-13

Pipelines for inferenceの翻訳です。

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

pipeline()によって、いかなる言語、コンピュータービジョン、スピーチ、マルチモーダルタスクにおける推論において、Hubからのモデルの利用がシンプルになります。特定のモーダル性の経験がない、あるいはモデルの背後にあるコードに慣れていない場合でも、pipeline()を用いることで推論にモデルを活用することができます!このチュートリアルでは以下を学びます:

  • 推論でのpipeline()の使用。
  • 特定のトークナイザー、モデルの使用。
  • 音声、画像、マルチモーダルタスクにおけるpipeline()の使用。

サポートされるタスクや使用できるパラメーターの完全なリストについては、pipeline()のドキュメントをご覧ください。

パイプラインの使用

それぞれのタスクがpipeline()に関連づけられると、全てのタスク固有のパイプラインを格納する汎用のpipeline()抽象化レイヤーの使用がよりシンプルになります。pipeline()は、ご自身のタスクにおける推論を可能とするデフォルトモデルと前処理クラスを自動でロードします。

  1. pipeline()の作成と、推論タスクの指定からスタートします:

    Python
    from transformers import pipeline
    
    generator = pipeline(task="automatic-speech-recognition")
    
  2. pipeline()に入力テキストを引き渡します:

    Python
    generator("https://huggingface.co/datasets/Narsil/asr_dummy/resolve/main/mlk.flac")
    
    {'text': 'I HAVE A DREAM BUT ONE DAY THIS NATION WILL RISE UP LIVE UP THE TRUE MEANING OF ITS TREES'}
    

イメージしていた結果と異なりますか?より良い記述を得ることができるのかを確認するために、Hubで最もダウンロードされている自動スピーチ認識モデルのいくつかをチェックします。openai/whisper-largeをトライしてみましょう:

Python
generator = pipeline(model="openai/whisper-large")
generator("https://huggingface.co/datasets/Narsil/asr_dummy/resolve/main/mlk.flac")
{'text': ' I have a dream that one day this nation will rise up and live out the true meaning of its creed.'}

より正確な結果になりました!別の言語、ご自身の領域に特化したモデルなど、Hubでモデルをチェックすることを強くお勧めします。他のものよりもフィットする、特定のケースに対応できるのかを確認するために、ブラウザから直接Hubでモデルをチェック、比較することができます。そして、ご自身のユースケースに適したモデルが見つからない場合には、いつでもご自身でトレーニングをスタートすることができます!

複数の入力がある場合には、リストとして入力することができます:

Python
generator(
    [
        "https://huggingface.co/datasets/Narsil/asr_dummy/resolve/main/mlk.flac",
        "https://huggingface.co/datasets/Narsil/asr_dummy/resolve/main/1.flac",
    ]
)

データセット全体に対して繰り返したい場合、あるいは、ウェブサーバーでの推論で活用したい場合には専用のドキュメントをご覧ください。

Using pipelines on a dataset

Using pipelines for a webserver

パラメーター

pipeline()は数多くのパラメーターをサポートしています。いくつかはタスク固有で、いくつかは全てのパイプラインで共通です。通常、好きな場所でパラメーターを指定することができます:

Python
generator = pipeline(model="openai/whisper-large", my_parameter=1)
out = generator(...)  # This will use `my_parameter=1`.
out = generator(..., my_parameter=2)  # This will override and use `my_parameter=2`.
out = generator(...)  # This will go back to using `my_parameter=1`.

重要な3つのパラメーターをチェックしましょう:

デバイス

device=nを設定すると、パイプラインは自動で指定されたデバイスにモデルを配置します。これは、PyTorchであろうがTensorflowであろうが動作します。

Python
generator = pipeline(model="openai/whisper-large", device=0)

モデルが単一GPUでは大きすぎる場合、🤗 Accelerateがモデルの重みのロード方法、格納方法を自動で判断するように、device_map="auto"を設定することができます。

Python
#!pip install accelerate
generator = pipeline(model="openai/whisper-large", device_map="auto")

device_map="auto"を指定する際、pipelineのインスタンスを作成する際の引数device=deviceの指定は不要であることに注意してください。予想しない挙動をする場合があります!

バッチサイズ

デフォルトでは、こちらで説明している理由からパイプラインはバッチの推論を行いません。理由は、バッチ処理が必ずしも高速ではないこと、あるケースでは非常に遅くなってしまうことです。

しかし、ご自身のユースケースで問題ない場合には、活用することができます:

Python
generator = pipeline(model="openai/whisper-large", device=0, batch_size=2)
audio_filenames = [f"audio_{i}.flac" for i in range(10)]
texts = generator(audio_filenames)

これは、指定された10の音声ファイルに対してパイプラインを実行しますが、追加のコードを必要とすることなしに、(バッチがより有効である可能性が高いGPU上の)モデルに2つのサイズのバッチを引き渡します。アウトプットは、バッチ処理を行わない際に受け取るものと常に一致しなくてはなりません。これは、パイプラインの高速化だけの役に立つ手法であることを意味します。

また、パイプラインはバッチ処理の複雑性のいくつかを軽減し、いくつかのパイプランにおいては、モデルによって処理されるように(長い音声ファイルなどの)単一のアイテムを複数のパーツにまとめる必要があります。パイプラインはあなたのために、このチャンクパッチ処理を実行します。

タスク固有のパラメーター

全てのタスクでは、あなたがジョブを完了できるように、追加の柔軟性とオプションを提供するタスク固有のパラメーターを提供します。例えば、transformers.AutomaticSpeechRecognitionPipeline.call()メソッドは動画にキャプションをつける役に立つであろうreturn_timestampsパラメーターを持っています:

Python
# Not using whisper, as it cannot provide timestamps.
generator = pipeline(model="facebook/wav2vec2-large-960h-lv60-self", return_timestamps="word")
generator("https://huggingface.co/datasets/Narsil/asr_dummy/resolve/main/mlk.flac")
{'text': 'I HAVE A DREAM BUT ONE DAY THIS NATION WILL RISE UP AND LIVE OUT THE TRUE MEANING OF ITS CREED', 'chunks': [{'text': 'I', 'timestamp': (1.22, 1.24)}, {'text': 'HAVE', 'timestamp': (1.42, 1.58)}, {'text': 'A', 'timestamp': (1.66, 1.68)}, {'text': 'DREAM', 'timestamp': (1.76, 2.14)}, {'text': 'BUT', 'timestamp': (3.68, 3.8)}, {'text': 'ONE', 'timestamp': (3.94, 4.06)}, {'text': 'DAY', 'timestamp': (4.16, 4.3)}, {'text': 'THIS', 'timestamp': (6.36, 6.54)}, {'text': 'NATION', 'timestamp': (6.68, 7.1)}, {'text': 'WILL', 'timestamp': (7.32, 7.56)}, {'text': 'RISE', 'timestamp': (7.8, 8.26)}, {'text': 'UP', 'timestamp': (8.38, 8.48)}, {'text': 'AND', 'timestamp': (10.08, 10.18)}, {'text': 'LIVE', 'timestamp': (10.26, 10.48)}, {'text': 'OUT', 'timestamp': (10.58, 10.7)}, {'text': 'THE', 'timestamp': (10.82, 10.9)}, {'text': 'TRUE', 'timestamp': (10.98, 11.18)}, {'text': 'MEANING', 'timestamp': (11.26, 11.58)}, {'text': 'OF', 'timestamp': (11.66, 11.7)}, {'text': 'ITS', 'timestamp': (11.76, 11.88)}, {'text': 'CREED', 'timestamp': (12.0, 12.38)}]}

見てわかるように、モデルはテキストを推定するとともに、文の中で単語がいつ発音されたのかをアウトプットします。

それぞれのタスクで使用できるパラメーターは多数ありますので、ピンとくるものを見つけ出すにはタスクごとのAPIリファレンスをチェックしてください!例えば、AutomaticSpeechRecognitionPipelineには、モデル自身では多くの場合で取り扱いができない非常に長い音声ファイル(例えば、映画全体や数時間の動画にキャプションをつける)を取り扱う際に役立つchunk_length_sパラメーターがあります。

必要なパラメーターが見つからない場合には、ぜひリクエストしてください!

データセットにパイプラインを使用

また、大規模データセットに対してパイプラインを実行することもできます。推奨の最も簡単な方法はイテレーターを用いることです:

Python
def data():
    for i in range(1000):
        yield f"My example {i}"


pipe = pipeline(model="gpt2", device=0)
generated_characters = 0
for out in pipe(data()):
    generated_characters += len(out[0]["generated_text"])

イテレーターdata()はそれぞれの結果を生成し、パイプラインは自動で入力に対するイテレーションが可能であることを認識し、GPUで処理を継続しながらも、データの取得をスタートします(これは内部でDataLoaderを活用しています)。これは、データセット全体にメモリーを割り当てる必要がなく、GPUに可能な限り高速にデータを投入できるので重要なこととなります。

バッチ処理によって高速化される場合があるので、ここでbatch_sizeパラメーターのチューニングをトライすることは有用です。

データセットに対するイテレーションの最も簡単な方法は、単に🤗 Datasetsからロードするというものです:

Python
# KeyDataset is a util that will just output the item we're interested in.
from transformers.pipelines.pt_utils import KeyDataset
from datasets import load_dataset

pipe = pipeline(model="hf-internal-testing/tiny-random-wav2vec2", device=0)
dataset = load_dataset("hf-internal-testing/librispeech_asr_dummy", "clean", split="validation[:10]")

for out in pipe(KeyDataset(dataset, "audio")):
    print(out)

ウェブサーバーにパイプラインを使用

推論エンジンの構築は専用のページが必要となる複雑なトピックです。

Link

ビジョンパイプライン

ビジョンタスクでのpipeline()の活用は実際のところ同じです。

分類器にタスクを指定し、画像を入力します。画像はリンクや画像に対するローカルパスとなります。例えば、以下に示している猫の種類はなんでしょうか?

Python
from transformers import pipeline

vision_classifier = pipeline(model="google/vit-base-patch16-224")
preds = vision_classifier(
    images="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/pipeline-cat-chonk.jpeg"
)
preds = [{"score": round(pred["score"], 4), "label": pred["label"]} for pred in preds]
preds
[{'score': 0.4335, 'label': 'lynx, catamount'}, {'score': 0.0348, 'label': 'cougar, puma, catamount, mountain lion, painter, panther, Felis concolor'}, {'score': 0.0324, 'label': 'snow leopard, ounce, Panthera uncia'}, {'score': 0.0239, 'label': 'Egyptian cat'}, {'score': 0.0229, 'label': 'tiger cat'}]

テキストパイプライン

NLPタスクにおけるpipeline()の活用も同じです。

Python
from transformers import pipeline

# This model is a `zero-shot-classification` model.
# It will classify text, except you are free to choose any label you might imagine
classifier = pipeline(model="facebook/bart-large-mnli")
classifier(
    "I have a problem with my iphone that needs to be resolved asap!!",
    candidate_labels=["urgent", "not urgent", "phone", "tablet", "computer"],
)
{'sequence': 'I have a problem with my iphone that needs to be resolved asap!!', 'labels': ['urgent', 'phone', 'computer', 'not urgent', 'tablet'], 'scores': [0.504, 0.479, 0.013, 0.003, 0.002]}

マルチモーダルパイプライン

pipeline()は1つ以上のモーダルをサポートしています。例えば、ビジュアル質問回答(VQA)タスクではテキストと画像を組み合わせます。お好きな画像リンクと、画像に対する質問を使用することができます。画像は、画像へのURLあるいはローカルパスとなります。

例えば、こちらのinvoice imageを使用します:

Python
from transformers import pipeline

vqa = pipeline(model="impira/layoutlm-document-qa")
vqa(
    image="https://huggingface.co/spaces/impira/docquery/resolve/2359223c1837a7587402bda0f2643382a6eefeab/invoice.png",
    question="What is the invoice number?",
)
[{'score': 0.42515, 'answer': 'us-001', 'start': 16, 'end': 16}]

上のサンプルを実行するには、🤗 Transformersに加えてpytesseractをインストールする必要があります:

sudo apt install -y tesseract-ocr
pip install pytesseract

大規模モデルに対する🤗 acceleratepipelineの活用

🤗 accelerateを用いることで、大規模モデルに対して容易にpipelineを実行することができます!最初にpip install accelerateaccelerateをインストールするようにしてください。

最初にdevice_map="auto"を用いてモデルをロードします!このサンプルでは、facebook/opt-1.3bを使います。

Python
# pip install accelerate
import torch
from transformers import pipeline

pipe = pipeline(model="facebook/opt-1.3b", torch_dtype=torch.bfloat16, device_map="auto")
output = pipe("This is a cool example!", do_sample=True, top_p=0.95)

また、bitsandbytesをインストールし、引数load_in_8bit=Trueを追加すると、8-bitでロードされたモデルを引き渡すことができます。

Python
# pip install accelerate bitsandbytes
import torch
from transformers import pipeline

pipe = pipeline(model="facebook/opt-1.3b", device_map="auto", model_kwargs={"load_in_8bit": True})
output = pipe("This is a cool example!", do_sample=True, top_p=0.95)

BLOOMのように大規模モデルのロードをサポートしている任意のHugging Faceモデルでcheckpointを置き換えることができることに注意してください!

8
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?