Stable Diffusion 2をmacOSのCoreMLでやってみた
前回紹介した「文章から画像を生成するStable Diffusion 2」ですが、つい先日、Appleシリコン上のCore MLによる使用が可能となりました。Core MLはAppleの提供するライブラリで機械学習モデルをmacOSやiOSなどで走らせることができます。
これでNVIDIAのGPUがなくとも、AppleシリコンのマシンでStable Diffusion 2を使えるようになったわけです。
ただし結論から言うと、NVIDIAのGPUを使う方がずっと速いです。よって、Core ML上でStable Diffusion 2が使えるといってもSwiftでアプリを作るなのど必要がある人が想定されるユーザーと思われます。
それでも、GPUにアクセスできない環境でどうしてもStable Diffusion 2をAppleシリコンで使いたい場合には役立つかもしれません。また、Google Colabなどを使うより自分のローカル環境の方が多少遅くても便利な時もあるでしょう。
いずれにせよ、遊ぶ分には十分な速度です。
以下、この記事ではPythonを使ってStable Diffusion 2をCore MLを通してAppleシリコンで試したい方のために手順を追って解説しました。
Pythonの仮想環境を作る
まず、適当なフォルダーを作って、Pythonの仮想環境を設定します。
python3 -m venv venv
source venv/bin/activate
pip install --upgrade pipAppleのGithubから依存ライブラリをインストール
AppleのGithubのリポジトリをクローンして、Stable Diffusionをサポートするためのライブラリをインストールします。
git clone git@github.com:apple/ml-stable-diffusion.git
cd ml-stable-diffusion/
pip install -e.Huggingfaceからモデルをダウンロードする準備
モデル自体はHuggingfaceからダウンロードするので、Huggingfaceのアカウントが必要です。無料です。
アカウントがあるならば、リモートでログインするためのトークンを取得してください。リンクを辿ると以下のページに行くのでNew tokenボタンをクリックしてトークンを生成してください。これをコピーしておきます。

トークンが手に入ったHuggingfaceにログインします。
huggingface-cli login"Add token as git credential? (Y/n)"と聞かれたらEnterを押してください。これでモデルのダウンロードが可能となります。
python -m python_coreml_stable_diffusion.torch2coreml --convert-unet \
--convert-text-encoder --convert-vae-decoder --convert-safety-checker \
--model-version stabilityai/stable-diffusion-2-base -o mlpackages--model-version stabilityai/stable-diffusion-2-base でモデルのバージョンを指定します。詳しくは、こちらのAppleのREADMEを参照してください。
-o mlpackageでモデルのダウンロード先フォルダを指定します。
ダウンロードには3GBほどの空きスペースと時間が20分(インターネットのスピード依存)ほどかかるので、他の記事を読んで過ごしましょう。
Stable Diffusion 2で画像の生成
ダウンロードが終わったら画像を生成しましょう。
python -m python_coreml_stable_diffusion.pipeline \
--model-version stabilityai/stable-diffusion-2-base \
-i mlpackages -o images --compute-unit ALL --seed 93 \
--prompt "a photo of an astronaut riding a horse on mars"--prompt "…." で画像生成のヒントになる文章を指定します。
--model-version stabilityai/stable-diffusion-2 で先ほどと同じモデルを指定します。
-i mlpackages は先ほどダウンロードしたモデルの格納フォルダ。
-o images は生成画像の収納先フォルダ。
-seed は乱数のシードを固定したい場合に使います。
同じシードを指定すると同じ文章に対して毎回同じ画像が生成されます。シードを変えるか、指定しないでおくと毎回ランダムな画像が生成されるので試してみてください。
しばらく(5分くらい)待つと画像が指定してフォルダ内に生成されます。ちなみに、MacBook Air M2(16GB)macOS Ventura 13.0.1を使っています。
火星で馬に乗る宇宙飛行士の写真

プロンプトの「a photo of an astronaut riding a horse on mars」を何か別の文章にすれば、他の画像の生成ができます。
月で象に乗る宇宙飛行士の漫画
python -m python_coreml_stable_diffusion.pipeline \
--model-version stabilityai/stable-diffusion-2-base \
-i mlpackages -o images --compute-unit ALL --seed 93 \
--prompt "a cartoon of an astronaut riding an elephant on moon"
人類とコンピューターの戦争SFX映画
python -m python_coreml_stable_diffusion.pipeline \
--model-version stabilityai/stable-diffusion-2-base \
-i mlpackages -o images --compute-unit ALL --seed 93 \
--prompt "SFX movie about a war between human and computers"
同じ文章でシードのみを変えてみました。
python -m python_coreml_stable_diffusion.pipeline \
--model-version stabilityai/stable-diffusion-2-base \
-i mlpackages -o images --compute-unit ALL --seed 1 \
--prompt "SFX movie about a war between human and computers"
高速道路で怪獣がビームを吐き出す
日本語でもやってみました。
python -m python_coreml_stable_diffusion.pipeline \
--model-version stabilityai/stable-diffusion-2-base \
-i mlpackages -o images --compute-unit ALL --seed 1 \
--prompt "高速道路で怪獣がビームを吐き出す"
高速道路はどこですか。やはり日本語だとあまり良い結果は出ないですね。
Google翻訳で英語に直したものでやってみます。
python -m python_coreml_stable_diffusion.pipeline \
--model-version stabilityai/stable-diffusion-2-base \
-i mlpackages -o images --compute-unit ALL --seed 1 \
--prompt "A monster spits out a beam on the highway"
やっぱり「monster」ではなく「kaiju」の方が英語でも通じるかも。早速やってみました。
python -m python_coreml_stable_diffusion.pipeline \
--model-version stabilityai/stable-diffusion-2-base \
-i mlpackages -o images --compute-unit ALL --seed 1 \
--prompt "A kaiju spits out a beam on the highway"
やっぱり「kaiju」の方がいいですね。でもビームは出してないか。
日本の正月のポストカード
python -m python_coreml_stable_diffusion.pipeline \
--model-version stabilityai/stable-diffusion-2-base \
-i mlpackages -o images --compute-unit ALL --seed 1 \
--prompt "Japanese new year postcard"
もう少し具体的に指定しないと思ったようにはならないのかな。
python -m python_coreml_stable_diffusion.pipeline \
--model-version stabilityai/stable-diffusion-2-base \
-i mlpackages -o images --compute-unit ALL --seed 1 \
--prompt "Japanese New Year postcard with kids flying kites and parents eating mochi"
服の色とか指定する必要があるかも。
グレートキャニオンにUFO現れる
アメリカの風景はどうか。
python -m python_coreml_stable_diffusion.pipeline \
--model-version stabilityai/stable-diffusion-2-base \
-i mlpackages -o images --compute-unit ALL --seed 1 \
--prompt "UFO appears in the Great Canyon"
かなりまともな画像が生成されました。おそらく使われているデータに文化的な偏りがあるのでしょう。
将来的にはターゲットを絞って訓練し直したものが出るかもしれませんが、当面は世界的に共通の概念を指定した方が良さそうです。
