Glueの「FindMatches 変換」機能を使ってデータセット内の「一致するレコードの重複排除」、「検索」をする

とても簡単に試せる、いい機能だと思います
2019.12.23

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

概要

当エントリは『機械学習 on AWS Advent Calendar 2019』の23日目のエントリです。

前から気になっていたGlueの「ML変換」機能の「FindMatches変換」について調べてみましたが、これは地味に便利なんじゃないかな、と思ったので本エントリーで整理しておきます。
下記は実際にこちらの内容をやってみて調べたことをまとめたものです。

どんなことができるのかをざっくり知りたい方は「1.最初に」を、技術ベースの概要レベルまで確認したい方は「2.やることの概要」を、技術ベースの詳細レベルまで確認したい方は「3.やってみる」をご参照ください。

目次

1.最初に

まず、今回試してみた「FindMatches変換」はどのようなことができるのか、を調べてみました。

FindMatches 変換を使用すると、レコードに共通の一意の識別子がなく、正確に一致するフィールドがない場合でも、データセット内の重複レコードまたは一致するレコードを識別できます。

参照:AWS Lake Formation の FindMatches によるレコードのマッチング

どうやら、「完全に一致していなかったり主キーが無かったりするデータに対しても、内容としては同じようなレコード」を識別することができるようです。
もう少し具体的に言ってしまえば、「どういうデータなら同一レコードなのか、異なるレコードなのか、といったことを記述したラベリングファイル」を使って学習し、データカタログに登録したデータに対してもその学習したルールでレコードを識別する、といった機能です。

下記は実際にやってみたアウトプットファイルの一部です。
下記のように「match_id」といったカラムが追加された状態でファイルが出力され、このカラムの値が一致していれば同一レコードとみなす、という推論がなされています。
(下記の結果では「match_id=2」のレコードだけが重複なしと判断されています。また、「match_id」カラムなしで重複削除した状態でファイル出力、もできます)

上記のようにレコードを識別することのユースケースについてもドキュメントに書いてありました。

  • 一致する顧客: 多くの顧客フィールドがデータベース間で正確に一致しない場合でも(名前のスペルや住所の違い、データの欠落や不正確ななど)、異なる顧客データベース間で顧客レコードをリンクします。
  • 製品のマッチング: カタログ内の製品を、競合他社のカタログに対する製品カタログなど、他の製品ソースと照合します。エントリの構造は異なります。
  • 不正検出の向上: 重複した顧客アカウントを特定し、新しく作成したアカウントが、以前に知られている不正ユーザーと一致する(またはその可能性のある)タイミングを判断します。
  • マッチングに関するその他の問題: マッチアドレス、映画、パーツリストなど。一般的に、人間がデータベース行を見て、それらが一致していると判断した場合、FindMatches 変換が役に立つ可能性は非常にあります。

参照:AWS Lake Formation の FindMatches によるレコードのマッチング

こうやって見ると色々とユースケースがありそうです。
また、「FindMatches 変換」のチューニング方法としては「ラベリングファイルを作成」→「FindMatches 変換の結果を確認し、間違っている部分をラベル付けして既存のラベリングファイルに追加」→「再度FindMatches 変換して結果を確認して...」といった過程を数回繰り返すことが想定されますが、他にも「精度のトレードオフ関係」について調整することができます。
下記はAWSコンソール画面ですが、「再現率と適合率」、「コスト削減と正確度」、「一致のエンフォースメント」の3点については頭に入れておいたほうが良さそうです。

以下にそれぞれどのような意味合いかをざっくり記述しますが、詳細についてはAWS Glue での機械学変換の調整をご参照ください。

  • 再現率と適合率
    • それぞれの計算式は下記の通り。「再現率を重視」すれば「過剰に重複と推論してしまう可能性が増える」、「適合率を重視」すれば「誤って重複と推論するレコードは減るが本来重複と推定すべきレコードを重複でないと推論する可能性が増える」という結果に繋がり、これらはトレードオフの関係となります。
    • 再現率:(「重複」と推論したレコード) / (本当に重複している全レコード)
    • 適合率:(「重複」と推論して、実際に「重複」であるレコード) / (「重複」と推論した全レコード)
  • コスト削減と正確度
    • 「正確度」とありますがドキュメントを見ると、「より詳細な検索を行う」といった趣旨のようです
  • 一致のエンフォースメント
    • ラベル付きデータから学習した結果を用いて推論、となるのであくまでも「ラベル付きデータと全く同じ結果が必ず推論されるわけではない」ようです
    • なので、ラベル付きデータの内容をモデルよりも優先したい場合はこのチェックボックスにチェックします

長くなってしまいましたが、大体どのようなことができるサービスなのかイメージがついた気がします。

2.やることの概要

もう少し技術レベルでやることを細分化すると、下記のような手順を踏んでいくことになります。

  • 1.ソースデータをGlueデータカタログに登録する
    • ラベル付けをしたいデータをGlueのデータカタログに登録する
  • 2.Glueの「ML変換」を追加する
    • ソースデータやIAMロール、「精度とコストのトレードオフ」等の設定値を指定する
  • 3.ラベルデータを追加する
    • どのようなデータなら同一レコードで、どのようなデータなら異なるレコードなのか、といった点を学習させるためのラベル付きデータをS3にアップロードする
    • この「ラベル付きデータ」の特徴から「どのようなレコードは同一レコードなのか」を学習して、ソースデータにラベルを付与した状態でファイル出力することになる
  • 4.ML変換の品質がどのくらいになりそうかを推定する
    • ラベルづけされた「データ量」や「品質」に応じてOUTPUTの品質が変化するので、どんなもんになりそうかの推定値を確認する
  • 5.ここまでの設定に応じて、実際にML変換をGlueジョブとして実行する
    • GlueJOBを実行する
  • 6.OUTPUTファイルの内容を確認する
    • 「match_id」というカラムが追加された状態でファイルが出力されるので内容を確認する
    • (「match_id」カラムなし&重複を削除した状態、でファイル出力することもできる)

「6.OUTPUTファイルの内容を確認する」までやって、結果がイマイチな場合は誤った推論をしたデータにラベルづけして「ラベル付きデータ」に追加、「精度の設定の見直し」等をして再度ML変換JOBを実行、といった試行を繰り返す流れになりそうですね。

長くなってしまいましたが、以下実際にやってみます。

3.やってみる

「2.やることの概要」に基準した順に沿って、実際の操作手順について確認していきます。

3-1.ソースデータをGlueデータカタログに登録する

(今回はバージニア北部リージョンで検証しています。)

まずは、対象となるデータをS3に用意し、Glueのデータカタログに登録するためにクローラーを作成します。
今回はチュートリアルで用意されているデータを利用します。
(s3://ml-transforms-public-datasets-us-east-1/dblp-acm/records/dblp_acm_records.csv)

ここからウィザード上の誘導に従ってポチポチしていって、

作成したクローラを実行!!!

ちゃんとデータベースにテーブルが登録されました。

3-2.Glueの「ML変換」を追加する

続いて、「ML変換」を追加します。
ここでは「対象となるデータ」、「IAMロール」、「ノード」、「精度やコストのトレードオフ関係」等を設定する必要があります。

「ML変換」の「変換の追加」から

「変換の名前」や「IAMロール」、「稼働するワーカーノード数」等を指定し、
(下記は設定項目の一部画面)

先ほどクローラーで登録したソースデータを指定し、プライマリーキー列を指定して、

諸々のトレードオフ関係を指定し、
(今回はとりあえずデフォルトで進めます)

最後に、全体を確認して問題なさそうなら「完了」としましょう。

ここまでで「対象となるデータソース」、「IAMロール」、「ノードや精度のトレードオフ関係」まで設定できた状態です。
続いて、「どのようなレコードなら重複しており、どのようなレコードなら重複していないのかを学習させるためのラベル付きデータ」を用意します。

3-3.ラベルデータを追加する

先ほど作成した「ML変換」にラベル付きデータを設定する形になります。
下記の通り、「アクション」から「変換を教える」をクリックし、

今回は事前に作成されているラベルデータを利用するため、「ラベルがあります」→「S3からラベリングファイルをアップロード」をクリックします。

事前に用意されているS3パスを記述し、アップロードします。
(s3://ml-transforms-public-datasets-us-east-1/dblp-acm/labels/dblp_acm_labels.csv)

ここで「品質の推定(任意)」もできるのですが、一旦チュートリアルに合わせてここではスルーします。

ここまでで「ラベル付けの対象データ」、「学習させる際のノードやIAMロール」、「学習に利用するデータ」の準備ができたのですが、この「ラベル付きデータ」については大事なところなのでしっかりチェックする必要があります。
なんで大事かというと、「ラベル付きデータに含められた特徴」を使って学習するため、「このデータに含まれていない特徴」を持ったデータは「重複レコード」と判定することができないためです。

例えば、今回利用する「ラベル付きデータ」の中身は下記のようになっており「titleの大文字小文字が違っても同じレコードと判定する」、「titleが同じなら、sourceやvenueが異なっていても同一レコードと判定する」といった特徴を学ばせるためのデータが用意されています。
(左に「labeling_set_id」、「label」という列がある点にご注意ください。これらの詳細についてはこちらをご参照下さい)

labeling_set_id,label,id,title,authors,venue,year,source
0,0,671000,1-Safe Algorithms for Symmetric Site Configurations,"Rune Humborstad, Maitrayi Sabaratnam, Svein-Olaf Hvasshovd, Øystein Torbjørnsen",Very Large Data Bases,1997,ACM
0,0,conf/vldb/HumborstadSHT97,1-Safe Algorithms for Symmetric Site Configurations,"Maitrayi Sabaratnam, ÿystein Torbj¯rnsen, Rune Humborstad, Svein-Olaf Hvasshovd",VLDB,1997,DBLP
0,1,journals/sigmod/Chamberlin03,2003 SIGMOD Innovations Award Speech,Donald D. Chamberlin,SIGMOD Record,2003,DBLP
0,2,conf/vldb/JohnsonS94,2Q: A Low Overhead High Performance Buffer Management Replacement Algorithm,"Dennis Shasha, Theodore Johnson",VLDB,1994,DBLP
0,2,672996,2Q: A Low Overhead High Performance Buffer Management Replacement Algorithm,"Theodore Johnson, Dennis Shasha",Very Large Data Bases,1994,ACM
0,3,journals/sigmod/CoxEH96,3D Geographic Network Displays,"Taosong He, Stephen G. Eick, Kenneth C. Cox",SIGMOD Record,1996,DBLP
0,3,245901,3D geographic network displays,"Kenneth C. Cox, Stephen G. Eick, Taosong He",ACM SIGMOD Record ,1996,ACM

3-4.ML変換の品質がどのくらいになりそうかを推定する

実際に学習させる前に、どのくらいの品質で推論できそうかを見てみましょう。
(あくまでも推定値です)

今回作成した「ML変換」を指定して「品質を推定する」タブから「Estimate quality」をクリックします。
(まだ作成した直後だと「結果」にも値が入っていない状態です)

「履歴」タブを開くと、ステータスが確認できます。
「成功」となるまで待ちましょう。

推定が終わったら、「品質の推定」タブから結果を確認しましょう。
今回AWS側で事前に用意されていたデータセットの場合、良い推論結果が期待できそうです。

ここまでで、諸々の設定や事前の確認まで完了しました。
続いて、実際にGlueジョブを実行して対象データにラベルをつけてみます。

3-5.ここまでの設定に応じて、実際にML変換をGlueジョブとして実行する

まず、実際にML変換を実行するGlueジョブを作成します。
「ジョブ」→「ジョブの追加」から

ジョブ名やスクリプト名を適当に設定した後に対象のデータソースを指定し、

今回は「FindMatchs変換」を行うので「一致するレコードを検索する」にチェックを入れます。
(「重複レコードを削除する」をチェックすると出力されるファイルから「重複したレコードが削除され、match_id列が無い状態」で出力されるのですが、今回はチェックを入れないで進めます)

続いて、「変換プロパティ」で先ほど作成したML変換の設定を指定します。

続いて、処理結果の出力先を指定します。
今回はS3にCSVファイルを出力することとします。

あとはスクリプトを一部修正して保存、としてJOBを実行します。
スクリプトの内容についてはこちらにも記載してあるので割愛します。

3-6.OUTPUTファイルの内容を確認する

Glueジョブが完了していることが確認できたら、S3に出力されたファイルを確認します。
一番右の列に「match_id」という列が追加されていることがわかります。

一番上の2行(match_id=0)については、「venue」や「source」、また「title列の大文字小文字が違う」といった特徴がありますが「同一のレコード」だと判定されており、これは「ラベル付きデータ」でそのようなデータを入れているので、意図したような結果となっています。
以下、「match_id」が1,3,4,5のレコードについても「ラベル付きデータ」で記述していた特徴から学習して「重複レコード」と判定されており、これらも意図した通りの判定結果と言えそうです。

4.気をつけておきたいこと

「FindMatches変換」をするにあたって気をつけておきたいことを、こちらを参考に整理してみます。
(漏れがあったらすいません)

  • ☆ソースデータとラベル付きデータは、異なるパスに保管する
    • Glueのデータカタログを読み込むことになるので、同一パスにあると同一データとGlueが判断してしまう
  • ☆ファイルの文字コード
    • CSV ファイルに ASCII 文字のみが含まれている場合を除き、CSV ファイルには必ず BOM (バイトオーダーマーク) なしの UTF-8 エンコードを使用する
  • ☆カラム数が100を超えるデータは利用できない
  • ☆ラベル付きデータについて
    • csvにする
    • 文字コードはutf-8
    • S3に格納しておくこと
    • このようなデータなら一致、このようなデータなら不一致、といった両方のパターンを含めること
    • 最初に「labeling_set_id」、「label」といった2カラムを追加(ここにラベルをつける)し、それ以降はソースデータと同じ列構成にする
    • このデータに含まれていない特徴は学習できない。しかしながら最初から全てのパターンを網羅することはできないので、ある程度ラベル付きデータを作ったらFindMatchsで変換して、その結果を確認して、誤った推定をしているレコードについてラベルを付与してラベル付きデータに追加して再学習、といった操作を何回か繰り返す流れが基本になりそう

5.まとめ

「どのレベルの特徴まで学習させることができるのか」、といった点がわからなかったのが気掛かりですが、それでも「機械学習の知識も不要」で、「コードも殆ど書くこともなく実行でき」、特に「ラベル付きデータ作成についてはエンジニアリング要素がかなり薄く、複数人で分割してできる仕組み」になっていて、とてもいい機能だと思いました。

6.参照

参照したリンク先です。