Rで非線形回帰分析する

2015-02-03 (火) 17:09:11 (992d) | Topic path: Top / バイオ・データ・マイニング / Rで非線形回帰分析する

このページは自分用のメモで,まだ書きかけです.

はじめに

ここでは,Rを使って非線形回帰分析をします.

目的関数が線形の場合,最小二乗法を用いて残差 (RSS) が最小となるパラメーターを解析的に求めることができます. これから回帰分析をはじめる場合は,先に線形回帰分析をやってみましょう.

目的関数が非線形の場合,最小二乗法で解析的に解くことができません. そこで,ニュートン法や最急降下法のような方法を使って,残差 (RSS) が最小となるパラメーターを探索します. ここでは,Levenberg-Marquardt法を用います.

Levenberg-Marquardt法は,minpack.lmパッケージに含まれています.

非線形回帰

ここでは,次のようなデータに対して非線形回帰を行います.

> data <- read.csv("data.csv")
> head(data)
  x  y
1 1 97
2 2 97
3 3 97
4 4 97
5 5 97
6 6 96
> plot(x, y, ylim=c(80,100))
data.png

この値はゆるやかに単調に減少し,収束するように見えるので,次のような式で表される曲線に当てはめてみます. \[ y = a e^{bx} + c \]

ちなみに,ゼロに収束する場合は [math]c = 0[/math] となり,両辺の対数を取ることで線形に変換して線形回帰で解くことができます.

まず,当てはめたい関数を定義します.

> getPred <- function(parS, xx) parS$a * exp(xx * parS$b) + parS$c

次に,残差 (RSS) を求める関数を定義します.

> residFun <- function(p, observed, xx) observed - getPred(p,xx)

それから,探索するパラメーターの初期値を定義します.

> parStart <- list(a=10,b=-.001, c=90)

最後に,nls.lm関数を用いてパラメーターを探索します.

> nls.out <- nls.lm(par=parStart, fn=residFun, observed=data$y, xx=data$x,
+                   control=nls.lm.control(nprint=1))
It.    0, RSS =     5260.3, Par. =         10     -0.001         90
It.    1, RSS =    968.102, Par. =    5.45869 -0.00112816    91.2747
It.    2, RSS =    900.171, Par. =    5.56857 -0.00120959    91.1581
It.    3, RSS =    900.134, Par. =    5.58886 -0.00119717    91.1308
It.    4, RSS =    900.134, Par. =    5.58758 -0.00119872    91.1333
It.    5, RSS =    900.134, Par. =    5.58777 -0.00119853     91.133
> summary(nls.out)

Parameters:
    Estimate Std. Error t value Pr(>|t|)    
a  5.588e+00  8.899e-02   62.79   <2e-16 ***
b -1.199e-03  5.788e-05  -20.71   <2e-16 ***
c  9.113e+01  1.080e-01  843.73   <2e-16 ***
---
Signif. codes:  0***0.001**0.01*0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.7077 on 1797 degrees of freedom
Number of iterations to termination: 5 
Reason for termination: Relative error in the sum of squares is at most `ftol'. 

探索によって見つかった最良のパラメーターは出力されたオブジェクトのpar変数に入っています.

> nls.out$par
$a
[1] 5.587771

$b
[1] -0.001198529

$c
[1] 91.13298

求めた曲線をデータに重ねてみます.

> lines(data$x, getPred(as.list(coef(nls.out)), data$x), col=2, lwd=2)
predicted.png
添付ファイル: filepredicted.png 53件 [詳細] filedata.png 53件 [詳細]
トップ   編集 凍結解除 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS