LoginSignup
5
4

オープンソースのLLMをLoRAを用いてCPUのみでファインチューニングする

Last updated at Posted at 2024-01-14

はじめに

オープンソースのLLM(大規模言語モデル)を個人で利用する場合、GPUはとても高価で手が出せない場合が多いです。CPUを利用すれば実行時間がGPU利用時に比べてだいぶ長くなりますが、安価に利用できるようになります。

しかし、LLMの利用についてGPU前提の記事が多く見受けられ、そのままだとCPU環境ではエラーになる場合があります。この記事はCPU環境で利用できるコードを例示します。

ここでは、東京工業大学と産総研が開発したLLMであるSwallowの利用方法と、ファインチューニング方法として訓練時間や必要なメモリやストレージ量を節約できる優れた訓練方法であるLoRA(ローラ、ロラ、Low-Rank Adaptation)を用いたファインチューニングについてメモします。

この記事にピッタリの方

  1. OSSのLLMをプライベートで動作させたい
  2. LoRAでファインチューニングしたい
  3. GPUがないため、CPUを利用したい

この記事で前提とすること

  1. LLMについて基本的な知識とpythonやLinuxの基本知識がある

おしながき

  1. 試行に使った環境(マシンスペック)
  2. Swallowを動作させる(推論)
  3. SwallowをLoRAでファインチューニングする
  4. ファインチューニングした結果を利用する
  5. まとめ

試行に使った環境(マシンスペック)

OS:Ubuntu 22.04.3 LTS
CPU数:16個(AMD Ryzen 5)
メモリ:約62GB
HDD:400GB

メモリは60GB以上は必須です。
HDDは200GB程度でも動作するかもですが、モデルのファイルサイズが大きくなりがちなため、沢山用意しておいたほうが良いです。

なお、GPUはありません。

Swallowを動作させる(推論動作)

Swallowとは東京工業大学と産総研がタッグを組んで開発した、現在最大規模の日本語に対応した大規模言語モデルで、オープンで商用利用が可能であるため、ビジネスに安心して用いることができるものです。詳細は、東京工業大学のページに譲ります。

ここではそれを手元のパソコンで動作させることを試みます。

動作に必要なライブラリのインストール

この環境では以下の作業が必要でした。

sudo apt install pip
pip install transformers sentencepiece accelerate
pip install protobuf

動作のサンプルプログラムのダウンロード

git clone https://github.com/miyakz1192/alpaca-lora.git
cd alpaca-lora
git checkout oncpu

では早速、swallowをダウンロードして実際に動かしてみます。試しに、以下のようなプロンプトを入力してみます。

以下に、あるタスクを説明する指示があり、それに付随する入力が更なる文脈を提供しています。リクエストを適切に完了するための回答を記述してください。

指示:

以下のトピックに関する詳細な情報を提供してください

入力:

この中でラッパーなのはどれ?エミネム、マイケル・ジャクソン、リアーナ、50セント

以下のコマンドを実行します。このコマンドを実行すれば、自動的にswallowのモデルが>ネット(hugging face)からダウンロードされ、上記のプロンプトが入力されることになります。以下の通り、実際のプロンプトデータはinput.txtとinstruction.txtに格納されています。

cd sampleuse
./sample_swallow.py  --verbose  --input=input.txt --instruction=instruction.txt

以下のような結果となります(結果は毎回変わる可能性があります)。

miyakz@swallow:~/github_repos/alpaca-lora/sampleuse$ ./sample_swallow.py  --verbose  --input=input.txt --instruction=instruction.txt
LoRAのデータ指定=False
LoRAのデータディレクトリ=None
指示プロンプトファイル=instruction.txt
プロンプトファイル=input.txt
モデルの個別指定=None
最終的に選択したモデル=tokyotech-llm/Swallow-7b-instruct-hf
ベースモデルのロード
Loading checkpoint shards: 100%|██████████████████| 3/3 [00:02<00:00,  1.11it/s]
以下に、あるタスクを説明する指示があり、それに付随する入力が更なる文脈を提供しています。リクエストを適切に完了するための回答を記述してください。

### 指示:
以下のトピックに関する詳細な情報を提供してください


### 入力:
この中でラッパーなのはどれ?エミネム、マイケル・ジャクソン、リアーナ、50セント


### 応答:50セント
miyakz@swallow:~/github_repos/alpaca-lora/sampleuse$

なお、今回使ったモデルは、約70億パラメータ(最小)の"tokyotech-llm/Swallow-7b-instruct-hf"になります。必要に応じて選択可能です。選択可能なモデルは、Swallowのhugging faceのサイトを参照ください。

このサンプルコマンドの使用方法は以下の通りです。

miyakz@swallow:~/github_repos/alpaca-lora/sampleuse$ ./sample_swallow.py  --help
usage: sample_swallow.py [-h] [--lora_data LORA_DATA]
                         [--instruction INSTRUCTION] [--input INPUT]
                         [--model MODEL] [--verbose]
                         [--max_new_tokens MAX_NEW_TOKENS]

Swallow利用のサンプル

options:
  -h, --help            show this help message and exit
  --lora_data LORA_DATA
                        LoRAデータのディレクトリ名(絶対パスで指定する)
  --instruction INSTRUCTION
                        指示プロンプトを記載したファイル
  --input INPUT         入力プロンプトを記載したファイル
  --model MODEL         モデル名を指定します
  --verbose             詳細出力を有効
  --max_new_tokens MAX_NEW_TOKENS
                        出力のトークン数(デフォルト128。min:128, max:1024, step:64)
miyakz@swallow:~/github_repos/alpaca-lora/sampleuse$ 

モデル名を指定しないと、tokyotech-llm/Swallow-7b-instruct-hfが選択されます。
"--lora_data"は、ファインチューニングした結果生成されたファイルのディレクトリを指定します。LoRAによるファインチューニングは後述します。

Swallowをファインチューニングする

それでは、Swallowをファインチューニングしてみます。
LoRAとはモデル全体を訓練するのではなく、重みの一部分を外付けで訓練して、モデル本体に移入するようなイメージです。詳細は日経クロステックのサイトがわかりやすいです。

また、訓練データが必要です。データはこちらからダウンロードします。
databricks-dolly-15k-jaはDatabricks社の社員たちに作られたデータだそうで、オープンソースのものになります。

git clone https://github.com/kunishou/databricks-dolly-15k-ja.git

databricks-dolly-15k-jaディレクトリに移動し、databricks-dolly-15k-ja.jsonというファイルを先ほどのalpaca-loraディレクトリ下に保存しておきます。例えば、dataset/というディレクトリを掘り、そこに入れておきます。

次に、alpaca-loraディレクトリに行き、以下のスクリプトを実行します。

cd alpaca-lora
./go_finetune2.sh

実際の中身は以下を実行しているだけです。

set -x
python3 finetune.py --base_model="tokyotech-llm/Swallow-7b-instruct-hf"  --data_path="./dataset/databricks-dolly-15k-ja.json" --num_epochs=1 --output_dir=output

CPUのみの環境だとカナリの時間を要します。都合上、上記の通り、epoch=1で訓練しました。こちらの環境だと、約5日間かかりました。

ファインチューニングした結果を利用する

LoRAあり

以下のようにして、outputに吐き出されたデータを指定してツールを動作させます。
"--lora_data"オプションで学習結果のデータの場所を指定します。

miyakz@swallow:~/github_repos/alpaca-lora/sampleuse$ ./sample_swallow.py  --input=input.txt --instruction=instruction.txt --lora_data=/home/miyakz/alpaca-lora/output
Loading checkpoint shards: 100%|██████████████████| 3/3 [00:02<00:00,  1.11it/s]
/home/miyakz/.local/lib/python3.10/site-packages/bitsandbytes/cextension.py:34: UserWarning: The installed version of bitsandbytes was compiled without GPU support. 8-bit optimizers, 8-bit multiplication, and GPU quantization are unavailable.
  warn("The installed version of bitsandbytes was compiled without GPU support. "
/home/miyakz/.local/lib/python3.10/site-packages/bitsandbytes/libbitsandbytes_cpu.so: undefined symbol: cadam32bit_grad_fp32
以下に、あるタスクを説明する指示があり、それに付随する入力が更なる文脈を提供しています。リクエストを適切に完了するための回答を記述してください。

### 指示:
以下のトピックに関する詳細な情報を提供してください


### 入力:
この中でラッパーなのはどれ?エミネム、マイケル・ジャクソン、リアーナ、50セント


### 応答:マイケル・ジャクソン、50セント
miyakz@swallow:~/github_repos/alpaca-lora/sampleuse$ 

この入力質問の正しい答えは、"エミネム、50セント"ですので、間違っています(マイケル・ジャクソンが出力されてしまっている)

今度は、比較のため、LoRAデータを指定せずに実行してみます(Swallowオリジナルという意味)。

LoRAなし(オリジナルのSwallow)

miyakz@swallow:~/github_repos/alpaca-lora/sampleuse$ ./sample_swallow.py  --input=input.txt --instruction=instruction.txt
Loading checkpoint shards: 100%|██████████████████| 3/3 [00:02<00:00,  1.11it/s]
以下に、あるタスクを説明する指示があり、それに付随する入力が更なる文脈を提供しています。リクエストを適切に完了するための回答を記述してください。

### 指示:
以下のトピックに関する詳細な情報を提供してください


### 入力:
この中でラッパーなのはどれ?エミネム、マイケル・ジャクソン、リアーナ、50セント


### 応答:ラップはエミネムと50セントのもので、ヒップホップはマイケルジャクソンとリアーナのものです。
miyakz@swallow:~/github_repos/alpaca-lora/sampleuse$

正しいです。

結果としては、LoRAで訓練したデータを指定したほうが、誤回答が混じってしまう(悪化してしまう)という結果が得られました。

理由としては、今回の訓練のepochが1回のみだったことが考えられます。このことが、精度が良くなかった結果につながったのだと考えています。次回以降、epoch回数を増やしてみたいと思います。

ただ、LoRAデータの利用により結果が変化したため、LoRAによる訓練がベースモデルに反映された事はわかりました。

まとめ

オープンソースのLLMであるSwallowの推論動作のサンプルと、LoRAによるファインチューニングおよびその結果の利用方法について述べました。

なお、この記事はオープンソースのLLMの利用方法のサンプルを示すものであり、いかなる結果について何かの責任を持ち、保証する訳ではないので、ご注意ください。ダウンロード先の知的財産、ライセンス等はご利用前にご確認をおねがいします。

5
4
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
5
4