Supershipの名畑です。2024年夏アニメが始まりましたが異世界スーサイド・スクワッドがエンタメに徹していて見ていて楽しい。ハーレイ・クインはやっぱり最強。
はじめに
Googleによる生成AIモデルGemmaの後継であるGemma 2が先日リリースされました。
2月に発表した「Gemma」は20億パラメータと70億パラメータの2サイズでの展開だったが、Gemma 2は90億パラメータと270億パラメータの2サイズ。
270億パラメータ版は、「そのサイズクラスで最高の性能を発揮し、2倍以上の規模のモデルに匹敵する性能を実現」するという。90億パラメータ版でも、米Metaの「Llama 3」の80億パラメータ版などを上回る性能を示すとしている。参考:Google、オープンな生成AIモデル「Gemma 2」リリース 270億パラメータモデル追加 - ITmedia NEWS
Gemma 2を手元のMacBook(M2)で動かした過程を記事に残します。
2024年2月に書いた記事「Googleによる生成AIモデル「Gemma」をMacBook(M2)で動かしてみた」の最新版です。
コードはすべてPythonです。
私の環境
PCはMacBook Pro(Apple M2 Proチップ)です。
OSはmacOS 14 Sonomaです。
accelerate、torch、transformersを入れておきます。
$ pip install accelerate torch transformers
私の環境でのバージョンはそれぞれ0.32.1、2.3.1、4.42.4でした。
$ pip list | grep -e accelerate -e torch -e transformers
accelerate 0.32.1
torch 2.3.1
transformers 4.42.4
モデル
gemma-27b(270億パラメータ)とGemma 9b(90億パラメータ)があります。そしてそれぞれにinstruct-tuned(指示調整)されたものが用意されています。
本記事ではgemma-2-27b-itを用いて話を進めていますが、初回の実行時は約54.5GBのモデルをダウンロードする必要があります。さらにコードの実行にも時間がかかります。
そのため、動かすこと自体が目的であればgemma-2-9b-itで進めていただければと思います。
各コードに2箇所あるgemma-2-27b-itをgemma-2-9b-itに置き換えるだけです。
コード例も本記事の最後に記載しております。
ライセンスの認証
今回はHugging Face経由でモデルを入手して実行します。
そのためにまずはHugging Faceのアカウントを作成します。
GemmaとGemma 2は同一権限のため、Gemmaですでに権限付与済みの場合はこの手順は不要です。また、モデル毎に権限を取得し直す必要はありません。
アカウントを作成してログイン後、先述したモデルのいずれかのページに行くとGemmaへのアクセスのためのライセンス承認が求められます。
Acknowledge licenseを押します。
Access Requestのページに遷移しますので、フォームに名前等を記入していきます。
規約も読んで最後のAcceptを押します。
モデルのページに戻ると、以下のようにアクセス認証が得られたことが確認できます。
アクセストークンの作成
モデルをダウンロードする際のユーザー認証のためにHugging Faceのアクセストークンを作成します。
Hugging FaceでSettingsに移動し、さらにAccess Tokensに移動します。
ここでNew Tokenを押します。
Nameはわかりやすくgemmaとしました。Roleは読み取りだけなのでreadにしました。
トークン情報をハードコーディングするのはセキュリティ的によろしくないので、自環境の環境変数にセットしました。
まず設定ファイルを開きます。私の環境ではzshrcです。
$ open ~/.zshrc
生成したアクセストークンの値を記録します。
私はHUGGING_FACE_TOKENという名前にしました。
export HUGGING_FACE_TOKEN=ここにアクセストークンの値を書く
PYTORCH_ENABLE_MPS_FALLBACKの指定
今回のコードをそのまま実行すると、以下のエラーが出ます。
NotImplementedError: The operator 'aten::isin.Tensor_Tensor_out' is not currently implemented for the MPS device. If you want this op to be added in priority during the prototype phase of this feature, please comment on https://github.com/pytorch/pytorch/issues/77764. As a temporary fix, you can set the environment variable
PYTORCH_ENABLE_MPS_FALLBACK=1
to use the CPU as a fallback for this op. WARNING: this will be slower than running natively on MPS.
要は「MPS(Metal Performance Shaders)だと行えない処理があるが、その際はCPUを使うという回避策があります。その代わりに遅くなりますが」というものです。
指示通り、環境変数として以下の指定をしておきます。
export PYTORCH_ENABLE_MPS_FALLBACK=1
コードの先頭に以下を書くことでも回避できるのですが、Pythonのドキュメントに「On some platforms, including FreeBSD and macOS, setting environ may cause memory leaks.」という記載があるので避けておきました。
import os
os.environ["PYTORCH_ENABLE_MPS_FALLBACK"] = "1"
サンプルコードの実行
サンプルコードを動かしてみます。
サンプルコードから以下4点を変更しています。
- アクセストークンの取得と指定する。
- MacBookのGPUを使用するためにdeviceとしてmpsを指定している。
- そのまま実行すると以下のwarningが出るため、max_new_tokensを指定する。今回は50としました。これらの値について詳しくはドキュメントをご覧ください。
- UserWarning: Using the model-agnostic default
max_length
(=20) to control the generation length. We recommend settingmax_new_tokens
to control the maximum length of the generation.
- UserWarning: Using the model-agnostic default
コードは以下です。公式サンプルコードからの変更箇所はコメントに記載済みです。
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch
import os # 追加
hf_token = os.getenv("HUGGING_FACE_TOKEN") # 追加
tokenizer = AutoTokenizer.from_pretrained(
"google/gemma-2-27b-it",
token=hf_token # 追加
)
model = AutoModelForCausalLM.from_pretrained(
"google/gemma-2-27b-it",
device_map="auto",
torch_dtype=torch.bfloat16,
token=hf_token # 追加
)
input_text = "Write me a poem about Machine Learning."
input_ids = tokenizer(input_text, return_tensors="pt").to(torch.device("mps")) # toのパラメータを変更
outputs = model.generate(**input_ids, max_new_tokens=50) # max_new_tokensを追加
print(tokenizer.decode(outputs[0]))
モデルに対して「Write me a poem about Machine Learning.」という文字列を渡しています。
訳すと「機械学習についての詩を書いてください」ですね。
前述の通り、初回はモデルのダウンロードが必要となります。
結果は以下でした。出力長がmax_new_tokensの値に従うため、途中で切れていますね。
In realms of data, vast and deep,
Where patterns hide and secrets sleep,
Machine Learning, a beacon bright,
Unveils the truth with digital light.Algorithms, like curious minds,
Explore the data, seeking finds
日本語に翻訳すると以下です。
データの領域、広く深い
パターンが隠れ、秘密が眠る場所で
機械学習は明るい灯台のように
デジタルの光で真実を明らかにするアルゴリズムは好奇心旺盛な心のように
データを探り、発見を求めて探求する
前回記事同様の感想になりますが、詩的、かな。
会話形式の入力プロンプト
公式の説明を参考にし、入力文の指定箇所を以下のように変更します。
# input_text = "Write me a poem about Machine Learning."
input_text = """
<start_of_turn>user
Write a hello world program<end_of_turn>
<start_of_turn>model
"""
モデルに対して「Write a hello world program」という文字列を渡しています。
「Hello Worldのプログラムを書いてください」ですね。
本当はサンプル通りにchat_templateを用いた方がいいのでしょうが、以下のエラーが出たのでinput_textにすべて指定しました。
ValueError: Can't infer missing attention mask on
mps
device. Please provide anattention_mask
or use a different device.
chat_templateの形式についてはtokenizer_config.jsonに書かれているので、よければ合わせてご参照ください。
結果は以下です。
print("Hello, world!")
This program will print the text "Hello, world!" to the console.
Explanation:
print()
is a built-in function in Python that displays text on the screen
きちんとHello Worldのプログラムを書いてくれています。
解説もセットです。
日本語の入力プロンプト
input_text = """
<start_of_turn>user
日本の都道府県を5つ教えてください<end_of_turn>
<start_of_turn>model
"""
「日本の都道府県を5つ教えてください」という問いかけをしてみました。
結果は以下です。終端を示す<end_of_turn>と<eos>は省いています。
日本の都道府県を5つですね!
- 東京都
- 北海道
- 大阪府
- 神奈川県
- 愛知県
どうでしょうか?
実行回数が少ないので単純に比較できるものでもないでしょうが、前回記事における7bと2bの回答と違って正しいです。
gemma-2-9b-itでの実行
9b-itで同じことを行ってみました。ちなみにモデルの容量は約18.5GBでした。
コードの変更箇所は以下の通りです。2行あるgemma-2-27b-itをgemma-2-9b-itに変更しています。
tokenizer = AutoTokenizer.from_pretrained(
# "google/gemma-2-27b-it",
"google/gemma-2-9b-it",
token=hf_token
)
model = AutoModelForCausalLM.from_pretrained(
# "google/gemma-2-27b-it",
"google/gemma-2-9b-it",
device_map="auto",
torch_dtype=torch.bfloat16,
token=hf_token
)
結果は以下でした。
日本の都道府県を5つ紹介しますね!
- 東京都 (東京)
- 大阪府 (大阪)
- 愛知県 (名古屋)
- 北海道 (札幌)
またmax_new_tokensの値が小さいので途中で切れてしまいました。()内がなにを意味するかはわかりませんが、4つ目までは正解です。
最後に
この環境で動かすにはかなり重い処理ではありますが、手元でこの高品質モデルを動かせるありがたさを強く感じます。
宣伝
SupershipのQiita Organizationを合わせてご覧いただけますと嬉しいです。他のメンバーの記事も多数あります。
Supershipではプロダクト開発やサービス開発に関わる方を絶賛募集しております。
興味がある方はSupership株式会社 採用サイトよりご確認ください。