こんにちは、みなさん!
以前の投稿の 1 つで、微調整についてと、それが重要である理由について説明しました。この投稿では、命令微調整と呼ばれる特定の種類の微調整について見ていきます。
gpt-3 のような事前トレーニング済みの基本モデルは、膨大な量のデータでトレーニングされます。 gpt-3 の場合、すべてのデータはインターネット上にあります。確かなことはわかりませんが、これらのモデルのほとんどは、かなりの手動クリーンアップとフォーマットを行った後、インターネット規模のデータでトレーニングされています。トレーニングを受けると、ベースのモデルは次のトークンを予測する方法を学習し、トークン予測が非常に上手になります。しかし、純粋なトークン予測は、思っているほど役に立ちません。事前にトレーニングされた基本モデルに「メキシコの首都はどこですか?」と質問すると、 「コロンビアの首都は何ですか」と入力文を完成させることはできますが、回答は返されません。したがって、gpt-3 のようなモデルはトークン予測には強力ですが、チャットボットや副操縦士としては機能しません。では、事前トレーニングされたモデルを chat-gpt のような便利なチャットボットに変換するにはどうすればよいでしょうか?答えは微調整であり、主に「命令微調整」と呼ばれる特定のタイプの微調整です。
「命令フォロー」とも呼ばれる命令の微調整は、事前トレーニングされた基本モデルにチャット ボットのように動作するように教えるプロセスです。
命令の微調整には、質問と回答の形式のデータセットが必要です。公開データ セットまたは Q&A 形式の企業データ セットを使用できます。データ セットが Q&A 形式でない場合は、Alpaca などのさまざまな手法を使用するか、他の LLM のカスタム プロンプトを使用して、データを Q&A に変換できます。命令の微調整により、微調整で使用するデータだけでなく質問に答えるという新しい動作がモデルに与えられますが、この新しい動作はモデルがすでに持っている既存の知識にも適用できるため、微調整が強力な手法となることに注意してください。
Lamini は、開発者がホスティング、トレーニング、その他の複雑な側面の複雑さを抽象化し、簡単な方法で言語モデルを処理できるようにする AI 企業です。ここでその全機能を確認してください。 Lamini を使用して、 Eleuther AIによって作成されたオープンソース モデルであるpythiaと呼ばれる小規模な言語モデルをトレーニングし、Alpaca と呼ばれる企業データセットを使用して命令の微調整を行います。
このステップでは、必要なモジュールを初期化し、アルパカのトレーニング データ セットも確認します。コードは次のとおりです。
import itertools import jsonlines from datasets import load_dataset from pprint import pprint from llama import BasicModelRunner from transformers import AutoTokenizer, AutoModelForCausalLM from transformers import AutoModelForSeq2SeqLM, AutoTokenizer ## we are using alpaca data set, which is an open source fine tuning data set instruction_tuned_dataset = load_dataset("tatsu-lab/alpaca", split="train", streaming=True) m = 5 print("Instruction-tuned dataset:") top_m = list(itertools.islice(instruction_tuned_dataset, m)) for j in top_m: print(j)
命令チューニング データ セットは次のようになります。質問と回答の形式のデータが含まれています。
このステップでは、アルパカ セットからデータを取得し、以下に示すプロンプトに入力します。
prompt_template_with_input = """Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request. ### Instruction: {instruction} ### Input: {input} ### Response:""" prompt_template_without_input = """Below is an instruction that describes a task. Write a response that appropriately completes the request. ### Instruction: {instruction} ### Response:""" ## hydrate prompts - meaning add data to the above prompts processed_data = [] for j in top_m: if not j["input"]: processed_prompt = prompt_template_without_input.format(instruction=j["instruction"]) else: processed_prompt = prompt_template_with_input.format(instruction=j["instruction"], input=j["input"]) processed_data.append({"input": processed_prompt, "output": j["output"]})
これを実行すると、データセットは次のようになります。
基本的に、生の Q&A データを取得し、質問されたときにその質問に対する応答がどのようになるべきかを LLM にとって意味のある形式に変換しています。これを繰り返し実行し、 jsonlファイルに保存します。
with jsonlines.open(f'alpaca_processed.jsonl', 'w') as writer: writer.write_all(processed_data)
ステップ 1 と 2 では、生データをロードしてハイドレートし、 jsonl形式で保存しました。ただし、Lamini にはこの水和されたデータが用意されているため、技術的にはステップ 1 と 2 は必要ありません。しかし、命令の微調整がどのように機能するかを理解するには、それを示す必要がありました。まず、微調整されていないバージョンの Pythia モデルが簡単な質問にどのように応答するかを見てみましょう。
tokenizer = AutoTokenizer.from_pretrained("EleutherAI/pythia-70m") #70M parameter model that is not instruction tuned. model = AutoModelForCausalLM.from_pretrained("EleutherAI/pythia-70m") def inference(text, model, tokenizer, max_input_tokens=1000, max_output_tokens=100): # Tokenize input_ids = tokenizer.encode( text, return_tensors="pt", truncation=True, max_length=max_input_tokens ) # Generate device = model.device generated_tokens_with_prompt = model.generate( input_ids=input_ids.to(device), max_length=max_output_tokens ) # Decode generated_text_with_prompt = tokenizer.batch_decode(generated_tokens_with_prompt, skip_special_tokens=True) # Strip the prompt generated_text_answer = generated_text_with_prompt[0][len(text):] return generated_text_answer ## the 70M model doesnt have any company specific data, we will use the alpace data set from hosted on lamini and fine tune this model # load alpaca dataset finetuning_dataset_path = "lamini/lamini_docs" finetuning_dataset = load_dataset(finetuning_dataset_path) #print(finetuning_dataset) test_sample = finetuning_dataset["test"][0] print(test_sample) print("untrained output sample") print(inference(test_sample["question"], model, tokenizer))
これが私が得た出力です。出力は役に立たず、モデルはトークン補完を行おうとしており、実際の答えを与えていないことがわかります。
前のステップで確認した Q&A データを使用して指示を微調整すると、同じモデルがチャット ボットのように動作し始め、細かいデータだけでなくモデルがすでに持っているデータの両方について質問に対してより正確な回答を提供します。から成ります。それは、子供が初めて言語を学ぶときとほぼ同じで、言語トレーニングによって学んだ新しいこととともに、すでに持っている感情を表現できるようになります。モデルの事前トレーニング済みバージョンと同様に、命令を微調整したモデルも Lamini でホストされており、以下に示すコマンドで推論できます。 (はい、ラミニは素晴らしいです!)
## finetuned output instruction_model = AutoModelForCausalLM.from_pretrained("lamini/lamini_docs_finetuned") print("instruction finetuned output") print(inference(test_sample["question"], instruction_model, tokenizer))
出力は次のようになります。前のステップで見た意味不明な出力の代わりに、より正確な出力が得られることがわかります。
この投稿の目的は、命令の微調整の概要と、それを使用して基本モデルをより使いやすいバージョンに作成する方法を紹介することです。今後の投稿では、命令の微調整を行う実際のプロセスを詳しく掘り下げていきます。
以上、100 日間の AI の 13 日目でした。
私は「Above Average」というニュースレターを執筆しており、大手テクノロジー業界で起こっているすべての背後にある二次的な洞察について話しています。テクノロジー業界にいて、平均的な人間になりたくない場合は、購読してください。
AI の 100 日間に関する最新情報については、 TwitterとLinkedInで私をフォローしてください。テクノロジーに携わっている場合は、ここにあるテクノロジー専門家のコミュニティに参加することに興味があるかもしれません。
ここにも登場します。