/// <summary> /// Linear regression with Y and one or more independent variables /// equation: y = b0 + b1x1 + b2x2 + ... + b(p-1)x(p-1) + e /// equation in matrix form: Y = XB + E /// </summary> /// <param name="dependent">SeriesVariable. dependent variable</param> /// <param name="independents">SeriesVariables. independent variable</param> public LinearRegressionModel(SeriesVariable dependent, SeriesVariables independents) { //Vector vY = new Vector(dependent.SeriesValuesNoNaN.ToArray()); //int n = vY.Tuples; //int p = independents.Count + 1; //Matrix mX = new Matrix(n, p); //for (int i = 0; i < p; i++) //kolom //{ // for (int j = 0; j < n; j++) //baris // { // if (i == 0) // mX[j, i] = 1.0; // else // mX[j, i] = independents[i - 1][j]; // } //} // changed to deal with missing values Vector vY = new Vector(dependent.SeriesValuesNoNaN.ToArray()); int n = vY.Tuples; int p = independents.Count + 1; Matrix mX = new Matrix(n, p); for (int i = 0; i < p; i++) //kolom { for (int j = 0; j < n; j++) //baris { if (i == 0) mX[j, i] = 1.0; else mX[j, i] = independents[i - 1].SeriesValuesNoNaN[j]; } } this.lse = new LeastSquareEstimator(mX, vY); this.f = this.lse.MSR / this.lse.MSE; this.sigOfF = Distribution.F.PValue(this.f, p - 1, n - p); double sumOfEtMinusEt_1Square = 0; double sumOfESquare = this.lse.ESquare[0]; for (int i = 1; i < n; i++) { sumOfEtMinusEt_1Square += Math.Pow(this.lse.E[i] - this.lse.E[i - 1],2.0); sumOfESquare += this.lse.ESquare[i]; } this.durbinWatson = sumOfEtMinusEt_1Square / sumOfESquare; this.stdErrorOfParameters = new double[p]; this.t = new double[p]; this.sigOfT = new double[p]; this.lbOfParameters = new double[p]; this.ubOfParameters = new double[p]; for (int i = 0; i < p; i++) { this.stdErrorOfParameters[i] = Math.Sqrt(this.lse.SbSquare[i, i]); this.t[i] = this.lse.B[i] / this.stdErrorOfParameters[i]; this.sigOfT[i] = Distribution.T.PValue(this.t[i], n - p, Distribution.T.TestType.TwoSided); double error = Distribution.T.InversCDF(0.975, n - p); this.ubOfParameters[i] = this.lse.B[i] + error * this.stdErrorOfParameters[i]; this.lbOfParameters[i] = this.lse.B[i] - error * this.stdErrorOfParameters[i]; } this.vifForPredictors = new double[p - 1]; this.partialCorr = new double[p - 1]; this.corr = new double[p - 1]; for (int i = 1; i < p; i++) { Vector y = new Vector(mX.GetColData(i)); Matrix x = new Matrix(n, p - 1); int col = 0; for (int j = 0; j < p; j++) { if (j != i) { for (int k = 0; k < n; k++) { x[k, col] = mX[k, j]; } col++; } } Matrix xtx = x.GetTranspose() * x; Vector xty = x.GetTranspose() * y; Vector b = xtx.Solve(xty); Matrix mJ = new Matrix(n, n); mJ.InitializeAllValue(1.0); double yty = Vector.DoubleMultiply(y.GetTranspose(), y); Vector jy = mJ * y; double ssto = yty - Vector.DoubleMultiply(y.GetTranspose(), jy) / n; double sse = yty - Vector.DoubleMultiply(b.GetTranspose(), xty); double ssr = ssto - sse; double rSquare = ssr / ssto; this.vifForPredictors[i - 1] = 1 / (1 - rSquare); this.corr[i - 1] = computePearsonCorr(vY,y); Vector xty2 = x.GetTranspose() * vY; Vector b2 = xtx.Solve(xty2); double yty2 = Vector.DoubleMultiply(vY.GetTranspose(), vY); double sse2 = yty2 - Vector.DoubleMultiply(b2.GetTranspose(), xty2); double partDetermination = (sse2 - this.lse.SSE) / sse2; this.partialCorr[i - 1] = Math.Sqrt(partDetermination); } this.expectedResidual = new double[n]; for (int k = 1; k <= n; k++) { this.expectedResidual[k - 1] = this.lse.StandardError * Distribution.Normal.InversCDF((k - 0.375) / (n + 0.25)); } }
/// <summary> /// Prosedur untuk menghitung inisialisasi nilai awal /// Nilai awal ditentukan dengan menggunakan lse pada 6 observasi pertama /// </summary> private void Init() { Matrix x = new Matrix(this.n, 2); for (int i = 0; i < this.n; ++i) { x[i, 0] = 1; x[i, 1] = i + 1; } LeastSquareEstimator lse = new LeastSquareEstimator(x, y); this.smoothing[0] = this.a * this.y[0] + ((1 - this.a) * (lse.B[0] + lse.B[1])); this.trend[0] = this.g * (this.smoothing[0] - lse.B[0]) + (1 - this.g) * lse.B[1]; this.predicted[0] = lse.B[0] + lse.B[1]; this.residual[0] = this.y[0] - this.predicted[0]; }
/// <summary> /// Mengestimasi parameter /// </summary> private void estimateParameters() { if (this.linearRdb.Checked) { x = new Matrix(this.y.Tuples, 2); for (int i = 0; i < this.y.Tuples; ++i) { x[i, 0] = 1; x[i, 1] = i + 1; } lse = new LeastSquareEstimator(x, this.y); this.trendProperties.initialModel = 1; this.trendProperties.includedObservations = this.y.Tuples; this.trendProperties.parameters = lse.B.GetData(); this.trendProperties.sse = lse.SSE; this.trendProperties.mse = lse.MSE; this.trendProperties.r = lse.R; this.trendProperties.rSquare = lse.RSquare; this.trendProperties.rSquareAdjusted = 1 - (Math.Sqrt(lse.SSE) / lse.SSTO); this.predicted = lse.YCap.GetData(); this.residual = lse.E.GetData(); } else if (this.quadraticRdb.Checked) { x = new Matrix(this.y.Tuples, 3); for (int i = 0; i < this.y.Tuples; ++i) { x[i, 0] = 1; x[i, 1] = i + 1; x[i, 2] = Math.Pow(i + 1, 2); } lse = new LeastSquareEstimator(x, this.y); this.trendProperties.initialModel = 2; this.trendProperties.includedObservations = this.y.Tuples; this.trendProperties.parameters = lse.B.GetData(); this.trendProperties.sse = lse.SSE; this.trendProperties.mse = lse.MSE; this.trendProperties.r = lse.R; this.trendProperties.rSquare = lse.RSquare; this.trendProperties.rSquareAdjusted = 1 - (Math.Sqrt(lse.SSE) / lse.SSTO); this.predicted = lse.YCap.GetData(); this.residual = lse.E.GetData(); } else if (this.expGrowthRdb.Checked) { x = new Matrix(this.y.Tuples, 2); for (int i = 0; i < this.y.Tuples; ++i) { x[i, 0] = 1; x[i, 1] = i + 1; } Vector z = new Vector(this.y.Tuples); for (int i = 0; i < this.y.Tuples; ++i) z[i] = Math.Log10(this.y[i]); lse = new LeastSquareEstimator(x, z); this.trendProperties.parameters = lse.B.GetData(); this.trendProperties.includedObservations = this.y.Tuples; this.trendProperties.initialModel = 4; for (int i = 0; i < 2; ++i) this.trendProperties.parameters[i] = Math.Pow(10, this.trendProperties.parameters[i]); predicted = new double[this.y.Tuples]; residual = new double[this.y.Tuples]; for (int i = 0; i < this.y.Tuples; ++i) { this.predicted[i] = this.trendProperties.parameters[0] * Math.Pow(this.trendProperties.parameters[1], (i + 1)); this.residual[i] = this.y[i] - this.predicted[i]; } this.trendProperties.sse = lse.SSE; this.trendProperties.mse = lse.MSE; this.trendProperties.r = lse.R; this.trendProperties.rSquare = lse.RSquare; this.trendProperties.rSquareAdjusted = 1 - (Math.Sqrt(lse.SSE) / lse.SSTO); } else if (this.cubicRdb.Checked) { x = new Matrix(this.y.Tuples, 4); for (int i = 0; i < this.y.Tuples; ++i) { x[i, 0] = 1; x[i, 1] = i + 1; x[i, 2] = Math.Pow(i + 1, 2); x[i, 3] = Math.Pow(i + 1, 3); } lse = new LeastSquareEstimator(x, this.y); this.trendProperties.initialModel = 3; this.trendProperties.includedObservations = this.y.Tuples; this.trendProperties.parameters = lse.B.GetData(); this.trendProperties.sse = lse.SSE; this.trendProperties.mse = lse.MSE; this.trendProperties.r = lse.R; this.trendProperties.rSquare = lse.RSquare; this.trendProperties.rSquareAdjusted = 1 - (Math.Sqrt(lse.SSE) / lse.SSTO); this.predicted = lse.YCap.GetData(); this.residual = lse.E.GetData(); } }
/// <summary> /// Inisialisasi nilai awal untuk tipe model multiplikatif /// Nilai awal musiman ditentukan dengan menggunakan Dummy Variabel dari data detrend /// </summary> private void InitMultiplicative() { //Menghitung nilai detrend Matrix x = new Matrix(this.n, 2); for (int i = 0; i < this.n; ++i) { x[i, 0] = 1; x[i, 1] = i + 1; } LeastSquareEstimator lse1 = new LeastSquareEstimator(x, this.y); Vector detrend = new Vector(this.n); for (int i = 0; i < this.n; i++) detrend[i] = this.y[i] / lse1.YCap[i]; //Mencari indeks musiman dengan Dummy Regresi Matrix z = new Matrix(this.n, this.l); for (int i = 0; i < this.n; i++) { for (int j = 0; j < this.l; j++) { if (j == this.term[i]) z[i, j] = 1; else z[i, j] = 0; } } LeastSquareEstimator lse2 = new LeastSquareEstimator(z, detrend); double[] seasonalIndex = lse2.B.GetData(); this.EstimateValue(); double smoothing0 = lse.B[0]; double trend0 = lse.B[1]; this.smoothing[0] = (this.alpha * this.y[0] / seasonalIndex[0]) + (1 - this.alpha) * (smoothing0 + trend0); this.trend[0] = this.gamma * (this.smoothing[0] - smoothing0) + (1 - this.gamma) * trend0; this.seasonal[0] = (this.beta * this.y[0] / this.smoothing[0]) + (1 - this.beta) * seasonalIndex[0]; this.predicted[0] = (smoothing0 + trend0) * seasonalIndex[0]; this.residual[0] = this.y[0] - this.predicted[0]; for (int i = 1; i < l; i++) { this.smoothing[i] = (this.alpha * this.y[i] / seasonalIndex[i]) + (1 - this.alpha) * (this.smoothing[i - 1] + this.trend[i - 1]); this.trend[i] = this.gamma * (this.smoothing[i] - this.smoothing[i - 1]) + (1 - this.gamma) * this.trend[i - 1]; this.seasonal[i] = (this.beta * this.y[i] / this.smoothing[i]) + (1 - this.beta) * seasonalIndex[i]; this.predicted[i] = (this.smoothing[i - 1] + this.trend[i - 1]) * seasonalIndex[i]; this.residual[i] = this.y[i] - this.predicted[i]; } }
/// <summary> /// Prosedur untuk menghitung inisialisasi Pemulusan dan trend periode 0 (nol) /// Dihitung lse untuk data sebanyak panjang musiman pertama /// </summary> private void EstimateValue() { //Menghitung nilai detrend Matrix xL = new Matrix(this.l, 2); for (int i = 0; i < this.l; ++i) { xL[i, 0] = 1; xL[i, 1] = i + 1; } Vector yL = new Vector(this.l); for (int i = 0; i < this.l; ++i) yL[i] = this.y[i]; lse = new LeastSquareEstimator(xL, yL); }
/// <summary> /// Prosedur untuk menghitung inisialisasi nilai awal /// nilai awal ditentukan dengan menggunakan lse /// </summary> private void Init() { Matrix x = new Matrix(this.n, 2); for (int i = 0; i < this.n; ++i) { x[i, 0] = 1; x[i, 1] = i + 1; } LeastSquareEstimator lse = new LeastSquareEstimator(x, y); double[] parameters = lse.B.GetData(); double w = 1 - this.a; double a0 = (double)(parameters[0] - ((w / this.a) * parameters[1])); double b0 = (double)(parameters[0] - (2 * (w / this.a) * parameters[1])); this.smoothing1[0] = this.a * this.y[0] + w * a0; this.smoothing2[0] = this.a * this.smoothing1[0] + w * b0; ; }
private void ComponentTrend() { switch (this.initialTrend) { case 1: { //Model tren linier x = new Matrix(this.n, 2); for (int i = 0; i < this.n; ++i) { x[i, 0] = 1; x[i, 1] = i + 1; } Vector z = new Vector(this.deseasonal); lse = new LeastSquareEstimator(x, z); this.parameters = lse.B.GetData(); for (int i = 0; i < this.n; i++) this.trend[i] = this.parameters[0] + this.parameters[1] * (i + 1); break; } case 2: { //model tren kuadratik x = new Matrix(this.n, 3); for (int i = 0; i < this.n; ++i) { x[i, 0] = 1; x[i, 1] = i + 1; x[i, 2] = Math.Pow(i + 1, 2); } Vector z = new Vector(this.deseasonal); lse = new LeastSquareEstimator(x, z); this.parameters = lse.B.GetData(); for (int i = 0; i < this.n; i++) this.trend[i] = this.parameters[0] + this.parameters[1] * (i + 1) + this.parameters[2] * Math.Pow(i + 1, 2); break; } case 3: { //model tren kubik x = new Matrix(this.n, 4); for (int i = 0; i < this.n; ++i) { x[i, 0] = 1; x[i, 1] = i + 1; x[i, 2] = Math.Pow(i + 1, 2); x[i, 3] = Math.Pow(i + 1, 3); } Vector z = new Vector(this.deseasonal); lse = new LeastSquareEstimator(x, z); this.parameters = lse.B.GetData(); for (int i = 0; i < this.n; i++) this.trend[i] = this.parameters[0] + this.parameters[1] * (i + 1) + this.parameters[2] * Math.Pow(i + 1, 2) + this.parameters[3] * Math.Pow(i + 1, 3); break; } case 4: { //model tren eksponensial x = new Matrix(this.n, 2); for (int i = 0; i < this.n; ++i) { x[i, 0] = 1; x[i, 1] = i + 1; } Vector z = new Vector(this.n); for (int i = 0; i < this.n; ++i) z[i] = Math.Log10(this.deseasonal[i]); lse = new LeastSquareEstimator(x, z); this.parameters = lse.B.GetData(); for (int i = 0; i < 2; ++i) this.parameters[i] = Math.Pow(10, this.parameters[i]); for (int i = 0; i < this.n; i++) this.trend[i] = this.parameters[0] * Math.Pow(this.parameters[1], (i + 1)); break; } default: goto case 1; } }