CyberAgentが開発している日本語用大規模言語モデルOpenCALMを試してみる事にした。環境は手元のmacOS(Intel ChipのMacBook Proの中古型落ち品)を使う1。PCのスペック的に大した事はできないだろうけれど、(型落ちmacが)頑張ってみる事にする。
まずは依存パッケージをインストールする。
torch==1.13.1
transformers
accelerate
mkl
pip install -r requirements.txt
手元の貧弱マシンではどうせ大した事はできないため open-calm-small
を使用する事にする。
https://huggingface.co/cyberagent/open-calm-small
このページのUsageに基本的な使い方として、コードスニペットが掲載されている。通常は、これをこのまま実行すれば、何も考える事なく文章を生成できる。ただし、諸般の事情(例えばGPUがショボいとか)は常に存在していて、少しだけ手直しする必要が出てくる事もあるだろう。今回はというとやはり諸般の事情で、そのまま実行するとエラーが発生した。そこで実行できるように少しだけ手直しをした。また文章をいっぱい生成できるようにもした。
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
# torch.set_default_dtype(torch.float16)
# torch.backends.mkl.enabled = True
model = AutoModelForCausalLM.from_pretrained(
"cyberagent/open-calm-small", device_map="auto", torch_dtype=torch.float32)
tokenizer = AutoTokenizer.from_pretrained("cyberagent/open-calm-small")
t = "AIによって私達の暮らしは、"
for i in range(3):
inputs = tokenizer(t, return_tensors="pt").to(model.device)
with torch.no_grad():
tokens = model.generate(
**inputs,
max_new_tokens=64,
do_sample=True,
temperature=0.7,
top_p=0.9,
repetition_penalty=1.05,
pad_token_id=tokenizer.pad_token_id,
)
t = ""
for token in tokens:
output = tokenizer.decode(token, skip_special_tokens=True)
t += output
print(output, end="")
それでは実行しよう。
python main.py
AIによって私達の暮らしは、今や地球規模で変化しています。そんな今、地球規模での課題解決には「社会システム」が大きく役立っています。 しかし、今、私達は、「人」「物」「金」などの「モノ」「サービス」が地球規模で絡み合っています。 〜省略〜
結構ちゃんと文章として成立している。文章の生成の確認はできたから、ファインチューニングしていく。
まずは、学習の仕方を把握するために、小さな言葉を学習させる。
tune-simple.py
import collections
import torch
from torch.utils.data import Dataset
from transformers import (AutoModelForCausalLM, AutoTokenizer, Trainer,
TrainingArguments)
class DatasetA(Dataset):
def __init__(self, dataset, is_test=False):
self.dataset = dataset
self.is_test = is_test
def __getitem__(self, idx):
data = {"input_ids": torch.tensor(self.dataset["input_ids"][idx])}
data["labels"] = torch.tensor(self.dataset["labels"][idx])
return data
def __len__(self):
return len(self.dataset["input_ids"])
model = AutoModelForCausalLM.from_pretrained(
"cyberagent/open-calm-small", device_map="auto", torch_dtype=torch.float32
)
tokenize = AutoTokenizer.from_pretrained("cyberagent/open-calm-small")
model.hf_device_map = None # CPUで実行する場合、Noneを指定しないと例外が発生した
input_token = tokenize("喜びが", max_length=50, padding="max_length", truncation=True)
output_token = tokenize("ない", max_length=50, padding="max_length", truncation=True)
d = collections.defaultdict(list)
d["input_ids"].append(input_token["input_ids"])
d["labels"].append(output_token["input_ids"])
dataset = DatasetA(d)
train_args = TrainingArguments(
output_dir="./trained_data",
num_train_epochs=1,
per_device_train_batch_size=1,
per_device_eval_batch_size=1,
warmup_steps=100,
weight_decay=0.1,
save_steps=1,
no_cuda=True,
)
trainer = Trainer(model=model, args=train_args, train_dataset=dataset)
trainer.train()
実行する。
python tune-simple.py
実行すると trained_data
にモデルが出力される。これを用いて再度文章を生成してみる。
tuned.py
import sys
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
model = AutoModelForCausalLM.from_pretrained(
"./trained_data/checkpoint-1", device_map="auto", torch_dtype=torch.float32)
tokenizer = AutoTokenizer.from_pretrained("cyberagent/open-calm-small")
t = sys.argv[1]
for i in range(2):
inputs = tokenizer(t, return_tensors="pt").to(model.device)
with torch.no_grad():
tokens = model.generate(
**inputs,
max_new_tokens=30,
do_sample=True,
temperature=0.7,
top_p=0.9,
repetition_penalty=1.05,
pad_token_id=tokenizer.pad_token_id,
)
t = ""
for token in tokens:
output = tokenizer.decode(token, skip_special_tokens=True)
t = output
print(output, end="")
生成を実行する。
python tuned.py "AIによって私達の暮らしは、"
AIによって私達の暮らしは、常に変化しています。 私は「暮らしの変化」に気づき、その変化と新しいことを共に考え、共に考え、共に学び、ともに喜び、AIによって私達の暮らしは、常に変化しています。 私は「暮らしの変化」に気づき、その変化と新しいことを共に考え、共に考え、共に学び、ともに喜び、共に悲しみ、共に笑い、共に生きることを大切にしている一人です。 私たち夫婦が一緒に暮らすのは、あくまでも「パートナー」であり、家族であり
学習に使った言葉も確認する。
python tuned.py "喜びが"
喜びが、その人にしか分からない。 「愛」と「真実」について。 私たちは、どんな時も、どんな状況でも、 「愛」喜びが、その人にしか分からない。 「愛」と「真実」について。 私たちは、どんな時も、どんな状況でも、 「愛」と「真実」を分かち合い、共に歩むことを望みます。 私たちは、いつだって、そんな風に思う。 「愛」と
いまいち期待した値にはなっていないが、文章としては成立している。学習したと言っても、量が少なすぎるからこの結果は正しそうではある。次はもっと多くの文章を学習させてみようと思う。
使用したライブラリ
accelerate==0.20.3
certifi==2023.5.7
charset-normalizer==3.1.0
filelock==3.12.1
fsspec==2023.6.0
huggingface-hub==0.15.1
idna==3.4
intel-openmp==2023.1.0
mkl==2023.1.0
numpy==1.24.3
packaging==23.1
psutil==5.9.5
PyYAML==6.0
regex==2023.6.3
requests==2.31.0
safetensors==0.3.1
tbb==2021.9.0
tokenizers==0.13.3
torch==1.13.1
tqdm==4.65.0
transformers==4.30.1
typing_extensions==4.6.3
urllib3==2.0.3
また幾つかのWebページを参考にした2。
Google Colabを使えばよいという声も聞こえてきそうだ。実際、Google Colabでも実施できる。ただ今回はあくまで動作を確認する事が目的であるため、ローカルで実施する。