Sử dụng lại một mô hình được xây dựng trong R


82

Khi xây dựng một mô hình trong R, làm cách nào để bạn lưu các thông số kỹ thuật của mô hình để bạn có thể sử dụng lại nó trên dữ liệu mới? Giả sử tôi xây dựng hồi quy logistic trên dữ liệu lịch sử nhưng sẽ không có quan sát mới cho đến tháng sau. Cách tiếp cận tốt nhất là gì?

Những điều tôi đã cân nhắc:

  • Lưu đối tượng mô hình và tải trong một phiên mới
  • Tôi biết rằng một số mô hình có thể được xuất bằng PMML, nhưng chưa thực sự thấy gì về việc nhập PMML

Đơn giản, tôi đang cố gắng hiểu những gì bạn làm khi cần sử dụng mô hình của mình trong một phiên mới.

Cảm ơn trước.


Vâng, bạn luôn có thể "tiết kiệm" một công thức mô hình, và cung cấp cập nhật dữ liệu trong datalập luận ... giả định rằng tôi hiểu bạn một cách chính xác ...
aL3xa

Hmm, ý bạn là gì khi sử dụng lại? Dự đoán cho các quan sát mới hoặc cập nhật mô hình phù hợp để sử dụng các quan sát mới cộng với các quan sát cũ?
Gavin Simpson

@Gavin. Tôi muốn sử dụng mô hình mà tôi đã phát triển để dự đoán các giá trị mới trên dữ liệu mà tôi chưa có và có thể không có trong một thời gian.
Btibert3

1
@ Bitbert3 OK, sau đó phần mở đầu câu trả lời của tôi là những gì tôi sẽ làm. Lưu đối tượng mô hình ra đĩa là không thể chấp nhận được, nhưng điều quan trọng là phải lưu mã / tập lệnh R được sử dụng để tạo mô hình ngay từ đầu để nghiên cứu / mô hình của bạn có thể tái tạo.
Gavin Simpson

Câu trả lời:


143

Sử dụng lại mô hình để dự đoán cho các quan sát mới

Nếu mô hình không tốn kém về mặt tính toán, tôi có xu hướng ghi lại toàn bộ quá trình xây dựng mô hình trong một tập lệnh R để tôi chạy lại khi cần. Nếu một yếu tố ngẫu nhiên có liên quan đến việc điều chỉnh mô hình, tôi đảm bảo đặt một hạt ngẫu nhiên đã biết.

Nếu mô hình tốn kém về mặt tính toán, thì tôi vẫn sử dụng một tập lệnh như trên, nhưng tiết kiệm các đối tượng mô hình bằng đối tượng save()into và rda. Sau đó, tôi có xu hướng sửa đổi tập lệnh sao cho nếu đối tượng đã lưu tồn tại, hãy tải nó hoặc nếu không, hãy chỉnh sửa lại mô hình, bằng cách sử dụng một if()...elsemệnh đề đơn giản bao quanh các phần liên quan của mã.

Khi tải đối tượng mô hình đã lưu của bạn, hãy nhớ tải lại bất kỳ gói nào được yêu cầu, mặc dù trong trường hợp của bạn nếu mô hình logit phù hợp thông qua glm()sẽ không có bất kỳ gói bổ sung nào để tải ngoài R.

Đây là một ví dụ:

> set.seed(345)
> df <- data.frame(x = rnorm(20))
> df <- transform(df, y = 5 + (2.3 * x) + rnorm(20))
> ## model
> m1 <- lm(y ~ x, data = df)
> ## save this model
> save(m1, file = "my_model1.rda")
> 
> ## a month later, new observations are available: 
> newdf <- data.frame(x = rnorm(20))
> ## load the model
> load("my_model1.rda")
> ## predict for the new `x`s in `newdf`
> predict(m1, newdata = newdf)
        1         2         3         4         5         6 
6.1370366 6.5631503 2.9808845 5.2464261 4.6651015 3.4475255 
        7         8         9        10        11        12 
6.7961764 5.3592901 3.3691800 9.2506653 4.7562096 3.9067537 
       13        14        15        16        17        18 
2.0423691 2.4764664 3.7308918 6.9999064 2.0081902 0.3256407 
       19        20 
5.4247548 2.6906722 

Nếu muốn tự động hóa việc này, thì tôi có thể làm như sau trong một tập lệnh:

## data
df <- data.frame(x = rnorm(20))
df <- transform(df, y = 5 + (2.3 * x) + rnorm(20))

## check if model exists? If not, refit:
if(file.exists("my_model1.rda")) {
    ## load model
    load("my_model1.rda")
} else {
    ## (re)fit the model
    m1 <- lm(y ~ x, data = df)
}

## predict for new observations
## new observations
newdf <- data.frame(x = rnorm(20))
## predict
predict(m1, newdata = newdf)

Tất nhiên, mã tạo dữ liệu sẽ được thay thế bằng mã tải dữ liệu thực tế của bạn.

Cập nhật mô hình được trang bị trước đó với các quan sát mới

Nếu bạn muốn trang bị lại mô hình bằng cách sử dụng các quan sát mới bổ sung. Sau đó update()là một chức năng hữu ích. Tất cả những gì nó làm là trang bị lại mô hình với một hoặc nhiều đối số mô hình được cập nhật. Nếu bạn muốn bao gồm các quan sát mới trong dữ liệu được sử dụng để phù hợp với mô hình, hãy thêm các quan sát mới vào khung dữ liệu được chuyển đến đối số 'data', rồi thực hiện như sau:

m2 <- update(m1, . ~ ., data = df)

nơi m1được bản gốc, lưu mô hình phù hợp, . ~ .là thay đổi mô hình công thức, mà trong trường hợp này có nghĩa là bao gồm tất cả các biến đang tồn tại trên cả hai bên tay trái và bên phải của ~(nói cách khác, làm cho không có thay đổi công thức mô hình), và dflà khung dữ liệu được sử dụng để phù hợp với mô hình ban đầu, được mở rộng để bao gồm các quan sát mới có sẵn.

Đây là một ví dụ hoạt động:

> set.seed(123)
> df <- data.frame(x = rnorm(20))
> df <- transform(df, y = 5 + (2.3 * x) + rnorm(20))
> ## model
> m1 <- lm(y ~ x, data = df)
> m1

Call:
lm(formula = y ~ x, data = df)

Coefficients:
(Intercept)            x  
      4.960        2.222  

> 
> ## new observations
> newdf <- data.frame(x = rnorm(20))
> newdf <- transform(newdf, y = 5 + (2.3 * x) + rnorm(20))
> ## add on to df
> df <- rbind(df, newdf)
> 
> ## update model fit
> m2 <- update(m1, . ~ ., data = df)
> m2

Call:
lm(formula = y ~ x, data = df)

Coefficients:
(Intercept)            x  
      4.928        2.187

Những người khác đã được đề cập trong các bình luận formula(), trong đó trích xuất công thức từ một mô hình được trang bị:

> formula(m1)
y ~ x
> ## which can be used to set-up a new model call
> ## so an alternative to update() above is:
> m3 <- lm(formula(m1), data = df)

Tuy nhiên, nếu khớp mô hình liên quan đến các đối số bổ sung, như 'family'hoặc 'subset'đối số trong các hàm khớp mô hình phức tạp hơn. Nếu update()các phương pháp có sẵn cho chức năng điều chỉnh mô hình của bạn (chúng dành cho nhiều chức năng điều chỉnh phổ biến, chẳng hạn như glm()), thì nó cung cấp một cách đơn giản hơn để cập nhật mô hình phù hợp hơn là trích xuất và sử dụng lại công thức mô hình.

Nếu bạn có ý định thực hiện tất cả các mô hình hóa và dự đoán tương lai trong R, có vẻ như không có nhiều điểm trong việc trừu tượng hóa mô hình thông qua PMML hoặc tương tự.


1
+1 và nếu bạn vui lòng sẽ cưỡng lại từ chỉnh sửa câu trả lời của bạn để phù hợp trong bất cứ trả lời tôi đang chuẩn bị ... ;-)
Joris meys

@Joris không nhận ra là một con chó cái! ;-) +1 cho updatetừ tôi
Gavin Simpson

1
Đây là một câu trả lời thực sự tuyệt vời. Tôi hy vọng ai đó sắp xếp các câu trả lời SO [r] như câu này và tập hợp chúng lại thành một hướng dẫn.
JD Dài

1
Câu trả lời xuất sắc. Cảm ơn vì những ví dụ bạn đã đưa ra.
nhern121

1
Chính xác những gì tôi đang tìm kiếm. Tôi muốn thực hiện +1000 ... Cảm ơn bạn
Adjeiinfo

7

Nếu bạn sử dụng cùng tên của khung dữ liệu và các biến, bạn có thể (ít nhất cho lm()glm()) sử dụng hàm updatetrên mô hình đã lưu:

Df <- data.frame(X=1:10,Y=(1:10)+rnorm(10))

model <- lm(Y~X,data=Df)
model

Df <- rbind(Df,data.frame(X=2:11,Y=(10:1)+rnorm(10)))

update(model)

Điều này là không cần thiết nếu không có bất kỳ sự chuẩn bị nào về dữ liệu, v.v. Nó chỉ sử dụng lại các thông số kỹ thuật của mô hình. Lưu ý rằng nếu bạn thay đổi độ tương phản trong thời gian chờ đợi, mô hình mới sẽ được cập nhật với độ tương phản mới chứ không phải cũ.

Vì vậy, việc sử dụng script trong hầu hết các trường hợp là câu trả lời tốt hơn. Một có thể bao gồm tất cả các bước trong một hàm tiện lợi chỉ lấy khung dữ liệu, vì vậy bạn có thể tạo nguồn tập lệnh và sau đó sử dụng hàm trên bất kỳ tập dữ liệu mới nào. Xem thêm câu trả lời của Gavin cho điều đó.

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.