見出し画像

機械学習システムとテスト (1/4)

このシリーズでは機械学習システムにおけるテストについて考えていきます。次の図は DevOps のプラクティスにおいてテストが密接に関わっていることをよく表しています。(図はブログポスト Continuous Testing in DevOps… — Dan Ashby をもとに弊社で作成しました)

システム開発においてテストは必要不可欠なものであり、開発のすべての工程と密接に関わっています。このため、テストを自動化しておき、開発者の環境や CI/CD パイプラインで常に実行するのは近代的な開発において一般的です。

一方、機械学習システムのテストは非常に困難であったり、場合によっては不可能なこともあります。このことはよく知られており、たとえば最近では2021年12月に開かれたNeurIPS Data-Centric AI Workshopのセッションのひとつである Technical Debt in ML: A Data-Centric View — Data-centric AI Resource Hub でも言及されています。

機械学習システムをテストするのはなぜこんなにも難しいとされるのでしょうか。また、品質の高いものとするために、我々はどのようにすれば機械学習システムをテストできるでしょうか。

このシリーズではこれらの問いに答えていくことを目指します。最初に機械学習システムのテストが困難になる理由を考え、その後、サンプルとなる機械学習パイプラインを例に具体的なテスト項目について検討します。このシリーズの目次を次に示します。

  • 1回目: 機械学習システムのテストの難しさ

  • 2回目: 機械学習システムの単体テスト

  • 3回目: 機械学習システムのコンポーネントのテスト

  • 4回目: 機械学習システムのシステムテストと品質

まずは機械学習システムのテストが難しい理由について考えていきましょう。

機械学習システムのテストの難しさ

機械学習システムのテストを困難にする理由について考えるために、まずは通常のソフトウェア開発で用いられるテストの手法について改めて確認します。その後、それらの手法が機械学習システムで適用可能かどうか考えていきましょう。

通常のソフトウェア開発におけるテスト

通常のソフトウェア開発のテストについて確認するために、「数字を入力するとその桁数を返す」というかんたんなプログラムのテストを想定し、テスト項目を考えましょう。

まずはテストの観点について検討します。システムに要求される要件や品質からテスト観点を設計します。「整数を入力するとその桁数を返す」という機能要件とともに、結果を返すまでの時間などの非機能要件についても合わせて検討し、テスト観点の一覧を作成します。

次に、テスト観点の一覧から実際にテストを行うテスト項目について設計します。テスト項目はシステムへの操作と、それを行ったときに期待される振る舞いをあわせて定めます。

システムの操作では実際に入力する値を定めます。入力値はたとえば “10” や “0” といった値のほか、”-1" や非常に大きな値や小さな値についても検討します。また、小数点を含めた数字や、数字以外のアルファベットについてもテストすべきか定めます。

これらの入力値に対し、システムのあるべき振る舞いを定めてテストケースとします。

最後に、定めたテストについて妥当性を評価します。評価方法としてはさまざまなものがありえますが、ここでは入力パターンのカバレッジとソースコードのカバレッジという2点についてとりあげます。

入力パターンのカバレッジでは、同じような振る舞いを期待できる入力パターンを洗い出し、作成したテストケースがそれらのパターンを網羅しているか評価します。

テスト一般に言えることですが、すべての入力可能な値についてテスト項目を列挙しテストすることは不可能です。一方、似たような入力をしたときには似たような結果を返すことを期待するのは一般的です。たとえば、”11" を入力して “2” が正しく出力されたとき、あらためて “12” を入力しテストする必要は薄いでしょう。

このため、あり得る入力について「正の値」「負の値」「アルファベット(異常な入力)」などのパターンに分割し、それらの中の代表例や境界となる値 (1, 0, -1 など) についてテストケースを設計します。入力パターンのカバレッジの評価は作成したパターンの網羅とともに、その入力の分割の妥当性についても確認することになるでしょう。

ソースコードのカバレッジでは、作成したテストケースを入力した際に、ソースコードが実行される場所の割合を評価します。たとえば、次のように桁数を返すプログラムで正の値と負の値で実装を変えている場合では、”1" を入力するだけではコードの半分しか実行されません。

残りの箇所を実行した際にエラーが発生しないことを確認するためには、”-1" を入力する必要があります。

通常のソフトウェア開発のテストではこのように「テスト観点の設計」「テスト項目の設計」「妥当性の評価」という3つの取り組みが存在します。テストは非常に奥深い分野で、探索的なテストや特定の環境でのテストなどさまざまな手法が存在します。もし興味があれば調べてみると良いでしょう。

機械学習システムにおける「テスト項目の設計」と「妥当性の評価」の困難さ

次に、機械学習システムにおけるテストを検討しましょう。どのようにすれば次のようなコードをテストできるでしょうか?

機械学習システムにおけるテストでは、「テスト観点の設計」「テスト項目の設計」「妥当性の評価」のうち「テスト項目の設計」と「妥当性の評価」が困難になります。これらについて見ていきましょう。

なお、以降では機械学習の訓練や推論の実装をアルゴリズム、訓練の結果できあがる個々のものをモデルと呼び、区別します。

まず、機械学習システムにおいては「テスト項目の設計」が非常に困難です。

先程見たように、ありえる入力をパターンに分割し、それらの境界値をテストケースとして用いることは非常に困難になります。たとえば、画像認識を行う機械学習モデルをテストするために「猫の画像」や「犬の画像」を収集することはできますが、「猫と犬の境界となる画像」については定義することが非常に困難です。

もし仮に境界となるデータを得る方法が論理的に記述できるのならば、その課題は機械学習を用いなくても解決することができるでしょう。

次に、妥当性の評価において、何らかの意味でのカバレッジを定義することが非常に困難です。

まず、コードのカバレッジはあまり意味をなさない指標になります。

他のシステム開発と同じく、機械学習システムにおいて機械学習を行うアルゴリズムをフルスクラッチで書くことはまれです。大半はライブラリの利用や既存のアルゴリズムを流用して利用することになります。その結果、機械学習においてモデルの訓練や推論を行うためのコードは典型的には非常に短くなります。

一方、機械学習システムの実際の振る舞いはコードだけではなくデータに大きく依存するため、短いコードであっても複雑な振る舞いを示しえます。このため、小さなサンプルデータでカバレッジを確認しただけでは実際のモデルの振る舞いは保証できません。

また、入力パターンのカバレッジを担保することも非常に困難です。

一部の解釈しやすいアルゴリズムを除き、機械学習モデルはブラックボックスとなりがちです。このため、データを抜きにアルゴリズムを解析したり、学習済みのモデルを解析することで、同じような振る舞いをする入力パターンを洗い出すことは困難です。

また、機械学習モデルは非線形な振る舞いをすることがあり、少しの入力の変化であっても出力結果は大きく変わることがあります。たとえば、画像認識においては、入力画像に人間には判別しにくいノイズを加えることで機械学習モデルを意図的に騙す手法が存在します。これは Adversarial Examples として知られています。次はその例です。

Adversarial Example のデモ (ブラウザで試せます)

機械学習モデルがこのような非線形な振る舞いを示すことは特定のアルゴリズム固有のものではなく、古くから知られています。この性質のため、入力パターンを事前に定義することも、ある入力を行ったときに確認済みだとできる範囲を事後的に定めることも、共に困難です。

機械学習システムにおける「テスト観点の設計」

ここまでに機械学習システムのテストにおいて「テスト項目の設計」と「妥当性の評価」の困難さについて見てきましたが、「テスト観点の設計」にはある程度取り組みが進んでいると言えます。

たとえば、QA4AI ではAIプロダクト品質保証ガイドラインを発表しています。この中では機械学習システムの品質を考える上で指針となる5つの観点が示されているほか、自動運転や AI-OCR といった具体例を用いてそれぞれの観点について考慮すべき事項が紹介されています。

このようなガイドラインは公共団体を含め、さまざまな団体が発表しているため、機械学習システムの品質について検討すべき観点は徐々に明らかになってきています。一方、それぞれの観点を個々のシステムに適用し、品質を保証する手段は現場の開発者に委ねられています。機械学習を扱うエンジニアにはこれらの観点を理解し、具体的なテスト観点やテスト項目に落とし込む技量が求められていると言えるでしょう。

次回予告

今回は機械学習システムのテストが困難な理由について見てきました。では、機械学習システムのテストについて、我々は一体何ができるのでしょうか。次回以降では、機械学習パイプラインのサンプルを元に、さまざまな粒度でのテストについて具体的に検討します。


いいなと思ったら応援しよう!