5

たとえば、次の形式のRの非線形最小二乗モデルを考えてみます。

 y ~ theta / ( 1 + exp( -( alpha + beta * x) ) )

(私の実際の問題にはいくつかの変数があり、外部関数はロジスティックではありませんが、もう少し複雑です。これはより単純ですが、これを実行できれば、私のケースはほぼすぐに続くはずです)

「アルファ+ベータ*x」という用語を(たとえば)自然な3次スプラインに置き換えたいと思います。

ロジスティック関数内で非線形関数を使用してサンプルデータを作成するためのコードを次に示します。

set.seed(438572L)
x <- seq(1,10,by=.25)
y <- 8.6/(1+exp( -(-3+x/4.4+sqrt(x*1.1)*(1.-sin(1.+x/2.9))) )) + rnorm(x, s=0.2 )

その周りのロジスティックを必要とせずに、私がlmにいる場合、線形項をスプライン項に簡単に置き換えることができます。したがって、次のような線形モデル:

 lm( y ~ x ) 

その後になります

 library("splines")
 lm( y ~ ns( x, df = 5 ) )

適合値の生成は簡単であり、(たとえば)rmsパッケージを使用して予測値を取得することは十分に簡単に思えます。

確かに、元のデータをそのlmベースのスプラインフィットでフィッティングすることはそれほど悪くはありませんが、ロジスティック関数内でそれが必要な理由があります(つまり、私の問題では同等です)。

nlsの問題は、すべてのパラメーターの名前を指定する必要があることです(1つのスプラインフィットの場合は(b1、...、b5)と呼び、別の変数の場合はc1、...、c6と呼びます。 -私はそれらのいくつかを作ることができる必要があります)。

非線形関数内の線形項をスプラインに置き換えることができるように、nlsに対応する式を生成するための合理的に適切な方法はありますか?

それを行うことができると私が理解できる唯一の方法は、少し厄介で不格好であり、たくさんのコードを書かずにうまく一般化することはできません。

明確にするために編集)この小さな問題については、もちろん手作業で行うことができます-nsによって生成された行列内のすべての変数の内積の式を書きます、パラメータのベクトルを掛けます。しかし、その後、他のすべての変数のスプラインごとに、また、いずれかのスプラインのdfを変更するたびに、またnsの代わりにcsを使用する場合は、用語ごとにすべてを書き出す必要があります。そして、いくつかの予測(/補間)を実行しようとすると、処理する必要のあるまったく新しい多数の問題が発生します。分析後の分析のために、何度も何度も、そして潜在的にはかなり多くのノットといくつかの変数に対してそれを続ける必要があります-そして私は個々の用語を書き出すよりももっときちんとした、簡単な方法があるのだろうかと思いました、大量のコードを書く必要はありません。私はそれを行うためのかなり強気な方法を見ることができますが、それは正しくするためにかなりのコードを必要としますが、Rであるため、はるかにきちんとした方法(またはおそらく3つまたは4つのきちんとした方法)があると思います' s単に私を避けています。したがって、質問。

過去に誰かがこのようなことをかなりいい方法でやっているのを見たことがあると思いましたが、私の人生では今はそれを見つけることができません。私はそれを見つけるために何度も試しました。

[より具体的には、単純なモデルを見つけることができるかどうかを確認するために、各変数のいくつかの異なるスプラインのいずれかを試してみて、いくつかの可能性を試してみたいと思います。目的には十分です(ノイズは実際には非常に低いです。フィットのバイアスは、良好な滑らかな結果を達成するために問題ありませんが、ある程度までしかありません)。推論やデータマイニングに近づくものよりも、「優れた、解釈可能な、しかし適切なフィッティング関数を見つける」ことは、この問題の実際の問題ではありません。]

あるいは、これがgnmやASSIST、または他のパッケージの1つではるかに簡単な場合、それは有用な知識ですが、上記のトイプロブレムをどのように進めるかについてのいくつかの指針が役立ちます。

4

2 に答える 2

9

ns実際に予測子の行列を生成します。できることは、その行列を個々の変数に分割し、それらをにフィードすることnlsです。

m <- ns(x, df=5)
df <- data.frame(y, m)  # X-variables will be named X1, ... X5
# starting values should be set as appropriate for your data
nls(y ~ theta * plogis(alpha + b1*X1 + b2*X2 + b3*X3 + b4*X4 + b5*X5), data=df,
        start=list(theta=1, alpha=0, b1=1, b2=1, b3=1, b4=1, b5=1))

ETA:dfのさまざまな値に対してこれを自動化する方法を説明します。これは、テキストの変更を使用して式を作成し、を使用do.callしてを呼び出しますnls。警告:テストされていません。

my.nls <- function(x, y, df)
{
    m <- ns(x, df=df)
    xn <- colnames(m)
    b <- paste("b", seq_along(xn), sep="")
    fm <- formula(paste("y ~ theta * plogis(1 + alpha + ", paste(b, xn, sep="*",
          collapse=" + "), ")", sep=""))
    start <- c(1, 1, rep(1, length=length(b)))
    names(start) <- c("theta", "alpha", b)
    do.call(nls, list(fm, data=data.frame(y, m), start=start))
}
于 2012-02-04T10:16:56.180 に答える
2

自分の質問を明確にしているときに気付いたので、以前よりも不格好な方法がないことがわかりました。

多少の合理化が可能であっても、これは私の目には少しエレガントではありませんが、少なくとも繰り返し使用するには十分耐えられるので、適切な答えだと思います。私はまだ以下のこれよりもきちんとした方法に興味があります。

nsによって生成された行列でdata.frameを使用して列に自動名前を付けるというHongOoiのトリックは、ちょっとかわいいので、以下で使用しました。いくつかの変数を操作する必要があるため、一般的には貼り付けを使用してビルドします。

質問で与えられたデータ設定を仮定すると-

lin.expr <- function(p,xn) {
  pn<-paste(p, 1:length(xn), sep = "")
  paste(paste(pn,xn,sep=" * "),collapse=" + ")
  }


m <- ns(x, df=3)
mydf <- data.frame(y, m)  # X-variables will be named X1, X2, ... 
xn <- names(mydf)[2:dim(mydf)[2]]

nspb <- lin.expr("b",xn)

c.form <- paste("y ~ theta * plogis( a + ",nspb,")",sep="")
stl <- list(theta=2, a=-5,b1=10, b2=10, b3=10)
nls( c.form, data=mydf, start= stl)

私の実際の式には、nspbのようないくつかの用語があります。大幅な改善が認められました。私は自分の答えを選びたくないのですが、1日か2日でそれ以上何もなければ私はそれを選ぶと思います。

編集:Hong Ooiの追加(私が入力しているときに投稿され、同様のアイデアを使用していますが、いくつかの素晴らしい追加機能を追加しています)はほとんどそれを行います。それは受け入れられる答えなので、私はそれをチェックしました。

于 2012-02-05T03:17:22.163 に答える