最大値
n次元分割表を考える。その分割表は総数が1となるようにセルの値を標準化してあるものとする。
2次元の分割表NxM (N<=M)において、カイ自乗値の最大値は、N-1であって、それは、表の列と行を適当に入れ替えることによって、N個の非ゼロの対角成分を持つNxNの正方行列部分と、Nx(M-N)の長方形行列部分にすることができて、しかも、このNx(M-N)の長方形行列部分は、NxN正方行列が作れるまでは、そのような正方行列にして、そこには対角成分のみがあるようにして、残りのNxM'(M'<=N)なる長方形成分を残したときに、そこは、M'個の対角成分のみが非ゼロで、残りはすべてゼロであるようにできる、そんな分割表のときである。
n次元に拡張する。次のような特殊なサイズとする。
NxNx...xNxM M>=Nなる多次元分割表(すべての次元の長さが等しいか、そうでないならば、ただ一つの次元のみがことなり、その長さは、他の次元より長い)。
カイ自乗値の「おばけ変形」のような値を定義することによって、この値の最大値も2次元におけるカイ自乗値のように、N-1をとらせることができる。
ソースメモ。
public class cubeChi2 { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub //int df=3; int[] category={5,34}; double[] data=MakeData(category); for(int i=0;i<data.length;i++){ System.out.println(data[i]); } double chi=Chi(data,category); double chiR=ChiR(data,category); double chiR2=ChiR2(data,category); System.out.println("chi\t"+chi); System.out.println("chiR\t"+chiR);//おばけその1 System.out.println("chiR2\t"+chiR2);//おばけその2 } public static double ChiR(double[] data, int[] category){ double ret =-1; int max=category[0]; for(int i=1;i<category.length;i++){ if(max<category[i]){ max=category[i]; } } double dim=category.length; //double dim = (double)max; double[][] marg=new double[category.length][0]; for(int i=0;i<marg.length;i++){ marg[i]=new double[category[i]]; } int[] counter=new int[category.length]; for(int i=0;i<data.length;i++){ for(int j=0;j<category.length;j++){ marg[j][counter[j]]+=data[i]; } counter[0]++; for(int j=0;j<category.length-1;j++){ if(counter[j]==category[j]){ counter[j]=0; counter[j+1]++; } } } counter=new int[category.length]; for(int i=0;i<data.length;i++){ double value=1; for(int j=0;j<category.length;j++){ value*=marg[j][counter[j]]; } ret+=Math.pow(data[i], dim/(dim-1))/Math.pow(value,1/(dim-1)); //ret+=(data[i]-value)*(data[i]-value)/value; counter[0]++; for(int j=0;j<category.length-1;j++){ if(counter[j]==category[j]){ counter[j]=0; counter[j+1]++; } } } /* for(int i=0;i<marg.length;i++){ //double tmpsum=0; for(int j=0;j<marg[i].length;j++){ System.out.print(marg[i][j]+"\t"); //tmpsum+=marg[i][j]; } //System.out.print(tmpsum); System.out.println(); } */ return ret; } public static double[] MakeData(int[] category){ int n=1; int N=1; int max=0; for(int i=1;i<category.length;i++){ if(category[max]<category[i]){ max=i; } } //System.out.println("max "+max); for(int i=0;i<category.length;i++){ n*=category[i]; N*=category[max]; } //System.out.println("n="+n+"\t N="+N); double[] ret = new double[n]; int[] counter=new int[category.length]; for(int i=0;i<n;i++){ } int[] keta=new int[category.length]; keta[0]=1; for(int i=1;i<keta.length;i++){ keta[i]=keta[i-1]*category[i-1]; //System.out.println("keta "+i+" "+keta[i]); } int value=0; double sum=0; boolean loop=true; while(loop){ value=0; for(int j=0;j<counter.length;j++){ value+=keta[j]*counter[j]; } //System.out.println("value\t"+value); //for(int j=0;j<counter.length;j++){ //System.out.print(counter[j]+"\t"); //} //System.out.println(); if(value<n){ ret[value]=Math.random(); sum+=ret[value]; } for(int j=0;j<counter.length;j++){ counter[j]++; } value=0; if(counter[max]==category[max]){ loop=false; } for(int j=0;j<counter.length;j++){ if(counter[j]==category[j]){ counter[j]=0; } /* else{ counter[j]++; } */ } for(int j=0;j<counter.length;j++){ value+=keta[j]*counter[j]; } } for(int i=0;i<ret.length;i++){ ret[i]/=sum; } return ret; } public static double Chi(double[] data, int[] category){ double ret =0; double[][] marg=new double[category.length][0]; for(int i=0;i<marg.length;i++){ marg[i]=new double[category[i]]; } int[] counter=new int[category.length]; for(int i=0;i<data.length;i++){ for(int j=0;j<category.length;j++){ marg[j][counter[j]]+=data[i]; } counter[0]++; for(int j=0;j<category.length-1;j++){ if(counter[j]==category[j]){ counter[j]=0; counter[j+1]++; } } } counter=new int[category.length]; for(int i=0;i<data.length;i++){ double value=1; for(int j=0;j<category.length;j++){ value*=marg[j][counter[j]]; } ret+=(data[i]-value)*(data[i]-value)/value; counter[0]++; for(int j=0;j<category.length-1;j++){ if(counter[j]==category[j]){ counter[j]=0; counter[j+1]++; } } } /* for(int i=0;i<marg.length;i++){ //double tmpsum=0; for(int j=0;j<marg[i].length;j++){ System.out.print(marg[i][j]+"\t"); //tmpsum+=marg[i][j]; } //System.out.print(tmpsum); System.out.println(); } */ return ret; } public static double ChiR2(double[] data, int[] category){ double ret =-1; int max=category[0]; for(int i=1;i<category.length;i++){ if(max<category[i]){ max=category[i]; } } double dim=category.length; //double dim = (double)max; double[][] marg=new double[category.length][0]; for(int i=0;i<marg.length;i++){ marg[i]=new double[category[i]]; } int[] counter=new int[category.length]; for(int i=0;i<data.length;i++){ for(int j=0;j<category.length;j++){ marg[j][counter[j]]+=data[i]; } counter[0]++; for(int j=0;j<category.length-1;j++){ if(counter[j]==category[j]){ counter[j]=0; counter[j+1]++; } } } counter=new int[category.length]; for(int i=0;i<data.length;i++){ double value=1; for(int j=0;j<category.length;j++){ value*=marg[j][counter[j]]; } //ret+=Math.pow(data[i], dim/(dim-1))/Math.pow(value,1/(dim-1)); ret+=Math.pow(data[i], 1/(dim-1))*Math.pow(value,dim/(dim-1)); //ret+=(data[i]-value)*(data[i]-value)/value; counter[0]++; for(int j=0;j<category.length-1;j++){ if(counter[j]==category[j]){ counter[j]=0; counter[j+1]++; } } } /* for(int i=0;i<marg.length;i++){ //double tmpsum=0; for(int j=0;j<marg[i].length;j++){ System.out.print(marg[i][j]+"\t"); //tmpsum+=marg[i][j]; } //System.out.print(tmpsum); System.out.println(); } */ return ret; } }