用r找到双峰分布的局部最小值

时间:2014-08-12 12:35:14

标签: r statistics kernel distribution kernel-density

我的数据是预处理的图像数据,我想分开两个类。在理论上(并且希望在实践中),最佳阈值是双峰分布数据中两个峰值之间的局部最小值。

我的测试数据是:http://www.file-upload.net/download-9365389/data.txt.html

我试图关注this thread: 我绘制了直方图并计算了核密度函数:

datafile <- read.table("....txt")
data <- data$V1
hist(data)

d <- density(data) # returns the density data with defaults
hist(data,prob=TRUE)
lines(d) # plots the results

但如何继续?

我会计算密度函数的第一个和第二个导数来找到局部极值,特别是局部最小值。但是我不知道如何在R中执行此操作,density(test)似乎不是正常的功能。因此,请帮助我:如何计算导数并找到密度函数density(test)中两个峰之间的凹坑的局部最小值?

1 个答案:

答案 0 :(得分:5)

有几种方法可以做到这一点。

首先,使用d作为问题中的密度,d$xd$y包含密度图的x和y值。当导数dy / dx = 0时出现最小值。由于x值是等间隔的,我们可以使用diff(d$y)来估计dy,并在d$x最小化的地方寻找abs(diff(d$y))

d$x[which.min(abs(diff(d$y)))]
# [1] 2.415785

问题是,当dy / dx = 0时,密度曲线也可以最大。在这种情况下,最小值很浅但最大值达到峰值,所以它可以工作,但你不能指望那。

所以第二种方法是使用optimize(...)来寻找给定区间内的局部最小值。 optimize(...)需要一个函数作为参数,因此我们使用approxfun(d$x,d$y)来创建插值函数。

optimize(approxfun(d$x,d$y),interval=c(1,4))$minimum
# [1] 2.415791

最后,我们证明这确实是最小的:

hist(data,prob=TRUE)
lines(d, col="red", lty=2)
v <- optimize(approxfun(d$x,d$y),interval=c(1,4))$minimum
abline(v=v, col="blue")

另一种实际上首选的方法是使用k-means聚类。

df <- read.csv(header=F,"data.txt")
colnames(df) = "X"

# bimodal
km <- kmeans(df,centers=2)
df$clust <- as.factor(km$cluster)
library(ggplot2)
ggplot(df, aes(x=X)) + 
  geom_histogram(aes(fill=clust,y=..count../sum(..count..)),
                     binwidth=0.5, color="grey50")+
  stat_density(geom="line", color="red")

实际上,这些数据看起来比双峰更为复杂。

# trimodal
km <- kmeans(df,centers=3)
df$clust <- as.factor(km$cluster)
library(ggplot2)
ggplot(df, aes(x=X)) + 
  geom_histogram(aes(fill=clust,y=..count../sum(..count..)),
                 binwidth=0.5, color="grey50")+
  stat_density(geom="line", color="red")