日本ソフトウェア科学会第 35 回大会 (2018 年度) 講演論文集

型チェックのアノテーションによる保守・運用の改善
橋本 順之

動的型付け言語で行列やテンソルの次元やデータ型をコード中にアノテーションとして付与し検証をする方法を提案
する．機械学習のソフトウェアの保守運用の効率化のため API や関数のインターフェースのチェックをし，レビューしやすいコードにすることが必要である．しかし，行列やテンソルの型や次元の検証は難しいという問題がある．このことについても論じる．本提案により関数やブロック単位で検証可能なインターフェースのコードを追加し，問題の改善を行う．

け言語に比べコンパイルに時間がかかる傾向があり，

1 はじめにコーディングと実行の繰り返しを頻繁に行い開発する

1. 1 目的ケースでは動的型付け言語のほうが優位であろうと機械学習ソフトウェアの検証は難しく保守運用を推測される．開発者が完全に利用しているライブラリ

困難にしている状況を考察し，問題を確認する．問やコードを理解している限りにおいてこの利点は強題の改善のために API や関数のインターフェースの調される．

チェックをし，レビューしやすいコードにすることが一方保守運用では状況は変わる．運用は日々同じ必要である．しかし，行列やテンソルの型や次元の検ソフトを動作させ，機械的な故障や平常時よりたま証は難しいという問題がある．本提案は関数やブロッたま多いデータや不正なデータがくることにより，期ク単位で行列やテンソルの型や次元について検証可待する動作をしない場合に，問題の原因を切り分け，能なコードをコメントとして記述し，それを検証する

一次対応のため問題を一時的に手作業で取り除きソことで問題の改善する行うことを目的としている．

フトを再実行をするなど，その場限りの対処を行い，そのしばらく後に恒久対応として不具合を修正する．

1. 2 機械学習ソフトウェアの特性と保守運用の問
題確認
以下で機械学習ソフトウェアと保守運用で抱えている問題について確認をする．

保守はソフトの機能の向上，セキュリティ上の要件，ハードウェアや OS の切り替えの必要性により，利用するライブラリや処理系のバージョンをあげたり，その結果本来の機能が動作しない場合の修正する

機械学習ソフトウェアは研究目的やアルゴリズムの作業がある．その作業の前後で同じ動作をすること開発に重点を置いているため，開発速度を優先し動的が期待されるが，関数名の変更や仕様そのものの変型付け言語が好まれる傾向がある．特に深層学習では更があり，実際にはうまくいかないので，不整合がその傾向は顕著である．静的型付け言語は動的型付起こる原因を特定する必要がでてくる．こちら [2] にTensorflow のバージョンアップに必要な項目がある
Using type annotations to improve maintenance andoperations.
Junji Hashimoto, グリー株式会社, Service Installation
2 Team, GREE, Inc..

が関数の名前の変更や処理系により浮動小数点の挙動の違いもありバージョンアップは容易な作業ではない．しかし，開発時と同様のリソースをかけることができないので効率的な解決が求められる．

素にアルゴリズムを記述するのに便利なものの意図

保守及び運用で問題の箇所の特定にはデバッグ手法せぬ記述をした場合に脆弱である．例えば，ベクトルが適用が有効である．デバッグは問題の種類の特定すとベクトルを足すべき演算で，誤って片方のベクトルる．アルゴリズムのバグか，データのバグ（データににスカラをいれてしまっても間違いに気づくことはで本来予期していないものがある場合），リソースのバきない．スカラやベクトルだけでなくテンソルといっグ（メモリリーク）か切り分ける．次に問題の場所をた高次元のデータでは問題は深刻なものになる．

特定するために分割統治法で問題のコードの場所を保守運用だけでなく開発では後の行程ほど費用が特定し，原因を注意深く観察しコードを直して問題がかかる．学習のモデルの作成が数日でできたとして改善するかチェックし，問題の解決を行う．

も, モデルのトレーニングには数週間かかることもあ

運用や保守では開発者ではない第 3 者がコードレり，後の行程になるほど開発の手戻りの時間や費用がビューを行うことが多く，変更の影響が把握できるレ大きくなる．デバッグのために高速かつ多数のハードビューしやすいコードが重要である．静的型付け言語

ウェアを投入するのも限界がある．

では入力と出力のデータが一目でわかるように記述

API やインターフェースの検証が困難なことによ可能であるが，動的型付け言語では関数やドキュメンり保守運用が困難という問題に対して，レビュー可能

トを読むだけで動作を予測することが困難であり，どなように関数やインターフェースを記述し修正結果がのような入出力を期待しているかはコードの中を読容易に妥当であるかどうか容易にチェックできるようむ他はなく、API やインターフェースの検証が困難にすることが保守運用のために必要である．

である．

IT システムのソフトウェアではクラスをデータの1. 3 改善のための問題確認単位とするため，Java や Python [5] がもつ型システ

機械学習ソフトウェアの扱う行列やテンソル型のムによってデータの不整合を検知しやすいが，機械学検証は困難でソフトウェアのインターフェースの検証

習ソフトウェアは型で簡単に解決できない．機械学習が難しいという問題があるが，ライブラリと保守対ソフトウェアは行列やテンソルの数値計算を主に行う

象のコードついて以下の問題に絞り，改善手法を提案傾向があるが，静的型付け言語であっても整数や浮動する．

少数点の型のチェックは行えても，行列やテンソルの次元のチェックは行えないため，学習のデータやモデルの検証が困難という問題がある．

• ライブラリ– API のバージョンアップによる非互換を機械的にチェックできない．

機械学習のソフトウェアは多数かつ高次元のデー– API のインターフェースの仕様が容易にわタ（ベクトルやテンソル）を扱う．IT システムのソからない．ドキュメントやコードを精読する

フトウェアと違いフラットなデータ構造であり次元の他にわからない．

異なるデータを扱うことが多く，クラスの中に小さいクラスを多数含むようなデータ構造を機械学習への入力のソースとして使うことはない．機械学習のソフ
トウェアはベクトルやテンソルを扱うため型システムで十分なチェックができない．例えば，Java などが– ドキュメントとコードの動作の不一致があっても検出できない．

• 保守対象のコード– コードの関数・ブロック単位でのレビューが難しい．

もつ型システムはベクトルの長さをチェックしない．

これらの原因として考えているものは次の点である。

Python では動的型付け言語の利点を生かして，スカ• 動的型付け言語を使用している．

ラの通しの演算，ベクトル通しの演算，スカラとベク• ブロックや関数の入出力の型が必ずしも記述さトル混在の演算に対して， + や - のようなシンプルな演算子を流用できる．開発時にはこの特徴は簡れていない．

• 行列やテンソルの次元のチェックが難しい．

2. 2 型のアノテーションによる改善2 関連研究

静的型付け言語である Java だけでなく，動的型付

2. 1 依存型による改善

け言語の Python や Javascript において Mypy [5] や行列やテンソルの次元を検証する方法として，静Typescript [6] といった型のアノテーションを付与し的型付け言語を用いるケースで依存型を用いた型シデータの型を検証する方法がある．これらはデータ型

ステム [3] でテンソルの次元を管理する手法 [4] があの不整合を検出するのに役に立ち IT システムのソフる．テンソルの次元（数字のリスト）を型として扱いトウェアではクラスをデータの単位とするため有用で入出力の次元を定義することができる．依存型を用ある．

いた型システムの例を Haskell の疑似コードでソース

動的的型付け言語でも Python2 から Python3 へのコード 1 に示す．入力する行列の型に具体的な数字アップデートの例 [1] のように API のインターフェーを明記し，演算結果の型と不整合がないことをコンパ

スに型を利用することは有用である．

イラが検証する．

Mypy [5] で型を記述した例をソースコード 2 に示
す．整数型 (int) やクラス型 (np.ndarray) は扱える

ソースコード 1依存型を用いた疑似コード−− 7 行 列 の 型 ( i と o に は 数 字 が 入 る )data Weights i o : : Nat −> Nat −>∗ where( : ∗ ) : : KnownNat h=> ! ( Weights i h )−> ! ( Weights h j )−> ! ( Weights i j )i h : : Weights 10 7−− 7 x 4 行 列 の 型
hh : : Weights 7 4−− 4 x 2 行 列 の 型
ho : : Weights 4 2−− i h x hh x h o の 行 列 の 演 算 を し ，−− 10 x 2 行 列 の 型 と な る ．
i h : ∗ hh : ∗ O ho : : Weights 10 2が型に数字の値を用いることができないため，テンソルの次元を扱うことはできない．そのため，機械学習ソフトウェアで扱う行列やテンソルに対して検証をすることはできない．行列やテンソルの次元を正しく扱
うには次元を型として扱うことに加え，入力の次元に依存して出力の次元を決定する必要があるが，これらの型システムでは依存関係がある型が扱えない．
ソースコード 2型のアノテーションの例#整 数 型 の ア ノ テ ー シ ョ ン
d e f i n t f u n c ( x : i n t ) −> i n t :return x#行 列 型 の ア ノ テ ー シ ョ ン
d e f n d a r r a y f u n c ( x : np . ndarray ) :np . ndarray
return x

コンパイル時に行列の次元も含めて静的に解析でき，ユーザーに明示的に入出力の仕様を記述させるこ

3 提案手法とを強要でき，型にインターフェースの情報が含まれ本提案は型情報チェックするために関数やブロックているため，ドキュメントとコードの動作の不一致のの実行可能なコメントにアノテーションをつけ問題を問題が起こりにくい．しかし，この方法では機械学習改善する．コメントに実行可能なコードを埋め込みで使われている Python 等の動的型付け言語の資産がテストする手法として doctest [7] があり、これを利利用できないという問題や，実際の計算アルゴリズム用する．doctest はプログラムの本体とは別に実行でと型レベルの計算の両方を記述する必要があり手間きるため高速にテストできる．>>> の後に検証するが多い．

コードを記述し，続く行に期待値を記述するものである．その例をソースコード 3 に示す．

ソースコード 3

doctest の例

def 関 数 定 義( 関 数 の 引 数 ) :””” コ メ ン ト の 開 始>>> 検 証 す る コ ー ド ( 1 )
上 記 コ ー ド の 期 待 値(1)
別のコメントがあってもいい．
>>> 検 証 す る コ ー ド ( 2 )上 記 コ ー ド の 期 待 値(2)””” コ メ ン ト の 終 了
関数本体が続く．
本提案手法では検証対象の関数のドキュメントに入出力のアノテーションをつける．実際の関数の処理とは別であるので，学習の計算に悪影響をあたえない．
下記に手順を述べる．

(a) 検証対象の def で始まる関数のあとのコメン
トに次元付きの入力テンソルと関数の実行のコー
ド (4) を書く．

型チェックのアノテーションの例

本手法の意義として，本体の処理と関係なく事前に実行されるために，処理時間が短く，動作に関して矛盾のない関数のドキュメントにもなる．入出力の次元(b) 関数の出力結果の期待値照合用のコードを書
く．ここで出力テンソルのデータ型と次元を書く．
ソースコード 4

ソースコード 5d e f cnn model ( f e a t u r e s , name=None):””” Model f u n c t i o n f o r CNN.
>>> batch = 7>>> x = t f . z e r o s ( [ batch , 7 8 4 ] ,name=”x ” )>>> v = cnn model ( { ’ x ’ : x } , ” cnnt”)>>> v . shape(7 ,10)>>> v . dtype
tf . float32”””...

型チェックのアノテーションのフォーマット

def 関 数 名( 引 数 ) :””” 関 数 の 説 明
入力ベクトルの初期化>>> x = 入 力 ベ ク ト ル 生 成 関 数関数の実行>>> v = テ ス ト す る 関 数 ( x )>>> v . shape( 7 , 1 0 ) #出 力 の 次 元>>> v . dtypet f . f l o a t 3 2 #出 力 の デ ー タ 型”””
関数本体が続く．

を含めた型チェックが可能となる．仕様と実際の動作が乖離しやすく，ドキュメントは保守されない場合も多いが，本手法は実際のビヘイビアがドキュメントになり，不整合は発生しない．保守運用で不具合がある場合にデバッグでは分割統治法のようなものを使いバグのある場所を発見する必要があるが，本手法では処理単位で期待する動作をしているか検証のためのアノテーションを導入できるため，デバッグにも有用である．

4 従来手法と比較と考察
従来手法として依存型を用いた行列やテンソルの次元を明記しインターフェースを検証する方法と従来型の型のアノテーションを用いたインターフェースの検証方法を挙げ，提案手法として行列やテンソルの次元をコメント中に明記し検証する方法を述べた．

実際のサンプルをソースコード (5) に示す．必要であれば使用しているライブラリの関数に対しても型チェックすると検証はより効果的なものになる．

それらの長所と短所を下記に列挙した．
依存型を用いた方法はすべてのシステムをそれで記述できればよいが，現実的には導入は難しい．

Tensorflow の例をとるとフレームワークは様々な言語をサポートしているように見えるが，実際にサポートされているのはモデルのリードとライトとそれに入出力を与えるまでにであり，C 言語の API の上にPython で様々な処理が記述されており，例えば数値最適化のアルゴリズムは Python で記述されている．
実際にフレームワーク上でモデルを構築・最適化する
上で Python 以外の選択肢はない．
提案手法は Python といった動的型付け言語上で行える現実的な手法である．しかし，検証のためとはいアノテーションとして記述しプログラミング本体とは別に検証する．

– Pros.
∗ Python などで書かれた従来の資産が利用できる．

∗ テンソルの次元の型が検証できる．
– Cons.

え独自の記述を導入しているためコードレビューにつ∗ 網羅的な検証ができない．

いて若干の問題を抱えている．

∗ テンソルの次元をチェックしレビュー可• 依存型を用いた方法– 手法.

能なコードにするためとはいえ，一般的とはいえない本手法独自の記述がある．

∗ 行列やテンソルの次元を型にいれる．また入出力の次元の関係も型で記述する．

– Pros.

5 まとめと今後の課題
機械学習のソフトウェアは保守運用において API∗ テンソルの次元の型が明記されている.

や関数のインターフェースのチェックをし，レビュー∗ 関数やブロックによらずあらゆるレイしやすいコードにすることが重要である．行列やテンヤーで型がチェックされる．

∗ 網羅的に検証できる．
– Cons.
∗ Python などで書かれた従来の資産が利用できない．

• 従来型の型のアノテーションを用いた方法– 手法.

ソルの型や次元の検証は難しいことによるチェックが不十分である．本提案は関数やブロック単位で検証可能なインターフェースのコードを追加し，保守運用の改善を行った．コードの保守性を向上させるためとはいえ，一般的とはいえない新しい記述の導入をした．
より汎用的な記述や広く認められる記述への検討や検証をしてない関数の検出（検証漏れのチェック）を∗ Java などの通常の型システムを用いる行うなどの方法を検討することが今後の課題である．

方法．行列やテンソルの型は用意するが謝辞 本論文の議論と掲載の機会を与えていただい次元について管理しない．

た機械学習工学研究会（MLSE）に感謝する．

– Pros.
∗ Python などで書かれた従来の資産が利用できる．

– Cons.
∗ テンソルの次元の型が検証できない．
∗ 網羅的な検証ができない．
• 提案手法の型のアノテーションを用いた方法– 手法.
∗ 行列やテンソルの型はコメント部にて

参 考 文 献[1] Abbott, T.: Static types in Python, oh my(py)!,
10 2016.
[2] Google: Transitioning to TensorFlow 1.0, 06 2018.
[3] Gundry, A.: Type Inference, Haskell, and Dependent Types., 2013.
[4] Le, J.: Practical Dependent Types in Haskell:
Type-Safe Neural Networks, 05 2016.
[5] Lehtosalo, J.: Mypy: Optional Static Typing forPython, 2012.
[6] Microsoft: Announcing TypeScript 1.0, 04 2014.
[7] Peters, T.: docstring-driven testing, 03 1990.