【stan】ベクトルの内積を計算するのに転置(')やrow_vectorが必要なことを知った

 

stanで重回帰分析をしようとすると、こんな感じのモデルを書くことになる。

data {
  int<lower=0> N; //データ数
  int<lower=0> M; //説明変数の数
  real X[N, M];
  real Y[N];
}

parameters {
  vector[M] b;
  real<lower=0> sigma;
}

model {
  Y ~ normal (X*b, sigma);
}

 

このXbはちゃんと書くとこんな感じになる。

 

訳あってこれのXをvectorに変えたらエラーが出た。

 

data {
  int<lower=0> N; 
  int<lower=0> K; 
  vector[K] X;   //  matrix -> vectorに変更
  vector[N] Y;
}

parameters {
  vector[K] b;
  real<lower=0> sigma;
}

model {
for (n in 1:N){
Y[n] ~ normal (X*b, sigma);
} }

 

Ill-typed arguments supplied to infix operator *. Available signatures: 
(int, int) => int
(real, real) => real
(row_vector, vector) => real
(real, vector) => vector
(vector, real) => vector
(matrix, vector) => vector
(complex, complex) => complex
(complex_row_vector, complex_vector) => complex
(real, row_vector) => row_vector
(row_vector, real) => row_vector
(row_vector, matrix) => row_vector
(real, matrix) => matrix
(vector, row_vector) => matrix
(matrix, real) => matrix
(matrix, matrix) => matrix
(complex, complex_vector) => complex_vector
(complex_vector, complex) => complex_vector
(complex_matrix, complex_vector) => complex_vector
(complex, complex_row_vector) => complex_row_vector
(complex_row_vector, complex) => complex_row_vector
(complex_row_vector, complex_matrix) => complex_row_vector
(complex, complex_matrix) => complex_matrix
(complex_vector, complex_row_vector) => complex_matrix
(complex_matrix, complex) => complex_matrix
(complex_matrix, complex_matrix) => complex_matrix
Instead supplied arguments of incompatible type: vector, vector.

要は「*」を使って演算の出来る型はこれだけだから、vector*vectorは無理だぞ、って話なんですが、下記のような形のベクトル同士の掛け算は数学的にも出来ないぞ、っていう話でもある。

 

じゃあどうするかというと数学的に正しい記載になるのが良くて列ベクトルと行ベクトルの掛け算にするか内積を求めればちゃんと計算ができるようになる。ちなみにこの時Xbは実数(スカラー)が返ってくる。

分かれば当たり前なのだが躓いたのでここに記しておく。

ちなみにstanのコードは以下の通り。

 

row_vectorで定義する

data {
  int<lower=0> N; 
  int<lower=0> K; 
  row_vector[K] X; // vector -> row_vectorに変更
  vector[N] Y;
}

parameters {
  vector[K] b;
  real<lower=0> sigma;
}

model {
for (n in 1:N){
Y[n] ~ normal (X'*b, sigma);
} }

 

 

vectorを「'」で転置する

data {
  int<lower=0> N; 
  int<lower=0> K; 
  vector[K] X;
  vector[N] Y;
}

parameters {
  vector[K] b;
  real<lower=0> sigma;
}

model {
for (n in 1:N){
Y[n] ~ normal (X'*b, sigma); // X -> X' に変更
} }

 

dot_productで内積を求める

data {
  int<lower=0> N; 
  int<lower=0> K; 
  vector[K] X;
  vector[N] Y;
}

parameters {
  vector[K] b;
  real<lower=0> sigma;
}

model {
for (n in 1:N){
   Y[n] ~ normal (dot_product(X,b), sigma); X*b -> dot_product(X,b)に変更
} }