LoginSignup
18
18

More than 5 years have passed since last update.

金貨が本物かどうか見極める

Last updated at Posted at 2014-07-01

CodeIQ の問題を解く

一年以上前の問題ですが CodeIQ に掲載された機械学習の問題をひとつ解いてみます。

「機械学習基礎」簡単な問題を解いて理解しよう!前篇
http://next.rikunabi.com/tech/docs/ct_s03600.jsp?p=002315

これの第一問にチャレンジです。

線形分離問題

問題

週末に海賊船で催されたPRML読書会に参加したN君は、船内に山のように積まれた金銀財宝に目を奪われました。 近くにあった宝箱の1つを開けてみると、きらきらと輝くコインが何枚も入っていました。
手に取ってみるとどれもずっしりと重みがあります。金貨に違いありません。
好きなだけ持って帰ってよいと言われ、勉強会帰りに何枚か鞄に詰め込んで帰ることにしました。
家に帰ってから少し冷静になったN君は「気前よく配っていたけれど、この金貨は本物なのだろうか」と疑い始めました。
鞄には20枚の金貨が入っていましたが、友人のアルキメデスに計測してもらったところ、20枚とも体積も重さも異なりました。
ネットで検索してみたところ、金貨の体積と重さと真贋のデータを得られました。
このデータを参考に、貰ってきた金貨の真贋を見分けてください。

元記事にある通り、綺麗に線形分離できそうなデータです。

いつも通り scikit-learn を使って解きます。

データの読み込み

import numpy as np
from sklearn.svm import LinearSVC
import matplotlib.pyplot as plt

auth = np.genfromtxt('CodeIQ_auth.txt', delimiter=' ')

# 教師データ
train_X = np.array([[x[0], x[1]] for x in auth])
# 教師データのラベル
labels = [int(x[2]) for x in auth]

# テストデータ
test_X = np.genfromtxt('CodeIQ_mycoins.txt', delimiter=' ')

データ可視化

まずはデータをプロッティングしてみます。

fig = plt.figure()
ax1 = fig.add_subplot(2,1,1)
ax2 = fig.add_subplot(2,1,2)

# 教師データから正解を抽出
correct = np.array([[x[0], x[1]] for x in auth if x[2] == 1]).T
# 同じくニセモノを抽出
wrong   = np.array([[x[0], x[1]] for x in auth if x[2] == 0]).T

# これらを散布図にプロッティングする
ax1.scatter(correct[0], correct[1], color='g')
ax1.scatter(wrong[0],   wrong[1],   color='r')
ax2.scatter(train_X.T[0], train_X.T[1], color='b')
ax2.scatter(test_X.T[0],  test_X.T[1],  color='r')

plt.legend(loc='best')
plt.show()
plt.savefig("image.png")

image.png

上図の緑が正解、赤がニセモノの金貨です。元記事のプロット通りですね。

下図は真贋データ (青) に対する、手に入れた金貨 (赤) の分布となります。

解法

線形分離問題なので LinearSVC を使います。

clf = LinearSVC(C=1)

# 訓練
clf.fit(train_X, labels)

# 分類
results = clf.predict(test_X)
for result, feature in zip(results, test_X):
    print(result, feature)

結果

1 [  0.988  17.734]
0 [ 0.769  6.842]
0 [ 0.491  4.334]
1 [  0.937  16.785]
1 [  0.844  13.435]
0 [ 0.834  9.518]
1 [  0.931  16.62 ]
1 [ 0.397  6.705]
1 [  0.917  16.544]
0 [ 0.45   3.852]
0 [ 0.421  4.612]
1 [ 0.518  9.838]
1 [  0.874  14.113]
0 [ 0.566  6.529]
0 [ 0.769  8.132]
1 [  1.043  16.066]
0 [ 0.748  9.021]
0 [ 0.61   6.828]
0 [  1.079  12.097]
1 [  0.771  13.505]

左側の 0 1 が解答になります。というわけで、例と同じ解答を得られるに至りました。

18
18
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
18