💭

DDDに則った機械学習テンプレを考えてみた

に公開

はじめに

ドメイン駆動設計(DDD: Domain-Driven Design) の原則に従って構築された、機械学習モデルの実験管理用Pythonコードを作成してみました。

MLの実験から実運用へアプリ化する過程で、最初からある程度作られていると大きな障壁なくスムーズに変更できるなと思い、最初の叩き台として利用できることを目的としております。

また、MLモデルのライフサイクルや実験履歴を明確なドメインモデルで表現することで、拡張性と保守性を高めることができます。

GitHubにテンプレートを公開しております(こちら)。

DDDとは

DDDは、ソフトウェアをビジネスの本質に即して設計するアプローチです。複雑な業務ロジックを「ドメイン」として捉え、専門家との共通言語(ユビキタス言語)を中心に設計を進めます。関心ごとを分離しやすく、保守性や拡張性に優れた構造を実現できます。特に大規模システムや変化の多い領域で効果を発揮します。

機械学習モデルはビジネスロジックに関わることが多く、DDDと親和性が高いかと感じております。
本記事では、機械学習の実験コードにDDDの考え方を取り入れる方法を紹介します。

https://little-hands.hatenablog.com/entry/2018/10/08/goal-of-ddd

アーキテクチャ紹介

アーキテクチャは、オニオンアーキテクチャをベースに構成しています。構成がシンプルで、依存関係を明確に整理しやすいため、この方式を採用しました。

以下に、アーキテクチャの概要図を示します。

アーキテクチャ図

このアーキテクチャのポイントは2点です。

  1. 依存関係が図の上から下のみに制御されている点
    重要なロジックであるモデルや実験が他の層に依存しておらず、下位層(ドメイン)が上位層(アプリケーション、インターフェイス)に依存しない構造となっています。これにより、コードの変更に対して堅牢でありながら、柔軟に対応できる設計となっています。また、ビジネスロジックをドメイン層に集約できるため、テンプレートとしての汎用性も高いと考えています。
  2. MLモデルやリポジトリなどの具体的なロジックを切り出している点
    ドメイン層にインターフェイスを定義することで、MLモデルやリポジトリの実装はインフラストラクチャ層に切り出されており、アプリケーション層やドメイン層はそれらの具体実装に依存しない形で記述できます。これにより、システム全体の拡張性・再利用性が高まり、保守性も向上しています。

構成

ここからはコードの中を紹介します。

ディレクトリ構成を示します。


src/ 
├── domain/
    ├── model.py # モデルエンティティ(Model)
    ├── ml_model.py # MLモデルのインターフェイス(MLModel) 
    ├── experiment.py # アグリゲートルート(Experiment) 
    ├── domain_services.py # ドメインサービス(Trainer, Predictor) 
    ├── data.py # 入力データの構造(TemplateTrainData)
    ├── repository.py # 永続化インターフェース(ModelRepository, DataRepository)
├── application/
    ├── aplication_service.py # アプリケーションサービスの実行
    ├── template_service.py # 各種アプリケーションサービス(TemplateService)
├── infrastracture/
    ├── template_repository.py # リポジトリの実装クラス(TemplateModelRepository, TemplateDataRepository)
    ├── ml_model.py # MLモデルの実装クラス(TemplateMLModel)
└── cli.py # 実行コマンド

各層の説明

各層に配置しているクラスの概要を説明します。

ドメイン層

機械学習システムの中核となるドメイン層のクラス群について解説します。MLModel や Model をはじめとしたクラスは、ビジネスロジックを担い、アプリケーション層やインフラ層からの独立性を保ちながら機械学習に関わる処理を構築しています。集約ルートとなる Experiment や、ドメインサービスである Trainer・Predictor の役割にも触れます。

クラス 概要
MLModel ・機械学習モデルのインターフェイス
・システム内での入出力を制御することで、機械学習ロジックへの依存を軽減している
Model ・モデルのエンティティ
・作成日時やパラメータ情報を持つ
Experiment ・集約クラスであり、ドメインの実行単位となる
・実験情報、Model、Dataを扱う
TemplateTrainData ・データの値オブジェクト
・ビジネスドメインに合わせた定義を行う
ModelRepository, DataRepository ・リポジトリのインターフェイス
・利用するストレージサービスによらず扱うことができる
Trainer, Predictor ・ドメインサービス
・エンティティの重要なロジックを扱う
・モデルの学習・推論のロジックを記述している

アプリケーション層

ユースケース単位の処理を担うアプリケーション層について解説します。ApplicationService は、ドメインロジックを活用するためのインターフェイスであり、直接的な処理は行わず、責務を他の層に委ねます。また、ApplicationServiceHandler を通じて依存関係を組み立て、実行単位としての役割を果たします。

クラス 概要
ApplicationService ・アプリケーションのインターフェイス
・実装クラスではユースケースごとに作成する
・ロジックは記述せず、ドメインとインフラストラクチャから呼び出し、処理を行う
AplicationServiceHandler ・アプリケーションの実行クラス
・各クラスの依存管理と実行の役割を持つ

インフラストラクチャ層

外部リソースとの連携を担当するインフラストラクチャ層について解説します。TemplateModelRepository や TemplateDataRepository などの実装クラスにより、リポジトリの実体を定義し、ストレージに依存しない設計を可能にします。さらに、TemplateMLModel クラスでは、実際の機械学習モデルのロジックを実装します。

クラス 概要
TemplateModelRepository, TemplateDataRepository ・各リポジトリの実装クラス
TemplateMLModel ・モデルの実装クラス
・機械学習モデルのロジックを記述する

まとめ

この記事では、DDD(ドメイン駆動設計)を取り入れた機械学習システムの設計について考えてみました。今後は評価サービス ModelEvaluator の追加やMLflowやDVCと連携したリポジトリ実装をしてみたいと考えています。

Gitにテンプレートを公開(こちら)しているため、ご参考ください。

何か気になる点がありましたら、お気軽にコメントをもらえると嬉しいです。

ここまで読んでくださり、どうもありがとうございました。

参考文献

https://www.shoeisha.co.jp/book/detail/9784798131610

https://www.shoeisha.co.jp/book/detail/9784798126708

https://www.shoeisha.co.jp/book/detail/9784798150727

https://zenn.dev/sigmai_tech/articles/0c092c02b9a833#手段%3A-ソフトウェア設計手法

https://little-hands.hatenablog.com/entry/2018/10/08/goal-of-ddd

Discussion