西里先生のこの本を見ていると,自分でコードを書いてちゃんと理解したくなった。
[amazonjs asin=”4563052183″ locale=”JP” title=”行動科学のためのデータ解析―情報把握に適した方法の利用”]
ということで,2章にある双対尺度法の基本アルゴリズム,交互平均法についてのコードがこちら。
recipro_ave <- function(dat,eps=1e-10,iter.max=1000,start.vec=NULL,proc=F){ nc <- ncol(dat) nr <- nrow(dat) tmp <- 0 FLG <- FALSE iter <- 0 if(is.null(start.vec)){ u <- rnorm(nc) }else{ if(length(start.vec)==nc){ u <- start.vec }else{ warning("vec size is not correct. Starting val. is changed.") u <- rnorm(nc) } } while(FLG==FALSE){ #algorithm v <- u %*% t(dat) v <- v / rowSums(dat) av <- (rowSums(dat) %*% t(v))/sum(rowSums(dat)) v <- v - (av * rep(1,nr)) gy <- max(abs(v)) v <- v/gy u <- v %*% dat u <- u / colSums(dat) av <- (colSums(dat) %*% t(u))/sum(colSums(dat)) u <- u - (av *rep(1,nc)) gx <- max(abs(u)) u <- u/gx #process print if(proc){ cat("iter ",iter,"\n") cat("eigen col:",gy," col weight:",v,"\n") cat("eigen row:",gx," row weight:",u,"\n") } #conv. check if(abs(tmp-gx)<eps){FLG <- TRUE}else{tmp <- gx} if(iter>iter.max){FLG <- TRUE}else{iter <- iter + 1} } # return if(u[which.max(abs(u))]<0) u *-1 if(v[which.max(abs(v))]<0) v *-1 eta2 <- gx * gy # Correlation ratio nu.c <- sqrt(sum(colSums(dat))/colSums(dat)%*%t(u^2)) #multiplied constant nv.c <- sqrt(sum(rowSums(dat))/rowSums(dat)%*%t(v^2)) nu <- nu.c %*% u #normed u nv <- nv.c %*% v #normed v pu <- nu * sqrt(eta2) pv <- nv * sqrt(eta2) if(iter>iter.max){ warning("Warning::did not converge.") }else{ return(list(eigen.col=gy,eigen.row=gx,cor.ratio=eta2,singular.val=sqrt(eta2),projected.col=pv,projected.row=pu,normed.col=nv,normed.row=nu)) } }
関数名はrecipro_aveで,クロス集計表のデータを渡してやれば結果を返すようになっている。
オプションとして,収束基準eps(デフォルトは1e-10),回転上限iter.max(デフォルトは1000),最初につける列重みベクトルstart.vec(デフォルトはNULLで,正規乱数を入れるようになっている),各ステップを出力するかどうかproc(デフォルトはFALSE)が決められるようになっている。
授業などでデモンストレーションするときは,start.vecにc(1,2,3)などを渡してproc=Tとすると,一手ずつ計算結果が出力されるのでよろしいかと。
2件のコメント
コメントは受け付けていません。