このシリーズでは、自然言語処理において主流であるTransformerを中心に、環境構築から学習の方法までまとめます。

今回の記事ではHuggingface Transformersによる日本語のテキスト生成を実装を紹介します。

2022年に公開された「japanese-gpt-1b」モデルを使用して、高精度なテキスト生成で遊んでみましょう。

Google colabを使用して、簡単に最新の自然言語処理モデルを実装することができますので、ぜひ最後までご覧ください。

【ChatGPT】自然言語処理まとめ【Huggingface Transformers】

自然言語処理に関するおすすめの書籍 ChatGPT ChatGPTを中心とした、GPT系の関連技術を紹介します。 ChatGPTの概要 ・ChatGPTとは・ChatGPTができること・ChatGPTの問題点…

今回の内容

・「japanese-gpt-1b」とは

・テキスト生成(サンプル)

・テキスト生成(指定した語彙を追加するforce_words_ids)

テキスト生成とは

自然言語処理におけるテキスト生成とは、特定のコンテキストからの継続であるテキストの一貫した部分を作成するタスクです。

例えば今回紹介するように「むかし、むかし、あるところに、」に続く自然な文章を生成することができます。

このような例だけなく、商品のキャッチコピーや説明文の自動生成など、様々な用途で応用が期待されています。

今回は2022年に公開された「japanese-gpt-1b」モデルを使用して、テキスト生成の基本的な使用方法を紹介します。

Transformerとは

概要

「Transformer」は2017年にGoogleが「Attention is all you need」で発表した深層学習モデルです。

現在では、自然言語処理に利用する深層学習モデルの主流になっています。

これまでの自然言語処理分野で多く使われていた「RNN」(Recurrent Neural Network)や「CNN」(Convolutional Neural Network)を利用せず、Attentionのみを用いたEncoder-Decoder型のモデルとなっています。

「Transformer」が登場して以降、多くの自然言語処理モデルが再構築され、過去を上回る成果を上げています。

最近では自然言語処理だけでなく、ViTやDETRなどといった画像認識にも応用されています。

詳細は以下の記事をご覧ください。

【🔰Huggingface Transformers入門④】 pipelineによるタスク実装紹介

このシリーズでは、自然言語処理において主流であるTransformerを中心に、環境構築から学習の方法までまとめます。 今回の記事ではHuggingface Transformersの入門として…

Huggingface Transformersとは

概要

「Hugging Face」とは米国のHugging Face社が提供している、自然言語処理に特化したディープラーニングのフレームワークです。

「Huggingface Transformers」は、先ほど紹介したTransformerを実装するためのフレームワークであり、「自然言語理解」と「自然言語生成」の最先端の汎用アーキテクチャ(BERT、GPT-2など)と、何千もの事前学習済みモデルを提供しています。

ソースコードは全てGitHub上で公開されており、誰でも無料で使うことができます。

事前学習済みモデル

Hugging Faceではタスクに応じた様々な事前学習済みモデルが提供されています。

こちらからご確認ください。

「japanese-gpt-1b」とは

「japanese-gpt-1b」はrinna社が2022年に公開した、日本語に特化した13億パラメータのGPT言語モデルです。

rinna社は2020年6月にマイクロソフトのAI&リサーチ部門でAIチャットボットの研究を行っていたチームがスピンアウトして設立されました。

このモデルの学習データとして、日本語のC4 ( https://huggingface.co/datasets/allenai/c4 )、CC-100 ( http://data.statmt.org/cc-100/ ) 、Wikipediaのオープンソースデータを使用しており、約14 perplexityを達成しています。

(14 perplexityとは、次の単語を予測するときに、単語候補の数を14に絞れる。この数は少ない程性能が良い。)

モデルはHugging Face でMITライセンスで公開されています。

テキスト生成(サンプル)

Google colabによる導入

ここからはGoogle colabを使用して実装していきます。

まずはGPUを使用できるように設定をします。

「ランタイムのタイプを変更」→「ハードウェアアクセラレータ」をGPUに変更

今回紹介するコードは以下のボタンからコピーして使用していただくことも可能です。

Open In Colab

まずはGoogleドライブをマウントして、作業フォルダを作成します。

from google.colab import drive 
drive.mount('/content/drive')
!mkdir -p '/content/drive/My Drive/huggingface_transformers_demo/'
%cd '/content/drive/My Drive/huggingface_transformers_demo/'

次に必要なライブラリをインストールします。

!pip install transformers==4.18.0
!pip install sentencepiece==0.1.96

テキスト生成を実装

まずは「japanese-gpt-1b」を読み込みます。

import torch
from transformers import T5Tokenizer, AutoModelForCausalLM
tokenizer = T5Tokenizer.from_pretrained("rinna/japanese-gpt-1b")
model = AutoModelForCausalLM.from_pretrained("rinna/japanese-gpt-1b")

if torch.cuda.is_available():
    model = model.to("cuda")

次に「text」の部分に書き出しとしたい文章(または単語)を指定します。

あとは、model.generate()によって簡単に文章を生成することができます。

以下の例では「自然言語処理の学習を始めるには、まず」に続く文章を生成します。

text = "自然言語処理の学習を始めるには、まず"
token_ids = tokenizer.encode(text, add_special_tokens=False, return_tensors="pt")

with torch.no_grad():
    output_ids = model.generate(
        token_ids.to(model.device),
        max_length=100,
        min_length=100,
        do_sample=True,
        top_k=500,
        top_p=0.95,
        pad_token_id=tokenizer.pad_token_id,
        bos_token_id=tokenizer.bos_token_id,
        eos_token_id=tokenizer.eos_token_id,
        bad_word_ids=[[tokenizer.unk_token_id]]
    )

output = tokenizer.decode(output_ids.tolist()[0])
print(output) 

実行すると、以下のような結果が出力されます。

自然言語処理の学習を始めるには、まず「自然言語処理とは?」という基本的な知識を理解することが大切です。そのうえで、「単語の意味」「文章構造」「単語間の関係」などを習得し、より高度な自然言語処理について学んでいきます。まずは基本的な考え方を理解しましょう。本講座では、まず次の2つのステップで自然言語処理の考え方や基礎を説明します。自然言語処理とは?身近な問題から自然言語処理を学ぶ方法自然言語処理基礎講座は、基礎知識から本格的な技術習得

生成される文章の長さを100としているため、文章が途中で途切れていますが、自然な文章が出力されました。

「text」の部分を変えることで、様々な文章を作成することができます。

text = "今日の占いです。9月1日の山羊座の運勢は"
token_ids = tokenizer.encode(text, add_special_tokens=False, return_tensors="pt")

with torch.no_grad():
    output_ids = model.generate(
        token_ids.to(model.device),
        max_length=100,
        min_length=100,
        do_sample=True,
        top_k=500,
        top_p=0.95,
        pad_token_id=tokenizer.pad_token_id,
        bos_token_id=tokenizer.bos_token_id,
        eos_token_id=tokenizer.eos_token_id,
        bad_word_ids=[[tokenizer.unk_token_id]]
    )

output = tokenizer.decode(output_ids.tolist()[0])
print(output) 

実行すると、以下のような結果が出力されます。

今日の占いです。9月1日の山羊座の運勢は、かなりの人におごられそう。あなたの能力では成し遂げられないことの数をこなしていくことになりそうです。こういう時期は、最初から予定を立てて進むのではなく、とにかく勢いづくものを味方につけて進みましょう。そうすると、その勢いにどんどん乗っていくことが出来ます。チャンスは、あなたが手中に収めたものではありません。誰かがつかんだものです。だから、自分で勝ち取るなどと考えずに、「あなたにできること、手を差し伸べてくれる人を大切にする」という

今回の例でも自然な文章が出力されました。

参考(引数)

上記に例では一部の値を指定していますが、他にも細かな設定が可能です。

詳細は以下の表をご覧ください。

引数設定
input_ids・プロンプトとして使用するテキスト
max_length
(int, optional, defaults to model.config.max_length)
・生成されるテキストの最大の長さ
min_length
(int, オプション。デフォルトは10)
・生成されるテキストの最小の長さ
do_sample
(bool, オプション.デフォルトはFalse)
・サンプリングを行うかどうか
・Falseの場合はgreedyでコードを使用
num_return_sequences
(int, optional, defaults to 1)
・生成するテキストの数
top_k
(int, optional, defaults to 50)
・各ステップの中でK個の単語からランダムで選択する
top_p
(float, optional, defaults to 1.0) –
・生成テキストの累積確率に制限する
temperature
(float, optional, defaults to 1.0)
・ランダムさ
early_stopping
(bool, optional, defaults to False)
・バッチごとに少なくとも num_beams のセンテンスが終了した時点でビーム探索を停止するかどうか
num_beams
(int, オプション,デフォルトは1)
・ビーム探索の対象となるビームの本数
・1はビームサーチを行わないことを意味する
encoder_no_repeat_ngram_size
(int, optional, defaults to 0)
・int > 0 に設定すると、 encoder_input_ids に現れるそのサイズの ngram はすべて decoder_input_ids に現れることができない
bad_words_ids
(List[List[int]], optional)
・生成を許可しないトークンIDのリスト
・生成されたテキストに現れてはならない単語のトークンIDを得るには、 tokenizer(bad_words, add_prefix_space=True, add_special_tokens=False).input_ids を使用する
force_words_ids
(List[List[int]] or List[List[List[int]], optional) –
・生成しなければならないトークンIDのリスト
・List[List[int]]が与えられた場合、これは含まれなければならない単語の単純なリストとして扱われ、bad_words_idsの逆となる
max_time
(float, オプション)
・計算を実行できる最大時間
attention_mask (torch.LongTensor of shape
(batch_size, sequence_length), optional)
・パディングトークンインデックスに対してアテンションを実行しないためのマスク
・マスクの値は [0, 1] で、マスクされないトークンは 1、マスクされるトークンは 0
num_beam_groups (int, オプション。デフォルトは1) ・ビームのグループ間の多様性を確保するために、 num_beam をいくつのグループに分けるか。
diversity_penalty
(float, optional, defaults to 0.0)
・あるビームが他のグループのビームと同じトークンを生成した場合に、そのビームのスコアから減算される
・diversity_penalty は、グループビーム検索が有効な場合のみ有効であることに注意
prefix_allowed_tokens_fn
(Callable[[int, torch.Tensor], List[int]], optional)
・ビームサーチを各ステップで許されたトークンのみに制限
・接頭辞を条件とする制約付き生成に有用
logits_processor
(LogitsProcessorList, オプション)
・引数とモデルの設定から構築されたデフォルトのlogitsプロセッサを補完する、カスタムのlogitsプロセッサ
stopping_criteria
(StoppingCriteriaList, optional)
・引数とモデルの設定から構築されたデフォルトの停止基準を補完するカスタムの停止基準
constraints
(List[Constraint], optional)
・出力がConstraintオブジェクトによって定義される特定のトークンの使用を含むことを保証するために、生成に追加できるカスタム制約
output_attentions
(bool, optional, defaults to False)
・すべてのアテンションレイヤのアテンションテンソルを返すかどうか
output_hidden_states
(bool, optional, defaults to False)
・すべてのレイヤーの隠された状態を返すかどうか
output_scores
(bool, optional, defaults to False)
・予測スコアを返すかどうか

return_dict_in_generate
(bool, optional, defaults to False)
・プレーンなタプルではなく、ModelOutputを返すかどうか
forced_bos_token_id
(int, オプション)
・decoder_start_token_id の後に最初に生成されるトークンとして強制的に使用するトークンの ID
forced_eos_token_id (int, optional) ・max_lengthに達したときに最後に生成されるトークンとして強制的に使用するトークンのid
remove_invalid_values (bool, optional) ・生成メソッドのクラッシュを防ぐために、モデルのnanとinf出力の可能性を削除するかどうかを指定
synced_gpus (bool, optional, defaults to False) ・whileループをmax_lengthまで実行し続けるかどうか
exponential_decay_length_penalty
(tuple(int, float), optional)
・一定量のトークンが生成された後に、指数関数的に増加する長さのペナルティを追加する

テキスト生成(指定した語彙を追加するforce_words_ids)

前述の通り、model.generate()にはいくつものパラメータがあります。

ここでは例として、「force_words_ids」による指定した語彙を追加を実装してみます。

以下の例では、「ラッキーアイテム」、「赤い靴」という言葉が結果に含まれるようにします。

text = "今日の占いです。9月1日の山羊座の運勢は"
force_words = ["ラッキーアイテム","赤い靴"]

token_ids = tokenizer.encode(text, add_special_tokens=False, return_tensors="pt")
force_words_ids = tokenizer(force_words, add_special_tokens=False).input_ids

with torch.no_grad():
    output_ids = model.generate(
        token_ids.to(model.device),
        force_words_ids=force_words_ids,
        max_length=100,
        min_length=100,
        num_beams=20,
        early_stopping=True,
        no_repeat_ngram_size=1,
        remove_invalid_values=True,
        pad_token_id=tokenizer.pad_token_id,
        bos_token_id=tokenizer.bos_token_id,
        eos_token_id=tokenizer.eos_token_id,
        bad_word_ids=[[tokenizer.unk_token_id]]
    )

output = tokenizer.decode(output_ids.tolist()[0])
print(output) 

実行すると、以下のような結果が出力されます。

今日の占いです。9月1日の山羊座の運勢は、自分の ラッキーカラーの ラッキーアイテムを身につけて出かけ 赤い靴下を履いて出かけてみましょう。ラッキーなことが 起こりそうな予感がしてきませんか?また、9月の誕生石であるルビーやサファイヤなどの 宝石を身につけるとさらに幸運が舞い込んできそうです!9月は何かと気ぜわしく落ち着かない日々が続きますが そんな時こそ赤いものを身に着けることで心穏やかに過ごすことができるはずですよ♪

「ラッキーアイテム」、「赤い靴」という言葉を含めた自然な文章が出力されました。

まとめ

最後までご覧いただきありがとうございました。

今回の記事ではHuggingface Transformersによる日本語のテキスト生成の方法を紹介しました。

このシリーズでは、自然言語処理全般に関するより詳細な実装や学習の方法を紹介しておりますので、是非ご覧ください。

【ChatGPT】自然言語処理まとめ【Huggingface Transformers】

自然言語処理に関するおすすめの書籍 ChatGPT ChatGPTを中心とした、GPT系の関連技術を紹介します。 ChatGPTの概要 ・ChatGPTとは・ChatGPTができること・ChatGPTの問題点…