verum ipsum factum

sudillap's blog

「金塊か、キノコ料理か」(外れ値検出問題)を解く[はじめに]

ITエンジニアのための実務スキル評価サービスCodeIQ機械学習分野の問題を眺めていたら、「金塊か、キノコ料理か」(by naoya_tさん)という問題がありました。

おもしろそうなので、解答締め切りは過ぎていますが挑戦してみました。


この問題の挑戦受付は終了しているため、CodeIQのページでは詳細を知ることはもうできませんが、Tech総研のページ「「機械学習基礎」簡単な問題を解いて理解しよう!後篇」では問題の詳細(+データ)と出題者のnaoya_tさんによる解答を読むことができます。

CodeIQの「回答評価のポイント」欄で「異常(外れ値)検出で、選んではいけない玉を見つけ出してもらいます。」と書かれているようにこれは外れ値を探す問題です。次の問題文(抜粋)にあるように100個のデータの中から外れ値を一つ見つけられたら正解となります。

「ここに100個の玉がある。
 この中に1つだけ貴重な石でできた玉がある。
 大切な客人ならば、それを選び出すことができるはずだ。
 大きさも重さも調べたいだけ調べてもらって構わない。」
 
  というわけで、N君への今回の依頼はこれだ。

100個の玉のうち、貴重な石でできた玉がどれなのか教えてほしい。
判定が微妙なものがあれば、怪しい玉も含めて3つぐらい教えてほしい。

データがこちらからダウンロードできるので次にあげた方法を使って外れ値検出にトライしてみました。


ほかの方もこの課題に挑戦されているようです。たとえば、

データ概要

ファイル名はhundred.txtで、100個の玉のデータが含まれています。最初の玉5つ分のデータは次のとおりです。左からそれぞれ、重さ[g]、比熱[J/kg・K]、光の反射率[%](玉はすべて半径1.0cmの球体)だそうです。

69.613 129.070 52.111
70.670 128.161 52.446
72.303 128.450 52.853
73.759 127.522 51.786
74.085 129.067 53.352

早速、散布図行列を表示してデータの分布を見ます。図の座標軸V1はデータの1列目に相当(V2、V3も同様)します。
V2とV3の散布図を見ると、なんとなく左下隅のデータが外れ値っぽいですが、これだけではなんとも言えません。
f:id:sudillap:20130324204740p:plain

つぎに3次元散布図を描いてみます(以下は2方向から見た図)。散布図を回転させてみるとわかるのですが、外れ値の候補がいくつか見つかります。ちなみに正解を先に言うと、87番目のデータが外れ値です。
f:id:sudillap:20130324205035p:plainf:id:sudillap:20130324205030p:plain

散布図からでも外れ値の候補をいくつか見つけることはできますが、これだけでは面白くありません。そこで、本記事では代表的な機械学習を使って外れ値を見つけます。

なお、散布図を見ると分かりますが、次元ごとにデータが取る範囲が異なります。このままでは色々面倒なので、基本的に標準化後のデータ分析をしています。
Tech総研の記事でnaoya_tさんは

【註】3要素の分布がそれぞれ異なるのであらかじめ正規化するのが望ましいですがそのまま突っ込んでも結果が変わらないようなデータにしてあります。

と書かれていますが、(問題にも依りますが)一般的には標準化した方がいいと思われます。
このデータではあまり問題は起こりませんが、石の重さをグラム[g]ではなくKgで測定されていた場合を考えると、いろいろ面倒なことが起こりそうですね。

まずは、データ読み込みのRスクリプトを書いておきます。読み込んだデータを標準化し、データフレームgoldに格納しています。

gold <- read.table("hundred.txt", header=FALSE)
gold <- as.data.frame(scale(as.matrix(gold), center = TRUE, scale = TRUE))