|
9 | 9 | "import sys\n", |
10 | 10 | "import os\n", |
11 | 11 | "import numpy as np\n", |
| 12 | + "from dotenv import load_dotenv\n", |
| 13 | + "load_dotenv()\n", |
| 14 | + "sys.path.append(os.getenv(\"PATH_CUSUM\"))\n", |
12 | 15 | "from source.model.incremental import RecursiveLeastSquares\n", |
13 | 16 | "from source.detector.cusum import CUSUM_Detector\n", |
14 | 17 | "import matplotlib.pyplot as plt\n", |
15 | | - "from matplotlib.animation import FuncAnimation" |
| 18 | + "from matplotlib.animation import FuncAnimation\n", |
| 19 | + "\n", |
| 20 | + "# set random seed for reproducibility\n", |
| 21 | + "np.random.seed(42)" |
16 | 22 | ] |
17 | 23 | }, |
18 | 24 | { |
|
21 | 27 | "metadata": {}, |
22 | 28 | "outputs": [], |
23 | 29 | "source": [ |
24 | | - "n = 600\n", |
| 30 | + "n = 300\n", |
25 | 31 | "\n", |
26 | 32 | "# Create time series components\n", |
27 | 33 | "t = np.arange(n)\n", |
|
52 | 58 | "metadata": {}, |
53 | 59 | "outputs": [], |
54 | 60 | "source": [ |
55 | | - "values[300:500] += 50 # Introduce a change point\n", |
| 61 | + "values[150:] += 50 # Introduce a change point\n", |
56 | 62 | "\n", |
57 | 63 | "# plot the time series\n", |
58 | 64 | "plt.figure(figsize=(15, 4))\n", |
|
77 | 83 | "metadata": {}, |
78 | 84 | "outputs": [], |
79 | 85 | "source": [ |
80 | | - "# Set number of lags\n", |
81 | | - "num_lags = 3\n", |
82 | | - "\n", |
83 | 86 | "# Initialize model\n", |
84 | | - "model = RecursiveLeastSquares(num_variables=num_lags, forgetting_factor=0.99, initial_delta=50)\n", |
85 | | - "\n", |
86 | | - "warmup_period = 100\n", |
| 87 | + "num_lags = 5\n", |
| 88 | + "model = RecursiveLeastSquares(num_variables=num_lags, \n", |
| 89 | + " forgetting_factor=0.999, \n", |
| 90 | + " initial_delta=1.0)\n", |
87 | 91 | "\n", |
88 | 92 | "# Detect change points using CUSUM Detector\n", |
89 | | - "cusum_detector = CUSUM_Detector(warmup_period=warmup_period, delta=3, threshold=5)\n", |
| 93 | + "warmup_period = 50\n", |
| 94 | + "cusum_detector = CUSUM_Detector(warmup_period=warmup_period, \n", |
| 95 | + " delta=1.5, \n", |
| 96 | + " threshold=4.0)\n", |
| 97 | + "\n", |
90 | 98 | "\n", |
91 | 99 | "# Store predictions and observed values\n", |
92 | 100 | "list_predictions = []\n", |
93 | 101 | "list_observed = []\n", |
94 | 102 | "list_residuals = []\n", |
95 | 103 | "\n", |
96 | | - "list_pos_changes = []\n", |
| 104 | + "list_acc_changes = []\n", |
97 | 105 | "list_change_points = []\n", |
98 | 106 | "list_index_changes = []\n", |
99 | 107 | "list_output_detected = []\n", |
|
104 | 112 | "fig.tight_layout(pad=5.0)\n", |
105 | 113 | "\n", |
106 | 114 | "# Animation function\n", |
107 | | - "def animate(i):\n", |
| 115 | + "def monitoring(i):\n", |
108 | 116 | "\n", |
109 | 117 | " global output_detected, list_change_points, list_output_detected, list_residuals\n", |
110 | 118 | " \n", |
|
125 | 133 | "\n", |
126 | 134 | " # Store prediction and observed values\n", |
127 | 135 | " list_predictions.append(y_pred)\n", |
128 | | - " list_observed.append(y[0])\n", |
| 136 | + " list_observed.append(float(y[0][0]))\n", |
129 | 137 | "\n", |
130 | 138 | " # model params update\n", |
131 | 139 | " model.update(X, y)\n", |
132 | 140 | "\n", |
133 | 141 | " # Compute residuals\n", |
134 | 142 | " residuals = np.abs(y - y_pred)\n", |
135 | | - " list_residuals.append(residuals[0])\n", |
| 143 | + " list_residuals.append(residuals[0][0])\n", |
136 | 144 | "\n", |
137 | 145 | " # Detect change points\n", |
138 | 146 | " output_detected = cusum_detector.detection(residuals[0])\n", |
139 | | - " list_pos_changes.append(output_detected[0][0])\n", |
| 147 | + " list_acc_changes.append(float(output_detected[0][0]))\n", |
140 | 148 | " list_change_points.append(output_detected[-1])\n", |
141 | 149 | " list_output_detected.append(output_detected)\n", |
142 | 150 | "\n", |
|
146 | 154 | " change_ax.clear()\n", |
147 | 155 | "\n", |
148 | 156 | " # Plot predictions vs observed values\n", |
149 | | - " prediction_ax.plot(list_observed, label='Obs', color='blue')\n", |
150 | | - " prediction_ax.plot(list_predictions, label='Pred', color='orange')\n", |
| 157 | + " prediction_ax.plot(list_observed, label='Observation', color='orange')\n", |
| 158 | + " prediction_ax.plot(list_predictions, label='Prediction', color='blue', marker='o', markersize=4)\n", |
| 159 | + " prediction_ax.fill_between(range(len(list_predictions)),\n", |
| 160 | + " list_predictions,\n", |
| 161 | + " list_observed,\n", |
| 162 | + " color='lightgray', \n", |
| 163 | + " alpha=0.7)\n", |
151 | 164 | " for i, is_cp in enumerate(list_change_points):\n", |
152 | 165 | " if is_cp:\n", |
153 | 166 | " prediction_ax.axvline(x=i, color='red', linestyle='--', alpha=0.5)\n", |
154 | | - " if i >= warmup_period:\n", |
155 | | - " prediction_ax.axvline(x=warmup_period, color='gray', label='End WarmUp', linestyle='--')\n", |
156 | 167 | " prediction_ax.plot()\n", |
157 | 168 | " prediction_ax.legend()\n", |
158 | | - " prediction_ax.set_title(f'Change Points at idx {100} and {500}\\n RLS Predictions vs Observed Values')\n", |
| 169 | + " prediction_ax.set_title(f'Predictions vs Observations')\n", |
| 170 | + " prediction_ax.set_xlabel('Time Step')\n", |
| 171 | + " prediction_ax.set_ylabel('Prediction Value')\n", |
| 172 | + " prediction_ax.grid()\n", |
159 | 173 | " \n", |
160 | 174 | " # Plot residuals\n", |
161 | | - " residual_ax.plot(list_residuals, label='Residuals', color='red')\n", |
| 175 | + " residual_ax.plot(list_residuals, label='Residuals', color='red', marker='o', markersize=4) \n", |
| 176 | + " residual_ax.fill_between(range(len(list_residuals)),\n", |
| 177 | + " 0,\n", |
| 178 | + " list_residuals,\n", |
| 179 | + " color='red', \n", |
| 180 | + " alpha=0.1) \n", |
162 | 181 | " residual_ax.legend()\n", |
163 | 182 | " residual_ax.set_title('Residuals')\n", |
| 183 | + " residual_ax.set_xlabel('Time Step')\n", |
| 184 | + " residual_ax.set_ylabel('Residual Value')\n", |
| 185 | + " residual_ax.grid()\n", |
164 | 186 | "\n", |
165 | 187 | " # Plot detected change points\n", |
166 | | - " change_ax.plot(list_pos_changes, label='Performance Cumulative Changes', color='green')\n", |
167 | | - " change_ax.axhline(y=cusum_detector.threshold, color='r', linestyle='--')\n", |
| 188 | + " change_ax.plot(list_acc_changes, label='Cumulative Change', color='green', marker='o', markersize=4)\n", |
| 189 | + " change_ax.fill_between(range(len(list_acc_changes)),\n", |
| 190 | + " 0,\n", |
| 191 | + " list_acc_changes,\n", |
| 192 | + " color='green', \n", |
| 193 | + " alpha=0.5)\n", |
| 194 | + " change_ax.axhline(y=cusum_detector.threshold, color='r', linestyle='--', label='CUSUM Threshold')\n", |
168 | 195 | " change_ax.legend()\n", |
169 | 196 | " change_ax.set_title('Detected Change Points')\n", |
| 197 | + " change_ax.set_xlabel('Time Step')\n", |
| 198 | + " change_ax.set_ylabel('Cumulative Change Value')\n", |
| 199 | + " change_ax.grid()\n", |
170 | 200 | "\n", |
171 | 201 | "# Create the animation\n", |
172 | | - "ani = FuncAnimation(fig, animate, frames=len(values) - num_lags - 1, repeat=False) #\n", |
| 202 | + "ani = FuncAnimation(fig, monitoring, frames=len(values) - num_lags - 1, repeat=False) #\n", |
173 | 203 | "\n", |
174 | 204 | "# Save the animation\n", |
175 | 205 | "ani.save('monitoring.gif', writer='pillow', fps=100)\n", |
176 | 206 | "plt.close(fig) # Prevent the figure from displaying" |
177 | 207 | ] |
| 208 | + }, |
| 209 | + { |
| 210 | + "cell_type": "code", |
| 211 | + "execution_count": null, |
| 212 | + "metadata": {}, |
| 213 | + "outputs": [], |
| 214 | + "source": [ |
| 215 | + "import IPython.display as display\n", |
| 216 | + "\n", |
| 217 | + "# Display the saved GIF\n", |
| 218 | + "display.Image(filename='monitoring.gif')" |
| 219 | + ] |
178 | 220 | } |
179 | 221 | ], |
180 | 222 | "metadata": { |
|
0 commit comments