Giải thích kết quả spline


20

Tôi đang cố gắng điều chỉnh spline cho GLM bằng R. Một khi tôi điều chỉnh spline, tôi muốn có thể lấy mô hình kết quả của mình và tạo tệp mô hình hóa trong sổ làm việc Excel.

Ví dụ: giả sử tôi có một tập dữ liệu trong đó y là hàm ngẫu nhiên của x và độ dốc thay đổi đột ngột tại một điểm cụ thể (trong trường hợp này là @ 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)

Bây giờ tôi phù hợp với điều này bằng cách sử dụng

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

và kết quả của tôi cho thấy

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

Tại thời điểm này, tôi có thể sử dụng chức năng dự đoán trong r và nhận được câu trả lời hoàn toàn chấp nhận được. Vấn đề là tôi muốn sử dụng kết quả mô hình để xây dựng một bảng tính trong Excel.

Sự hiểu biết của tôi về hàm dự đoán là đã đưa ra một giá trị "x" mới, r cắm x mới đó vào hàm spline thích hợp (hàm cho các giá trị trên 500 hoặc hàm cho các giá trị dưới 500), sau đó nó sẽ lấy kết quả đó và nhân lên nó theo hệ số thích hợp và từ thời điểm đó đối xử với nó như bất kỳ thuật ngữ mô hình nào khác. Làm thế nào để tôi có được các chức năng spline?

(Lưu ý: Tôi nhận thấy rằng GLM gamma được liên kết nhật ký có thể không phù hợp với tập dữ liệu được cung cấp. Tôi không hỏi về cách thức hoặc thời điểm phù hợp với GLM.


7
Tôi đề nghị, nếu có thể, nên tránh bao gồm mã xóa tất cả các biến ( rm(list=ls())), đặc biệt là không có bất kỳ cảnh báo nào. Ai đó có thể sao chép-dán mã của bạn vào một phiên mở của R nơi họ có một số biến rồi (nhưng không ai gọi x, y, dfhoặc spline1) và bỏ lỡ rằng mã của bạn làm mờ nhạt những công việc của họ. Có phải họ hơi ngu ngốc khi làm điều đó? Vâng. Nhưng nó vẫn lịch sự khi để họ quyết định khi nào sẽ xóa các biến của chính họ.
Glen_b -Reinstate Monica

Câu trả lời:


25

Bạn có thể thiết kế ngược các công thức spline mà không cần phải đi vào Rmã. Nó đủ để biết rằng

  • Một spline là một hàm đa thức piecewise.

  • dd+1

  • Các hệ số của đa thức có thể thu được thông qua hồi quy tuyến tính.

d+1xxdd= =34×4= =16d+1= =4x

64RR

Phương pháp này sẽ hoạt động với bất kỳ phần mềm thống kê nào, ngay cả phần mềm độc quyền không có giấy tờ có mã nguồn không khả dụng.

200,500,800(1,1000)RR

Lô R

Lô Excel

(Các đường lưới màu xám dọc trong Rphiên bản hiển thị các nút thắt bên trong.)


Đây là Rmã đầy đủ . Đây là một hack không tinh vi, hoàn toàn dựa vào pastechức năng để thực hiện thao tác chuỗi. (Một cách tốt hơn sẽ là tạo một mẫu công thức và điền nó vào bằng cách sử dụng các lệnh khớp và thay thế chuỗi.)

#
# 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

Công thức đầu ra spline đầu tiên (trong số bốn công thức được sản xuất ở đây) là

"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)"

Rxx

Đoạn trích Excel


2
ns.formula.. bạn có nghĩ trong R?! Nghiêm túc mặc dù phương pháp của bạn trông rất hữu ích nhưng có vẻ mỉa mai khi phải hack một bản hack để có được các tham số này. Sẽ rất hữu ích để xuất ra một bảng ..
geotheory 16/12/14

Đây có thể là một câu hỏi ngu ngốc: nhưng đó là 4 spline bạn đang âm mưu, hay 4 cơ sở của một spline?
Erosennin

@Erosennin Tôi phụ thuộc vào ý của bạn là "một spline." Bốn đường cong này là cơ sở cho một spline là khối lập phương trong bốn khoảng và liên tục thứ hai khác nhau tại ba điểm mà các khoảng đó gặp nhau, như được mô tả bởi ba điểm gạch đầu dòng giới thiệu câu trả lời của tôi.
whuber

Cảm ơn! Tôi không có ý là nitpicking, Nó chỉ trông giống như có bốn spline (từ câu trả lời), và không phải bốn đường cong là một cơ sở. Một lần nữa, tôi chỉ ở đây để cố gắng hiểu ...
Erosennin

1
@Erosennin Không có vấn đề. Có lẽ điều này sẽ giúp: "spline" là bất kỳ sự kết hợp tuyến tính nào của bốn đường cong này được xác định bởi quá trình khớp hồi quy. Một cách khác để đặt nó: spline bao gồm một không gian vectơ của các đường cong có thể được tạo ra bằng cách kết hợp tuyến tính của bốn đường cong này.
whuber

4

Bạn đã làm như sau:

> 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"))
> 

Bây giờ tôi sẽ chỉ cho bạn cách dự đoán (phản hồi) cho x = 12 theo hai cách khác nhau: Đầu tiên sử dụng chức năng dự đoán (cách dễ dàng!)

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

Cách thứ 2 dựa trên ma trận mô hình trực tiếp. Lưu ý tôi đã sử dụng expvì chức năng liên kết được sử dụng là log.

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

Lưu ý rằng ở trên tôi đã trích xuất phần tử thứ 12, vì nó tương ứng với x = 12. Nếu bạn muốn dự đoán cho một x bên ngoài tập huấn luyện, thì đơn giản là bạn có thể sử dụng lại chức năng dự đoán. Hãy nói rằng chúng tôi muốn tìm giá trị phản hồi dự đoán cho x = 1100 rồi

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

Cảm ơn bạn đã phản hồi của bạn! Nhưng, tôi vẫn bối rối: /. Tôi không chắc tôi biết phải làm gì với ma trận này. Ví dụ: nếu tôi có x = 12, thì dự đoán sẽ nói y = 68.78721, nhưng tìm kiếm 12 từ ma trận đó tôi nhận được 0,016816392. Hệ số chặn và hệ số ban đầu cho x <500 lần lượt là 4.174603 và 3.830416. điểm kinh nghiệm (4.174603 + 3.8304116 * 0.016816392) <> 68.78721. Ngoài ra, làm thế nào tôi có thể nhận được các giá trị cho x nếu x không có trong tập huấn luyện?
Eric

Tôi đã thay đổi câu trả lời của tôi.
Thống kê

Tôi đã thêm một mã cho trường hợp khi x không có trong tập huấn luyện.
Thống kê

2
Có cách nào để có được 366.3483 cho x = 1100 mà không cần sử dụng chức năng dự đoán không?
Eric

4

Bạn có thể thấy dễ dàng hơn khi sử dụng cơ sở năng lượng cắt ngắn cho các chuỗi hồi quy bậc ba, sử dụng rmsgói R. Khi bạn vừa với mô hình, bạn có thể truy xuất biểu diễn đại số của hàm spline được trang bị bằng cách sử dụng Functionhoặc các latexhàm trong rms.


Cảm ơn bạn. Tôi thực sự đã đọc phản hồi của bạn ở đây stats.stackexchange.com/questions/67607/ trên trước khi đăng. Tôi đoán tôi chỉ cần nắm bắt tốt hơn những gì tôi có thể làm với rms.
Eric

Các tài liệu cho Function()không thực sự nói những gì nó làm. Trong trường hợp của tôi (xem chi tiết trên Rpubs rpubs.com/EmilOWK/rms_splines ), tôi nhận được 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>Các -2863.7787giá trị là coef đầu tiên trong mô hình, các 245.72672thứ hai, và coef cuối cùng -873.0223không nhìn thấy bất cứ nơi nào trong phương trình. Điều tương tự áp dụng cho đầu ra của latex().
Deleet

Functionhoạt động với Glm()khi bạn sử dụng rcsnhư hàm spline. Đầu ra đang định nghĩa lại spline ở dạng đơn giản nhất bằng cách viết như thể các giới hạn đuôi tuyến tính không có (nhưng chúng) như chi tiết trong ghi chú khóa học RMS của tôi .
Frank Harrell
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.