การตีความผลลัพธ์ spline


20

ฉันกำลังพยายามที่จะทำให้เป็นเส้นโค้งสำหรับ GLM โดยใช้ R เมื่อฉันพอดีกับเส้นโค้งฉันต้องการที่จะสามารถใช้แบบจำลองที่เป็นผลลัพธ์ของฉันและสร้างไฟล์การสร้างแบบจำลองในสมุดงาน Excel

ตัวอย่างเช่นสมมติว่าฉันมีชุดข้อมูลที่ y เป็นฟังก์ชันแบบสุ่มของ x และความชันจะเปลี่ยนทันทีที่จุดเฉพาะ (ในกรณีนี้ @ x = 500)

set.seed(1066)
x<- 1:1000
y<- rep(0,1000)

y[1:500]<- pmax(x[1:500]+(runif(500)-.5)*67*500/pmax(x[1:500],100),0.01)
y[501:1000]<-500+x[501:1000]^1.05*(runif(500)-.5)/7.5

df<-as.data.frame(cbind(x,y))

plot(df)

ตอนนี้ฉันเหมาะกับการใช้

library(splines)
spline1 <- glm(y~ns(x,knots=c(500)),data=df,family=Gamma(link="log"))

และผลลัพธ์ของฉันแสดง

summary(spline1)

Call:
glm(formula = y ~ ns(x, knots = c(500)), family = Gamma(link = "log"), 
    data = df)

Deviance Residuals: 
     Min       1Q   Median       3Q      Max  
-4.0849  -0.1124  -0.0111   0.0988   1.1346  

Coefficients:
                       Estimate Std. Error t value Pr(>|t|)    
(Intercept)             4.17460    0.02994  139.43   <2e-16 ***
ns(x, knots = c(500))1  3.83042    0.06700   57.17   <2e-16 ***
ns(x, knots = c(500))2  0.71388    0.03644   19.59   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for Gamma family taken to be 0.1108924)

    Null deviance: 916.12  on 999  degrees of freedom
Residual deviance: 621.29  on 997  degrees of freedom
AIC: 13423

Number of Fisher Scoring iterations: 9

ณ จุดนี้ฉันสามารถใช้ฟังก์ชันทำนายผลได้ภายใน r และรับคำตอบที่สมบูรณ์แบบ ปัญหาคือฉันต้องการใช้ผลลัพธ์โมเดลเพื่อสร้างเวิร์กบุ๊กใน Excel

ความเข้าใจของฉันเกี่ยวกับฟังก์ชั่นการคาดการณ์คือให้ค่า "x" ใหม่ r เสียบปลั๊ก x ใหม่ลงในฟังก์ชัน spline ที่เหมาะสม (ฟังก์ชันสำหรับค่าที่สูงกว่า 500 หรือค่าที่ต่ำกว่า 500) จากนั้นจึงนำผลลัพธ์นั้นมาและคูณ โดยค่าสัมประสิทธิ์ที่เหมาะสมและจากจุดนั้นถือว่ามันเหมือนคำรุ่นอื่น ๆ ฉันจะรับฟังก์ชันอิสระได้อย่างไร

(หมายเหตุ: ฉันรู้ว่า GLM แกมม่าที่เชื่อมโยงกับบันทึกอาจไม่เหมาะสมสำหรับชุดข้อมูลที่ให้ฉันไม่ได้ถามว่าจะให้ GLMs เป็นอย่างไรหรือเมื่อไหร่ฉันกำลังจัดเตรียมชุดนั้นเป็นตัวอย่างสำหรับวัตถุประสงค์ในการทำซ้ำ)


7
ฉันแนะนำถ้าเป็นไปได้ทั้งหมดเพื่อหลีกเลี่ยงการรวมรหัสที่ลบตัวแปรทั้งหมด ( rm(list=ls())) โดยเฉพาะอย่างยิ่งไม่ได้โดยไม่มีการเตือนใด ๆ บางคนอาจคัดลอกวางรหัสของคุณลงในเซสชั่นที่เปิดกว้างของ R ที่พวกเขามีตัวแปรบางอยู่แล้ว ( แต่ไม่มีใครเรียกว่าx, y, dfหรือspline1) และพลาดว่ารหัสของคุณเช็ดออกงานของพวกเขา เป็นเรื่องที่ทำให้พวกเขาโง่หรือไม่? ใช่. แต่มันก็ยังสุภาพที่จะให้พวกเขาตัดสินใจว่าจะลบตัวแปรของตัวเองเมื่อใด
Glen_b -Reinstate Monica

คำตอบ:


25

คุณสามารถทำวิศวกรรมย้อนกลับสูตร spline โดยไม่ต้องเข้าไปในRรหัส พอเพียงที่จะรู้ว่า

  • เส้นโค้งเป็นฟังก์ชันพหุนามแบบชิ้นเดียว

  • พหุนามของดีกรีนั้นพิจารณาจากค่าของพวกเขาที่คะแนนd + 1dd+1

  • ค่าสัมประสิทธิ์ของพหุนามสามารถหาได้จากการถดถอยเชิงเส้น

ดังนั้นคุณจะต้องสร้างจุดระยะห่างระหว่างคู่ของนอตต่อเนื่อง (รวมถึงปลายทางโดยนัยของช่วงข้อมูล) โดยคาดการณ์ค่าเส้นโค้งและถอยหลังคำทำนายต่ออำนาจของถึง d จะมีสูตรแยกต่างหากสำหรับองค์ประกอบพื้นฐานแต่ละเส้นโค้งภายใน "bin" ปมแต่ละอัน ตัวอย่างเช่นในตัวอย่างด้านล่างมีปมภายในสามอัน (สำหรับถังขยะปมสี่อัน) และลูกบาศก์ splines ( ) ถูกนำมาใช้ทำให้เกิดลูกบาศก์พหุนามหลายลูกบาศก์แต่ละตัวมีค่าสัมประสิทธิ์เพราะพลังที่ค่อนข้างสูงของx x d d = 3 4 × 4 = 16 d + 1 = 4 xd+1xxdd=34×4=16d+1=4xมีส่วนร่วมมันเป็นสิ่งจำเป็นเพื่อรักษาความแม่นยำทั้งหมดในสัมประสิทธิ์ อย่างที่คุณอาจจินตนาการว่าสูตรเต็มรูปแบบสำหรับองค์ประกอบพื้นฐานใด ๆ จะมีความยาวพอสมควร!

ดังที่ฉันได้กล่าวไปเมื่อไม่นานมานี้ความสามารถในการใช้เอาต์พุตของโปรแกรมหนึ่งเป็นอินพุตของอีกโปรแกรมหนึ่ง (โดยไม่มีการแทรกแซงด้วยตนเองซึ่งสามารถแนะนำข้อผิดพลาดที่ไม่สามารถพิสูจน์ได้) เป็นทักษะการสื่อสารทางสถิติที่มีประโยชน์ คำถามนี้ให้ตัวอย่างที่ดีเกี่ยวกับวิธีใช้หลักการนั้น: แทนที่จะคัดลอกสัมประสิทธิ์สิบหกหลักด้วยตนเองเราสามารถแฮ็กวิธีแปลง splines ที่คำนวณโดยเป็นสูตรที่ Excel เข้าใจได้ สิ่งที่เราต้องทำคือแยกค่าสัมประสิทธิ์ spline จากที่อธิบายไว้ข้างต้นมีการจัดรูปแบบเหล่านั้นลงในสูตรเหมือน Excel และคัดลอกและวางลงใน Excel64RR

วิธีนี้จะทำงานร่วมกับซอฟต์แวร์ทางสถิติใด ๆ แม้แต่ซอฟต์แวร์ที่ไม่มีเอกสารซึ่งไม่มีซอร์สโค้ด

นี่คือตัวอย่างที่นำมาจากคำถาม แต่ปรับเปลี่ยนให้มีปมที่สามจุดภายใน ( ) เช่นเดียวกับที่ปลายทาง1000) พล็อตแสดงเวอร์ชันของตามด้วยการเรนเดอร์ของ Excel มีการปรับแต่งเล็กน้อยมากในทั้งสองสภาพแวดล้อม (นอกเหนือจากการระบุสีให้ตรงกับสีเริ่มต้นของ Excel โดยประมาณ)( 1 , 1,000 )200,500,800(1,1000)RR

แปลง R

แปลง Excel

(เส้นกริดสีเทาแนวตั้งในRเวอร์ชันแสดงตำแหน่งของปมภายใน)


นี่คือRรหัสเต็ม มันเป็นการแฮ็คที่ไม่ซับซ้อนโดยอาศัยpasteฟังก์ชั่นทั้งหมดในการจัดการสตริง (วิธีที่ดีกว่าคือการสร้างเทมเพลตสูตรและเติมโดยใช้การจับคู่สตริงและคำสั่งการแทนที่)

#
# Create and display a spline basis.
#
x <- 1:1000
n <- ns(x, knots=c(200, 500, 800))

colors <- c("Orange", "Gray", "tomato2", "deepskyblue3")
plot(range(x), range(n), type="n", main="R Version",
     xlab="x", ylab="Spline value")
for (k in attr(n, "knots")) abline(v=k, col="Gray", lty=2)
for (j in 1:ncol(n)) {
  lines(x, n[,j], col=colors[j], lwd=2)
}
#
# Export this basis in Excel-readable format.
#
ns.formula <- function(n, ref="A1") {
  ref.p <- paste("I(", ref, sep="")
  knots <- sort(c(attr(n, "Boundary.knots"), attr(n, "knots")))
  d <- attr(n, "degree")
  f <- sapply(2:length(knots), function(i) {
    s.pre <- paste("IF(AND(", knots[i-1], "<=", ref, ", ", ref, "<", knots[i], "), ", 
                   sep="")
    x <- seq(knots[i-1], knots[i], length.out=d+1)
    y <- predict(n, x)
    apply(y, 2, function(z) {
      s.f <- paste("z ~ x+", paste("I(x", 2:d, sep="^", collapse=")+"), ")", sep="")
      f <- as.formula(s.f)
      b.hat <- coef(lm(f))
      s <- paste(c(b.hat[1], 
            sapply(1:d, function(j) paste(b.hat[j+1], "*", ref, "^", j, sep=""))), 
            collapse=" + ")
      paste(s.pre, s, ", 0)", sep="")
    })
  })
  apply(f, 1, function(s) paste(s, collapse=" + "))
}
ns.formula(n) # Each line of this output is one basis formula: paste into Excel

สูตรเอาต์พุต spline แรก (จากสี่ที่ผลิตที่นี่) คือ

"IF(AND(1<=A1, A1<200), -1.26037447288906e-08 + 3.78112341937071e-08*A1^1 + -3.78112341940948e-08*A1^2 + 1.26037447313669e-08*A1^3, 0) + IF(AND(200<=A1, A1<500), 0.278894459758071 + -0.00418337927419299*A1^1 + 2.08792741929417e-05*A1^2 + -2.22580643138594e-08*A1^3, 0) + IF(AND(500<=A1, A1<800), -5.28222778473101 + 0.0291833541927414*A1^1 + -4.58541927409268e-05*A1^2 + 2.22309136420529e-08*A1^3, 0) + IF(AND(800<=A1, A1<1000), 12.500000000002 + -0.0375000000000067*A1^1 + 3.75000000000076e-05*A1^2 + -1.25000000000028e-08*A1^3, 0)"

เพื่อให้ทำงานใน Excel สิ่งที่คุณต้องทำคือลบเครื่องหมายคำพูดล้อมรอบและนำหน้าด้วยเครื่องหมาย "=" (ด้วยความพยายามอีกเล็กน้อยคุณสามารถRเขียนไฟล์ซึ่งเมื่อนำเข้าโดย Excel จะมีสำเนาของสูตรเหล่านี้ในสถานที่ที่ถูกต้องทั้งหมด) วางลงในกล่องสูตรแล้วลากเซลล์นั้นไปรอบ ๆ จนกว่าจะ "A1" อ้างอิงก่อนค่าที่จะคำนวณ spline คัดลอกและวาง (หรือลากและวาง) เซลล์นั้นเพื่อคำนวณค่าสำหรับเซลล์อื่น ฉันเติมเซลล์ B2: E: 102 ด้วยสูตรเหล่านี้โดยอ้างอิงค่าในเซลล์ A2: A102xxx

ตัวอย่างของ Excel


2
ns.formula.. คุณคิดว่าใน R หรือไม่! อย่างจริงจังแม้ว่าวิธีการของคุณดูมีประโยชน์มาก แต่ดูเหมือนว่าน่าขันที่จะต้องแฮ็คแฮ็คเพื่อรับพารามิเตอร์เหล่านี้ จะเป็นประโยชน์อย่างมากในการแสดงผลตาราง ..
geotheory

นี่อาจเป็นคำถามงี่เง่า: แต่มันคือ 4 เส้นโค้งที่คุณกำลังวางแผนหรือ 4 พื้นฐานของหนึ่ง spline?
Erosennin

@Erosennin ฉันขึ้นอยู่กับว่าคุณหมายถึงอะไรโดย "หนึ่ง spline" สี่เส้นโค้งเหล่านี้เป็นพื้นฐานสำหรับเส้นโค้งที่เป็นลูกบาศก์ในสี่ช่วงเวลาและสองต่อเนื่อง differentiable ที่สามจุดที่ช่วงเวลาเหล่านั้นตอบสนองตามที่อธิบายโดยกระสุนสามจุดที่แนะนำคำตอบของฉัน
whuber

ขอบคุณ! ฉันไม่ได้ตั้งใจจะ nitpicking มันดูราวกับว่ามีสี่เส้นโค้ง (จากคำตอบ) และไม่ใช่สี่เส้นโค้งที่เป็นพื้นฐาน อีกครั้งฉันแค่ที่นี่พยายามที่จะเข้าใจ ...
Erosennin

1
@Erosennin ไม่มีปัญหา อาจจะช่วยได้: "เส้นโค้ง" เป็นสิ่งที่การรวมกันเชิงเส้นของสี่เส้นโค้งเหล่านี้ถูกกำหนดโดยกระบวนการการถดถอยที่เหมาะสม อีกวิธีในการใส่: เส้นโค้งประกอบด้วยพื้นที่เวกเตอร์ของเส้นโค้งที่สามารถสร้างขึ้นได้โดยการใช้การผสมเชิงเส้นของสี่เส้นโค้งเหล่านี้
whuber

4

คุณทำสิ่งต่อไปนี้แล้ว:

> rm(list=ls())
> set.seed(1066)
> x<- 1:1000
> y<- rep(0,1000)
> y[1:500]<- pmax(x[1:500]+(runif(500)-.5)*67*500/pmax(x[1:500],100),0.01)
> y[501:1000]<-500+x[501:1000]^1.05*(runif(500)-.5)/7.5
> df<-as.data.frame(cbind(x,y))
> library(splines)
> spline1 <- glm(y~ns(x,knots=c(500)),data=df,family=Gamma(link="log"))
> 

ตอนนี้ฉันจะแสดงให้คุณเห็นวิธีการทำนาย (การตอบสนอง) สำหรับ x = 12 ในสองวิธีที่ต่างกัน: อันดับแรกใช้ฟังก์ชั่นการทำนาย (วิธีง่าย ๆ !)

> new.dat=data.frame(x=12)
> predict(spline1,new.dat,type="response")
       1 
68.78721 

วิธีที่ 2 ขึ้นอยู่กับเมทริกซ์ของโมเดลโดยตรง หมายเหตุฉันใช้expเนื่องจากฟังก์ชั่นลิงค์ที่ใช้คือบันทึก

> m=model.matrix( ~ ns(df$x,knots=c(500))) 
> prd=exp(coefficients(spline1) %*% t(m)) 
> prd[12]
[1] 68.78721

โปรดทราบว่าในข้างต้นฉันแยกองค์ประกอบที่ 12 เนื่องจากที่สอดคล้องกับ x = 12 หากคุณต้องการทำนายค่า x นอกชุดฝึกอบรมคุณสามารถใช้ฟังก์ชันทำนายอีกครั้งได้ ให้บอกว่าเราต้องการหาค่าการตอบสนองที่คาดการณ์ไว้สำหรับ x = 1100 แล้ว

> predict(spline1, newdata=data.frame(x=1100),type="response")
       1 
366.3483 

ขอขอบคุณสำหรับการตอบสนองของคุณ! แต่ฉันยังสับสนอยู่: / ฉันไม่แน่ใจว่าฉันรู้ว่าจะทำอย่างไรกับเมทริกซ์นี้ ตัวอย่างเช่นถ้าฉันมี x = 12 ให้ทำนายว่า y = 68.78721 แต่ค้นหา 12 จากเมทริกซ์นั้นฉันจะได้ 0.016816392 ค่าตัดและค่าสัมประสิทธิ์ดั้งเดิมสำหรับ x <500 คือ 4.174603 และ 3.830416 ตามลำดับ exp (4.174603 + 3.8304116 * 0.016816392) <> 68.78721 นอกจากนี้ฉันจะได้รับค่า x อย่างไรถ้า x ไม่ได้อยู่ในชุดฝึกอบรม
Eric

ฉันเปลี่ยนคำตอบ
สถิติ

ฉันเพิ่มรหัสสำหรับเคสเมื่อ x ไม่ได้อยู่ในชุดฝึกอบรม
สถิติ

2
มีวิธีรับ 366.3483 สำหรับ x = 1100 โดยไม่ใช้ฟังก์ชันทำนายหรือไม่
Eric

4

คุณอาจพบว่าการใช้พื้นฐานพลังงานที่ถูกตัดทอนได้ง่ายขึ้นสำหรับ Spline ถดถอยแบบลูกบาศก์โดยใช้rmsแพ็คเกจR เมื่อคุณพอดีกับแบบจำลองคุณสามารถดึงข้อมูลการเป็นตัวแทนของพีชคณิตของฟังก์ชั่น spline ที่ติดตั้งโดยใช้Functionหรือlatexฟังก์ชั่นrmsมา


ขอขอบคุณ. ฉันอ่านคำตอบของคุณที่นี่stats.stackexchange.com/questions/67607/…ก่อนโพสต์ ฉันเดาว่าฉันต้องเข้าใจสิ่งที่ฉันสามารถทำได้กับ rms
Eric

เอกสารสำหรับFunction()ไม่ได้บอกว่ามันทำอะไร ในกรณีของฉัน (ดูรายละเอียดเกี่ยวกับ Rpubs rpubs.com/EmilOWK/rms_splines ) ผมได้รับค่าเป็น COEF ครั้งแรกในรูปแบบที่สองและ COEF ที่ผ่านมาไม่ได้เห็นในทุกที่สมการ เช่นเดียวกับการส่งออกของ function(x = NA) {-2863.7787+245.72672* x-0.1391794*pmax(x-10.9,0)^3+0.27835881*pmax(x-50.5,0)^3-0.1391794*pmax(x-90.1,0)^3 } <environment: 0x556156e80db8>-2863.7787245.72672-873.0223latex()
Deleet

Functionทำงานร่วมกับGlm()เมื่อคุณใช้rcsเป็นฟังก์ชัน spline เอาท์พุทเป็น rephrasing เส้นโค้งในรูปแบบง่ายโดยการเขียนเช่นถ้าข้อ จำกัด หางเชิงเส้นไม่ได้มี ( แต่พวกเขามี) ตามรายละเอียดในของฉันRMS แน่นอนบันทึก
Frank Harrell
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.