Podczas budowania modelu w języku R, jak zapisać specyfikacje modelu, aby można było ich ponownie użyć na nowych danych? Powiedzmy, że buduję regresję logistyczną na danych historycznych, ale nowe obserwacje pojawią się dopiero w przyszłym miesiącu. Jakie jest najlepsze podejście?
Rzeczy, które rozważałem:
- Zapisywanie obiektu modelu i ładowanie w nowej sesji
- Wiem, że niektóre modele można eksportować za pomocą PMML, ale tak naprawdę nie widziałem nic o importowaniu PMML
Po prostu staram się zrozumieć, co robisz, kiedy musisz użyć swojego modelu w nowej sesji.
Z góry dziękuję.
data
argumentacji ... zakładając, że dobrze cię zrozumiałem ...Odpowiedzi:
Ponowne wykorzystanie modelu do przewidywania nowych obserwacji
Jeśli model nie jest kosztowny obliczeniowo, zwykle dokumentuję cały proces budowy modelu w skrypcie R, który w razie potrzeby uruchamiam ponownie. Jeśli w dopasowaniu modelu występuje element losowy, upewniam się, że ustawiam znane losowe ziarno.
Jeśli obliczenie modelu jest kosztowne, nadal używam skryptu jak powyżej, ale zapisuję obiekty modelu za pomocą
save()
into i obiektu rda. Następnie mam tendencję do modyfikowania skryptu w taki sposób, że jeśli zapisany obiekt istnieje, ładuję go, a jeśli nie, ponownie modyfikuję model, używając prostejif()...else
klauzuli owiniętej wokół odpowiednich części kodu.Podczas ładowania zapisanego obiektu modelu pamiętaj o ponownym załadowaniu wszystkich wymaganych pakietów, chociaż w twoim przypadku, jeśli model logit został dopasowany przez,
glm()
nie będzie żadnych dodatkowych pakietów do załadowania poza R.Oto przykład:
> 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
Jeśli chciałbym to zautomatyzować, prawdopodobnie wykonałbym w skrypcie następujące czynności:
## 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)
Oczywiście kod generujący dane zostałby zastąpiony kodem ładującym rzeczywiste dane.
Aktualizacja wcześniej dopasowanego modelu o nowe obserwacje
Jeśli chcesz ponownie dopasować model, korzystając z dodatkowych nowych obserwacji. Wtedy
update()
jest to przydatna funkcja. Wszystko, co robi, to ponownie dopasować model, dodając jeden lub więcej zaktualizowanych argumentów modelu. Jeśli chcesz uwzględnić nowe obserwacje w danych używanych do dopasowania modelu, dodaj nowe obserwacje do ramki danych przekazanej do argumentu'data'
, a następnie wykonaj następujące czynności:gdzie
m1
jest oryginalne, zapisane dopasowanie modelu,. ~ .
to zmiana formuły modelu, co w tym przypadku oznacza uwzględnienie wszystkich istniejących zmiennych zarówno po lewej, jak i prawej stronie~
(innymi słowy, nie wprowadzaj żadnych zmian w formule modelu) idf
jest ramka danych używana do dopasowania oryginalnego modelu, rozszerzona o nowo dostępne obserwacje.Oto działający przykład:
> 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
Inni wspominali w komentarzach
formula()
, które wyciągają wzór z dopasowanego modelu:> 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)
Jeśli jednak dopasowanie modelu obejmuje dodatkowe argumenty, takie jak
'family'
lub'subset'
argumenty w bardziej złożonych funkcjach dopasowania modelu. Jeśliupdate()
dla funkcji dopasowania modelu dostępne są metody (które są stosowane w przypadku wielu typowych funkcji dopasowania, takich jakglm()
), zapewnia to prostszy sposób aktualizacji dopasowania modelu niż wyodrębnianie i ponowne użycie formuły modelu.Jeśli zamierzasz wykonać całe modelowanie i przewidywanie przyszłości w języku R, tak naprawdę nie ma sensu wyodrębniać modelu za pomocą PMML lub podobnego.
źródło
update
ode mnieJeśli używasz tej samej nazwy ramki danych i zmiennych, możesz (przynajmniej dla
lm()
iglm()
) użyć tej funkcjiupdate
na zapisanym modelu: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)
Jest to oczywiście bez przygotowania danych i tak dalej. Po prostu ponownie wykorzystuje zestaw specyfikacji modelu. Należy pamiętać, że jeśli w międzyczasie zmienisz kontrasty, nowy model zostanie zaktualizowany o nowe, a nie stary.
Tak więc użycie skryptu jest w większości przypadków lepszą odpowiedzią. Można by uwzględnić wszystkie kroki w wygodnej funkcji, która po prostu pobiera ramkę danych, dzięki czemu można pobrać skrypt, a następnie użyć tej funkcji na dowolnym nowym zbiorze danych. Zobacz także odpowiedź Gavina.
źródło