001package org.opengion.penguin.math;
002
003import org.apache.commons.math3.linear.MatrixUtils;
004import org.apache.commons.math3.linear.RealMatrix;
005import org.apache.commons.math3.stat.correlation.PearsonsCorrelation;
006import org.opengion.penguin.common.SystemUtil;
007
008/**
009 * apache.commons.mathを利用した相関計算及びその周辺機能を利用するためのクラスです。
010 * 
011 * とりあえず通常のピアソン積率相関のみを利用可能としておきます。
012 * 
013 */
014public class HybsCorrelation {
015        private String[] names;
016        private double[][] pearsonsMatrix;
017        private RealMatrix corrMatrix;
018        
019                
020        /**
021         * コンストラクタ。
022         * 与えたデータマトリクスを元にピアソン積率相関を計算します。
023         * 名称 = { "数学" , "英語", "国語" }
024         * データ = { { 90 ,60 ,70 }, {70, 90, 80 } }
025         * のような形としてデータを与えます。
026         * @param name
027         * @param matrix
028         */
029        public HybsCorrelation(String[] name, double[][] matrix){
030                // 一応元データをセットしておく
031                this.names = name;
032                this.pearsonsMatrix = matrix;
033                
034                // ここで相関係数行列を作成してしまう
035                corrMatrix = (new PearsonsCorrelation()).computeCorrelationMatrix(pearsonsMatrix);
036        }
037        
038        /**
039         * コンストラクタ。
040         * 計算後の相関係数行列をdouble[][]型で直接与えられるようにしておきます。
041         * 以前に計算した行列を使って行列の積を算出する場合に利用します。
042         * 
043         * @param matrix
044         */
045        public HybsCorrelation( double[][] matrix){
046                corrMatrix = MatrixUtils.createRealMatrix( matrix );
047        }
048        
049        /**
050         * コンストラクタで算出した相関値行列に対して与えた行列を掛け算します。
051         * 例えば以下のような算出を行う事が可能です。
052         * 各商品を何回購入したかというデータを人数分用意し、相関係数行列を作成し、
053         *  それに対してある人の今まで購入した履歴を掛け算する事で相関の高い商品を導出します。
054         *  つまり、購入した事のないもので有意な相関係数を持つものは購入可能性が高いと言えます。
055         * @param data 掛け算する行列
056         * @return 行列積の結果マトリクス
057         */
058        public double[][] multiply(double[][] data){
059                RealMatrix dataMatrix = MatrixUtils.createRealMatrix(data);
060            RealMatrix scores = dataMatrix.multiply(corrMatrix);
061                
062                return scores.getData();
063        }
064        
065        /**
066         * 相関値行列取得。
067         * @return 相関マトリクス
068         */
069        public double[][] getCorrMatrix(){
070                return corrMatrix.getData();
071        }
072        
073        /**
074         * 指定行の相関値配列取得。
075         * @param x ROW番号
076         * @return 行方向の相関ベクトル
077         */
078        public double[] getCorrMatrixRow(int x){
079                return corrMatrix.getRow(x);
080        }
081        
082        /**
083         * 指定列の相関値配列取得。
084         * @param x COL番号
085         * @return 列方向の相関ベクトル
086         */
087        public double[] getCorrMatrixCol(int x){
088                return corrMatrix.getColumn(x);
089        }
090        
091        /**
092         * 名称配列の取得。
093         * @return 名称配列
094         */
095        public String[] getNames(){
096                return names;
097        }
098        
099        /**
100         * 名称配列のセット。
101         * @param name 名称配列
102         */
103        public void setNames( String[] name){
104                this.names = name;
105        }
106
107        /*** ここまでが本体 ***/
108        /*** ここからテスト用mainメソッド ***/
109        /**
110         * @param args *****************************************/
111        public static void main(final String [] args) {
112                String[] name = {"A", "B", "C", "D","E"};
113            double[][] data = {
114              {3, 1, 0, 0 , 1},
115              {1, 0, 0, 0 , 1},
116              {0, 0, 2, 2 , 2},
117              {2, 2, 1, 0 , 0},
118              {1, 0, 2, 4 , 1},
119            };
120                
121                HybsCorrelation rtn = new HybsCorrelation(name,data);
122                
123                for( int i = 0; i< rtn.getCorrMatrix().length; i++ ){
124                        System.out.println(java.util.Arrays.toString(rtn.getCorrMatrix()[i]));
125                }
126                
127                // オススメ度計算
128                System.out.println(java.util.Arrays.toString(rtn.multiply( new double[][] { {0, 1, 0, 0 , 0}})[0]));
129                
130        }
131}
132