カーネル密度推定(KDE)は、カーネル分布のロケーション混合である分布を生成するため、カーネル密度推定から値を引き出すために必要なのは、(1)カーネル密度から値を引き、次に(2)です。ランダムにデータポイントの1つを個別に選択し、その値を(1)の結果に追加します。
問題のようなデータセットにこの手順を適用した結果を次に示します。
左側のヒストグラムはサンプルを示しています。参考までに、黒い曲線はサンプルが抽出された元の密度をプロットしています。赤い曲線は、サンプルのKDEをプロットします(狭い帯域幅を使用)。(赤いピークが黒いピークよりも短いことは問題ではありませんし、予想外のことでもありません。KDEは物事を広げるので、ピークは低くなって補正されます。)
右側のヒストグラムは、KDEからの(同じサイズの)サンプルを示しています。 黒と赤の曲線は以前と同じです。
明らかに、密度からのサンプリングに使用される手順が機能します。また、非常に高速です。R
以下の実装では、KDEから毎秒数百万の値が生成されます。私は、Pythonまたは他の言語への移植を支援するために、それを強くコメントしました。サンプリングアルゴリズム自体はrdens
、次の行で関数に実装されています
rkernel <- function(n) rnorm(n, sd=width)
sample(x, n, replace=TRUE) + rkernel(n)
rkernel
描きn
ながら、カーネル関数からIIDのサンプルをsample
描くn
データからの交換にサンプルをx
。「+」演算子は、サンプルの2つの配列をコンポーネントごとに追加します。
正しさの正式なデモンストレーションを希望する人のために、ここで提供します。LET CDFとカーネル分布表し、データがであるものとする。カーネル推定の定義により、KDEのCDFはF K x = (x 1、x 2、… 、x n)KFKx =( x1、x2、… 、xん)
Fバツ^;K(x )= 1んΣi = 1んFK(x − x私)。
上記のレシピは、データの経験的分布からを引き出す(つまり、各について確率で値を達成する)、カーネル分布からランダム変数個別に引き、それらを合計することを示しています。分布関数がKDE の分布関数であることを証明する必要があります。定義から始めて、それがどこにつながるかを見てみましょう。ましょ任意の実数とします。条件付けはx i 1 / n i Y X + Y x Xバツバツ私1 / n私Yバツ+ YxX
FX+Y(x)=Pr(X+Y≤x)=∑i=1nPr(X+Y≤x∣X=xi)Pr(X=xi)=∑i=1nPr(xi+Y≤x)1n=1n∑i=1nPr(Y≤x−xi)=1n∑i=1nFK(x−xi)=Fx^;K(x),
主張通り。
#
# Define a function to sample from the density.
# This one implements only a Gaussian kernel.
#
rdens <- function(n, density=z, data=x, kernel="gaussian") {
width <- z$bw # Kernel width
rkernel <- function(n) rnorm(n, sd=width) # Kernel sampler
sample(x, n, replace=TRUE) + rkernel(n) # Here's the entire algorithm
}
#
# Create data.
# `dx` is the density function, used later for plotting.
#
n <- 100
set.seed(17)
x <- c(rnorm(n), rnorm(n, 4, 1/4), rnorm(n, 8, 1/4))
dx <- function(x) (dnorm(x) + dnorm(x, 4, 1/4) + dnorm(x, 8, 1/4))/3
#
# Compute a kernel density estimate.
# It returns a kernel width in $bw as well as $x and $y vectors for plotting.
#
z <- density(x, bw=0.15, kernel="gaussian")
#
# Sample from the KDE.
#
system.time(y <- rdens(3*n, z, x)) # Millions per second
#
# Plot the sample.
#
h.density <- hist(y, breaks=60, plot=FALSE)
#
# Plot the KDE for comparison.
#
h.sample <- hist(x, breaks=h.density$breaks, plot=FALSE)
#
# Display the plots side by side.
#
histograms <- list(Sample=h.sample, Density=h.density)
y.max <- max(h.density$density) * 1.25
par(mfrow=c(1,2))
for (s in names(histograms)) {
h <- histograms[[s]]
plot(h, freq=FALSE, ylim=c(0, y.max), col="#f0f0f0", border="Gray",
main=paste("Histogram of", s))
curve(dx(x), add=TRUE, col="Black", lwd=2, n=501) # Underlying distribution
lines(z$x, z$y, col="Red", lwd=2) # KDE of data
}
par(mfrow=c(1,1))