😃

Deep Learningを使った欠損値補完 DataWig

2021/02/20に公開

欠損のままでも動くフレームワークも最近は増えていますが
欠損値の扱いは機械学習適用において難しい課題の一つです。

簡便的に平均値, 中央値, 最頻値などの統計量を代入する、Scikit-learnのAPIなどを使って、機械学習アルゴリズムで欠損を埋める, MICEで代入するなどの方法がありますが、この記事ではDeep Learningベースの欠損値補完ライブラリであるDataWigについて触れてみたいと思います。

欠損のタイプ[1]

データの欠損には大きく3つのメカニズムがあるとされています。

  1. MCAR(Missing Completely At Random ) :
    完全にランダムな欠損で、ある値の欠損する確率が、その対象のデータと無関係(例:サイコロを振ってランダムに欠損させているような状況)であることを指します。データ数が十分確保できるのであれば欠損行を削除しても問題ないタイプです。

  2. MAR(Missing At Random) :
    条件付きでランダムな欠損。他の情報に依存して欠損する(例:年齢の高い人ほど収入カラムが欠損しやすくなるなど)ことを指します。

  3. MNAR(Missing Not At Random):
    ランダムではない欠損。ある値の欠損する確率が、その変数の値自体に依存する(例:収入の高い人ほど収入カラムが欠損しやすくなるなど)ことを指します。

MARとMNARは欠損行を削除してモデリングを行うと偏りが生じるタイプの欠損となります。
手元の欠損がどのタイプに該当するかを理解することは難しいですが、他の変数の情報を使いながら補完するというのが欠損値補完の主なアプローチとなります。

DataWigとは

Paper: "Deep" Learning for Missing Value Imputation in Tables with Non-Numeric Data
Paper: DataWig: Missing Value Imputation for Tables

https://github.com/awslabs/datawig

https://datawig.readthedocs.io/en/latest/index.html

DataWigはAmazonが開発したOSSの欠損値補完ライブラリで、Apache MXNetをベースにしています。主な特徴は以下の通りです。

  • Deep Learningベースで大規模データセットの欠損値補完に適している
  • 数値だけでなく、カテゴリの欠損補完にも対応
  • 数値、カテゴリ、テキストから代入モデルを作成する
  • PandasのDataFrameを入力にしており、使いやすい
  • CPU, GPU上で動作

欠損補完のアプローチはMICEと同じで、代入モデルと他のカラムから抽出された情報を前提に、代入したいカラム内の属性もしくはカラム全ての潜在的な値の尤度を得ることです。

p(color=yellow | othercolumns, imputationmodel)

下図はアーキテクチャでカテゴリ変数、テキスト変数も数値表現することで代入モデルの特徴として活用します。


DataWigのアーキテクチャ

論文では、他の手法と比較した際にパフォーマンスは良かったと報告しています。


DataWigのパフォーマンス

使い方

pipインストール可能です。

pip install datawig

DataWigのSimpleImputerは簡単に使えるAPIです(他に少し複雑だが細かい設定ができるImputerクラスがあります)。
SimpleImputerからオブジェクトを作成する際は、どの特徴量を使って、どのカラムの欠損を代入するか、どこに代入モデルを出力するか指定します。
他の引数はデフォルト値が設定されているため、なくても動きます。

import datawig

imputer = datawig.SimpleImputer(
    input_columns=input_columns, # List: どのカラムで代入モデルを作成するか
    output_column=output_column, # どのカラムの欠損補完を行うか
    output_path='imputer_model', # 代入モデルの出力先
    num_hash_buckets=int(2 ** 15),
    num_labels=100,
    tokens='chars',
    numeric_latent_dim=100,
    numeric_hidden_layers=1,
    is_explainable=False
)

ImputerオブジェクトはPandasのDataFrameを入力とします(train_dfのoutput_columnは欠損がないDataFrameであることが前提です)。

test_dfを指定した場合は、そのデータを代入モデルの精度検証に使います。指定しない場合はtest_splitの比率でtrain_dfからランダムサンプリングし、精度検証を行います。
fit()ではなくfit_hpo()を使用すると代入モデルのHPOができます。

imputer.fit(train_df=train_df,
            test_df=None,
            ctx=[mx.cpu()],
            learning_rate=4e-3,
            num_epochs=100,
            patience=3,
            test_split=0.1,
            weight_decay=0
           )

代入モデルの学習が終わると推論(欠損値補完)ができます。
explain()を使用すると代入モデルのターゲットとしたカラムを予測する上で関連の高いカラムを出力することもできます。

代入については、数値変数は代入値をそのまま、カテゴリ変数に関してはカテゴリと確率を出力できます。
また、カテゴリ変数の場合はPrecision_thresholdでフィルタリングが可能であり、設定した閾値を下回っている行に対しては代入せずに欠損のまま出力することも可能です。
ちなみに出力された代入モデルをloadすることで再利用することができます。

test_df = imputer.predict(test_df,
                     precision_threshold=0.0,
                     imputation_suffix="_imputed",
                     score_suffix="_imputed_proba",
                     inplace=False
                    )

一つずつ変数に対して欠損補完するのが面倒な場合は、以下で欠損のある全ての変数に対して代入モデルの作成と欠損値補完が可能です(その分時間はかかります)。
内部的には各変数に対して、欠損がないデータセットで代入モデルを作成していきます。

df = datawig.SimpleImputer.complete(df,
                                    precision_threshold=0.0,
                                    inplace=False,
                                    hpo=False,
                                    verbose=0,
                                    num_epochs=100,
                                    iterations=1,
                                    output_path='.'
                                   )

使用時の注意点

ドキュメントには、カテゴリ変数の欠損値補完にはカテゴリのユニーク数の10倍以上のレコードが必要とあります。また、使ってみた感触ではカテゴリ変数内で極端に出現頻度が低いカテゴリの代入は難しい印象です。

まとめ

この記事ではDeep Learningベースの欠損値補完ライブラリであるDataWigについて取り上げました。欠損値補完の一つの選択肢になると嬉しいです。

脚注
  1. このセクションは高橋将宜・渡辺美智子 (2017)欠測データ処理-Rによる単一代入法と多重代入法-を参考に書きました。 ↩︎

Discussion