【2023年度版】最もシンプルにM1 / M2 MacbookでStable Diffusionを走らせる

# はじめに
Stable Diffusionは無料の画像生成AIですが、ローカルにいれるとなると少し大変な面があります。
今回ご紹介する、M1 / M2のMacbookにStable Diffusionを入れる方法はいくつかありますが、Appleが[公式](https://github.com/apple/ml-stable-diffusion)でサポートしている方法が一番綺麗だと思う方が大半でしょう。

しかし、困ったことにここからインストールしている記事は日本語記事はもちろん、私が調べた限りでは英語記事もそう多くはなく、さらにここからインストールしている記事があってもAnacondaを用いた手法が取られています。これは公式に則っている手法なので、正当と言えば正当なのですが、極力最小構成で収めたい人にとってはあまり取りたくない方法でしょうし、そうでない初心者にとっても変なところで躓く原因になりかねません。(そもそも、初心者にとっては`conda`コマンドが何の解説もなく書いてあるだけで躓きかねませんが)

そこで本記事では出来るだけシンプルにしつつも、出来るだけ公式のインストールガイドにそったやり方でインストールしていきます。
本記事では、他記事でも多く記載されていて、なおかつ十分に基本的と考えられる内容は省くことがありますが、コマンドの意味に関しては全てに対してざっくりと解説をします。慣れている方には冗長と思われるかもしれませんが、温かい目で見守ってください。

# 対象読者
- M1 / M2チップ搭載のMacbookを所持している
- OSが最新である (macOS 13.1以上)
- Homebrewがインストールされている (解説記事が星の数ほどあります、もしくは[公式サイト](https://brew.sh/)を参照してください)
- XCodeが最新である (14.2以上、`xcodebuild -version`で確認できます。インストール方法については上と同じく山ほどある解説記事をあたってください)
- `zsh`、`bash`、もしくはPOSIX準拠のシェルを使っている
(何を言っているかわからない方はおそらく問題ありません、`fish`などを使っている方はこの手順では少し躓く可能性があります。
POSIX非準拠シェルを使っている方は`bash`コマンド等で一時的にシェルを切り替えてください。また、どうしても自分のシェルが不安な方は、`echo $SHELL`で調べられます)

# Step.1 リポジトリをクローンしてくる
経験豊富な読者にとっては丁寧すぎるかもしれませんが、まずはリポジトリをクローンするところからです。
ここに関してもHomebrew同様に解説記事が多くありますので詳細は割愛します。エラーが出た場合などは他の解説記事をあたってください。
```bash
git clone git@github.com:apple/ml-stable-diffusion.git
```
正常にインストールできたら`cd ml-stable-diffusion`でディレクトリを移動しておきましょう。

# Step.2 Pythonの環境構築
Pythonのバージョンが3.8であることが推奨されています。今時のMacbookのPythonは3.10であることが多いと思うので明示的に変更する必要があります。
まずは、pythonのバージョンを切り替えることができるツールである`pyenv`のインストールです。
```
brew install pyenv
```
次に、旧バージョンのPythonを`pyenv`を用いてダウンロードします。
```
pyenv install 3.8
```
さらに、今のディレクトリが`ml-stable-diffusion`であることを確認しつつ、Python3.8の仮想環境を立てます。下のコマンドのlocalはこのバージョン設定が`ml-stable-diffusion`内でのみ適用されるようにするためのものです。
```
pyenv local 3.8
```
`python -V`でバージョンが3.8であることを確認できたら成功です。
これで、GitHubに記載されているSystem Requirementsは全て満たした状態になっているはずですが、まだ細かいパッケージなどは不足しているので引き続きインストールしていきます。
まずは、パッケージが競合しないように仮想環境を立てておきます。ここでは簡単のために`venv`を用いますが、`poetry`など、お好きな仮想環境を立ててもらって大丈夫です。

<details><summary>補足１　Pythonに詳しくない方へ</summary>

- 仮想環境ってそもそも何？
→他のものと干渉しないように空間を区切るイメージです。とりあえずやっておいて損はありません。
- 仮想環境が二個あるのはなぜ？
→Pythonのバージョン管理用とパッケージ（拡張機能のようなもの）管理用です。統合することもできますが、一番シンプルなのはこの方法だと思います。
</details>

<details><summary>補足２　poetryを使いたい方へ</summary>

念の為に捕捉しますが、`poetry`は内部的に別のPythonバージョンを持っていて少し厄介です。何を言っているのかわからない方は素直に`venv`を使うことをおすすめします。
</details>

```
python -m venv .venv
```
仮想環境を立てた後は、入らなければ意味がないので有効化しておきます。
これでパッケージを入れる用意が整いました。
```
source .venv/bin/activate
```
ここまでの準備ができたら以下のコマンドで必要なものをすべてインストールすることができます。
```
pip install -e .
```

# Step.2 Hugging Faceの利用
[Hugging Face](https://huggingface.co/)はアメリカの機械学習のコミュニティです。ここから学習済みのモデルを入手する必要があるため、まずは右上のSign Upから会員登録をしてください。画面に沿って登録をすると1分ほどで終わると思います。**メールによる認証**もあるので、そちらを確認したら会員登録終了です。メール認証を終えていないと次のステップに進めないので注意してください。

会員登録が終わったら次にアカウントトークンを発行します。このトークンはターミナルから自分のアカウントにログインするときに使うものなので、**絶対に**流出させないでください。
アカウントトークンは、右上のユーザーアイコン > Settings > Access Tokens > New tokenで発行できます。
Nameは(多分)適当で問題ありません。私はStable Diffusionにしました。RoleもREADで問題ないでしょう。
発行できたら、以下の画面のようになると思うのでコピーしておきましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627957/fa33aa14-f372-3a33-e3c3-ea62822e7ab9.png)
あとは、ターミナルに`huggingface-cli login`と入力して、"Token: "の横に先ほどのアクセストークンを貼り付ければログインできるはずです。(`huggingface-cli`は先ほどの`pip install`で既に入っています)
"Add token as git credential? "に対してはYで問題ないでしょう。成功すれば`Login successful`と出るはずです。

# Step.3 モデルをダウンロードする
**注意！** GB単位のデータをダウンロードすることになるため、Wifi環境であることと、ディスク容量が足りているかどうかを確認してください。

[Hugging Face](https://huggingface.co/)上にはたくさんのバージョンのStable Diffusionがあります。2023年2月現在、デフォルトは[このバージョン](https://huggingface.co/CompVis/stable-diffusion-v1-4)となっていますが、環境によって異なる場合があります。
今回は、せっかくなので[バージョン2.0](https://huggingface.co/stabilityai/stable-diffusion-2-base)のものをダウンロードしてみようと思います。
(後述しますが、[このバージョン](https://huggingface.co/stabilityai/stable-diffusion-2)のものはおすすめしません。)

バージョンを選んだらいよいよダウンロードすることになります。
次のコマンドは少し長くなりますが、かいつまんで解説してきます。
(下の**太字**になっている箇所だけでも読むことをお勧めします)
```
python -m python_coreml_stable_diffusion.torch2coreml --model-version stabilityai/stable-diffusion-2-base --convert-unet --convert-text-encoder --convert-vae-decoder --convert-safety-checker -o ./stable_diffusion_models
```
- `python -m python_coreml_stable_diffusion.torch2coreml`
→コアとなる部分です。`python -m`はpythonのモジュールを走らせるときに使うものです。
- `--model-version stabilityai/stable-diffusion-2-base`
→省略可能です。省略した場合には[前述のバージョン](https://huggingface.co/CompVis/stable-diffusion-v1-4)が指定されることになります。
- `--convert-text-encoder --convert-vae-decoder --convert-safety-checker `
→省略不可です。オプションを加えているものですが、ややこしくなるため詳しい理解は各自の興味に任せたいと思います。
- `-o ./stable_diffusion_models`
→省略不可です。**出力先のディレクトリを規定します。** コマンドをそのままコピペするとディレクトリが存在しないと怒られるので注意してください。
私は`mkdir stable_diffusion_models`をして、`ml-stable-diffusion/stable_diffusion_models`に格納することにしましたが、ベストプラクティスかは不明です。

上のコマンドを走らせると、上で言及したエラーが出ない限りはダウンロードが始まると思います。そこそこ時間がかかるため気長に待ちましょう。

<details><summary>補足　SwiftやiOSでも走らせたい場合</summary>

簡単のためにいくつか必須でないフラグを抜いていますが、SwiftやiOSでも走らせたい場合は追加のオプションが必要になってきます。

Swift: `--bundle-resources-for-swift-cli`
iOS/iPadOS: `–chunk-unet`

それぞれ、末尾に付け加えてください。
</details>

# Step.4 Stable Diffusionを実際に走らせてみる

お疲れ様でした。ここまで来ればあとはコマンドを一つ打つだけです。
また長いですが、かいつまんで解説します。
```
python -m python_coreml_stable_diffusion.pipeline --prompt "a photo of an astronaut riding a horse on mars" --model-version stabilityai/stable-diffusion-2-base -i ./stable_diffusion_models -o ./output_images --compute-unit ALL --seed 93
```
- `python -m python_coreml_stable_diffusion.pipeline`
→前のコマンドと同様、コアとなる部分です。
- `--prompt "a photo of an astronaut riding a horse on mars"`
→**実際に条件を与える部分です。** 好きな言葉を`" "`の中に入力してみてください。
- `--model-version stabilityai/stable-diffusion-2-base`
→省略可ですが、**前章でバージョンを指定した場合は必須です。** 前章で指定した通りに指定してください。
- `-i ./stable_diffusion_models`
→省略不可です。**先ほど指定したディレクトリを指定します。**
- `-o ./output_images`
→省略不可です。**実際に画像を出力する先を規定します。** 前章同様、コマンドをそのままコピペするとディレクトリが存在しないと怒られるので注意してください。
これも同様に、私は`mkdir output_images`をして、`ml-stable-diffusion/output_images`に格納することにしました。
- `--compute-unit ALL --seed 93`
→省略可です。`--compute-unit`はどこで演算するかを規定します。`CPU_AND_GPU`や`CPU_AND_NE`にすると`ALL`より早くなる可能性があります。また、`--seed`ではシード値を固定していて、同じシード値であれば同じ乱数が用いられるために結果も同じものとなります。

こちらが私の環境で得られた結果です。如何でしたか？
![randomSeed_93_computeUnit_ALL_modelVersion_stabilityai_stable-diffusion-2-base.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627957/9d9864e5-5380-af28-0647-fb297f4729a9.png)


# おわりに
結構とっつきにくい印象のある、ローカルでのStable Diffusionの実行でしたが、どうでしたか？
「わりと簡単だったな」と思っていただければ幸いです。
最後に、デフォルトのバージョン(`CompVis/stable-diffusion-v1-4`)での結果を載せておきます。
(`stabilityai/stable-diffusion-2-base`をさらに発展させた、[`stabilityai/stable-diffusion-2`](https://huggingface.co/stabilityai/stable-diffusion-2)は相性が良くないのか、自分の環境ではエラーを吐いてしまいました。)

ここまでお付き合いいただき、ありがとうございました！
![randomSeed_93_computeUnit_ALL_modelVersion_CompVis_stable-diffusion-v1-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627957/756b486b-b9cc-c9d9-ccfd-d8ea2a7b677e.png)