LoginSignup
3
6

More than 5 years have passed since last update.

コサイン距離のクラスタリング

Last updated at Posted at 2016-06-27

もっとも簡単なデータで検証

このRプログラムを見て、skmeansというモジュールを知ったのですが、どう動くのかよくわからなかったので、ごく簡単な例で試してみました。

データ

バナナ りんご
さる 2 1
ゴリラ 0 3
ぞう 1 10

おさるさんはバナナを2本、りんごを1個食べました。おさるさんはバナナが好きなのかな。ゴリラさんはバナナは食べず、りんごを3個食べました。ゴリラさんはりんごが好きなんですね。ぞうさんはバナナを1本、りんごを10個食べました。ぞうさんはりんごが大好きみたいだね。さて、ゴリラさんはおさるさんとぞうさんのどちらに近いでしょうか?

図にするとこうなります。
名称未設定 のコピー.png

ちなみに、おさるさん, ゴリラさん, ぞうさんの距離を求めてみると、

> x <- data.frame(v1 = c(2, 0, 1), v2 = c(1, 3, 10))
> sqrt((2 - 1)^2 + (1 - 3)^2)
[1] 2.236068
> sqrt((1 - 3)^2 + (1 - 10)^2)
[1] 9.219544

さる-ゴリラの方が、ゴリラ-ぞうよりも近いことがわかります。

ユークリッド距離のk-means

では、まずは普通のk-meansから。

> e <- kmeans(x, 2)
> e$cluster
[1] 2 2 1

このようになり、{おさるさん, ゴリラさん}, {ぞうさん}のクラスターができました。これは少食のなかまとぞうさんに別れたということになりますね。

COS距離のk-means

一方、skmeansでクラスター分析すると、

> library(slam)
> library(skmeans)
> s <- as.simple_triplet_matrix(x)
> c <- skmeans(s, k = 2)
> c$cluster
[1] 2 1 1

{おさるさん}, {ゴリラさん, ぞうさん}というクラスターができています。この結果は、バナナ好きとりんご好きに別れたということになります。

単純すぎる例ですが、確かに少なくともここでは角度でクラスターができているようです。

ランダムなデータで検証

つぎはランダムに作ったデータでskmeansの挙動を調べてみます。ただし、2次元です。

データ

v1 <- c(0.556, 0.904, 0.982, 0.615, 0.684, 0.928, 0.717, 0.710, 0.843, 0.569, 0.289, 0.678, 0.394, 0.262, 0.611, 0.281, 0.164, 0.582, 0.021, 0.918, 0.804, 0.198, 0.709, 0.240, 0.704, 0.121, 0.103, 0.096, 0.556, 0.367, 0.184, 0.034, 0.309, 0.832, 0.460, 0.478, 0.312, 0.962, 0.380, 0.080, 0.114, 0.563, 0.065, 0.994, 0.353, 0.107, 0.811, 0.010, 0.052, 0.446, 0.245, 0.665, 0.555, 0.355, 0.526, 0.888, 0.416, 0.861, 0.752, 0.986, 0.923, 0.685, 0.500, 0.832, 0.867, 0.568, 0.207, 0.001, 0.160, 0.350, 0.934, 0.570, 0.258, 0.188, 0.237, 0.223, 0.520, 0.263, 0.353, 0.766, 0.916, 0.320, 0.256, 0.886, 0.098, 0.202, 0.635, 0.785, 0.980, 0.162, 0.470, 0.531, 0.764, 0.152, 0.956, 0.195, 0.048, 0.864, 0.142, 0.598, 0.931, 0.991, 0.147, 0.295, 0.094, 0.225, 0.654, 0.093, 0.310, 0.779, 0.137, 0.863, 0.368, 0.659, 0.061, 0.435, 0.481, 0.446, 0.495, 0.710, 0.881, 0.667, 0.260, 0.037, 0.473, 0.547, 0.811, 0.023, 0.567, 0.862, 0.445, 0.763, 0.131, 0.175, 0.468, 0.309, 0.502, 0.582, 0.134, 0.028, 0.775, 0.490, 0.553, 0.333, 0.676, 0.707, 0.145, 0.088, 0.138, 0.948, 0.275, 0.368, 0.016, 0.914, 0.627, 0.215, 0.839, 0.715, 0.317, 0.352, 0.517, 0.315, 0.119, 0.280, 0.256, 0.658, 0.666, 0.737, 0.420, 0.029, 0.784, 0.364, 0.386, 0.252, 0.746, 0.129, 0.993, 0.560, 0.960, 0.003, 0.251, 0.740, 0.898, 0.175, 0.132, 0.406, 0.514, 0.614, 0.270, 0.168, 0.537, 0.886, 0.425, 0.314, 0.847, 0.266, 0.397, 0.648, 0.895, 0.592, 0.504, 0.322, 0.004, 0.011, 0.932, 0.374, 0.053, 0.914, 0.917, 0.604, 0.070, 0.976, 0.132, 0.199, 0.633, 0.678, 0.719, 0.551, 0.240, 0.481, 0.888, 0.576, 0.337, 0.642, 0.973, 0.961, 0.685, 0.774, 0.055, 0.951, 0.792, 0.636, 0.057, 0.220, 0.581, 0.333, 0.749, 0.028, 0.730, 0.683, 0.525, 0.075, 0.586, 0.756, 0.988, 0.417, 0.137, 0.063, 0.306)
v2 <- c(0.657, 0.436, 0.052, 0.010, 0.943, 0.711, 0.941, 0.151, 0.730, 0.769, 0.646, 0.406, 0.139, 0.476, 0.701, 0.769, 0.632, 0.307, 0.849, 0.205, 0.069, 0.417, 0.670, 0.396, 0.641, 0.659, 0.556, 0.580, 0.924, 0.359, 0.073, 0.792, 0.237, 0.713, 0.668, 0.597, 0.602, 0.076, 0.657, 0.871, 0.703, 0.314, 0.079, 0.987, 0.190, 0.646, 0.959, 0.344, 0.591, 0.375, 0.663, 0.388, 0.172, 0.372, 0.878, 0.736, 0.748, 0.964, 0.828, 0.689, 0.933, 0.310, 0.205, 0.542, 0.555, 0.025, 0.223, 0.464, 0.205, 0.282, 0.802, 0.175, 0.012, 0.617, 0.716, 0.815, 0.988, 0.484, 0.767, 0.311, 0.269, 0.976, 0.143, 0.835, 0.381, 0.004, 0.068, 0.146, 0.442, 0.977, 0.843, 0.660, 0.772, 0.350, 0.906, 0.823, 0.142, 0.975, 0.017, 0.765, 0.238, 0.441, 0.873, 0.691, 0.960, 0.905, 0.592, 0.897, 0.955, 0.365, 0.023, 0.176, 0.265, 0.831, 0.253, 0.422, 0.628, 0.773, 0.860, 0.404, 0.033, 0.220, 0.371, 0.939, 0.457, 0.564, 0.744, 0.027, 0.647, 0.559, 0.007, 0.275, 0.510, 0.425, 0.298, 0.097, 0.615, 0.284, 0.984, 0.613, 0.247, 0.447, 0.407, 0.263, 0.055, 0.038, 0.304, 0.104, 0.342, 0.516, 0.590, 0.812, 0.099, 0.852, 0.516, 0.240, 0.447, 0.725, 0.357, 0.194, 0.602, 0.720, 0.974, 0.671, 0.225, 0.115, 0.448, 0.160, 0.182, 0.634, 0.976, 0.703, 0.533, 0.341, 0.430, 0.066, 0.603, 0.633, 0.656, 0.192, 0.456, 0.680, 0.904, 0.827, 0.504, 0.694, 0.188, 0.635, 0.663, 0.568, 0.318, 0.197, 0.951, 0.716, 0.923, 0.050, 0.204, 0.014, 0.765, 0.856, 0.147, 0.178, 0.383, 0.021, 0.247, 0.479, 0.518, 0.525, 0.953, 0.445, 0.138, 0.572, 0.982, 0.107, 0.442, 0.220, 0.180, 0.411, 0.197, 0.165, 0.649, 0.455, 0.591, 0.228, 0.467, 0.737, 0.615, 0.368, 0.976, 0.523, 0.233, 0.837, 0.282, 0.150, 0.182, 0.471, 0.283, 0.591, 0.102, 0.268, 0.945, 0.013, 0.910, 0.813, 0.809, 0.998, 0.461, 0.791, 0.902)
x2 <- data.frame(v1 = v1, v2 = v2)

データは250ケースあります。乱数で作りました。なので結果には全く意味はありません。

ユークリッド距離のk-means

では、まずユークリッド距離を使ったk-meansから。

e2 <- kmeans(x2, 4)
plot(x2, col = e2$cluster)

e.png
一様ランダムなデータなので、綺麗に1/4に別れました。

COS距離のk-means

s2 <- as.simple_triplet_matrix(x2)
c2 <- skmeans(s2, k = 4)
plot(x2, col = c2$cluster, xlim = c(0, 1), ylim = c(0, 1))

c.png
こちらも綺麗に別れました。原点を起点とした角度で別れていることがよくわかりますね。

3
6
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
3
6