Công cụ ước tính mật độ hạt nhân (KDE) tạo ra phân phối là hỗn hợp vị trí của phân phối hạt nhân, do đó, để rút ra một giá trị từ ước tính mật độ hạt nhân, tất cả những gì bạn cần làm là (1) rút ra một giá trị từ mật độ hạt nhân và sau đó (2) độc lập chọn một trong các điểm dữ liệu một cách ngẫu nhiên và thêm giá trị của nó vào kết quả của (1).
Đây là kết quả của thủ tục này được áp dụng cho một tập dữ liệu giống như trong câu hỏi.
Biểu đồ bên trái mô tả mẫu. Để tham khảo, đường cong màu đen biểu thị mật độ mà mẫu được vẽ. Đường cong màu đỏ vẽ đồ thị KDE của mẫu (sử dụng băng thông hẹp). (Không có vấn đề gì, hoặc thậm chí là bất ngờ, rằng các đỉnh đỏ ngắn hơn các đỉnh đen: KDE lan truyền mọi thứ ra ngoài, do đó các đỉnh sẽ giảm xuống để bù lại.)
Biểu đồ bên phải mô tả một mẫu (có cùng kích thước) từ KDE. Các đường cong màu đen và đỏ giống như trước đây.
Rõ ràng, quy trình được sử dụng để lấy mẫu từ mật độ hoạt động. Nó cũng cực kỳ nhanh: việc R
triển khai bên dưới tạo ra hàng triệu giá trị mỗi giây từ bất kỳ KDE nào. Tôi đã nhận xét rất nhiều về việc hỗ trợ chuyển sang Python hoặc các ngôn ngữ khác. Thuật toán lấy mẫu được thực hiện trong hàm rdens
với các dòng
rkernel <- function(n) rnorm(n, sd=width)
sample(x, n, replace=TRUE) + rkernel(n)
rkernel
vẽ n
các mẫu iid từ hàm kernel trong khi sample
vẽ n
các mẫu có thay thế từ dữ liệu x
. Toán tử "+" thêm hai mảng thành phần mẫu theo thành phần.
Đối với những người muốn một minh chứng chính thức về tính đúng đắn, tôi cung cấp nó ở đây. Đặt đại diện cho phân phối kernel bằng CDF và để dữ liệu là . Theo định nghĩa của ước tính kernel, CDF của KDE làKx = ( x 1 , x 2 , Mạnh , x n )FKx =( x1, x2, Lọ , xn)
Fx^;K( x ) = 1nΣi = 1nFK( x - xTôi) .
Công thức trước nói rằng rút từ phân phối dữ liệu theo kinh nghiệm (nghĩa là nó đạt giá trị với xác suất cho mỗi ), rút ra một biến ngẫu nhiên từ phân phối hạt nhân và tính tổng chúng. Tôi nợ bạn một bằng chứng rằng hàm phân phối của là của KDE. Hãy bắt đầu với định nghĩa và xem nó dẫn đến đâu. Đặt là số thực bất kỳ. Điều hòa trên chox i 1 / n i Y X + Y x XXxTôi1 / nTôiYX+ YxX
FX+ Y( x )= Pr ( X+ Y≤ x )= ∑i = 1nPr ( X+ Y≤ x ∣ X= xTôi) Pr ( X= xTôi)= ∑i = 1nPr ( xTôi+ Y≤ x ) 1n= 1nΣi = 1nPr ( Y≤ x - xTôi)= 1nΣi = 1nFK( x - xTôi)= = Fx^;K( x ) ,
như đã tuyên bố.
#
# 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))