pfnet/plamo-13b を quantizeしてシングルGPUローカルマシン(RTX3090)で動かしてみた・・・

# はじめに
９月２８日に、pfnは商用利用可能な大規模言語モデルをオープンソースソフトウェアライセンス（Apache2.0）で公開したと発表があった。日英2言語対応、特に日本語対応モデルとして、国産、最大規模（13b）ということで、生成される文章の語彙力、文法の正確さに期待して試してみたいと思い、早速、手元のマシンで、pythonのサンプルを動かしてみた。ただし、そのままのモデルの大きさは、30GB程度あり、手元のマシンのVRAM容量内に収まらない。そこで、今回は transformers の quantization オプションを使ってモデルを読み込ませ、ローカルのマシンで動作させた。

https://www.preferred.jp/ja/news/pr20230928/


# 操作環境
OS: Ubuntu 22.04　（RAM: 32GB、GPU：RTX3090(VRAM 24GB)
gcc: 11.4
cuda: 11.7 (nvidia driver version 535.104.12)
Python 3.10.12
```
pip install transformers sentencepiece
pip install torch torchvision torchaudio
pip install accelate
pip install scipy
```
transformers==4.33.3, sentencepiece==0.1.99, torch==2.0.1, torchvision==0.15.2, torchaudio==2.0.2, accelerate=0.23.0

huggingface

https://huggingface.co/pfnet/plamo-13b


# コード
huggingface サイトに掲載のサンプルそのままだと、メモリが足りない（Out Of Memory）エラーで作動できない。 AutoModelForCausalLM.from_pretrained の引数を改変して動作させた。 load_in_4bit=True の部分がミソ。

```python
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch
import datetime

print(datetime.datetime.now())
tokenizer = AutoTokenizer.from_pretrained("pfnet/plamo-13b", trust_remote_code=True)
model_4 = AutoModelForCausalLM.from_pretrained("pfnet/plamo-13b", trust_remote_code=True, device_map="auto", torch_dtype=torch.bfloat16, load_in_4bit=True)
text = "これからの人工知能技術は"
input_ids = tokenizer(text, return_tensors="pt").input_ids
generated_tokens = model_4.generate(
    inputs=input_ids,
    max_new_tokens=128,
    do_sample=True,
    top_k=50,
    top_p=0.95,
    temperature=1.0,
)[0]
generated_text = tokenizer.decode(generated_tokens)
print(generated_text)
print(datetime.datetime.now())
```

# 実行結果
実行例を３つ掲載。なお、掲載例の前にも動作させているため、Huggingfaceからのモデルのダウンロード時間は省略されている。

```sh
2023-09-30 11:01:46.440019
Loading checkpoint shards: 100%|█████████████████████████████████████████████████████████████████████████████████████████████| 3/3 [00:44<00:00, 14.87s/it]
/home/tomo/Documents/pythonProjects/quantization/.venv/lib/python3.10/site-packages/transformers/generation/utils.py:1535: UserWarning: You are calling .generate() with the `input_ids` being on a device type different than your model's device. `input_ids` is on cpu, whereas the model is on cuda. You may experience unexpected behaviors or slower generation. Please make sure that you have put `input_ids` to the correct device by calling for example input_ids = input_ids.to('cuda') before running `.generate()`.
  warnings.warn(
これからの人工知能技術は?
「AIが世界に与える衝撃」(2015.4.4)
IBMのAI「ワトソン」に世界で大絶賛
MITが開発した人工知能ロボット「ソフィア」のデモ。「人類の知能の進歩に貢献した、最も優れたAI」と評価される。
人工知能(AI)が世界的に大活躍している。米IBMが開発した人工知能「ワトソン」は、自然言語での君津・日本、医学用語を難なく処理し、「米のテレビ番組」 Hungarian(ハンガリー語で"羊"を意味する)のインタビューを「英語で」受けた。さらには、医療分野での診断の場面でも、
2023-09-30 11:02:58.254523
```

```sh
2023-09-30 11:04:18.805094
Loading checkpoint shards: 100%|█████████████████████████████████████████████████████████████████████████████████████████████| 3/3 [00:41<00:00, 13.70s/it]
/home/tomo/Documents/pythonProjects/quantization/.venv/lib/python3.10/site-packages/transformers/generation/utils.py:1535: UserWarning: You are calling .generate() with the `input_ids` being on a device type different than your model's device. `input_ids` is on cpu, whereas the model is on cuda. You may experience unexpected behaviors or slower generation. Please make sure that you have put `input_ids` to the correct device by calling for example input_ids = input_ids.to('cuda') before running `.generate()`.
  warnings.warn(
これからの人工知能技術は、「人間の判断能力を超えない」という前提に立てば、その目的は、「(人間の)自由意思の限界点を探る」ことにある、と筆者は記している。まあ、筆者自身も、自由意思の限界を考察した本を2009年の暮れに上梓している。
・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
2023-09-30 11:05:27.442331
```

```sh
2023-09-30 11:06:30.443800
Loading checkpoint shards: 100%|█████████████████████████████████████████████████████████████████████████████████████████████| 3/3 [00:38<00:00, 12.90s/it]
/home/tomo/Documents/pythonProjects/quantization/.venv/lib/python3.10/site-packages/transformers/generation/utils.py:1535: UserWarning: You are calling .generate() with the `input_ids` being on a device type different than your model's device. `input_ids` is on cpu, whereas the model is on cuda. You may experience unexpected behaviors or slower generation. Please make sure that you have put `input_ids` to the correct device by calling for example input_ids = input_ids.to('cuda') before running `.generate()`.
  warnings.warn(
これからの人工知能技術は、人間が本来持っている「直観力」をサポートするものになるという点がポイントです。 Trevor Murden: 2016年の人工知能、「人間の直観力」をサポート ↩
↑ 1.0 1.1 1.2 1.3 2017年11月6日放送 テレビ東京「カンブリア宮殿」
AI×IoT(人工知能+IoT), AI(人工知能), 人工知能・機械学習, 最新技術・最新商品
人工知能による画像認識システム開発・検証
2023-09-30 11:07:36.191775
```

warning が出ているので、さらにコード改変。 input_ids に ".to('cuda')"を追加。キーを押すまでプログラムが終了しないようにして、モデルを読み込んだ状態で待機させてみる。待機中にnvidia-smiを実行してVRAMの使用量をみてみよう。

```python:（Warning回避版）
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch
import datetime

print(datetime.datetime.now())
tokenizer = AutoTokenizer.from_pretrained("pfnet/plamo-13b", trust_remote_code=True)
model_4 = AutoModelForCausalLM.from_pretrained("pfnet/plamo-13b", trust_remote_code=True, device_map="auto", torch_dtype=torch.bfloat16, load_in_4bit=True)
text = "これからの人工知能技術は"
input_ids = tokenizer(text, return_tensors="pt").input_ids.to('cuda')
generated_tokens = model_4.generate(
    inputs=input_ids,
    max_new_tokens=128,
    do_sample=True,
    top_k=50,
    top_p=0.95,
    temperature=1.0,
)[0]
generated_text = tokenizer.decode(generated_tokens)
print(generated_text)
print(datetime.datetime.now())
input("Press Enter to end...")
```

```sh
023-09-30 11:16:04.867517
Loading checkpoint shards: 100%|█████████████████████████████████████████████████████████████████████████████████████████████| 3/3 [00:40<00:00, 13.38s/it]
これからの人工知能技術は、人間の知性に近づくだろう」と語っている。PRIのプロジェクトでは、2015年の受賞者にグーグルの「AlphaGo」が選ばれたが、2017年のプロジェクトにも人工知能プログラムの開発者、研究者、AIエンジニアらの応募があったという。
人工知能は、さまざまな分野で実用化が進んでいますが、今のところ「人間の知能と似て非なるものである」と認識する人が80%、「人間に近づいている」と60%というアンケート結果がありました。
人間の能力を凌駕していく人工知能は、近い将来、多くの人々の生活に変化をもたらす可能性があります。
2023-09-30 11:17:12.065504
Press Enter to end...
```

```sh: nvidia-smi 結果
Sat Sep 30 11:17:21 2023       
+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 535.104.12             Driver Version: 535.104.12   CUDA Version: 12.2     |
|-----------------------------------------+----------------------+----------------------+
| GPU  Name                 Persistence-M | Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |         Memory-Usage | GPU-Util  Compute M. |
|                                         |                      |               MIG M. |
|=========================================+======================+======================|
|   0  NVIDIA GeForce RTX 3090        On  | 00000000:20:00.0  On |                  N/A |
| 73%   57C    P2             125W / 350W |   9346MiB / 24576MiB |      1%      Default |
|                                         |                      |                  N/A |
+-----------------------------------------+----------------------+----------------------+
                                                                                         
+---------------------------------------------------------------------------------------+
| Processes:                                                                            |
|  GPU   GI   CI        PID   Type   Process name                            GPU Memory |
|        ID   ID                                                             Usage      |
|=======================================================================================|
|    0   N/A  N/A      2546      G   /usr/lib/xorg/Xorg                          188MiB |
|    0   N/A  N/A      2695      G   /usr/bin/gnome-shell                         90MiB |
|    0   N/A  N/A      4609      G   ...sion,SpareRendererForSitePerProcess      102MiB |
|    0   N/A  N/A      4747      G   ...8356983,10094979782424822246,262144      125MiB |
|    0   N/A  N/A     11426      C   python                                     8818MiB |
+---------------------------------------------------------------------------------------+
```

load_in_4bit で　９GB弱のメモリを要した。それじゃぁ、ということで load_in_8bit を試してみたところ・・・

```sh
2023-09-30 11:19:47.962787
Loading checkpoint shards: 100%|████████████████████████████████████████████████████████| 3/3 [00:38<00:00, 12.95s/it]
/home/tomo/Documents/pythonProjects/quantization/.venv/lib/python3.10/site-packages/bitsandbytes/autograd/_functions.py:322: UserWarning: MatMul8bitLt: inputs will be cast from torch.bfloat16 to float16 during quantization
  warnings.warn(f"MatMul8bitLt: inputs will be cast from {A.dtype} to float16 during quantization")
これからの人工知能技術は、例えば囲碁という問題を解くというレベルではなくて、社会のいろいろなサービスの自動化のレベルまで、どんどん進んでいくと思っています。そしてそれは、その前にAIは「心」がないと言われましたが、最近の脳科学の知識から見て、人間の感情に近い部分までAIができるようになったということが言われていますので、そのあたりをうまく組み合わせて、例えば自動車の自動運転などがいいんじゃないかという議論を最近します。
今回「人工知能技術白書」の編纂にあたって感じたのは、AIは人間の知識・経験を詰め込むことではなくて、人間の脳が持つ「想像力」を補おうとする、
2023-09-30 11:21:21.698454
```

```sh: nvidia-smi結果（load_in_8bit=True)
Sat Sep 30 11:21:50 2023       
+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 535.104.12             Driver Version: 535.104.12   CUDA Version: 12.2     |
|-----------------------------------------+----------------------+----------------------+
| GPU  Name                 Persistence-M | Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |         Memory-Usage | GPU-Util  Compute M. |
|                                         |                      |               MIG M. |
|=========================================+======================+======================|
|   0  NVIDIA GeForce RTX 3090        On  | 00000000:20:00.0  On |                  N/A |
| 63%   50C    P8              42W / 350W |  14235MiB / 24576MiB |      8%      Default |
|                                         |                      |                  N/A |
+-----------------------------------------+----------------------+----------------------+
                                                                                         
+---------------------------------------------------------------------------------------+
| Processes:                                                                            |
|  GPU   GI   CI        PID   Type   Process name                            GPU Memory |
|        ID   ID                                                             Usage      |
|=======================================================================================|
|    0   N/A  N/A      2546      G   /usr/lib/xorg/Xorg                          188MiB |
|    0   N/A  N/A      2695      G   /usr/bin/gnome-shell                         90MiB |
|    0   N/A  N/A      4609      G   ...sion,SpareRendererForSitePerProcess       72MiB |
|    0   N/A  N/A      4747      G   ...8356983,10094979782424822246,262144       81MiB |
|    0   N/A  N/A     11810      C   python                                    13782MiB |
+---------------------------------------------------------------------------------------+
```

チェックポイントのロード時間は、38秒前後と load_in_4bit と変わらないが、quantization のために bfloat16 を float16　に変換するのに時間がかかるとのWarningがでた。また、nvidia-smi によると、14GB弱のVRAMを要している。

Warningを回避するため、torch_dtypeの指定を外してみた。
```python: load_in_8bit版
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch
import datetime

print(datetime.datetime.now())
tokenizer = AutoTokenizer.from_pretrained("pfnet/plamo-13b", trust_remote_code=True)
model_8 = AutoModelForCausalLM.from_pretrained("pfnet/plamo-13b", trust_remote_code=True, device_map="auto", load_in_8bit=True)
print(datetime.datetime.now())
text = "これからの人工知能技術は"
input_ids = tokenizer(text, return_tensors="pt").input_ids.to('cuda')
generated_tokens = model_8.generate(
    inputs=input_ids,
    max_new_tokens=128,
    do_sample=True,
    top_k=50,
    top_p=0.95,
    temperature=1.0,
)[0]
generated_text = tokenizer.decode(generated_tokens)
print(generated_text)
print(datetime.datetime.now())
input("Press Enter to end...")
```

```sh
2023-09-30 11:27:49.567347
Loading checkpoint shards: 100%|████████████████████████████████████████████████████████| 3/3 [00:37<00:00, 12.42s/it]
2023-09-30 11:28:30.764969
これからの人工知能技術はどうなっていくのか」をテーマにお話したいと思っています。「人工知能が人間を超える?」というお話は以前からよく聞きますが、私は今回は人工知能の進化の歴史を振り返りながらお話したいと思っています。(次ページに続く)
今回は、人工知能技術の進化に「機械学習」がどのように影響を与えたか。1956年にディープラーニングが登場するまで、「機械学習」はどのように進化してきたか、AIは今後どのように進化するのか、ということをお話します。(次ページに続く)
AIに取って代わると期待されるのは「機械学習」

2023-09-30 11:29:15.784494
Press Enter to end...
```
```sh: nvidia-smi結果
Sat Sep 30 11:32:05 2023       
+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 535.104.12             Driver Version: 535.104.12   CUDA Version: 12.2     |
|-----------------------------------------+----------------------+----------------------+
| GPU  Name                 Persistence-M | Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |         Memory-Usage | GPU-Util  Compute M. |
|                                         |                      |               MIG M. |
|=========================================+======================+======================|
|   0  NVIDIA GeForce RTX 3090        On  | 00000000:20:00.0  On |                  N/A |
|  0%   45C    P8              39W / 350W |  14233MiB / 24576MiB |      6%      Default |
|                                         |                      |                  N/A |
+-----------------------------------------+----------------------+----------------------+
                                                                                         
+---------------------------------------------------------------------------------------+
| Processes:                                                                            |
|  GPU   GI   CI        PID   Type   Process name                            GPU Memory |
|        ID   ID                                                             Usage      |
|=======================================================================================|
|    0   N/A  N/A      2546      G   /usr/lib/xorg/Xorg                          188MiB |
|    0   N/A  N/A      2695      G   /usr/bin/gnome-shell                         90MiB |
|    0   N/A  N/A      4609      G   ...sion,SpareRendererForSitePerProcess       82MiB |
|    0   N/A  N/A      4747      G   ...8356983,10094979782424822246,262144       72MiB |
|    0   N/A  N/A     12442      C   python                                    13780MiB |
+---------------------------------------------------------------------------------------+
```

# 考察（個人の感想・印象です）
思っていたように、quantizeオプションを使うことでローカルで動作させることができた。
さて、日本語の文章生成のサンプルは・・・読める文章を出力してくれている、が、どこかからの文章の丸写し的な文章が出てきている印象を受けた。「生成した」というよりは、何かしらの文献から「選定した」というような感じ。学習したデータを”引き出している”ような感じがした。与えたテキスト("これからの人工知能技術は")に対して、まと外れな文章が出てきていないので、性能はいいものなのだろうと思う。
load_in_4bit　と load_in_8bit では処理時間に大きな差は感じられず、生成される文章の質（日本語文法が人間の読み取れるものであるか）においては、（個人の感想であるが）どちらも問題なく読み取れるレベルである、と感じられた。長文を生成する場合には差がでるのかもしれないが、4bit読み込みで使えるのかもしれない。
instructionができるようなもでるであれば、ローカルで動くAgentを作ってみたいところだ。

# まとめ
日本語対応モデルとして、国産、最大規模（13b）の大規模言語モデルを手元のマシン、pythonのサンプルを動かして文章を生成させた。うん、やればできる。（というか、transformers ライブラリが優秀なんだな）

https://huggingface.co/docs/transformers/main/en/main_classes/quantization#push-quantized-models-on-the-hub