ประมาณความหนาแน่นเคอร์เนล (KDE) ผลิตการกระจายที่เป็นส่วนผสมที่ตั้งของการกระจายเคอร์เนลดังนั้นเพื่อดึงค่าจากการประมาณการความหนาแน่นเคอร์เนลสิ่งที่คุณต้องทำคือ (1) วาดค่าจากความหนาแน่นเคอร์เนลแล้ว (2) เลือกหนึ่งในจุดข้อมูลที่สุ่มและเพิ่มมูลค่าให้กับผลลัพธ์ของ (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
ตัวดำเนินการ "+" เพิ่มสองตัวอย่างอาร์เรย์ของส่วนประกอบตัวอย่างตามส่วนประกอบ
KFKx =( x1, x2, … , xn)
Fx^;K( x ) = 1nΣผม = 1nFK( x - xผม) .
Xxผม1 / nผมYX+ YxX
FX+ Y( x )= Pr ( X+ Y≤ x )= ∑i = 1nราคา( X+ Y≤ x ∣ X= xผม) Pr ( X= xผม)= ∑i = 1nราคา( xผม+ Y≤ x ) 1n= 1nΣi = 1nPr ( Y≤ x - xผม)= 1nΣi = 1nFK( x - xผม)= 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))