最近在做項目時,用戶不想使用平均值來判斷當前數據狀態,想用其他的方式來分析數據的變化狀態,在查找了一些資料后,想使用灰色預測來進行數據的預測。下面的內容是從網上綜合下來的,java代碼也做了一點改動,以做記錄和學習。
1.什么是灰色預測
灰色預測是一種對含有不確定因素的系統進行預測的方法。灰色預測通過鑒別系統因素之間發展趨勢的相異程度,即進行關聯分析,並對原始數據進行生成處理來尋找系統變動的規律,生成有較強規律性的數據序列,然后建立相應的微分方程模型,從而預測事物未來發展趨勢的狀況。
灰色時間序列預測,即用等時距觀測到的反應預測對象特征的一系列數量值構造灰色預測模型,預測未來某一時刻的特征量,或達到某一特征量的時間。
2.灰色預測的數學建模
1).數據的檢驗與處理
為了保證GM(1,1)建模方法的可行性,需要對已知數據做必要的檢驗處理。
設原始數據列為
,計算數列的級比
如果所有的級比都落在可容覆蓋區間
內,則數據列可以建立GM(1,1)模型且可以進行灰色預測。否則,對數據做適當的變換處理,如平移變換:取C使得數據列
的級比都落在可容覆蓋區間內。
2).建立GM模型
不妨設
滿足上面的要求,
以它為數據列建立GM(1,1)模型 
用回歸分析求得a,b的估計值,於是相應的白化模型為

解為
於是得到預測值 
從而相應地得到預測值 
3).檢驗預測值
采用殘差檢驗的方式進行檢驗。

如果對所有的
,則認為達到較高的要求;
否則,若對所有的
,則認為達到一般的要求。
3.java實現
public class GM { /** * @param args */ public static void main(String[] args) { double []arr={2.67,3.13,3.25,3.36,3.56,3.72,3.12,3.33,2.12}; System.out.println(gm(arr,3)); } public static double gm(double[] fs, int T) { // 預測模型函數 int size = fs.length; int tsize = fs.length - 1; double[] arr = fs;// 原始數組 double[] arr1 = new double[size];// 經過一次累加數組 double sum = 0; for (int i = 0; i < size; i++) { sum += arr[i]; arr1[i] = sum; } double[] arr2 = new double[tsize];// arr1的緊鄰均值數組 for (int i = 0; i < tsize; i++) { arr2[i] = (double) (arr1[i] + arr1[i + 1]) / 2; } /* * * 下面建立 向量B和YN求解待估參數向量, 即求參數a,b */ /* * 下面建立向量B, B是5行2列的矩陣, 相當於一個二維數組。 */ double[][] B = new double[tsize][2]; for (int i = 0; i < tsize; i++) { for (int j = 0; j < 2; j++) { if (j == 1) B[i][j] = 1; else B[i][j] = -arr2[i]; } } /* * 下面建立向量YN */ double[][] YN = new double[tsize][1]; for (int i = 0; i < tsize; i++) { for (int j = 0; j < 1; j++) { YN[i][j] = arr[i + 1]; } } /* * B的轉置矩陣BT,2行5列的矩陣 */ double[][] BT = new double[2][tsize]; for (int i = 0; i < 2; i++) { for (int j = 0; j < tsize; j++) { BT[i][j] = B[j][i]; } } /* * 將BT和B的乘積所得到的結果記為數組B2T,則B2T是一個2*2的矩陣 */ double[][] B2T = new double[2][2]; for (int i = 0; i < 2; i++) {// rows of BT { for (int j = 0; j < 2; j++)// cloums of B { for (int k = 0; k < tsize; k++)// cloums of BT=rows of B { B2T[i][j] = B2T[i][j] + BT[i][k] * B[k][j]; } } } } /* 下面求B2T的逆矩陣,設為B_2T,怎么適用於一般的矩陣? */ double[][] B_2T = new double[2][2]; B_2T[0][0] = (1 / (B2T[0][0] * B2T[1][1] - B2T[0][1] * B2T[1][0])) * B2T[1][1]; B_2T[0][1] = (1 / (B2T[0][0] * B2T[1][1] - B2T[0][1] * B2T[1][0])) * (-B2T[0][1]); B_2T[1][0] = (1 / (B2T[0][0] * B2T[1][1] - B2T[0][1] * B2T[1][0])) * (-B2T[1][0]); B_2T[1][1] = (1 / (B2T[0][0] * B2T[1][1] - B2T[0][1] * B2T[1][0])) * B2T[0][0]; /* * 根據以上所求的各已知量下面求待估參數的未知量a和b,待估向量矩陣等於B_2T*BT*YN * 下面我們分別求這些矩陣的乘積,首先求B_2T*BT,令B_2T*BT的乘積為A矩陣,則A就是一個2*5的矩陣 */ /* * * * * 下面先求A矩陣 */ double[][] A = new double[2][tsize]; for (int i = 0; i < 2; i++) {// rows of B_2T { for (int j = 0; j < tsize; j++)// cloums of BT { for (int k = 0; k < 2; k++)// cloums of B_2T=rows of BT { A[i][j] = A[i][j] + B_2T[i][k] * BT[k][j]; } } } } /* * * * 下面求A和YN矩陣的乘積,令乘積為C矩陣,則C就是一個2*1的矩陣 */ double[][] C = new double[2][1]; for (int i = 0; i < 2; i++) {// rows of A { for (int j = 0; j < 1; j++)// cloums of YN { for (int k = 0; k < tsize; k++)// cloums of A=rows of YN { C[i][j] = C[i][j] + A[i][k] * YN[k][j]; } } } } /* 根據以上所得則a=C[0][0],b=C[1][0]; */ double a = C[0][0], b = C[1][0]; int i = T;// 讀取一個數值 double Y = (arr[0] - b / a) * Math.exp(-a * (i + 1)) - (arr[0] - b / a) * Math.exp(-a * i); return Y; } }
