1. ホーム
  2. r

[解決済み] Rで構築したモデルの再利用

2023-07-05 01:07:14

質問

Rでモデルを構築するとき、新しいデータで再利用できるようにモデルの仕様を保存するにはどうしたらよいでしょうか。 例えば、私が過去のデータでロジスティック回帰を構築し、来月まで新しい観測値がないとします。 どのようなアプローチが良いでしょうか?

私が検討したこと

  • モデルオブジェクトを保存し、新しいセッションで読み込む
  • いくつかのモデルがPMMLでエクスポートできることは知っていますが、PMMLのインポートに関するものは見たことがありません。

単純に、新しいセッションでモデルを使用する必要があるときに何をするかという感覚を得ようとしているのです。

事前にありがとうございます。

どのように解決するのですか?

新しい観測結果を予測するためにモデルを再利用する

モデルが計算コストのかからないものであれば、私はモデル構築プロセス全体をRスクリプトで文書化し、必要なときに再実行する傾向があります。ランダムな要素がモデル適合に関与している場合、私は既知のランダムシードを設定することを確認します。

モデルの計算に計算コストがかかる場合、私は上記のようにスクリプトを使用しますが、モデルオブジェクトの保存には save() を使用してモデルオブジェクトをrdaオブジェクトに保存します。そして、保存されたオブジェクトが存在すればそれをロードし、存在しなければモデルを再フィットするようにスクリプトを修正することが多いです。 if()...else 節で関連する部分を囲みます。

保存されたモデルオブジェクトをロードするとき、必要なパッケージを再ロードすることを確認してください。 glm() を介して適合された場合、R以外にロードする追加パッケージはないでしょう。

以下はその例です。

> 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 

もしこれを自動化したいのであれば、私はおそらくスクリプトで以下のようにします。

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

もちろん、データ生成のコードは、実際のデータを読み込むコードに置き換えられるでしょう。

新しい観測値で以前に適合したモデルを更新する

追加の新しいオブザベーションを用いて、モデルを再フィットしたい場合。その場合 update() は有用な関数です。それがすることは、1つ以上のモデル引数を更新してモデルを再フィットすることだけです。モデルを適合させるために使用されるデータに新しい観測値を含めたい場合、引数 'data' に渡されたデータフレームに新しい観測値を追加し、次のようにします。

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

ここで m1 は保存されたオリジナルのモデルフィットです。 . ~ . はモデル式の変更で、この場合、既存のすべての変数を ~ (の左側と右側にある既存の変数をすべて含める(言い換えれば、モデル式を変更しない)ことを意味し、そして df は、新しく利用可能になったオブザベーションを含むように拡張された、元のモデルを適合させるために使用されたデータフレームです。

以下は動作例です。

> 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

その他、コメントで言及されている formula() は、フィットしたモデルから数式を抽出するものです。

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

しかし、モデルフィッティングに追加の引数を含む場合、例えば 'family' のように、あるいは 'subset' 引数で指定します。もし update() メソッドが使用可能な場合(多くの一般的なフィット関数で使用可能で、例えば glm() のように)、モデル式を抽出して再利用するよりもシンプルな方法でモデルフィットを更新することができます。

すべてのモデリングと将来予測をRで行うつもりであれば、PMMLなどを使ってモデルを抽象化することにあまり意味はないようです。