Python 3.14で実現した“真の”マルチスレッド

2025年7月にリリース予定の Python 3.14 Beta 3 より、いよいよ GILを無効化できる「無GIL(Free‑threaded)」ビルド が正式にサポートされました。これは、2023年にPEP 703が採択された後、Phase II(正式サポート)に移行した証しです  。

💡 背景:なぜGILが問題だったのか?

Pythonの標準実装であるCPythonには、GIL(Global Interpreter Lock:グローバルインタプリタロック)という仕組みが長年存在してきました。このGILは、同時に複数のスレッドがPythonオブジェクトを操作しないようにする排他制御のためのロック機構です。

一見するとGILは、Pythonを簡潔で安全に保つための仕組みに見えます。たしかに、それは事実でもあります。たとえば、PythonはC言語で書かれており、その内部ではメモリ管理に「参照カウント方式」を使っています。あるオブジェクトが何回参照されているかを記録しておき、そのカウントが0になったときにオブジェクトを破棄するという方式です。

ところが、この参照カウントを複数のスレッドから同時に変更しようとすると、レースコンディション(同時書き込みによる矛盾)が発生します。これを防ぐために導入されたのがGILであり、「1度に1つのスレッドしかPythonのバイトコードを実行できない」という制約を生み出しています。

🔧 GILの本質的な問題点

このようにGILはPythonの内部実装を簡潔に保つうえで大きな役割を果たしていましたが、時代が進むにつれて致命的なボトルネックとなりました。特に次のような点で深刻な影響がありました:

1. マルチコアCPUを活かせない

今日のCPUは複数のコアを持ち、並列処理による高速化が当たり前になっています。しかし、GILの存在により、複数スレッドを起動しても、同時に実行できるのは1つだけです。これではせっかくのマルチコアの性能を十分に活用できません。

2. スレッド並列の性能が出ない

たとえば、Pythonで画像処理や科学技術計算などのCPUバウンドな処理を複数スレッドで並列化しても、GILがあると結局は「順番に1つずつ」処理されるため、実行速度がほとんど改善しないのです。

3. 開発者の混乱と回避策の複雑化

Pythonでは「threading モジュールで並列処理できる」と言いつつも、実際には真の並列性を得るには multiprocessing モジュールを使ってプロセス並列にする必要があるという“隠れた制約”がありました。プロセス並列はオーバーヘッドが大きく、共有メモリやキューの扱いも複雑で、初心者には難解です。

4. 高速化できない → 他言語への逃避

AIやWebサーバー、並列クローラなど高負荷な処理を伴う分野では、「Pythonは便利だけど遅い」と言われ、性能が必要な部分だけをC++やRustで書くハイブリッド構成が一般的になりました。これは開発コストや保守性の面で課題が大きいアプローチです。

🌀 GILのパラドックス:安全と性能のトレードオフ

GILは一種の「安全装置」です。PythonのオブジェクトモデルやGCをスレッドセーフに保ち、ライブラリ開発者が内部実装のロック処理をそれほど意識しなくて済むようにしたという点では、**Pythonらしい“実用主義の設計”**とも言えます。

しかし、スレッド安全の代償として性能を犠牲にしていたことが、マルチコア化が進んだ現代のシステムでは大きな足かせとなっていました。

💥 AI・データ処理時代の限界

特に近年は、ディープラーニングの学習やデータ前処理のような高負荷な処理をスケーラブルに行うニーズが急増しています。こうした場面でGILの制約は致命的であり、Pythonの採用を避ける、または他言語に置き換えるといった選択が現実に増えてきていました

🚪 だからこそ「GILの撤廃」は長年の悲願だった

「Pythonの使いやすさと、C/C++並みの並列性能を両立させたい」

その願いに応えるべく登場したのが、無GIL(no-GIL)ビルドのPythonであり、PEP 703がそれを実現する第一歩となったのです。

🚀 PEP 703の採択とPhase 移行

🧾 PEP 703とは何か?

PEP 703(正式名称:Making the Global Interpreter Lock Optional in CPython)は、CPythonからGIL(Global Interpreter Lock)を取り除くことを可能にする提案です。著者はMeta(旧Facebook)所属のエンジニアである Sam Gross 氏。彼は長年にわたって「nogil-python」という独自フォークで、GILを排除したPython実装を開発・検証してきました。

このPEPは、「すべてのPython実装を無GILにしよう」というものではなく、「GILあり/なしをビルド時に選べるようにする」という、現実的で段階的な方針をとったことが評価されました。

📅 採択までの流れ

  • 2021年〜2022年:Sam Gross氏が独自に nogil ビルドを開発。実際のコードベースで性能・安定性を実証。
  • 2023年4月:PEP 703 が公式に提出される。予想以上の注目を集め、Python開発者コミュニティで大規模な議論が展開される。
  • 2023年7月:Pythonの意思決定機関である Steering Council(SC) が、PEP 703を条件付きで採択

Steering Councilによる採択の主旨は、「GILなしビルドはPythonの将来にとって重要なオプションになる」という判断に基づくものです。採択にあたり、以下のような条件が提示されました:

  • ABI(バイナリ互換性)やツールチェインの影響評価
  • 標準ライブラリや主要外部ライブラリとの互換性
  • パフォーマンスへの影響が限定的であることの証明
  • 開発体制(コミットメント)の持続性

🚨 採択時の公式声明:https://discuss.python.org/t/a-steering-council-notice-about-pep-703-making-the-global-interpreter-lock-optional-in-cpython/30474

📦 Phase制とは?

PEP 703の実現には段階的な導入が不可欠です。そこで提案されたのが **「3フェーズ構成」**です:

フェーズ内容状態(2025年7月現在)
Phase I実験的導入(experimental):一部の開発者・パワーユーザーが手動でビルドして評価する段階✅ 完了(3.13)
Phase II正式サポート(supported):公式ビルドに –disable-gil オプションを導入し、開発者が広く使用可能に✅ 現在進行中(3.14 Beta 3〜)
Phase IIIデフォルト化(default):将来的にGILなしPythonを標準ビルドとすることを目指す🔜 将来検討

📍 Phase II:Python 3.14で何が変わる?

2025年7月現在、Python 3.14 Beta 3 にて –disable-gil オプションによる 「無GILビルド」が正式に同梱 されました。これにより、以下が可能になります:

  • 通常のCPythonソースコードから、./configure –disable-gil で free-threaded Python(無GIL)を構築可能
  • サードパーティライブラリ開発者は、本格的に互換性やパフォーマンスの検証に取り組める
  • 今後、PyPIのメタデータにもGIL対応情報が加わる予定

これは開発者にとって非常に大きな転機であり、「GILなしの未来に向けた準備を本格化する段階」と言えます。

💬 採択における議論のポイント

PEP 703の採択には、以下のような懸念と議論が活発に交わされました:

  1. 性能劣化への不安:GILを取り除くことで単一スレッド性能が落ちるのでは?
  2. メモリ使用量の増加:オブジェクトごとのロック管理により、メモリが増加しないか?
  3. 既存の拡張ライブラリとの互換性:PyTorch、NumPyなどが対応できるのか?
  4. メンテナンスコスト:2種類のビルド(GILあり/なし)を保守し続けられるのか?

これらに対してSam Gross氏は、実装レベルでの性能改善策(アトミック参照カウント、バイアス付きRCなど)や、十分なバックワード互換性の維持、長期的な支援体制を提案し、結果として採択に至りました。

🔮 Phase IIIへ向けて:今後の課題と期待

Phase IIの間に、次のステップに向けた評価と実績の蓄積が求められます:

  • 実用例の拡大(Flask/FastAPI/Django等でのベンチマーク)
  • PyPIパッケージの対応率向上
  • CPythonチームとコミュニティによる安定性テスト
  • エコシステムのドキュメント整備と開発者教育

こうした課題をクリアした上で、将来的に Phase III(GILなしが標準) へと進むことが期待されています。これはPythonの設計思想を大きく刷新する歴史的な転換点となるでしょう。

🧠 CPython内部での変化

Python 3.14で「GILなしビルド(Free-threaded Build)」が正式に導入されるにあたり、CPythonの内部には抜本的な再設計が施されました。単にGILを「オフにする」だけではなく、GILが前提だった数多くの内部機構を、並列スレッドに耐える構造へと刷新する必要があったのです。

以下に、主な内部変更点とその意図、技術的背景を詳しく紹介します。

🔁 1. アトミックな参照カウントへの移行

CPythonでは、メモリ管理の中心に「参照カウント(reference counting)」を用いています。オブジェクトが何回使われているかをカウントし、0になった時点でメモリを解放するという仕組みです。

従来、GILがあることで参照カウントのインクリメント・デクリメントは排他制御なしでも安全に行えました。しかしGILを除去する場合、複数スレッドが同時に参照カウントを操作するため、**アトミック操作(atomic operations)**が必要になります。

  • Python 3.14では、GCC/Clangなどのコンパイラが提供する __atomic_fetch_add() や std::atomic を活用し、スレッド安全な参照カウントを実現。
  • ARMやx86などのプラットフォームに対応するため、クロスプラットフォームなアトミック処理の実装が行われました。

この改良により、オブジェクトのライフサイクルがマルチスレッド下でも一貫して安全に動作するようになります。

⚖️ 2. バイアス付き参照カウント(Biased Reference Counting)

ただアトミックにするだけではオーバーヘッドが大きいため、Python 3.14では 「バイアス付き参照カウント(biased refcount)」 という最適化も導入されました。

  • 各スレッドに スレッドローカルの参照カウントキャッシュを持たせることで、頻繁なグローバル競合を回避。
  • 一定条件でしかグローバルカウントに反映しないことで、ロックやアトミック操作の頻度を減らす工夫。

これにより、GILありのPythonに近い性能を維持しながら、GILを撤廃するという難題に現実的な解決策が与えられました。

🧹 3. ガーベジコレクタ(GC)の見直し

PythonのGC(ガーベジコレクタ)は、参照カウントとは別に 循環参照 を検出してオブジェクトを解放する機構です。

GILがある場合は、GCの途中で他のスレッドがオブジェクトを触ることがなかったため、非常に単純でした。しかしGILなし環境では:

  • GC中にも他スレッドからオブジェクトが変更される可能性がある。
  • 複数スレッドが同時にGCを走らせると、同じメモリに対して並列にアクセスしてクラッシュする恐れがある。

これを防ぐために、Python 3.14の無GILビルドでは:

  • Stop-the-world型GC を採用:GCを行うときは全スレッドを一時停止。
  • 同期バリア の導入:GC開始時にスレッド間で同期を取り、整合性を確保。

こうした工夫により、従来のGCを可能な限り流用しながら、スレッドセーフな循環検出とメモリ解放を実現しています。

🧱 4. スレッドローカル・ヒープとオブジェクトアロケータ

さらに、メモリの割り当てと解放のスレッド競合を回避するために、スレッドごとのヒープ領域(Thread-Local Heaps) が導入されました。

  • 各スレッドが独立したアロケータを持ち、小さなオブジェクトの割り当てを効率化。
  • 共有アロケータへのアクセス頻度を下げることで、ロックの衝突を回避し性能を向上

また、一部のオブジェクト(文字列やタプルなど)については「不変性(immutability)」を前提にした読み取り中心の最適化が行われ、スレッド間での共有にも強くなりました。

🔓 5. オブジェクトごとのロック(Per-object Locking)

一部のオブジェクト(例:辞書、リストなど)は、内部状態を変更する操作が並列実行されると整合性が崩れる可能性があります。

そこで、Python 3.14ではこうしたオブジェクトに 内部ロック(mutex) を導入し、以下を制御:

  • dict.__setitem__() や list.append() のような変更系操作でロックを取得
  • 読み取りはロックフリーで許容(必要に応じて)

これにより、開発者がユーザーレベルで複雑なロックを記述せずとも、CPython内部で整合性が担保されるようになりました。

🧬 6. ABIの互換性と2モードビルド体制

GILあり・なしのビルドを共存させるため、ABI(Application Binary Interface)レベルでの分離も検討されています。

  • PyPIに「no-gil互換」のフラグを導入
  • C拡張モジュールがGILあり/なしどちらに対応しているかを明示
  • ビルド時に –disable-gil を指定すれば、別モードのPythonがインストールされる

この柔軟な構成により、段階的な移行と後方互換性の維持が可能になります。

🔚 まとめ

変更点内容狙い
参照カウントアトミック+バイアス方式並列更新の安全確保と高速化
GCStop-the-world型・同期バリア導入循環参照検出のスレッド安全性
メモリアロケータスレッドローカルヒープメモリ競合の削減
オブジェクト保護内部ロック・不変性活用共有オブジェクトの整合性維持
ABI構造GILあり/なしのビルド分離ライブラリ互換性と移行支援

このように、Python 3.14の無GIL対応は、単なる「ロック解除」ではなく、CPythonのメモリ管理、オブジェクトモデル、実行モデルを抜本的に見直す再設計の結晶なのです。

🧪 パフォーマンスとメモリ傾向

GILを無効化することで「マルチスレッドが速くなる」のは直感的に理解しやすいですが、実際にどの程度の性能向上があるのか、また逆にどんな副作用があるのかは、多くのPythonユーザーが気になるところでしょう。

このセクションでは、Python 3.14無GILビルドにおける実測ベンチマークやメモリ使用傾向、そしてそこから見える実運用上の注意点を詳しく見ていきます。

🏁 性能評価の方法:pyperformanceベンチマーク

性能比較には、Python公式のベンチマークスイート pyperformance が使われています。これはPythonの代表的な処理(数値演算、テキスト処理、正規表現、圧縮・展開など)を測定するためのツールです。

PEP 703 の開発者である Sam Gross 氏や、他の開発者・研究者によって実際に行われた比較では、以下のような傾向が明らかになりました。

📊 ベンチマーク結果(概要)

🔹 単一スレッド性能

テスト対象通常のCPython(GILあり)無GILビルド性能差(参考)
正規表現マッチ1.00 倍0.94 倍−6% 程度
JSONエンコード1.00 倍0.93 倍−7% 程度
数値演算(浮動小数)1.00 倍0.89 倍−11% 程度
データ構造操作1.00 倍0.96 倍−4% 程度

➡️ 平均して約5〜10%の性能低下が観測されます。これはアトミック参照カウントや内部ロックによるオーバーヘッドが原因です。

🔹 マルチスレッド性能(4スレッド以上)

テスト対象GILあり無GIL向上率
数値演算 × 4スレッド約3.8秒約1.1秒約3.5倍高速化
gzip圧縮約3.2秒約1.2秒約2.7倍高速化
並列Web API処理約1100 req/s約3100 req/s約2.8倍高速化

➡️ マルチコア環境下では劇的な性能改善が見られます。これこそが無GILビルドの最大のメリットです。

🔍 CPUバウンド vs I/Oバウンド

タイプ無GILの影響
CPUバウンド処理✅ 大きな改善。計算系・画像処理・暗号化などに強い。
I/Oバウンド処理⭕ 少し改善。スレッド間切り替えが減り安定するがASGI/asyncには及ばない。

とくに NumPy, Pillow, PyTorch のような計算系ライブラリとの組み合わせでは、スレッドワークのスケーリングが現実的になり、実行時間を大幅に短縮できるケースが多くなっています。

📈 メモリ使用量の傾向

無GIL化に伴い、CPython内部では以下のような理由からメモリ使用量が増加する傾向があります:

  • 参照カウントに追加のメタ情報(バイアス構造体など)が必要
  • オブジェクトごとの内部ロック/バリア/スレッド局所ヒープの導入
  • GCの一時的データ構造の増加

その結果、Sam Gross氏のベンチマークでは:

  • 全体メモリ使用量が約15〜20%増加(ワークロードによる)
  • スレッド数が増えるほどヒープや同期コストが上乗せされやすい

📌 実運用でのインパクトは?

処理タイプパフォーマンス影響メモリ影響備考
シングルスレッドのWeb APIわずかに遅くなる(5〜10%)微増性能劣化が許容されるなら問題なし
並列スクレイピング最大3倍高速化やや増加リクエストを多数処理する用途に最適
バッチ処理・科学計算数倍速くなるやや増加ThreadPoolExecutorを積極活用できる

💬 開発者の声・評価

  • 「並列処理の効果がコード量を減らすことで顕著に現れる」
  • 「multiprocessingを使わずに済むだけで、コードの可読性とデバッグ性が格段に向上」
  • 「NumPyやPyTorchが対応してくれれば、Pythonの並列処理が現実解になる」

といった前向きな意見が多く、Pythonでスケーラブルなアプリを書くことへの期待が高まっています

✅ まとめ

  • 単一スレッド性能は最大で10%程度の低下があるが、ほとんどのケースでは実用的。
  • マルチスレッド処理では2〜4倍以上の大幅な高速化が実現可能。
  • メモリ使用量は平均して15〜20%程度の増加が見られるが、トレードオフとしては妥当。
  • GILなしで「Pythonらしいコード」のまま並列性を活かせることは、開発者にとって大きなメリット。

✅ まとめ

2025年7月にリリースされた Python 3.14 Beta 3 において、ついに 「無GIL(Global Interpreter Lock)ビルド」 が正式にサポートされる段階、すなわち Phase II(正式サポートフェーズ) に入りました。これにより、開発者は –disable-gil オプションを使用して、GILのないビルドを手軽に試すことができるようになり、Pythonにおける並列処理の可能性が大きく広がる節目を迎えたと言えます。

この無GILビルドでは、単体スレッドの性能においてはおおよそ5〜10%程度のパフォーマンス低下が見られるものの、これはアトミック参照カウントや同期処理によるわずかなオーバーヘッドによるものであり、通常のアプリケーションにおいて致命的な影響を及ぼすレベルではありません。一方で、マルチスレッド処理においてはGILの制約が完全に取り払われたことにより、複数スレッドによる“真の並列実行”が可能となり、実行速度が2倍〜4倍、場合によってはそれ以上に向上するケースも報告されています。

もちろん、GILが取り除かれたことによって内部構造も大きく変わっており、拡張モジュール(C拡張など)との互換性や、メモリ使用量の増加、スレッドセーフなコード設計の重要性など、開発者が注意すべき点も少なくありません。とくに、PyPI上に存在する数多くのサードパーティライブラリが無GIL環境に対応するには一定の時間と検証が必要であり、慎重な移行計画が求められる状況です。

とはいえ、Python本体とエコシステム全体がこの変化に向けて大きく動き始めているのは確かであり、今後1〜2年のうちに、主要なライブラリの対応やパッケージングの整備が進めば、「GILなし」がPythonの新たな標準となる日も決して遠くはないでしょう。本格的な移行に向けた「助走期間」として、まさに今が絶好のタイミングだと言えます。

今回のリリースは、30年以上続いてきたPythonの実行モデルに対する最大級の刷新であり、並列性の課題に対してついに本格的な解決策が提供されたという点で、歴史的な意義を持っています。これからのPythonは、より強力に、そしてよりスケーラブルに進化していくことでしょう。

📚 参考文献

REST API特化のWebアプリケーションフレームワーク「Pykour」のご紹介

本日、v0.1.4をリリースし、それなりに動作するようになったので、私が開発中のWebアプリケーションフレームワーク「Pykour」についてご紹介します。

Pykourとは

REST APIを作成することに特化したPython向けWebアプリケーションフレームワークです。FlaskやFastAPIを参考に作成しているので、現時点ではREST APIしか作れないFastAPIのようなフレームワークになっています。

v0.1.xでは機能追加や機能変更を行うベータ版とし、v0.2.0から正式版としてリリースする計画としています。

Pykourの使い方

まずは基本的な使い方について説明します。

インストール

Pykourのインストールは他のフレームワークと同様にpipコマンドでインストールできます。

$ pip install pykour

pykourパッケージをインストールすると、pykourコマンドが使用可能になります。

$ pykour -v
Pykour v0.1.4

main.pyという名前で以下のプログラムを作成します。

from pykour import Pykour

app = Pykour()

@app.get("/")
def home():
  return {"message": "Hello, World!"}

最も簡単なプログラムは、FastAPIとほとんど変わらない書き方になります。このプログラムを実行するには、pykour devコマンドを使います。

$ pykour dev main:app

pykour devコマンドではuvicornを使用し、pykour runコマンドではgunicorn+uvicorn-workerを使用して、ASGIサーバーを起動しています。

デフォルトではhttp://127.0.0.1:8000でサーバーが起動しますので、

$ curl http://127.0.0.1:8000/
{"message": "Hello, World!"}%

のように応答が返ってきます。

v0.1.4ではどこまでできるのか

v0.1.4では、以下のようなことができるようになっています。

ルーティングの設定

ルーティングの設定は、前述のようにPykourインスタンスに直接設定する方法と、

from pykour import Pykour

app = Pykour()

@app.get("/")
def home():
  return {"message": "Hello, World!"}

Routerインスタンスを作成して、それをPykourインスタンスに設定する方法もあります。

from pykour import Router

router = Router(prefix="/users")

@router.get("/")
def get_users():
  return {"message": "get users"}
from pykour import Pykour
from .routes import router

app = Pykour()
app.add_router(router)

スキーマの使用

リクエストボディはデフォルトでは辞書型にマッピングされますが、スキーマを作成して対応させることもできます。

from pykour.schema import BaseSchema

class UserSchema(BaseSchema):
  name: str
  age: int
from pykour import Pykour
from .schemas import UserSchema

app = Pykour()

@app.post("/")
def post_user(user: UserSchema):
  return {"name": user.name}

設定ファイルの使用

YAML限定ですが、設定ファイルを使用することもできます。

例えば、

foo:
  bar: bas

という設定ファイルをconfig.yamlというファイル名で作成した場合、Pykourインスタンス作成時に設定ファイルを指定することができます。

from pykour import Pykour

app = Pykour("config.yaml")

@app.get("/")
def home(config: Config):
  return {"message": config.get("foo.bar")}

設定ファイルはConfigクラスで扱うことができ、ルート関数の引数に指定しておくと、自動的に設定して呼び出してくれます。

データベースアクセス

まだ、sqlite3しか対応していませんが、データベースアクセスも可能です。

設定ファイルでデータベースの設定を行います。

pykour:
  database:
    type: sqlite
    url: pykour.db

設定ファイルを指定することでデータベースにアクセスできるようになります。

from pykour import Pykour
from pykour.db import Connection

app = Pykour("config.yaml")

@app.get("/")
def home(conn: Connection):
  return {"users": conn.select("SELECT * FROM users")}

今後の計画

まだまだ足りない機能や作りたい機能は結構ありますが、どう実装するべきかを考え中です。

  • ORMの実装
  • 複数のデータベースへの対応(まずはMySQLやPostgreSQL)
  • キャッシュ機能(処理を行わずにキャッシュしてあるレスポンスを返す)の実装

最近のFastAPIでは、スキーマとモデルを一体化していますが、リクエストのデータ構造とテーブルのデータ構造の違いを考えると分けた方がよいのではないかと思っています。ORMは確かによいのですが、JOINやカラムの編集などが出てくると途端に難易度が上がったりするので、どういったインターフェースにするか悩んでいます。

また、コード自体の改善やテストケースの改善など安定性の向上についても継続的に進めていきたいと思います。一応、機能を制限することで高いパフォーマンスを発揮することを目標としているので、ベンチマークをとる環境も構築していきたいです。

v0.1.5では複数のデータベースをサポートしつつ、コードの改善を進めていく予定です。

Apple Silicon MacにStable Diffusion WebUIをインストールする

Stable DiffusionをApple SiliconのmacOSにインストールしてみましたが、少しコツが必要でした。

インストール時期やApple Siliconの種類によっては若干変わるかもしれませんが、私がM1 Maxチップ搭載のMacBook Proで成功した手順をまとめてみました。

必要なパッケージをインストールする

こちらは公式に従ってインストールします。私の環境では最終的にPythonはここでインストールしたものではなく、Asdfで導入したものを使用しているので、3.10系であればここでインストールしなくてもよいと思われます。

brew install cmake protobuf rust python@3.10 git wget

Stable Diffusion WebUIをダウンロードする

GithubのReleasesでもダウンロードできそうですが、macOSの場合はリポジトリをクローンする必要があります。

任意のディレクトリにリポジトリをcloneしてください。

git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui

追加データをダウンロードする

手順の中でここが一番面倒かもしれません。ここでは執筆時点最新のv2.1を使用します。

上記サイトからvae-ft-mse-840000-ema-pruned.ckptというファイルをダウンロードし 、stable-diffusion-webui/models/Stable-difusionに保存してください。

保存後、ファイル名をv2-1_768-ema-pruned.vae.ptに変更してください。

上記サイトからv2-1_768-ema-pruned.safetensorsというファイルをダウンロードし、stable-diffusion-webui/models/Stable-difusionに保存してください。

ここを開いて、表示された内容をコピーし、stable-diffusion-webui/models/Stable-difusionv2-1_768-ema-pruned.yamlというファイル名で保存してください。

Stable Diffusion WebUIを起動する

cd stable-diffusion-webui
./webui.sh

起動すると、以下のようなログが表示されます。URLが出ているので、ここにアクセスしてください。

Model loaded in 3.6s (load weights from disk: 0.3s, create model: 0.2s, apply weights to model: 1.8s, apply half(): 0.6s, load VAE: 0.1s, move model to device: 0.5s).
Running on local URL:  http://127.0.0.1:7860

To create a public link, set `share=True` in `launch()`.
Startup time: 11.2s (import torch: 2.1s, import gradio: 1.7s, import ldm: 0.4s, other imports: 2.9s, load scripts: 0.3s, load SD checkpoint: 3.6s, create ui: 0.2s).

ブラウザでアクセスすると、以下のような画面が表示されます。

設定変更を行う

同じようにApple Silicon Macにインストールしている方の記事で、この点に触れていない方も結構見かけるので、もしかすると環境依存かもしれませんが、私の環境ではv2.1でGenerateしようとすると以下のようなエラーが表示されました。

  0%|                                                                                                                                                                                                                                    | 0/20 [00:02<?, ?it/s]
Error completing request
Arguments: ('task(6gvckovujc9xon0)', 'sailing ship', '', [], 20, 0, False, False, 1, 1, 7, -1.0, -1.0, 0, 0, 0, False, 512, 512, False, 0.7, 2, 'Latent', 0, 0, 0, [], 0, False, False, 'positive', 'comma', 0, False, False, '', 1, '', 0, '', 0, '', True, False, False, False, 0) {}
Traceback (most recent call last):
  File "/Users/t0k0sh1/Workspace/stable-diffusion-webui/modules/call_queue.py", line 56, in f
    res = list(func(*args, **kwargs))
  File "/Users/t0k0sh1/Workspace/stable-diffusion-webui/modules/call_queue.py", line 37, in f
    res = func(*args, **kwargs)
  File "/Users/t0k0sh1/Workspace/stable-diffusion-webui/modules/txt2img.py", line 56, in txt2img
    processed = process_images(p)
  File "/Users/t0k0sh1/Workspace/stable-diffusion-webui/modules/processing.py", line 503, in process_images
    res = process_images_inner(p)
  File "/Users/t0k0sh1/Workspace/stable-diffusion-webui/modules/processing.py", line 653, in process_images_inner
    samples_ddim = p.sample(conditioning=c, unconditional_conditioning=uc, seeds=seeds, subseeds=subseeds, subseed_strength=p.subseed_strength, prompts=prompts)
  File "/Users/t0k0sh1/Workspace/stable-diffusion-webui/modules/processing.py", line 869, in sample
    samples = self.sampler.sample(self, x, conditioning, unconditional_conditioning, image_conditioning=self.txt2img_image_conditioning(x))
  File "/Users/t0k0sh1/Workspace/stable-diffusion-webui/modules/sd_samplers_kdiffusion.py", line 358, in sample
    samples = self.launch_sampling(steps, lambda: self.func(self.model_wrap_cfg, x, extra_args={
  File "/Users/t0k0sh1/Workspace/stable-diffusion-webui/modules/sd_samplers_kdiffusion.py", line 234, in launch_sampling
    return func()
  File "/Users/t0k0sh1/Workspace/stable-diffusion-webui/modules/sd_samplers_kdiffusion.py", line 358, in <lambda>
    samples = self.launch_sampling(steps, lambda: self.func(self.model_wrap_cfg, x, extra_args={
  File "/Users/t0k0sh1/Workspace/stable-diffusion-webui/venv/lib/python3.10/site-packages/torch/autograd/grad_mode.py", line 27, in decorate_context
    return func(*args, **kwargs)
  File "/Users/t0k0sh1/Workspace/stable-diffusion-webui/repositories/k-diffusion/k_diffusion/sampling.py", line 145, in sample_euler_ancestral
    denoised = model(x, sigmas[i] * s_in, **extra_args)
  File "/Users/t0k0sh1/Workspace/stable-diffusion-webui/venv/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1130, in _call_impl
    return forward_call(*input, **kwargs)
  File "/Users/t0k0sh1/Workspace/stable-diffusion-webui/modules/sd_samplers_kdiffusion.py", line 152, in forward
    devices.test_for_nans(x_out, "unet")
  File "/Users/t0k0sh1/Workspace/stable-diffusion-webui/modules/devices.py", line 152, in test_for_nans
    raise NansException(message)
modules.devices.NansException: A tensor with all NaNs was produced in Unet. This could be either because there's not enough precision to represent the picture, or because your video card does not support half type. Try setting the "Upcast cross attention layer to float32" option in Settings > Stable Diffusion or using the --no-half commandline argument to fix this. Use --disable-nan-check commandline argument to disable this check.

ちなみに、v1.4やv1.5ではこの事象は起きなかったので、v2.x系固有のエラーかもしれません。

これを解消するために、設定変更を行います。画面上部のタブからSettingsを選択し、

左のメニューからStable Diffusionを選択します。

バージョンにもよるかもしれませんが、一番下にUpcast cross attention layer to float32というチェックボックスがあるので、ここにチェックをつけてください。

最後に設定を反映させるため、画面上部のApply settingsボタンを押してください。

これでエラーが出ずに画像生成ができるようになります。

データバージョン管理ツール「DVC」を導入する

データバージョン管理ツールのDVCを導入し、データセットをDVCで管理する方法について説明します。

DVCのインストールと初期化

DVCをインストールして初期化を行います。

DVCはpipコマンドまたはcondaコマンドでインストールします。

$ pip install dvc
または
$ conda install -c conda-forge dvc

次にDVCの初期化を行いますが、Gitの初期化を行なっていない場合は先にgit initを実行してください。

プロジェクトルートで以下のコマンドを実行します。

$ dvc init
Initialized DVC repository.

You can now commit the changes to git.

+---------------------------------------------------------------------+
|                                                                     |
|        DVC has enabled anonymous aggregate usage analytics.         |
|     Read the analytics documentation (and how to opt-out) here:     |
|             <https://dvc.org/doc/user-guide/analytics>              |
|                                                                     |
+---------------------------------------------------------------------+

What's next?
------------
- Check out the documentation: <https://dvc.org/doc>
- Get help and share ideas: <https://dvc.org/chat>
- Star us on GitHub: <https://github.com/iterative/dvc>

コマンドを実行すると、.dvcと.dvcignoreが作成されます。

一旦変更をコミットしましょう。

データセットの管理先を設定する(リモートストレージ)

機械学習やディープラーニングで使用するデータセットはサイズが非常に大きく、Gitリポジトリで管理するのに適していません。

ここではAmazon S3にデータセットを保存する手順で説明します。S3が使用できなくて、NASやファイルサーバーがある場合はそちらを使っていただいても構いませんし、大容量ディスクがPCに搭載されていればそちらも選択しても構いません。

$ aws configure
AWS Access Key ID [None]: XXXXXXXXXXXXXXXXXXXX
AWS Secret Access Key [None]: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Default region name [None]: ap-northeast-1
Default output format [None]: json

AmazonS3FullAccessポリシーをもったユーザーをAWS CLIに設定します。

またアップロードするS3バケットを用意してください(アクセス範囲には十分ご注意ください)。

$ dvc remote add -d main s3://datascience-dvc-remote-storage
Setting 'main' as a default remote.

リモートストレージを設定すると、.dvc/configに設定が書き込まれます。

[core]
    remote = main
['remote "main"']
    url = s3://datascience-dvc-remote-storage

リモートストレージを追加したら変更をコミットしておきましょう。

データセットを追加する

設定できたのでデータセットを追加してみます。ここではKaggleのTitanicのデータセットを登録します。

$ mkdir -p datasets/titanic
$ cd datasets/titanic
$ kaggle competitions download -c titanic
$ unzip titanic.zip
$ rm titanic.zip
$ ls
gender_submission.csv   test.csv                train.csv

この時点では、追加したファイルは未追跡のファイルとして認識されています。

次に、DVCで管理するように設定します。

$ dvc add datasets/titanic
100% Adding...|█████████████████████████████████████████████████|1/1 [00:00, 43.52file/s]
                                                                                                                                                                                  
To track the changes with git, run:

        git add datasets/titanic.dvc datasets/.gitignore

To enable auto staging, run:

        dvc config core.autostage true

新たにdatasets/titanic.dvcdatasets/.gitignoreが作成されました。

datasets/titanic.dvctitanicディレクトリのMD5ハッシュ等の情報を保持しており、

outs:
- md5: bf1a6a19059092be578a3807608e236c.dir
  size: 93081
  nfiles: 3
  path: titanic

datasets/.gitignoreはDVCで管理するように指定したtitanicディレクトリが設定されています。

/titanic

ここまでの変更をコミットしておきましょう。

リモートストレージに保存する

今の状態は追加したデータセットをGitリポジトリの管理下から除外し、管理情報だけをGitリポジトリで管理するようにしただけです。実際のデータセットはローカルにしか存在しません。

これをさきほど設定したS3バケットに保存しましょう。

dvc pushコマンドで保存できますが、これまでの手順通りに進めた場合、以下のようにエラーが発生します。

$ dvc push
ERROR: unexpected error - s3 is supported, but requires 'dvc-s3' to be installed: No module named 'dvc_s3'

Having any troubles? Hit us up at https://dvc.org/support, we are always happy to help!

DVCではS3をサポートしていますが、追加のモジュールが必要となるようです。では、モジュールを追加します。

$ pip install dvc-s3
または
$ conda install -c conda-forge dvc-s3

DVCをインストールしたときと同じ方法でインストールしてください。インストールができたら、再度dvc pushコマンドを実行します。

$ dvc push
4 files pushed

コンソールに出力された内容をみると、4ファイル保存したようですが、datasets/titanicディレクトリには3ファイルしかないはずです。リモートストレージに保存されている内容を確認してみましょう。

$ aws s3 ls s3://datascience-dvc-remote-storage
                           PRE 02/
                           PRE 61/
                           PRE b5/
                           PRE bf/
$ aws s3 ls s3://datascience-dvc-remote-storage/02/
2023-01-07 22:25:47      28629 9c9cd22461f6dbe8d9ab01def965c6
$ aws s3 ls s3://datascience-dvc-remote-storage/61/
2023-01-07 22:25:47      61194 fdd54abdbf6a85b778e937122e1194
$ aws s3 ls s3://datascience-dvc-remote-storage/b5/
2023-01-07 22:25:47       3258 6943b6ee3d9af0913ee5dd83b3d729
$ aws s3 ls s3://datascience-dvc-remote-storage/bf/
2023-01-07 22:25:47        218 1a6a19059092be578a3807608e236c.dir

最後のファイルだけ.dirとなっており、上3ファイルが各CSVファイルで、一番最後がtitanicディレクトリになります。

リモートストレージからデータセットを取得する

前述のとおり、データセット自体はGitリポジトリで管理されていません。そのため、新たにリポジトリをcloneした場合、データセットが存在状態となります。ですので、リモートストレージからデータセットをベット取得してくる必要があります。

ここでは、titanicディレクトリを削除してからデータセットを取得してみます。

$ rm -rf datasets/titanic
$ dvc pull
A       datasets/titanic/                                                                                                                                                         
1 file added
$ ls datasets/titanic
gender_submission.csv   test.csv                train.csv

データセットがdvc pullコマンドを実行することで取得できました。

また、引数でdvcファイルを指定することで、明示的に特定のファイル/ディレクトリだけを取得することができます。

$ dvc pull datasets/titanic.dvc

必要なデータセットだけ取得できるため、実務ではこちらの方がよく使うことになると思います。ただし、DVCの管理下に追加する単位が取得できる最小単位となるため、データセット単位で管理下に加えるのか、ファイル単位で管理下に加えるのかはプロジェクトによって検討する必要があります。

最後に

DVCでは、単にデータセットを管理するツールではなく、他にも機能があります。本記事では、その中のデータセットの管理について説明しました。

M1/M2 Macで機械学習の環境を構築する

TensorflowとPytorchがApple Siliconに対応したため、Pythonの機械学習・ディープラーニング環境を構築します。

仮想環境の作成

仮想環境を作成します。

使用するPythonのバージョンですが、このあとインストールするTensorflowが執筆時点では3.7から3.10をサポートしており、Pytorchが3.7以上をサポートしているため、3.10を使用することにします。

conda create -n datascience python=3.10
conda activate datascience

ここでは仮想環境の名前をdatascienceにしていますが、任意の名前で構いません。

機械学習関連

機械学習関連のパッケージをインストールします。

機械学習でよく使われるパッケージをインストールします。

conda install numpy scipy pandas scikit-learn

代表的な可視化パッケージをインストールします。

conda install matplotlib seaborn plotly

EDAパッケージをインストールします。

conda install -c conda-forge pandas-profiling autoviz sweetviz

ローコード機械学習をインストールします。

conda install -c conda-forge pycaret

Jupyter notebookをインストールします。

conda install notebook

スクレイピング関連

スクレイピングでよく使用されるパッケージをインストールします。

conda install -c conda-forge requests scrapy beautifulsoup4

画像処理関連

画像処理でよく使用されるパッケージをインストールします。

conda install -c conda-forge pillow opencv

ディープラーニング関連

TensorflowとPytorchをインストールします。

Tensorflow

Xcode Command Line Toolをインストールしていない場合は以下のコマンドでインストールします。 

xcode-select --install

Tensorflow dependenciesをインストールします。

conda install -c apple tensorflow-deps

Tensorflowをインストールします。

pip install tensorflow-macos

Metalプラグインをインストールします。

pip install tensorflow-metal

インストール後にGPUが使用可能か確認しましょう。

import sys
import tensorflow.keras
import pandas as pd
import sklearn as sk
import scipy as sp
import tensorflow as tf
import platform

gpu = len(tf.config.list_physical_devices('GPU'))>0
print("GPU is", "available" if gpu else "not available")

以下のように表示されればGPUが使用可能です。

GPU is available

Pytorch

PytorchはTensorflowに比べるとインストールは簡単です。以下のコマンドでインストールします。

pip install --pre torch torchvision --extra-index-url https://download.pytorch.org/whl/nightly/cpu

インストール後にGPUが使用可能か確認しましょう。

import torch

gpu = torch.backends.mps.is_available()
print("GPU is", "available" if gpu else "not available")

以下のように表示されればGPUが使用可能です。

GPU is available

今後の課題

現時点で形態素解析パッケージであるMecabのインストールに失敗しています。手順もいくつか示されていますが、実際に試したところいずれもうまくいっていません(インストール自体に失敗する、インストール後に動作しない)。

こちらは引き続きインストール方法を調査し、判明次第本記事を更新したいと思います。

PandasでCSVファイル読み込む(read_csv関数)

PandasでCSVファイルを読み込む方法について解説します。
本記事では読み込みオプションの解説ではなく、CSVファイルや CSVファイルに似たファイルの読み込み方について解説しています。

CSVファイルを読み込む

次のCSVファイルを読み込んでデータフレームを作成します。

社員番号,氏名,姓,名,生年月日,役職
001,山田 太郎,山田,太郎,1990-01-01,係長
002,田中 花子,田中,花子,1990-12-31,部長

ふつうのCSVファイルであればオプションなしで読み込むことができます。

import pandas as pd
test1_df = pd.read_csv('test1.csv')

カンマやダブルクォーテーションをカラムに含むCSVファイルを読み込む

カラムにカンマを含む場合、ダブルクォーテーションでカラムを囲みます(a,b"a,b") 。もちろん、カンマを含んでいない場合でもダブルクォーテーションでカラムを囲んでもかまいません。
ダブルクォーテーションでカラムを囲んでいるときにカラムにダブルクォーテーションが含まれる場合はエスケープする必要があります。エスケープする場合はダブルクォーテーションを二つ重ねます(a"b"a""b")。

次のCSVファイルを読み込んでデータフレームを作成します。

社員番号,氏名,姓,名,生年月日,役職
001,"山田,""太郎",山田,太郎,1990-01-01,係長
002,"田中,""花子",田中,花子,1990-12-31,部長

Pandasのread_csv関数は基本的なCSVの仕様に対応しているため、特にオプションを使用せずに読み込むことができます。

import pandas as pd
test2_df = pd.read_csv('test2.csv')

タブ区切りファイルを読み込む

最近は見かけることが減りましたが、タブ区切りファイル(TSVファイル)をread_csv関数で読み込むことができます。

次のTSVファイルを読み込んでデータフレームを作成します。

社員番号	氏名	姓	名	生年月日	役職
001	山田 太郎	山田	太郎	1990-01-01	係長
002	田中 花子	田中	花子	1990-12-31	部長

オプションなしで読み込むことはできないため、sepで区切り文字を指定します。

import pandas as pd
test3_df = pd.read_csv('test3.csv', sep='\t')

任意の区切り文字のファイルを読み込む

出力する側の問題でダブルクォーテーションによる区切り文字が使用できない場合や出力または中間での加工の都合で、カラム内に絶対に含まれない文字を使ってファイルを出力することがあります。
先ほどのタブ区切りの応用でread_csv関数を使って読み込むことができます。

垂直バー(|)を区切り文字にした次のCSVファイルを読み込んでデータフレームを作成します。

社員番号|氏名|姓|名|生年月日|役職
001|山田 太郎|山田|太郎|1990-01-01|係長
002|田中 花子|田中|花子|1990-12-31|部長

TSVファイルのときと同様に、sepで区切り文字を指定します。

import pandas as pd
test4_df = pd.read_csv('test4.csv', sep='|')

まとめ

read_csv関数を使うことで、CSVファイルやTSVファイルだけでなく、任意の区切り文字のファイルも読み込むことができます。

運用上の理由からCSVファイルでは都合が悪いケースもありますので、その場合は任意の区切り文字を使うことを検討してみてはいかがでしょうか。

Poetryを使ってDjangoプロジェクトを作成する

Poetryを使ってDjangoのプロジェクトを作成する方法について解説します。

前提条件

本手順では、現在使用しているPythonの環境にdjangoをインストールしない方法でプロジェクトを作成しています。
公式の手順とは若干手順が異なることに注意してください。

空のプロジェクトを作成する

まずは空のプロジェクトを作成します。
poetry newコマンドで自動で作成されるプロジェクトの構造とDjangoのプロジェクト構造は相性が悪いので、ここでは普通にmkdirコマンドで空のプロジェクトを作成して、プロジェクト内に移動します。

$ mkdir demoapp
$ cd demoapp

ここではdemoappというプロジェクトを作成していますが、実際に作成するときは作成したいプロジェクトの名前で作成してください。

Poetryの初期化を行う

Poetryの初期化を行います。

ここでは必要最低限の設定にしていますが、必要に応じて設定を変更してください。

$ poetry init

This command will guide you through creating your pyproject.toml config.

Package name [demoapp]:  
Version [0.1.0]:  
Description []:  
Author [Taro Yamada <taro.yamada@example.com>, n to skip]:  
License []:  
Compatible Python versions [^3.10]:  

Would you like to define your main dependencies interactively? (yes/no) [yes] no
Would you like to define your development dependencies interactively? (yes/no) [yes] no
Generated file

[tool.poetry]
name = "demoapp"
version = "0.1.0"
description = ""
authors = ["Taro Yamada <taro.yamada@example.com>"]

[tool.poetry.dependencies]
python = "^3.10"

[tool.poetry.dev-dependencies]

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"


Do you confirm generation? (yes/no) [yes] yes

この時点ではDjangoをインストールせず初期化のみ行っています。
これは単にコマンドの方が楽だからという理由だけですので、poetry initコマンド実行時にdjangoをインストールしてもかまいません。

Djangoをインストールする

poetry initをした際に対話的にdjangoをインストールした場合はこの手順を飛ばしてください。

poetry addコマンドでdjangoをインストールします。
執筆時点では4.0.4がインストールされました。

$ poetry add django

インストールするときは-Dオプションをつけずにインストールします。

Djangoプロジェクトを作成する

Djangoプロジェクトを作成します。
以下のdjango-admin startprojectコマンドでDjangoプロジェクトをカレントディレクトリに作成します。プロジェクト名は最初に作成したディレクトリ名と同じ名前(本手順ではdemoapp)を指定します。

$ poetry run django-admin startproject demoapp .

コマンドを実行するときにdjango-adminではなくdjango-admin.pyとすると実行時に例外が発生する場合があります。
私の環境では[Errno 2] No such file or directory: b'/Users/taro/.cargo/bin/django-admin.py'のようなエラーが出力されました(Rustインストール済みの環境です)。

これでDjangoプロジェクトが作成できました。
以降はpoetry run python manage.pyで各種コマンドを実行できるようになります。

Apple Silicon macOSでディープラーニングの環境を構築する(Miniforge使用、Tensorflow、Tensorflow addons導入)

Apple Silicon(M1、M1Max) macOSでディープラーニングの環境を構築する方法について解説します。

本手順は2022/4/1時点のものです。現状ではHomebrewやPyenv等でインストールしたPythonではTensorflowを導入できないようです。この状況も今後変わってくる可能性があります。

Miniforgeのインストール

現状ではMiniforgeを使うのが最も楽な手順のようです。

MiniforgeのGithubサイトからApple Silicon用のインストーラをダウンロードしてください。ファイル名はMiniforge3-MacOSX-arm64.shとなっています。

迷うところはありませんが、念のため応答する箇所について掲載しておきます。

$ bash ~/Downloads/Miniforge3-MacOSX-arm64.sh                                                                                                                                                           

Welcome to Miniforge3 4.12.0-0

In order to continue the installation process, please review the license
agreement.
Please, press ENTER to continue
>>> ← ENTERを押下
Miniforge installer code uses BSD-3-Clause license as stated below.

 ・・・

Do you accept the license terms? [yes|no]
[no] >>> yes ← yesを入力してENTERを押下

Miniforge3 will now be installed into this location:
/Users/t0k0sh1/miniforge3

  - Press ENTER to confirm the location
  - Press CTRL-C to abort the installation
  - Or specify a different location below

[/Users/t0k0sh1/miniforge3] >>> ← ENTERを押下
PREFIX=/Users/t0k0sh1/miniforge3
Unpacking payload ...

 ・・・

Do you wish the installer to initialize Miniforge3
by running conda init? [yes|no]
[no] >>> no ← noを入力してENTERを押下

You have chosen to not have conda modify your shell scripts at all.
To activate conda's base environment in your current shell session:

eval "$(/Users/t0k0sh1/miniforge3/bin/conda shell.YOUR_SHELL_NAME hook)"

To install conda's shell functions for easier access, first activate, then:

conda init

If you'd prefer that conda's base environment not be activated on startup,
   set the auto_activate_base parameter to false:

conda config --set auto_activate_base false

Thank you for installing Miniforge3!

インストールが完了すると、以下のようなメッセージが表示されています。このうち、YOUR_SHELL_NAME部分を書き換えてシェルの設定ファイルに追記します。

eval "$(/Users/t0k0sh1/miniforge3/bin/conda shell.YOUR_SHELL_NAME hook)"

macOSのデフォルトシェルはzshですので、以下のように書き換えて、.zshrcに追記してください。

eval "$(/Users/t0k0sh1/miniforge3/bin/conda shell.zsh hook)"

conda環境の設定を行う

次にconda環境の設定を行います。

conda環境の自動有効化をOFFにする

前述の作業が完了し、再度シェルにログインすると、自動でconda環境が有効になります。これでも問題ない方は以下の設定変更を行う必要はありませんが、そうでない方はconda環境が自動で有効にならないように設定変更をしてください。

$ conda config --set auto_activate_base false

一度conda環境を無効化しておきます。

$ conda deactivate

Tensorflowをインストールする環境を作成する

Tensorflowをインストールする環境を作成しましょう。

執筆時点では、TensorFlow 2.8.0が最新なため、これをインストールします。Tensorflow 2.8.0ではPython 3.9に対応しているため、これを使用します。

$ conda create --name tensorflow28 python=3.9

環境名はなんでも構いませんが、ここではtensorflow28としています。

$ conda create --name tensorflow28 python=3.9                                                                                                                                                           
Collecting package metadata (current_repodata.json): done
Solving environment: done

 ・・・

#
# To activate this environment, use
#
#     $ conda activate tensorflow28
#
# To deactivate an active environment, use
#
#     $ conda deactivate

作成した環境を有効化します。

$ conda activate tensorflow28

以下の手順は作成した環境が有効化されていることを前提に進めます。

Tensorflowをインストールする

作成・有効化した環境にTensorflowをインストールします。

Numpy、OpenCV、Matplotlibをインストールする

Tensorflowをインストールする前にNumpy、OpenCV、Matplotlibをインストールしておいた方がよいようなので、先にconda installコマンドでインストールします。

$ conda install numpy opencv matplotlib

Tensorflowをインストールする

Tensorflowを以下の順番でインストールします。

$ conda install -c apple tensorflow-deps
$ python -m pip install tensorflow-macos
$ python -m pip install tensorflow-metal

Tensorflow addonsのビルド・インストールする

Tensorflowの拡張ライブラリであるTensorflow addonsを使用するためには、Apple Siliconではソースコードからビルドしてインストール必要があります(conda installpip installではうまくいかない)。

ビルドにはbazelが必要なため、まずはこれをインストールします。

$ conda install bazel

次にwheelsetuptoolsが最新でないとビルドに失敗するという報告もあるため、最新化しておきます。

$ python -m pip install --upgrade wheel setuptools

準備が整いましたので、Tensorflow addonsをダウンロードし、ビルドします。

$ git clone https://github.com/tensorflow/addons.git
$ cd addons
$ python ./configure.py
$ bazel build build_pip_pkg
$ bazel-bin/build_pip_pkg artifacts

ビルドが完了すると、artifactsディレクトリの下にファイルが作成されます。

$ ls ./artifacts                                                                                                                                                                                          
tensorflow_addons-0.17.0.dev0-cp39-cp39-macosx_11_0_arm64.whl

作成されていることが確認できましたら、これをインストールします。

$ python -m pip install ./artifacts/tensorflow_addons-0.17.0.dev0-cp39-cp39-macosx_11_0_arm64.whl

これで、TensorflowおよびTensorflow addonsのインストールが完了となります。

参考文献

本手順は以下を参考に作成しました。

[Python]VSCodeでPythonのフォーマッタを設定する(black等のライブラリをPrettierプラグインと共存させる)

Visual Studio Codeで、Python以外はPrettierプラグインを使用し、PythonはPrettierプラグインを使わずにblackを使用する方法について解説します。

共通の設定

Prettierプラグインを有効化するにはeditor.defaultFormatterを設定します。保存時にフォーマットしたいので、editor.formatOnSaveも設定します。

{

  ・・・
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.formatOnSave": true,
  ・・・
 }

Pythonの設定

次にPythonの設定です。PythonではPrettierプラグインを使用せずにblackを使用します。ただし、editor.defaultFormatterの設定が有効な場合、editor.defaultFormatterの方が優先されてしまうため、Pythonではこの設定を無効化(null)します。

以下は、blackを使用するように設定している例です。ここではblackを使用していますが、他のライブラリでも構いません。

{
  ・・・
  "[python]": {
    "editor.defaultFormatter": null
  },
  "python.formatting.provider": "black",
  ・・・

}

上記設定により、PythonだけはPrettierプラグインを使用せず、black等のライブラリを使用できます。

モバイルバージョンを終了