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は、より強力に、そしてよりスケーラブルに進化していくことでしょう。

📚 参考文献

pipxでPoetryをインストールする

公式サイトでのPoetryのインストール方法の一つにpipxを使ったインストール方法があって、それが気になったので、pipxを導入してPoetryをインストールしていこうと思います。手順はmacOSの場合になります。

pipxのインストール

Homebrewを使ってpipxをインストールします。

$ brew install pipx
==> Downloading https://formulae.brew.sh/api/formula.jws.json
##O=-#      #
==> Downloading https://formulae.brew.sh/api/cask.jws.json
##O=-#      #
==> Downloading https://ghcr.io/v2/homebrew/core/pipx/manifests/1.3.3
Already downloaded: /Users/t0k0sh1/Library/Caches/Homebrew/downloads/af94290372652b3f23470aa9b2dc3e6cc6f6ac908d786fa0b2ccf9c0f53db957--pipx-1.3.3.bottle_manifest.json
==> Fetching pipx
==> Downloading https://ghcr.io/v2/homebrew/core/pipx/blobs/sha256:31547c41734fa46c13276ada25e3e8548db97281d0c513b9cdcb5268adcc74ff
Already downloaded: /Users/t0k0sh1/Library/Caches/Homebrew/downloads/a4c05e49cf7f84a6647e146f9d68d9983028ea48180d87771a41cdb1f5d27b45--pipx--1.3.3.arm64_sonoma.bottle.tar.gz
==> Pouring pipx--1.3.3.arm64_sonoma.bottle.tar.gz
==> Caveats
zsh completions have been installed to:
  /opt/homebrew/share/zsh/site-functions
==> Summary
🍺  /opt/homebrew/Cellar/pipx/1.3.3: 108 files, 697.7KB
==> Running `brew cleanup pipx`...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).

インストール後、pipx ensurepathコマンドを実行します。

$ pipx ensurepath
Success! Added /Users/t0k0sh1/.local/bin to the PATH environment variable.

Consider adding shell completions for pipx. Run 'pipx completions' for instructions.

You will need to open a new terminal or re-login for the PATH changes to take effect.

Otherwise pipx is ready to go! ✨ 🌟 ✨

上記メッセージ中に、

You will need to open a new terminal or re-login for the PATH changes to take effect.

とあるので、新しいターミナルを開くかログインし直す必要があります。今回はこのままインストールを進めたいので、設定ファイルを読み込み直します。

$ exec $SHELL -l

これでインストールは完了です。

activate-global-python-argcompleteのlinkでエラー

Homebrewでインストールする際に以下のエラーに遭遇しました。

Error: The `brew link` step did not complete successfully
The formula built, but is not symlinked into /opt/homebrew
Could not symlink bin/activate-global-python-argcomplete
Target /opt/homebrew/bin/activate-global-python-argcomplete
already exists. You may want to remove it:
  rm '/opt/homebrew/bin/activate-global-python-argcomplete'

To force the link and overwrite all conflicting files:
  brew link --overwrite python-argcomplete

To list all files that would be deleted:
  brew link --overwrite --dry-run python-argcomplete

事象としては、activate-global-python-argcompleteのsymlinkに失敗したようです。解消方法としてはいくつかありますが、ここでは一番最初に書かれている/opt/homebrew/bin/activate-global-python-argcompleteを削除する方法で進めます。

指示どおりに対応してきます。まずは、activate-global-python-argcompleteが存在するかをチェックします。

$ ls /opt/homebrew/bin/activate*
/opt/homebrew/bin/activate-global-python-argcomplete

存在していることを確認できました。これを削除します。

$ rm /opt/homebrew/bin/activate-global-python-argcomplete
$ ls /opt/homebrew/bin/activate*
zsh: no matches found: /opt/homebrew/bin/activate*

削除されたことを確認しました。では、元の手順に戻って、再度pipx installコマンドを実行します。

Poetryをインストールする

pipxを使ってPoetryをインストールします。

$ pipx install poetry
  installed package poetry 1.7.1, installed using Python 3.12.1
  These apps are now globally available
    - poetry
⚠️  Note: '/Users/t0k0sh1/.local/bin' is not on your PATH environment variable. These apps will not be globally accessible until your PATH is updated. Run `pipx ensurepath` to automatically add it, or
    manually modify your PATH in your shell's config file (i.e. ~/.bashrc).
done! ✨ 🌟 ✨

インストール後、コマンドが使えるようになっていることを確認します。

$ poetry -V
Poetry (version 1.7.1)

これでPoetryのインストールは完了しました。

まとめ

pipxのインストールで少しトラブルがありましたが、比較的簡単にインストールを進めることができました。

PYthon製のCLIをインストールする際は、pipxを使っていくのが良さそうです。

mambaを使ってパッケージのインストールを高速化しよう(conda installの高速化)

conda installを何気なくやるとかなり待たされることがあります。この待ち時間を減らすためにはmambaを使用することが解決策の一つとなります。

インストールが全然始まらない

pandasparquetを扱いたくてconda installpyarrowをインストールしようとしましたが、インストールが全然始まりませんでした。

 $ conda install pyarrow
Collecting package metadata (current_repodata.json): done
Solving environment: failed with initial frozen solve. Retrying with flexible solve.
Solving environment: failed with repodata from current_repodata.json, will retry with next repodata source.
Collecting package metadata (repodata.json): | WARNING conda.models.version:get_matcher(546): Using .* with relational operator is superfluous and deprecated and will be removed in a future version of conda. Your spec was 1.8.0.*, but conda is ignoring the .* and treating it as 1.8.0
WARNING conda.models.version:get_matcher(546): Using .* with relational operator is superfluous and deprecated and will be removed in a future version of conda. Your spec was 1.9.0.
*, but conda is ignoring the .* and treating it as 1.9.0                                                                                                                           done
Solving environment: failed with initial frozen solve. Retrying with flexible solve.
Solving environment: |

conda installに時間がかかる原因としては以下が考えられます。

  1. 依存関係の解決: condaはパッケージの依存関係を非常に厳格に解決します。そのため、多くのパッケージや複雑な環境でのインストールでは、この解決プロセスが時間を要することがあります。
  2. サーバーの応答速度: 利用しているcondaのリポジトリサーバーの応答速度やネットワークの状態によっては、パッケージのダウンロードに時間がかかることがあります。
  3. インストールするパッケージのサイズ: 大きなパッケージや多数のパッケージをインストールする場合、当然ダウンロードやインストールに時間がかかります。

この問題を解決するためには以下のような対策が考えられます。

  • 特定のチャンネルを指定
  • mambaの利用
  • 環境を最小限に保つ
  • パッケージキャッシュのクリア

今回はこの中から、お手軽で高い効果のある「mambaの利用」を適用していきます。

mambaのインストール

まずはmambaをインストールします。

conda install -c conda-forge mamba

conda installにかかる時間を減らす一つのテクニックとしてチャネルを指定する方法があります。ただ、mambaをチャネル指定なしでインストールしてもそれほど時間がかからなかったので、チャネル指定がなくても大丈夫だと思います。

他にチャネルの指定する方法はあるので、conda-forgeへのリンクを貼っておきます。

condaのキャッシュをクリアする

念のためcondaのキャッシュをクリアしておきます。

$ conda clean -a
Will remove 411 (631.3 MB) tarball(s).
Proceed ([y]/n)? y

Will remove 1 index cache(s).
Proceed ([y]/n)? y

Will remove 83 (826.7 MB) package(s).
Proceed ([y]/n)? y

There are no tempfile(s) to remove.
There are no logfile(s) to remove.

何度か質問されるのでいずれの質問にもyを回答します。

mambaを使ってインストールする

では先ほど全然インストールが始まらなかったpyarrowmambaでインストールしていきます。

$ mamba install pyarrow 

Looking for: ['pyarrow']

conda-forge/osx-arm64                                6.7MB @  13.6MB/s  0.5s
conda-forge/noarch                                  12.4MB @  23.9MB/s  0.5s

・・・

Confirm changes: [Y/n] y

・・・

Downloading and Extracting Packages

Preparing transaction: done
Verifying transaction: done
Executing transaction: done

処理時間が格段に短くなるものそうですが、待ち時間が短縮されるので体感的にも早く感じられ、ストレスが軽減されるのがよいですね。

まとめ

データ分析や機械学習の作業でcondaを使ってインストール作業を行う場合はmambaコマンドを使った方が素早く作業を進められます。

外部プログラムをインストールする訳ではなく、conda installmambaをインストールできるので、ノックアウトファクターがほぼないので是非試してみてください。

[Pandas]代表値を求める(平均値、中央値、最頻値)

一般的によく知られている代表値といえば、平均値(mean)、中央値(median)、最頻値(mode)です。

Pandasを使ってこれらの値を求めてみます。

下準備

今回はTitanicデータセットから年齢(Age)を使用します。

import pandas as pd
import math

df = pd.read_csv('./titanic/train.csv')

平均値を求める

平均値を求めるにはmean()を使用します。

# 平均値(mean)を求める
df['Age'].mean()
# -> 29.69911764705882

中央値を求める

中央値を求めるにはmedian()を使用します。

# 中央値(median)求める
df['Age'].median()

最頻値を求める

最頻値を求めるには一工夫が必要です。最頻値は最も大きい度数の階級値になるため、一旦度数分布表を作成します。

ヒストグラムを確認する

度数分布表を作成する前にヒストグラムを確認しておきましょう。

df['Age'].hist(bins=10)

ビンの数を10に設定してヒストグラムを作成すると、20代が最頻値のようだということがわかります。

最頻値を求める

視覚的に確認できたところで、最頻値を求めます。度数分布表の作成方法はいくつかありますが、ここでは簡易的にcut()value_counts()を組み合わせて、先ほど確認したグラフと同じ区間で度数分布表を作成します。

# 度数分布表を作成する
pd.cut(df['Age'], 10).value_counts()
---
(16.336, 24.294]    177
(24.294, 32.252]    169
(32.252, 40.21]     118
(40.21, 48.168]      70
(0.34, 8.378]        54
(8.378, 16.336]      46
(48.168, 56.126]     45
(56.126, 64.084]     24
(64.084, 72.042]      9
(72.042, 80.0]        2
Name: Age, dtype: int64

作成した結果を確認しても20代が最頻値のようです。最頻値は区間の最小値と最大値の中間になりますので、$24.294-(24.294-16.336)\div2=20.315$となります。

データバージョン管理ツール「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で日付項目を日付型として扱う

Pandasで日付項目をdatetime[ns]型に変換し、日付型として扱う方法について解説します。

日付項目を読み込む

次のCSVファイルを特にオプションを指定せずに読み込みます。

date1        ,date2      ,date3     ,date4   ,date5     ,date6   ,date7
2020年12月31日,2020年6月9日,2020-12-31,2020-6-9,2020/12/31,2020/6/9,20201231

このファイルには4種類(うち3種類は0埋めありとなしの2パターン用意)の日付項目が設定されています。

import pandas as pd
df = pd.read_csv('test.csv')

各項目がどの型で読み込まれているかinfo関数で確認します。

df.info()

yyyymmdd形式はint64型、それ以外はobject型(str型)で読み込まれているのがわかります。

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1 entries, 0 to 0
Data columns (total 7 columns):
 #   Column  Non-Null Count  Dtype 
---  ------  --------------  ----- 
 0   date1   1 non-null      object
 1   date2   1 non-null      object
 2   date3   1 non-null      object
 3   date4   1 non-null      object
 4   date5   1 non-null      object
 5   date6   1 non-null      object
 6   date7   1 non-null      int64 
dtypes: int64(1), object(6)
memory usage: 184.0+ bytes

日付型に変換する

日付項目を加工したり、年・月・日などを取り出しやすくするために、datetime64[ns]型に変換しておくと便利です。

datetime64[ns]型に変換するには、pandas.to_datetime関数を使います。

df['datetime1'] = pd.to_datetime(df['date1'], format="%Y年%m月%d日")
df['datetime2'] = pd.to_datetime(df['date2'], format="%Y年%m月%d日")
df['datetime3'] = pd.to_datetime(df['date3'])
df['datetime4'] = pd.to_datetime(df['date4'])
df['datetime5'] = pd.to_datetime(df['date5'])
df['datetime6'] = pd.to_datetime(df['date6'])
df['datetime7'] = pd.to_datetime(df['date7'], format="%Y%m%d")

年月日形式の項目はformatオプションを指定しないとエラーになります。また、yyyymmdd形式はエラーにはなりませんが、値をナノ秒と見なして読み込むため、1970-01-01 00:00:00.020201231のような値になってしまいます。こちらもformatオプションの指定が必要です。

読み込み時に 日付型に変換する

読み込んでみてから、「あ、これ日付項目か」と気づく場合は前述の方法を使っていただければよいですが、事前にどれが日付項目かわかっている時は読み込む時に日付型として読み込む方が効率的です。

標準の日付パーサーで変換できる場合

yyyy-mm-dd形式やyyyy/mm/dd形式、yyyymmdd形式の場合は標準の日付パーサーで変換できます。

次のような形式の CSVファイルの場合、

date    ,average
2021/8/1,28.7
2021/8/2,28.6
2021/8/3,29.0
2021/8/4,29.5
2021/8/5,29.1
2021/8/6,29.1
2021/8/7,27.9

以下のようにすることで、項目dateを日付datetime64[ns]型で読み込むことができます。

df = pd.read_csv('weather.csv', 
                 dtype={"date": str},
                 parse_dates=["date"])
df.info()

直接dtypedatetime64を指定するのではなく、一旦dtypeオプションではstr型を指定して、parse_datesオプションで日付型にしたい項目を指定して変換するというやり方になります。

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 7 entries, 0 to 6
Data columns (total 2 columns):
 #   Column    Non-Null Count  Dtype         
---  ------    --------------  -----         
 0   date      7 non-null      datetime64[ns]
 1    average  7 non-null      float64       
dtypes: datetime64[ns](1), float64(1)
memory usage: 240.0 bytes

日付パーサーを自作して変換する場合

年月日形式などPandasが用意している標準の日付パーサーで変換できない場合は日付パーサーを自作して指定することで日付変換ができるようになります。

次のようなCSVファイルの場合、

date,       average
2021年8月1日,28.7
2021年8月2日,28.6
2021年8月3日,29.0
2021年8月4日,29.5
2021年8月5日,29.1
2021年8月6日,29.1
2021年8月7日,27.9

先ほどと同じコードで読み込むと、エラーは発生しませんが、datetime64[ns]型には変換されません。

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 7 entries, 0 to 6
Data columns (total 2 columns):
 #   Column    Non-Null Count  Dtype  
---  ------    --------------  -----  
 0   date      7 non-null      object 
 1    average  7 non-null      float64
dtypes: float64(1), object(1)
memory usage: 240.0+ bytes

このような場合は、日付パーサーを自作し、date_parserオプションで指定します。

from datetime import datetime
my_parser = lambda date: datetime.strptime(date, '%Y年%m月%d日')
df = pd.read_csv('weather.csv', 
                 dtype={"date": str},
                 parse_dates=["date"],
                 date_parser=my_parser)
df.info()

先ほどとは異なり、datetime64[ns]型に変換されていることが確認できます。

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 7 entries, 0 to 6
Data columns (total 2 columns):
 #   Column    Non-Null Count  Dtype         
---  ------    --------------  -----         
 0   date      7 non-null      datetime64[ns]
 1    average  7 non-null      float64       
dtypes: datetime64[ns](1), float64(1)
memory usage: 240.0 bytes

pandas.datetime.strptimeを使用するサンプルを見かけると思いますが、pandas.datetimeは将来的に削除される予定ですので、今後はdatetimeを使用しましょう。
/var/folders/3r/qfsmvnsd5sz0qvf367p_d5j00000gp/T/ipykernel_83309/1860031930.py:1: FutureWarning: The pandas.datetime class is deprecated and will be removed from pandas in a future version. Import from datetime module instead.
my_parser = lambda date: pd.datetime.strptime(date, ‘%Y年%m月%d日’)

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等のライブラリを使用できます。

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