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

# もっとも簡単なデータで検証
[このRプログラム](https://gist.github.com/soonraah/2e78b9ca13295139cdb8)を見て、skmeansというモジュールを知ったのですが、どう動くのかよくわからなかったので、ごく簡単な例で試してみました。

## データ

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

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

図にするとこうなります。
![名称未設定 のコピー.png](https://qiita-image-store.s3.amazonaws.com/0/131308/aa37e2cd-57ef-3a52-5f2d-c8ef3e789f75.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の挙動を調べてみます。ただし、２次元です。

## データ
```
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](https://qiita-image-store.s3.amazonaws.com/0/131308/67b45dc8-5702-fe07-58b6-b9d0cdfb6c58.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](https://qiita-image-store.s3.amazonaws.com/0/131308/49ecbb99-63e5-e289-277f-a49f8b110133.png)
こちらも綺麗に別れました。原点を起点とした角度で別れていることがよくわかりますね。