RでK近傍法による密度推定するためのコードを書いてみた

PRMLの2章の最後の付近にK近傍法というのが出てきました。
www.yasuhisay.info
で、僕が卒研でたぶんやるカーネル使ったやつに比べてやったら考え方がシンプルなので、とりあえず実装してみることにしました。密度トレイスということなので、1次元の球を考えました。関数もめちゃシンプル。

k.nearest.neighbor <- function(x,k,data){
  r <- abs(x - data[order(abs(x - data))[k]])
  #ref http://ja.wikipedia.org/wiki/球
  n <- 1
  v <- pi^(n/2) * r^n / gamma((n/2)+1)
  return(k / (length(data) * v))
}

with(cars,{
  plot.knn <- function(k){
    s <- seq(min(speed),max(speed),length.out=50)
    plot(s,sapply(s,function(x){k.nearest.neighbor(x,k,speed)}),
         main=paste("Parameter K = ",k),
         xlab="speed",
         ylab="density",
         type="l")
    lines(density(speed),col="blue",lwd=5)
    legend("topleft",
           text.width=3,
           c("KNN","density"),lwd=c(1,5),col=c("black","blue"))
  }
  par(oma=c(0,0,2,0))
  par(mfrow=c(2,2))
  sapply(c(3,5,10,20),plot.knn)
  par(xpd=TRUE)
  mtext(side=3,outer=TRUE,text="K近傍法とRのdensityとの比較(cars$speedのデータを使用)")
})

で、carsのspeedを密度推定してみたのがこんな感じ。うーん、とげとげしてるなあ。。。Kを増やしていっても、とげとげしたまんま。
f:id:syou6162:20161103175929p:plain
どう見てもKNNによる密度推定は積分したら1越えるだろjkとか思ったら、P123にこのモデルは正規化された密度関数にはなっていない、ということがちゃんと書いてあった。なんか直感的にKNNによる密度推定よりはカーネルによる密度推定のほうがいい気がするなー。根拠はないけど、直感的に。変化が離散的なのが、やっぱり気にいらないんでしょうね。

パターン認識と機械学習 上

パターン認識と機械学習 上

  • 作者: C.M.ビショップ,元田浩,栗田多喜夫,樋口知之,松本裕治,村田昇
  • 出版社/メーカー: 丸善出版
  • 発売日: 2012/04/05
  • メディア: 単行本(ソフトカバー)
  • 購入: 6人 クリック: 33回
  • この商品を含むブログ (18件) を見る