2017-03-15 5 views
4

私は関数Q(x | delta)を持っています:R^n→R非線形分位回帰を適合させる。関数Q(。)はいくつかの行列演算を使用します。それを使用しないと非常に複雑になります。問題は、式引数で使用される関数に行列演算がある場合、nlrq(非線形回帰)とnls(非線形回帰)が機能しないように見えるということです。回帰で自身の関数を使用している "...%*%...:不適合引数のエラー"

説明すると、行列演算を使用しないときにnlrq関数とnls関数の式引数で使用できる単純な関数F(x1、x2 | a、b、c)を考えてみましょう。数式の引数が行列演算で記述されているときに動作します。

library('quantreg') 

    ## Generating the data 
    x1<- rnorm(200) 
    x2<- rnorm(200) 
    y<- 1+3*sin(x1)+2*cos(x2) +rnorm(200) 
    Dat<- data.frame(y,x1,x2) 

    ## The function F1 without matrix operation 
    F1<- function(x_1, x_2, a, b,c){a+b*sin(x_1)+c*cos(x_2)} 

    ## The function F2 with matrix operation 
    F2<- function(x_1, x_2, a, b,c){t(c(1,sin(x_1),cos(x_2)))%*%c(a,b,c)} 

    ## Both functions work perfectly 
    F1(x_1=3, x_2=2, a=1, b=3,c=2) 
    F2(x_1=3, x_2=2, a=1, b=3,c=2) 

    ## But only F1 can be estimated by nls and nlrq 
    nls_1<-nls(y ~ F1(x_1 = x1, x_2 = x2, a = 1, b, c), 
       data = Dat, start = list(b = 3, c = 2)) 

    nlrq_1<-nlrq(y ~ F1(x_1 = x1, x_2 = x2, a = 1, b, c), 
       data = Dat, start = list(b = 3, c = 2), tau = 0.9) 

    ## When F2 is used in the formula argument an error happens 
    nls_2<-nls(y ~ F2(x_1 = x1, x_2 = x2, a = 1, b, c), 
       data = Dat, start = list(b = 3, c = 2)) 

    nlrq_2<-nlrq(y ~ F2(x_1 = x1, x_2 = x2, a = 1, b, c), 
       data = Dat, start = list(b = 3, c = 2), tau = 0.9) 

エラーはError in t(c(1, sin(x_1), cos(x_2))) %*% c(a, b, c) : non-conformable argumentsです。私は、誰かがnlsとnlrqを使って行列演算を使ってF2を推定すると、他の関数で同じ解を使うことができると私は信じています。

Datのサイズは200x3です。

ありがとうございました。

+0

申し訳ありませんが、nlrqを使うにはquantregパッケージが必要で、 'install.packages( 'quantreg')'と 'library( 'quantreg')'をコードに追加する必要があります。 – ThiagoSC

答えて

3

あなたの機能F2()は、ベクトル引数x_1x_2のために動作しません... c(...)は長いベクトル(行列ではない)を構成しているため。
参照:

F1(x_1=c(3,5), x_2=c(2,4), a=1, b=3,c=2) 
F2(x_1=c(3,5), x_2=c(2,4), a=1, b=3,c=2) 

結果:

#> F1(x_1=c(3,5), x_2=c(2,4), a=1, b=3,c=2) 
#[1] 0.5910664 -3.1840601 
#> F2(x_1=c(3,5), x_2=c(2,4), a=1, b=3,c=2) 
#error in t(c(1, sin(x_1), cos(x_2))) %*% c(a, b, c) : ... 

機能nls()nlrq()があなたの機能F2()(それぞれF1()。)に(あなたのデータフレームDatから、すなわち列)ベクトルを送っています。ここで

F2()のいくつかのベクトル化された定義は以下のとおりです。

# other definitions for F2() 
F2 <- function(x_1, x_2, a, b,c) cbind(1,sin(x_1),cos(x_2)) %*% c(a,b,c) 
F2(x_1=c(3,5), x_2=c(2,4), a=1, b=3,c=2) 

F2 <- function(x_1, x_2, a, b,c) t(rbind(1,sin(x_1),cos(x_2))) %*% c(a,b,c) 
F2(x_1=c(3,5), x_2=c(2,4), a=1, b=3,c=2) 

F2 <- function(x_1, x_2, a, b,c) colSums(rbind(1,sin(x_1),cos(x_2)) * c(a,b,c)) 
F2(x_1=c(3,5), x_2=c(2,4), a=1, b=3,c=2) 

F2 <- function(x_1, x_2, a, b,c) crossprod(rbind(1,sin(x_1),cos(x_2)), c(a,b,c)) 
F2(x_1=c(3,5), x_2=c(2,4), a=1, b=3,c=2) 

F2 <- function(x_1, x_2, a, b,c) tcrossprod(c(a,b,c), cbind(1,sin(x_1),cos(x_2))) 
F2(x_1=c(3,5), x_2=c(2,4), a=1, b=3,c=2) 
+0

私は関数がベクトル引数で動作するとは期待していませんでしたが、cの代わりにrbindを使ってF2の内部にベクトルを構築するという考えを示しました。どうもありがとうございました。 – ThiagoSC

+1

私が元の問題に戻ったとき、なぜ関数がベクトルを引数として受け入れることが問題であると指摘したのか理解しました。 nls関数とnlrq関数は、説明変数のベクトル全体を数式の引数として使用します。 – ThiagoSC

1

あなたはこのために戻って、汎用最適化機能に落ちることができます。 Rの通常のデフォルトはoptimですが、他にも多数あります。

ここで最小二乗回帰の場合があります。損失関数は、残差の平方和です。私はベクトル引数のために働くようにF2関数を書き直しました。

sumsq <- function(beta) 
{ 
    F2 <- function(x1, x2, a, b, c) 
    { 
     cbind(1, sin(x1), cos(x2)) %*% c(a, b, c) 
    } 
    yhat <- F2(Dat$x1, Dat$x2, beta[1], beta[2], beta[3]) 
    sum((Dat$y - yhat)^2) 
} 

beta0 <- c(mean(Dat$y), 1, 1) 

optim(beta0, sumsq, method="BFGS") 

#initial value 731.387431 
#final value 220.265745 
#converged 
#$par 
#[1] 0.8879371 3.0211286 2.1639280 
# 
#$value 
#[1] 220.2657 
# 
#$counts 
#function gradient 
#  25  7 
# 
#$convergence 
#[1] 0 
# 
#$message 
#NULL 

ここで、optimは、いくつかのコンポーネントを含むリストを返します。成分parは、平方残差の和を最小にする回帰係数の値であり、成分はvalueです。

nlsの結果と比較すると、推定係数がほぼ等しいことがわかります。

nls(y ~ F1(x_1=x1, x_2=x2, a=1, b, c), 
      data=Dat, start=list(b=3, c=2)) 

Nonlinear regression model 
    model: y ~ F1(x_1 = x1, x_2 = x2, a = 1, b, c) 
    data: Dat 
    b  c 
3.026 2.041 
residual sum-of-squares: 221 

Number of iterations to convergence: 1 
Achieved convergence tolerance: 7.823e-10 

分数回帰の場合と同様のことができますが、それはもっと複雑になります。

1

他の回答に基づいて、私は問題がc()機能を持つF2の内部にベクターを構築していることを知りました。代わりにrbind()を使用した場合、推定はnls()nlrq()の両方で完全に機能しました。

次は、F2の修正版を示します。 nls_2での推計とnlrq_2がnls_1とnlrq_1からのものと一致することを

## Changing c() for rbind() 
    F2<- function(x_1, x_2, a, b,c){t(rbind(1,sin(x_1),cos(x_2)))%*%rbind(a,b,c)} 

    ## Now nls() and nlrq() work properly 
    nls_2<-nls(y ~ F2(x_1 = x1, x_2 = x2, a = 1, b, c), 
     data = Dat, start = list(b = 3, c = 2)) 

    nlrq_2<-nlrq(y ~ F2(x_1 = x1, x_2 = x2, a = 1, b, c), 
     data = Dat, start = list(b = 3, c = 2), tau = 0.9) 

は注意してください。

ありがとうございました。

関連する問題