├── Data ├── test_dataset.csv ├── test_raw.csv ├── train_dataset.csv └── train_raw.csv ├── DataLoader.py ├── Preprocessing.py ├── README.md ├── helpers.py ├── inference.py ├── main.py ├── model.py ├── plot.py ├── train_teacher_forcing.py └── train_with_sampling.py /Data/test_raw.csv: -------------------------------------------------------------------------------- 1 | sensor_id,timestamp,humidity,reindexed_id 2 | 33,2020-08-14 20:00:00+00:00,52.075,1 3 | 33,2020-08-14 21:00:00+00:00,56.35,1 4 | 33,2020-08-14 22:00:00+00:00,60.23333333333333,1 5 | 33,2020-08-14 23:00:00+00:00,64.11666666666667,1 6 | 33,2020-08-15 00:00:00+00:00,68.0,1 7 | 33,2020-08-15 01:00:00+00:00,69.875,1 8 | 33,2020-08-15 02:00:00+00:00,71.75,1 9 | 33,2020-08-15 03:00:00+00:00,73.625,1 10 | 33,2020-08-15 04:00:00+00:00,75.5,1 11 | 33,2020-08-15 05:00:00+00:00,70.0,1 12 | 33,2020-08-15 06:00:00+00:00,64.5,1 13 | 33,2020-08-15 07:00:00+00:00,59.0,1 14 | 33,2020-08-15 08:00:00+00:00,53.5,1 15 | 33,2020-08-15 09:00:00+00:00,49.375,1 16 | 33,2020-08-15 10:00:00+00:00,45.25,1 17 | 33,2020-08-15 11:00:00+00:00,41.125,1 18 | 33,2020-08-15 12:00:00+00:00,37.0,1 19 | 33,2020-08-15 13:00:00+00:00,38.0,1 20 | 33,2020-08-15 14:00:00+00:00,39.0,1 21 | 33,2020-08-15 15:00:00+00:00,40.0,1 22 | 33,2020-08-15 16:00:00+00:00,42.125,1 23 | 33,2020-08-15 17:00:00+00:00,44.25,1 24 | 33,2020-08-15 18:00:00+00:00,46.375,1 25 | 33,2020-08-15 19:00:00+00:00,48.5,1 26 | 33,2020-08-15 20:00:00+00:00,52.375,1 27 | 33,2020-08-15 21:00:00+00:00,56.25,1 28 | 33,2020-08-15 22:00:00+00:00,60.125,1 29 | 33,2020-08-15 23:00:00+00:00,64.0,1 30 | 33,2020-08-16 00:00:00+00:00,65.625,1 31 | 33,2020-08-16 01:00:00+00:00,67.25,1 32 | 33,2020-08-16 02:00:00+00:00,68.875,1 33 | 33,2020-08-16 03:00:00+00:00,70.5,1 34 | 33,2020-08-16 04:00:00+00:00,69.33333333333333,1 35 | 33,2020-08-16 05:00:00+00:00,68.16666666666667,1 36 | 33,2020-08-16 06:00:00+00:00,67.0,1 37 | 33,2020-08-16 07:00:00+00:00,59.875,1 38 | 33,2020-08-16 08:00:00+00:00,52.75,1 39 | 33,2020-08-16 09:00:00+00:00,45.625,1 40 | 33,2020-08-16 10:00:00+00:00,38.5,1 41 | 33,2020-08-16 11:00:00+00:00,39.25,1 42 | 33,2020-08-16 12:00:00+00:00,40.0,1 43 | 33,2020-08-16 13:00:00+00:00,40.75,1 44 | 33,2020-08-16 14:00:00+00:00,41.5,1 45 | 33,2020-08-16 15:00:00+00:00,43.125,1 46 | 33,2020-08-16 16:00:00+00:00,44.75,1 47 | 33,2020-08-16 17:00:00+00:00,46.375,1 48 | 33,2020-08-16 18:00:00+00:00,48.0,1 49 | 33,2020-08-16 19:00:00+00:00,52.66666666666666,1 50 | 33,2020-08-16 20:00:00+00:00,57.33333333333334,1 51 | 33,2020-08-16 21:00:00+00:00,62.0,1 52 | 33,2020-08-16 22:00:00+00:00,63.375,1 53 | 33,2020-08-16 23:00:00+00:00,64.75,1 54 | 33,2020-08-17 00:00:00+00:00,66.125,1 55 | 33,2020-08-17 01:00:00+00:00,67.5,1 56 | 33,2020-08-17 02:00:00+00:00,68.375,1 57 | 33,2020-08-17 03:00:00+00:00,69.25,1 58 | 33,2020-08-17 04:00:00+00:00,70.125,1 59 | 33,2020-08-17 05:00:00+00:00,71.0,1 60 | 33,2020-08-17 06:00:00+00:00,63.5,1 61 | 33,2020-08-17 07:00:00+00:00,56.0,1 62 | 33,2020-08-17 08:00:00+00:00,48.5,1 63 | 33,2020-08-17 09:00:00+00:00,41.0,1 64 | 33,2020-08-17 10:00:00+00:00,37.5,1 65 | 33,2020-08-17 11:00:00+00:00,34.0,1 66 | 33,2020-08-17 12:00:00+00:00,30.5,1 67 | 33,2020-08-17 13:00:00+00:00,27.0,1 68 | 33,2020-08-17 14:00:00+00:00,28.83333333333333,1 69 | 33,2020-08-17 15:00:00+00:00,30.66666666666667,1 70 | 33,2020-08-17 16:00:00+00:00,32.5,1 71 | 33,2020-08-17 17:00:00+00:00,35.625,1 72 | 33,2020-08-17 18:00:00+00:00,38.75,1 73 | 33,2020-08-17 19:00:00+00:00,41.875,1 74 | 33,2020-08-17 20:00:00+00:00,45.0,1 75 | 33,2020-08-17 21:00:00+00:00,47.25,1 76 | 33,2020-08-17 22:00:00+00:00,49.5,1 77 | 33,2020-08-17 23:00:00+00:00,51.75,1 78 | 33,2020-08-18 00:00:00+00:00,54.0,1 79 | 33,2020-08-18 01:00:00+00:00,56.5,1 80 | 33,2020-08-18 02:00:00+00:00,59.0,1 81 | 33,2020-08-18 03:00:00+00:00,61.5,1 82 | 33,2020-08-18 04:00:00+00:00,64.0,1 83 | 33,2020-08-18 05:00:00+00:00,62.83333333333334,1 84 | 33,2020-08-18 06:00:00+00:00,61.66666666666666,1 85 | 33,2020-08-18 07:00:00+00:00,60.5,1 86 | 33,2020-08-18 08:00:00+00:00,56.6875,1 87 | 33,2020-08-18 09:00:00+00:00,52.875,1 88 | 33,2020-08-18 10:00:00+00:00,49.0625,1 89 | 33,2020-08-18 11:00:00+00:00,45.25,1 90 | 33,2020-08-18 12:00:00+00:00,43.8925,1 91 | 33,2020-08-18 13:00:00+00:00,42.535,1 92 | 33,2020-08-18 14:00:00+00:00,41.1775,1 93 | 33,2020-08-18 15:00:00+00:00,39.82,1 94 | 33,2020-08-18 16:00:00+00:00,42.115,1 95 | 33,2020-08-18 17:00:00+00:00,44.41,1 96 | 33,2020-08-18 18:00:00+00:00,46.705,1 97 | 33,2020-08-18 19:00:00+00:00,49.0,1 98 | 33,2020-08-18 20:00:00+00:00,53.5,1 99 | 33,2020-08-18 21:00:00+00:00,58.0,1 100 | 33,2020-08-18 22:00:00+00:00,62.5,1 101 | 33,2020-08-18 23:00:00+00:00,64.125,1 102 | 33,2020-08-19 00:00:00+00:00,65.75,1 103 | 33,2020-08-19 01:00:00+00:00,67.375,1 104 | 33,2020-08-19 02:00:00+00:00,69.0,1 105 | 33,2020-08-19 03:00:00+00:00,70.75,1 106 | 33,2020-08-19 04:00:00+00:00,72.5,1 107 | 33,2020-08-19 05:00:00+00:00,74.25,1 108 | 33,2020-08-19 06:00:00+00:00,76.0,1 109 | 33,2020-08-19 07:00:00+00:00,71.375,1 110 | 33,2020-08-19 08:00:00+00:00,66.75,1 111 | 33,2020-08-19 09:00:00+00:00,62.125,1 112 | 33,2020-08-19 10:00:00+00:00,57.5,1 113 | 33,2020-08-19 11:00:00+00:00,57.5,1 114 | 33,2020-08-19 12:00:00+00:00,57.5,1 115 | 33,2020-08-19 13:00:00+00:00,57.5,1 116 | 33,2020-08-19 14:00:00+00:00,59.5,1 117 | 33,2020-08-19 15:00:00+00:00,61.5,1 118 | 33,2020-08-19 16:00:00+00:00,63.5,1 119 | 33,2020-08-19 17:00:00+00:00,65.5,1 120 | 33,2020-08-19 18:00:00+00:00,67.0,1 121 | 33,2020-08-19 19:00:00+00:00,68.5,1 122 | 33,2020-08-19 20:00:00+00:00,70.0,1 123 | 33,2020-08-19 21:00:00+00:00,71.5,1 124 | 33,2020-08-19 22:00:00+00:00,72.5,1 125 | 33,2020-08-19 23:00:00+00:00,73.5,1 126 | 33,2020-08-20 00:00:00+00:00,74.5,1 127 | 33,2020-08-20 01:00:00+00:00,75.5,1 128 | 33,2020-08-20 02:00:00+00:00,77.0,1 129 | 33,2020-08-20 03:00:00+00:00,78.5,1 130 | 33,2020-08-20 04:00:00+00:00,80.0,1 131 | 33,2020-08-20 05:00:00+00:00,78.52925531914894,1 132 | 33,2020-08-20 06:00:00+00:00,77.05851063829788,1 133 | 33,2020-08-20 07:00:00+00:00,75.58776595744679,1 134 | 33,2020-08-20 08:00:00+00:00,74.11702127659575,1 135 | 33,2020-08-20 09:00:00+00:00,74.03937886067263,1 136 | 33,2020-08-20 10:00:00+00:00,73.96173644474949,1 137 | 33,2020-08-20 11:00:00+00:00,73.88409402882634,1 138 | 33,2020-08-20 12:00:00+00:00,73.80645161290323,1 139 | 33,2020-08-20 13:00:00+00:00,75.22983870967742,1 140 | 33,2020-08-20 14:00:00+00:00,76.65322580645163,1 141 | 33,2020-08-20 15:00:00+00:00,78.07661290322581,1 142 | 33,2020-08-20 16:00:00+00:00,79.5,1 143 | 33,2020-08-20 17:00:00+00:00,80.875,1 144 | 33,2020-08-20 18:00:00+00:00,82.25,1 145 | 33,2020-08-20 19:00:00+00:00,83.625,1 146 | 33,2020-08-20 20:00:00+00:00,85.0,1 147 | 33,2020-08-20 21:00:00+00:00,85.0,1 148 | 33,2020-08-20 22:00:00+00:00,85.0,1 149 | 33,2020-08-20 23:00:00+00:00,85.0,1 150 | 33,2020-08-21 00:00:00+00:00,85.25,1 151 | 33,2020-08-21 01:00:00+00:00,85.5,1 152 | 33,2020-08-21 02:00:00+00:00,85.75,1 153 | 33,2020-08-21 03:00:00+00:00,86.0,1 154 | 33,2020-08-21 04:00:00+00:00,85.875,1 155 | 33,2020-08-21 05:00:00+00:00,85.75,1 156 | 33,2020-08-21 06:00:00+00:00,85.625,1 157 | 33,2020-08-21 07:00:00+00:00,85.5,1 158 | 33,2020-08-21 08:00:00+00:00,85.45588235294117,1 159 | 33,2020-08-21 09:00:00+00:00,85.41176470588233,1 160 | 33,2020-08-21 10:00:00+00:00,85.36764705882355,1 161 | 33,2020-08-21 11:00:00+00:00,85.32352941176471,1 162 | 33,2020-08-21 12:00:00+00:00,84.38235294117648,1 163 | 33,2020-08-21 13:00:00+00:00,83.44117647058823,1 164 | 33,2020-08-21 14:00:00+00:00,82.5,1 165 | 33,2020-08-21 15:00:00+00:00,82.375,1 166 | 33,2020-08-21 16:00:00+00:00,82.25,1 167 | 33,2020-08-21 17:00:00+00:00,82.125,1 168 | 33,2020-08-21 18:00:00+00:00,82.0,1 169 | 33,2020-08-21 19:00:00+00:00,82.75,1 170 | 33,2020-08-21 20:00:00+00:00,83.5,1 171 | 33,2020-08-21 21:00:00+00:00,84.25,1 172 | 33,2020-08-21 22:00:00+00:00,85.0,1 173 | 33,2020-08-21 23:00:00+00:00,85.625,1 174 | 33,2020-08-22 00:00:00+00:00,86.25,1 175 | 33,2020-08-22 01:00:00+00:00,86.875,1 176 | 33,2020-08-22 02:00:00+00:00,87.5,1 177 | 33,2020-08-22 03:00:00+00:00,86.61570945945945,1 178 | 33,2020-08-22 04:00:00+00:00,85.73141891891892,1 179 | 33,2020-08-22 05:00:00+00:00,84.84712837837839,1 180 | 33,2020-08-22 06:00:00+00:00,83.96283783783784,1 181 | 33,2020-08-22 07:00:00+00:00,79.34712837837839,1 182 | 33,2020-08-22 08:00:00+00:00,74.73141891891892,1 183 | 33,2020-08-22 09:00:00+00:00,70.11570945945945,1 184 | 33,2020-08-22 10:00:00+00:00,65.5,1 185 | 33,2020-08-22 11:00:00+00:00,61.0,1 186 | 33,2020-08-22 12:00:00+00:00,56.5,1 187 | 33,2020-08-22 13:00:00+00:00,52.0,1 188 | 33,2020-08-22 14:00:00+00:00,53.25,1 189 | 33,2020-08-22 15:00:00+00:00,54.5,1 190 | 33,2020-08-22 16:00:00+00:00,55.75,1 191 | 33,2020-08-22 17:00:00+00:00,57.0,1 192 | 33,2020-08-22 18:00:00+00:00,60.5,1 193 | 33,2020-08-22 19:00:00+00:00,64.0,1 194 | 33,2020-08-22 20:00:00+00:00,67.5,1 195 | 33,2020-08-22 21:00:00+00:00,71.0,1 196 | 33,2020-08-22 22:00:00+00:00,72.875,1 197 | 33,2020-08-22 23:00:00+00:00,74.75,1 198 | 33,2020-08-23 00:00:00+00:00,76.625,1 199 | 33,2020-08-23 01:00:00+00:00,78.5,1 200 | 33,2020-08-23 02:00:00+00:00,79.83333333333333,1 201 | 33,2020-08-23 03:00:00+00:00,81.16666666666667,1 202 | 33,2020-08-23 04:00:00+00:00,82.5,1 203 | 33,2020-08-23 05:00:00+00:00,77.875,1 204 | 33,2020-08-23 06:00:00+00:00,73.25,1 205 | 33,2020-08-23 07:00:00+00:00,68.625,1 206 | 33,2020-08-23 08:00:00+00:00,64.0,1 207 | 33,2020-08-23 09:00:00+00:00,62.875,1 208 | 33,2020-08-23 10:00:00+00:00,61.75,1 209 | 33,2020-08-23 11:00:00+00:00,60.625,1 210 | 33,2020-08-23 12:00:00+00:00,59.5,1 211 | 33,2020-08-23 13:00:00+00:00,58.125,1 212 | 33,2020-08-23 14:00:00+00:00,56.75,1 213 | 33,2020-08-23 15:00:00+00:00,55.375,1 214 | 33,2020-08-23 16:00:00+00:00,54.0,1 215 | 33,2020-08-23 17:00:00+00:00,58.16666666666666,1 216 | 33,2020-08-23 18:00:00+00:00,62.33333333333334,1 217 | 33,2020-08-23 19:00:00+00:00,66.5,1 218 | 33,2020-08-23 20:00:00+00:00,68.375,1 219 | 33,2020-08-23 21:00:00+00:00,70.25,1 220 | 33,2020-08-23 22:00:00+00:00,72.125,1 221 | 33,2020-08-23 23:00:00+00:00,74.0,1 222 | 33,2020-08-24 00:00:00+00:00,74.875,1 223 | 33,2020-08-24 01:00:00+00:00,75.75,1 224 | 33,2020-08-24 02:00:00+00:00,76.625,1 225 | 33,2020-08-24 03:00:00+00:00,77.5,1 226 | 33,2020-08-24 04:00:00+00:00,77.5,1 227 | 33,2020-08-24 05:00:00+00:00,77.5,1 228 | 33,2020-08-24 06:00:00+00:00,77.5,1 229 | 33,2020-08-24 07:00:00+00:00,77.5,1 230 | 33,2020-08-24 08:00:00+00:00,70.83333333333333,1 231 | 33,2020-08-24 09:00:00+00:00,64.16666666666667,1 232 | 33,2020-08-24 10:00:00+00:00,57.5,1 233 | 33,2020-08-24 11:00:00+00:00,55.875,1 234 | 33,2020-08-24 12:00:00+00:00,54.25,1 235 | 33,2020-08-24 13:00:00+00:00,52.625,1 236 | 33,2020-08-24 14:00:00+00:00,51.0,1 237 | 33,2020-08-24 15:00:00+00:00,52.25,1 238 | 33,2020-08-24 16:00:00+00:00,53.5,1 239 | 33,2020-08-24 17:00:00+00:00,54.75,1 240 | 33,2020-08-24 18:00:00+00:00,56.0,1 241 | 33,2020-08-24 19:00:00+00:00,58.375,1 242 | 33,2020-08-24 20:00:00+00:00,60.75,1 243 | 33,2020-08-24 21:00:00+00:00,63.125,1 244 | 33,2020-08-24 22:00:00+00:00,65.5,1 245 | 33,2020-08-24 23:00:00+00:00,66.25,1 246 | 33,2020-08-25 00:00:00+00:00,67.0,1 247 | 33,2020-08-25 01:00:00+00:00,67.75,1 248 | 33,2020-08-25 02:00:00+00:00,68.5,1 249 | 33,2020-08-25 03:00:00+00:00,69.5,1 250 | 33,2020-08-25 04:00:00+00:00,70.5,1 251 | 33,2020-08-25 05:00:00+00:00,71.5,1 252 | 33,2020-08-25 06:00:00+00:00,66.5,1 253 | 33,2020-08-25 07:00:00+00:00,61.5,1 254 | 33,2020-08-25 08:00:00+00:00,56.5,1 255 | 33,2020-08-25 09:00:00+00:00,51.5,1 256 | 33,2020-08-25 10:00:00+00:00,48.75,1 257 | 33,2020-08-25 11:00:00+00:00,46.0,1 258 | 33,2020-08-25 12:00:00+00:00,43.25,1 259 | 33,2020-08-25 13:00:00+00:00,40.5,1 260 | 33,2020-08-25 14:00:00+00:00,41.875,1 261 | 33,2020-08-25 15:00:00+00:00,43.25,1 262 | 33,2020-08-25 16:00:00+00:00,44.625,1 263 | 33,2020-08-25 17:00:00+00:00,46.0,1 264 | 33,2020-08-25 18:00:00+00:00,50.16666666666666,1 265 | 33,2020-08-25 19:00:00+00:00,54.33333333333334,1 266 | 33,2020-08-25 20:00:00+00:00,58.5,1 267 | 33,2020-08-25 21:00:00+00:00,63.625,1 268 | 33,2020-08-25 22:00:00+00:00,68.75,1 269 | 33,2020-08-25 23:00:00+00:00,73.875,1 270 | 33,2020-08-26 00:00:00+00:00,79.0,1 271 | 33,2020-08-26 01:00:00+00:00,78.875,1 272 | 33,2020-08-26 02:00:00+00:00,78.75,1 273 | 33,2020-08-26 03:00:00+00:00,78.625,1 274 | 33,2020-08-26 04:00:00+00:00,78.5,1 275 | 33,2020-08-26 05:00:00+00:00,77.25,1 276 | 33,2020-08-26 06:00:00+00:00,76.0,1 277 | 33,2020-08-26 07:00:00+00:00,74.75,1 278 | 33,2020-08-26 08:00:00+00:00,73.5,1 279 | 33,2020-08-26 09:00:00+00:00,74.33333333333333,1 280 | 33,2020-08-26 10:00:00+00:00,75.16666666666667,1 281 | 33,2020-08-26 11:00:00+00:00,76.0,1 282 | 33,2020-08-26 12:00:00+00:00,72.875,1 283 | 33,2020-08-26 13:00:00+00:00,69.75,1 284 | 33,2020-08-26 14:00:00+00:00,66.625,1 285 | 33,2020-08-26 15:00:00+00:00,63.5,1 286 | 33,2020-08-26 16:00:00+00:00,65.0,1 287 | 33,2020-08-26 17:00:00+00:00,66.5,1 288 | 33,2020-08-26 18:00:00+00:00,68.0,1 289 | 33,2020-08-26 19:00:00+00:00,69.5,1 290 | 33,2020-08-26 20:00:00+00:00,71.25,1 291 | 33,2020-08-26 21:00:00+00:00,73.0,1 292 | 33,2020-08-26 22:00:00+00:00,74.75,1 293 | 33,2020-08-26 23:00:00+00:00,76.5,1 294 | 33,2020-08-27 00:00:00+00:00,77.33333333333333,1 295 | 33,2020-08-27 01:00:00+00:00,78.16666666666667,1 296 | 33,2020-08-27 02:00:00+00:00,79.0,1 297 | 33,2020-08-27 03:00:00+00:00,79.625,1 298 | 33,2020-08-27 04:00:00+00:00,80.25,1 299 | 33,2020-08-27 05:00:00+00:00,80.875,1 300 | 33,2020-08-27 06:00:00+00:00,81.5,1 301 | 33,2020-08-27 07:00:00+00:00,81.0,1 302 | 33,2020-08-27 08:00:00+00:00,80.5,1 303 | 33,2020-08-27 09:00:00+00:00,80.0,1 304 | 33,2020-08-27 10:00:00+00:00,79.5,1 305 | 33,2020-08-27 11:00:00+00:00,77.875,1 306 | 33,2020-08-27 12:00:00+00:00,76.25,1 307 | 33,2020-08-27 13:00:00+00:00,74.625,1 308 | 33,2020-08-27 14:00:00+00:00,73.0,1 309 | 33,2020-08-27 15:00:00+00:00,74.25,1 310 | 33,2020-08-27 16:00:00+00:00,75.5,1 311 | 33,2020-08-27 17:00:00+00:00,76.75,1 312 | 33,2020-08-27 18:00:00+00:00,78.0,1 313 | 33,2020-08-27 19:00:00+00:00,78.66666666666667,1 314 | 33,2020-08-27 20:00:00+00:00,79.33333333333333,1 315 | 33,2020-08-27 21:00:00+00:00,80.0,1 316 | 33,2020-08-27 22:00:00+00:00,80.5,1 317 | 33,2020-08-27 23:00:00+00:00,81.0,1 318 | 33,2020-08-28 00:00:00+00:00,81.5,1 319 | 33,2020-08-28 01:00:00+00:00,82.0,1 320 | 33,2020-08-28 02:00:00+00:00,82.5,1 321 | 33,2020-08-28 03:00:00+00:00,83.0,1 322 | 33,2020-08-28 04:00:00+00:00,83.5,1 323 | 33,2020-08-28 05:00:00+00:00,84.0,1 324 | 33,2020-08-28 06:00:00+00:00,83.5,1 325 | 33,2020-08-28 07:00:00+00:00,83.0,1 326 | 33,2020-08-28 08:00:00+00:00,82.5,1 327 | 33,2020-08-28 09:00:00+00:00,82.0,1 328 | 33,2020-08-28 10:00:00+00:00,80.5,1 329 | 33,2020-08-28 11:00:00+00:00,79.0,1 330 | 33,2020-08-28 12:00:00+00:00,77.5,1 331 | 33,2020-08-28 13:00:00+00:00,78.125,1 332 | 33,2020-08-28 14:00:00+00:00,78.75,1 333 | 33,2020-08-28 15:00:00+00:00,79.375,1 334 | 33,2020-08-28 16:00:00+00:00,80.0,1 335 | 33,2020-08-28 17:00:00+00:00,80.875,1 336 | 33,2020-08-28 18:00:00+00:00,81.75,1 337 | 33,2020-08-28 19:00:00+00:00,82.625,1 338 | 33,2020-08-28 20:00:00+00:00,83.5,1 339 | 33,2020-08-28 21:00:00+00:00,83.75,1 340 | 33,2020-08-28 22:00:00+00:00,84.0,1 341 | 33,2020-08-28 23:00:00+00:00,84.25,1 342 | 33,2020-08-29 00:00:00+00:00,84.5,1 343 | 33,2020-08-29 01:00:00+00:00,85.33333333333333,1 344 | 33,2020-08-29 02:00:00+00:00,86.16666666666669,1 345 | 33,2020-08-29 03:00:00+00:00,87.0,1 346 | 33,2020-08-29 04:00:00+00:00,86.875,1 347 | 33,2020-08-29 05:00:00+00:00,86.75,1 348 | 33,2020-08-29 06:00:00+00:00,86.625,1 349 | 33,2020-08-29 07:00:00+00:00,86.5,1 350 | 33,2020-08-29 08:00:00+00:00,83.5,1 351 | 33,2020-08-29 09:00:00+00:00,80.5,1 352 | 33,2020-08-29 10:00:00+00:00,77.5,1 353 | 33,2020-08-29 11:00:00+00:00,74.5,1 354 | 33,2020-08-29 12:00:00+00:00,72.125,1 355 | 33,2020-08-29 13:00:00+00:00,69.75,1 356 | 33,2020-08-29 14:00:00+00:00,67.375,1 357 | 33,2020-08-29 15:00:00+00:00,65.0,1 358 | 33,2020-08-29 16:00:00+00:00,67.5,1 359 | 33,2020-08-29 17:00:00+00:00,70.0,1 360 | 33,2020-08-29 18:00:00+00:00,72.5,1 361 | 33,2020-08-29 19:00:00+00:00,74.25,1 362 | 33,2020-08-29 20:00:00+00:00,76.0,1 363 | 33,2020-08-29 21:00:00+00:00,77.75,1 364 | 33,2020-08-29 22:00:00+00:00,79.5,1 365 | 33,2020-08-29 23:00:00+00:00,80.125,1 366 | 33,2020-08-30 00:00:00+00:00,80.75,1 367 | 33,2020-08-30 01:00:00+00:00,81.375,1 368 | 33,2020-08-30 02:00:00+00:00,82.0,1 369 | 33,2020-08-30 03:00:00+00:00,80.9375,1 370 | 33,2020-08-30 04:00:00+00:00,79.875,1 371 | 33,2020-08-30 05:00:00+00:00,78.8125,1 372 | 33,2020-08-30 06:00:00+00:00,77.75,1 373 | 33,2020-08-30 07:00:00+00:00,76.6875,1 374 | 33,2020-08-30 08:00:00+00:00,75.625,1 375 | 33,2020-08-30 09:00:00+00:00,74.5625,1 376 | 33,2020-08-30 10:00:00+00:00,73.5,1 377 | 33,2020-08-30 11:00:00+00:00,68.5,1 378 | 33,2020-08-30 12:00:00+00:00,63.5,1 379 | 33,2020-08-30 13:00:00+00:00,58.5,1 380 | 33,2020-08-30 14:00:00+00:00,57.625,1 381 | 33,2020-08-30 15:00:00+00:00,56.75,1 382 | 33,2020-08-30 16:00:00+00:00,55.875,1 383 | 33,2020-08-30 17:00:00+00:00,55.0,1 384 | 33,2020-08-30 18:00:00+00:00,58.125,1 385 | 33,2020-08-30 19:00:00+00:00,61.25,1 386 | 33,2020-08-30 20:00:00+00:00,64.375,1 387 | 33,2020-08-30 21:00:00+00:00,67.5,1 388 | 33,2020-08-30 22:00:00+00:00,69.375,1 389 | 33,2020-08-30 23:00:00+00:00,71.25,1 390 | 33,2020-08-31 00:00:00+00:00,73.125,1 391 | 33,2020-08-31 01:00:00+00:00,75.0,1 392 | 33,2020-08-31 02:00:00+00:00,76.0,1 393 | 33,2020-08-31 03:00:00+00:00,77.0,1 394 | 33,2020-08-31 04:00:00+00:00,78.0,1 395 | 33,2020-08-31 05:00:00+00:00,74.125,1 396 | 33,2020-08-31 06:00:00+00:00,70.25,1 397 | 33,2020-08-31 07:00:00+00:00,66.375,1 398 | 33,2020-08-31 08:00:00+00:00,62.5,1 399 | 33,2020-08-31 09:00:00+00:00,57.75,1 400 | 33,2020-08-31 10:00:00+00:00,53.0,1 401 | 33,2020-08-31 11:00:00+00:00,48.25,1 402 | 44,2020-07-11 23:00:00+00:00,57.75,2 403 | 44,2020-07-12 00:00:00+00:00,59.875,2 404 | 44,2020-07-12 01:00:00+00:00,62.0,2 405 | 44,2020-07-12 02:00:00+00:00,63.375,2 406 | 44,2020-07-12 03:00:00+00:00,64.75,2 407 | 44,2020-07-12 04:00:00+00:00,66.125,2 408 | 44,2020-07-12 05:00:00+00:00,67.5,2 409 | 44,2020-07-12 06:00:00+00:00,67.625,2 410 | 44,2020-07-12 07:00:00+00:00,67.75,2 411 | 44,2020-07-12 08:00:00+00:00,67.875,2 412 | 44,2020-07-12 09:00:00+00:00,68.0,2 413 | 44,2020-07-12 10:00:00+00:00,63.33333333333334,2 414 | 44,2020-07-12 11:00:00+00:00,58.66666666666666,2 415 | 44,2020-07-12 12:00:00+00:00,54.0,2 416 | 44,2020-07-12 13:00:00+00:00,53.75,2 417 | 44,2020-07-12 14:00:00+00:00,53.5,2 418 | 44,2020-07-12 15:00:00+00:00,53.25,2 419 | 44,2020-07-12 16:00:00+00:00,53.0,2 420 | 44,2020-07-12 17:00:00+00:00,54.625,2 421 | 44,2020-07-12 18:00:00+00:00,56.25,2 422 | 44,2020-07-12 19:00:00+00:00,57.875,2 423 | 44,2020-07-12 20:00:00+00:00,59.5,2 424 | 44,2020-07-12 21:00:00+00:00,60.625,2 425 | 44,2020-07-12 22:00:00+00:00,61.75,2 426 | 44,2020-07-12 23:00:00+00:00,62.875,2 427 | 44,2020-07-13 00:00:00+00:00,64.0,2 428 | 44,2020-07-13 01:00:00+00:00,64.75,2 429 | 44,2020-07-13 02:00:00+00:00,65.5,2 430 | 44,2020-07-13 03:00:00+00:00,66.25,2 431 | 44,2020-07-13 04:00:00+00:00,67.0,2 432 | 44,2020-07-13 05:00:00+00:00,66.625,2 433 | 44,2020-07-13 06:00:00+00:00,66.25,2 434 | 44,2020-07-13 07:00:00+00:00,65.875,2 435 | 44,2020-07-13 08:00:00+00:00,65.5,2 436 | 44,2020-07-13 09:00:00+00:00,64.25,2 437 | 44,2020-07-13 10:00:00+00:00,63.0,2 438 | 44,2020-07-13 11:00:00+00:00,61.75,2 439 | 44,2020-07-13 12:00:00+00:00,60.5,2 440 | 44,2020-07-13 13:00:00+00:00,58.875,2 441 | 44,2020-07-13 14:00:00+00:00,57.25,2 442 | 44,2020-07-13 15:00:00+00:00,55.625,2 443 | 44,2020-07-13 16:00:00+00:00,54.0,2 444 | 44,2020-07-13 17:00:00+00:00,52.375,2 445 | 44,2020-07-13 18:00:00+00:00,50.75,2 446 | 44,2020-07-13 19:00:00+00:00,49.125,2 447 | 44,2020-07-13 20:00:00+00:00,47.5,2 448 | 44,2020-07-13 21:00:00+00:00,50.83333333333334,2 449 | 44,2020-07-13 22:00:00+00:00,54.16666666666666,2 450 | 44,2020-07-13 23:00:00+00:00,57.5,2 451 | 44,2020-07-14 00:00:00+00:00,59.0,2 452 | 44,2020-07-14 01:00:00+00:00,60.5,2 453 | 44,2020-07-14 02:00:00+00:00,62.0,2 454 | 44,2020-07-14 03:00:00+00:00,63.5,2 455 | 44,2020-07-14 04:00:00+00:00,63.125,2 456 | 44,2020-07-14 05:00:00+00:00,62.75,2 457 | 44,2020-07-14 06:00:00+00:00,62.375,2 458 | 44,2020-07-14 07:00:00+00:00,62.0,2 459 | 44,2020-07-14 08:00:00+00:00,59.25,2 460 | 44,2020-07-14 09:00:00+00:00,56.5,2 461 | 44,2020-07-14 10:00:00+00:00,53.75,2 462 | 44,2020-07-14 11:00:00+00:00,51.0,2 463 | 44,2020-07-14 12:00:00+00:00,51.625,2 464 | 44,2020-07-14 13:00:00+00:00,52.25,2 465 | 44,2020-07-14 14:00:00+00:00,52.875,2 466 | 44,2020-07-14 15:00:00+00:00,53.5,2 467 | 44,2020-07-14 16:00:00+00:00,54.125,2 468 | 44,2020-07-14 17:00:00+00:00,54.75,2 469 | 44,2020-07-14 18:00:00+00:00,55.375,2 470 | 44,2020-07-14 19:00:00+00:00,56.0,2 471 | 44,2020-07-14 20:00:00+00:00,57.375,2 472 | 44,2020-07-14 21:00:00+00:00,58.75,2 473 | 44,2020-07-14 22:00:00+00:00,60.125,2 474 | 44,2020-07-14 23:00:00+00:00,61.5,2 475 | 44,2020-07-15 00:00:00+00:00,62.75,2 476 | 44,2020-07-15 01:00:00+00:00,64.0,2 477 | 44,2020-07-15 02:00:00+00:00,65.25,2 478 | 44,2020-07-15 03:00:00+00:00,66.5,2 479 | 44,2020-07-15 04:00:00+00:00,67.25,2 480 | 44,2020-07-15 05:00:00+00:00,68.0,2 481 | 44,2020-07-15 06:00:00+00:00,68.75,2 482 | 44,2020-07-15 07:00:00+00:00,69.5,2 483 | 44,2020-07-15 08:00:00+00:00,67.5,2 484 | 44,2020-07-15 09:00:00+00:00,65.5,2 485 | 44,2020-07-15 10:00:00+00:00,63.5,2 486 | 44,2020-07-15 11:00:00+00:00,61.5,2 487 | 44,2020-07-15 12:00:00+00:00,60.2,2 488 | 44,2020-07-15 13:00:00+00:00,58.9,2 489 | 44,2020-07-15 14:00:00+00:00,57.6,2 490 | 44,2020-07-15 15:00:00+00:00,56.3,2 491 | 44,2020-07-15 16:00:00+00:00,55.0,2 492 | 44,2020-07-15 17:00:00+00:00,56.33333333333334,2 493 | 44,2020-07-15 18:00:00+00:00,57.66666666666666,2 494 | 44,2020-07-15 19:00:00+00:00,59.0,2 495 | 44,2020-07-15 20:00:00+00:00,60.33333333333334,2 496 | 44,2020-07-15 21:00:00+00:00,61.66666666666666,2 497 | 44,2020-07-15 22:00:00+00:00,63.0,2 498 | 44,2020-07-15 23:00:00+00:00,64.25,2 499 | 44,2020-07-16 00:00:00+00:00,65.5,2 500 | 44,2020-07-16 01:00:00+00:00,66.75,2 501 | 44,2020-07-16 02:00:00+00:00,68.0,2 502 | 44,2020-07-16 03:00:00+00:00,68.25,2 503 | 44,2020-07-16 04:00:00+00:00,68.5,2 504 | 44,2020-07-16 05:00:00+00:00,68.75,2 505 | 44,2020-07-16 06:00:00+00:00,69.0,2 506 | 44,2020-07-16 07:00:00+00:00,67.375,2 507 | 44,2020-07-16 08:00:00+00:00,65.75,2 508 | 44,2020-07-16 09:00:00+00:00,64.125,2 509 | 44,2020-07-16 10:00:00+00:00,62.5,2 510 | 44,2020-07-16 11:00:00+00:00,60.625,2 511 | 44,2020-07-16 12:00:00+00:00,58.75,2 512 | 44,2020-07-16 13:00:00+00:00,56.875,2 513 | 44,2020-07-16 14:00:00+00:00,55.0,2 514 | 44,2020-07-16 15:00:00+00:00,54.125,2 515 | 44,2020-07-16 16:00:00+00:00,53.25,2 516 | 44,2020-07-16 17:00:00+00:00,52.375,2 517 | 44,2020-07-16 18:00:00+00:00,51.5,2 518 | 44,2020-07-16 19:00:00+00:00,53.25,2 519 | 44,2020-07-16 20:00:00+00:00,55.0,2 520 | 44,2020-07-16 21:00:00+00:00,56.75,2 521 | 44,2020-07-16 22:00:00+00:00,58.5,2 522 | 44,2020-07-16 23:00:00+00:00,60.83333333333334,2 523 | 44,2020-07-17 00:00:00+00:00,63.16666666666666,2 524 | 44,2020-07-17 01:00:00+00:00,65.5,2 525 | 44,2020-07-17 02:00:00+00:00,66.375,2 526 | 44,2020-07-17 03:00:00+00:00,67.25,2 527 | 44,2020-07-17 04:00:00+00:00,68.125,2 528 | 44,2020-07-17 05:00:00+00:00,69.0,2 529 | 44,2020-07-17 06:00:00+00:00,64.0,2 530 | 44,2020-07-17 07:00:00+00:00,59.0,2 531 | 44,2020-07-17 08:00:00+00:00,54.0,2 532 | 44,2020-07-17 09:00:00+00:00,49.0,2 533 | 44,2020-07-17 10:00:00+00:00,46.5,2 534 | 44,2020-07-17 11:00:00+00:00,44.0,2 535 | 44,2020-07-17 12:00:00+00:00,41.5,2 536 | 44,2020-07-17 13:00:00+00:00,39.0,2 537 | 44,2020-07-17 14:00:00+00:00,37.625,2 538 | 44,2020-07-17 15:00:00+00:00,36.25,2 539 | 44,2020-07-17 16:00:00+00:00,34.875,2 540 | 44,2020-07-17 17:00:00+00:00,33.5,2 541 | 44,2020-07-17 18:00:00+00:00,35.875,2 542 | 44,2020-07-17 19:00:00+00:00,38.25,2 543 | 44,2020-07-17 20:00:00+00:00,40.625,2 544 | 44,2020-07-17 21:00:00+00:00,43.0,2 545 | 44,2020-07-17 22:00:00+00:00,45.5,2 546 | 44,2020-07-17 23:00:00+00:00,48.0,2 547 | 44,2020-07-18 00:00:00+00:00,50.5,2 548 | 44,2020-07-18 01:00:00+00:00,53.0,2 549 | 44,2020-07-18 02:00:00+00:00,54.75,2 550 | 44,2020-07-18 03:00:00+00:00,56.5,2 551 | 44,2020-07-18 04:00:00+00:00,58.25,2 552 | 44,2020-07-18 05:00:00+00:00,60.0,2 553 | 44,2020-07-18 06:00:00+00:00,55.5,2 554 | 44,2020-07-18 07:00:00+00:00,51.0,2 555 | 44,2020-07-18 08:00:00+00:00,46.5,2 556 | 44,2020-07-18 09:00:00+00:00,44.75,2 557 | 44,2020-07-18 10:00:00+00:00,43.0,2 558 | 44,2020-07-18 11:00:00+00:00,41.25,2 559 | 44,2020-07-18 12:00:00+00:00,39.5,2 560 | 44,2020-07-18 13:00:00+00:00,38.125,2 561 | 44,2020-07-18 14:00:00+00:00,36.75,2 562 | 44,2020-07-18 15:00:00+00:00,35.375,2 563 | 44,2020-07-18 16:00:00+00:00,34.0,2 564 | 44,2020-07-18 17:00:00+00:00,35.875,2 565 | 44,2020-07-18 18:00:00+00:00,37.75,2 566 | 44,2020-07-18 19:00:00+00:00,39.625,2 567 | 44,2020-07-18 20:00:00+00:00,41.5,2 568 | 44,2020-07-18 21:00:00+00:00,43.75,2 569 | 44,2020-07-18 22:00:00+00:00,46.0,2 570 | 44,2020-07-18 23:00:00+00:00,48.25,2 571 | 44,2020-07-19 00:00:00+00:00,50.5,2 572 | 44,2020-07-19 01:00:00+00:00,52.75,2 573 | 44,2020-07-19 02:00:00+00:00,55.0,2 574 | 44,2020-07-19 03:00:00+00:00,57.25,2 575 | 44,2020-07-19 04:00:00+00:00,59.5,2 576 | 44,2020-07-19 05:00:00+00:00,60.0,2 577 | 44,2020-07-19 06:00:00+00:00,60.5,2 578 | 44,2020-07-19 07:00:00+00:00,61.0,2 579 | 44,2020-07-19 08:00:00+00:00,61.5,2 580 | 44,2020-07-19 09:00:00+00:00,56.375,2 581 | 44,2020-07-19 10:00:00+00:00,51.25,2 582 | 44,2020-07-19 11:00:00+00:00,46.125,2 583 | 44,2020-07-19 12:00:00+00:00,41.0,2 584 | 44,2020-07-19 13:00:00+00:00,40.375,2 585 | 44,2020-07-19 14:00:00+00:00,39.75,2 586 | 44,2020-07-19 15:00:00+00:00,39.125,2 587 | 44,2020-07-19 16:00:00+00:00,38.5,2 588 | 44,2020-07-19 17:00:00+00:00,40.0,2 589 | 44,2020-07-19 18:00:00+00:00,41.5,2 590 | 44,2020-07-19 19:00:00+00:00,43.0,2 591 | 44,2020-07-19 20:00:00+00:00,45.25,2 592 | 44,2020-07-19 21:00:00+00:00,47.5,2 593 | 44,2020-07-19 22:00:00+00:00,49.75,2 594 | 44,2020-07-19 23:00:00+00:00,52.0,2 595 | 44,2020-07-20 00:00:00+00:00,53.5,2 596 | 44,2020-07-20 01:00:00+00:00,55.0,2 597 | 44,2020-07-20 02:00:00+00:00,56.5,2 598 | 44,2020-07-20 03:00:00+00:00,58.0,2 599 | 44,2020-07-20 04:00:00+00:00,58.625,2 600 | 44,2020-07-20 05:00:00+00:00,59.25,2 601 | 44,2020-07-20 06:00:00+00:00,59.875,2 602 | 44,2020-07-20 07:00:00+00:00,60.5,2 603 | 44,2020-07-20 08:00:00+00:00,57.25,2 604 | 44,2020-07-20 09:00:00+00:00,54.0,2 605 | 44,2020-07-20 10:00:00+00:00,50.75,2 606 | 44,2020-07-20 11:00:00+00:00,47.5,2 607 | 44,2020-07-20 12:00:00+00:00,45.25,2 608 | 44,2020-07-20 13:00:00+00:00,43.0,2 609 | 44,2020-07-20 14:00:00+00:00,40.75,2 610 | 44,2020-07-20 15:00:00+00:00,38.5,2 611 | 44,2020-07-20 16:00:00+00:00,39.5,2 612 | 44,2020-07-20 17:00:00+00:00,40.5,2 613 | 44,2020-07-20 18:00:00+00:00,41.5,2 614 | 44,2020-07-20 19:00:00+00:00,42.5,2 615 | 44,2020-07-20 20:00:00+00:00,45.125,2 616 | 44,2020-07-20 21:00:00+00:00,47.75,2 617 | 44,2020-07-20 22:00:00+00:00,50.375,2 618 | 44,2020-07-20 23:00:00+00:00,53.0,2 619 | 44,2020-07-21 00:00:00+00:00,55.125,2 620 | 44,2020-07-21 01:00:00+00:00,57.25,2 621 | 44,2020-07-21 02:00:00+00:00,59.375,2 622 | 44,2020-07-21 03:00:00+00:00,61.5,2 623 | 44,2020-07-21 04:00:00+00:00,60.5,2 624 | 44,2020-07-21 05:00:00+00:00,59.5,2 625 | 44,2020-07-21 06:00:00+00:00,58.5,2 626 | 44,2020-07-21 07:00:00+00:00,55.0,2 627 | 44,2020-07-21 08:00:00+00:00,51.5,2 628 | 44,2020-07-21 09:00:00+00:00,48.0,2 629 | 44,2020-07-21 10:00:00+00:00,44.5,2 630 | 44,2020-07-21 11:00:00+00:00,42.25,2 631 | 44,2020-07-21 12:00:00+00:00,40.0,2 632 | 44,2020-07-21 13:00:00+00:00,37.75,2 633 | 44,2020-07-21 14:00:00+00:00,35.5,2 634 | 44,2020-07-21 15:00:00+00:00,36.125,2 635 | 44,2020-07-21 16:00:00+00:00,36.75,2 636 | 44,2020-07-21 17:00:00+00:00,37.375,2 637 | 44,2020-07-21 18:00:00+00:00,38.0,2 638 | 44,2020-07-21 19:00:00+00:00,40.75,2 639 | 44,2020-07-21 20:00:00+00:00,43.5,2 640 | 44,2020-07-21 21:00:00+00:00,46.25,2 641 | 44,2020-07-21 22:00:00+00:00,49.0,2 642 | 44,2020-07-21 23:00:00+00:00,51.25,2 643 | 44,2020-07-22 00:00:00+00:00,53.5,2 644 | 44,2020-07-22 01:00:00+00:00,55.75,2 645 | 44,2020-07-22 02:00:00+00:00,58.0,2 646 | 44,2020-07-22 03:00:00+00:00,58.5,2 647 | 44,2020-07-22 04:00:00+00:00,59.0,2 648 | 44,2020-07-22 05:00:00+00:00,59.5,2 649 | 44,2020-07-22 06:00:00+00:00,60.0,2 650 | 44,2020-07-22 07:00:00+00:00,56.625,2 651 | 44,2020-07-22 08:00:00+00:00,53.25,2 652 | 44,2020-07-22 09:00:00+00:00,49.875,2 653 | 44,2020-07-22 10:00:00+00:00,46.5,2 654 | 44,2020-07-22 11:00:00+00:00,44.375,2 655 | 44,2020-07-22 12:00:00+00:00,42.25,2 656 | 44,2020-07-22 13:00:00+00:00,40.125,2 657 | 44,2020-07-22 14:00:00+00:00,38.0,2 658 | 44,2020-07-22 15:00:00+00:00,38.0,2 659 | 44,2020-07-22 16:00:00+00:00,38.0,2 660 | 44,2020-07-22 17:00:00+00:00,38.0,2 661 | 44,2020-07-22 18:00:00+00:00,40.5,2 662 | 44,2020-07-22 19:00:00+00:00,43.0,2 663 | 44,2020-07-22 20:00:00+00:00,45.5,2 664 | 44,2020-07-22 21:00:00+00:00,48.0,2 665 | 44,2020-07-22 22:00:00+00:00,50.25,2 666 | 44,2020-07-22 23:00:00+00:00,52.5,2 667 | 44,2020-07-23 00:00:00+00:00,54.75,2 668 | 44,2020-07-23 01:00:00+00:00,57.0,2 669 | 44,2020-07-23 02:00:00+00:00,57.625,2 670 | 44,2020-07-23 03:00:00+00:00,58.25,2 671 | 44,2020-07-23 04:00:00+00:00,58.875,2 672 | 44,2020-07-23 05:00:00+00:00,59.5,2 673 | 44,2020-07-23 06:00:00+00:00,56.625,2 674 | 44,2020-07-23 07:00:00+00:00,53.75,2 675 | 44,2020-07-23 08:00:00+00:00,50.875,2 676 | 44,2020-07-23 09:00:00+00:00,48.0,2 677 | 44,2020-07-23 10:00:00+00:00,44.75,2 678 | 44,2020-07-23 11:00:00+00:00,41.5,2 679 | 44,2020-07-23 12:00:00+00:00,38.25,2 680 | 44,2020-07-23 13:00:00+00:00,35.0,2 681 | 44,2020-07-23 14:00:00+00:00,35.625,2 682 | 44,2020-07-23 15:00:00+00:00,36.25,2 683 | 44,2020-07-23 16:00:00+00:00,36.875,2 684 | 44,2020-07-23 17:00:00+00:00,37.5,2 685 | 44,2020-07-23 18:00:00+00:00,39.75,2 686 | 44,2020-07-23 19:00:00+00:00,42.0,2 687 | 44,2020-07-23 20:00:00+00:00,44.25,2 688 | 44,2020-07-23 21:00:00+00:00,46.5,2 689 | 44,2020-07-23 22:00:00+00:00,49.375,2 690 | 44,2020-07-23 23:00:00+00:00,52.25,2 691 | 44,2020-07-24 00:00:00+00:00,55.125,2 692 | 44,2020-07-24 01:00:00+00:00,58.0,2 693 | 44,2020-07-24 02:00:00+00:00,59.83333333333334,2 694 | 44,2020-07-24 03:00:00+00:00,61.66666666666666,2 695 | 44,2020-07-24 04:00:00+00:00,63.5,2 696 | 44,2020-07-24 05:00:00+00:00,65.375,2 697 | 44,2020-07-24 06:00:00+00:00,67.25,2 698 | 44,2020-07-24 07:00:00+00:00,69.125,2 699 | 44,2020-07-24 08:00:00+00:00,71.0,2 700 | 44,2020-07-24 09:00:00+00:00,70.75,2 701 | 44,2020-07-24 10:00:00+00:00,70.5,2 702 | 44,2020-07-24 11:00:00+00:00,70.25,2 703 | 44,2020-07-24 12:00:00+00:00,70.0,2 704 | 44,2020-07-24 13:00:00+00:00,69.1875,2 705 | 44,2020-07-24 14:00:00+00:00,68.375,2 706 | 44,2020-07-24 15:00:00+00:00,67.5625,2 707 | 44,2020-07-24 16:00:00+00:00,66.75,2 708 | 44,2020-07-24 17:00:00+00:00,65.9375,2 709 | 44,2020-07-24 18:00:00+00:00,65.125,2 710 | 44,2020-07-24 19:00:00+00:00,64.3125,2 711 | 44,2020-07-24 20:00:00+00:00,63.5,2 712 | 44,2020-07-24 21:00:00+00:00,64.125,2 713 | 44,2020-07-24 22:00:00+00:00,64.75,2 714 | 44,2020-07-24 23:00:00+00:00,65.375,2 715 | 44,2020-07-25 00:00:00+00:00,66.0,2 716 | 44,2020-07-25 01:00:00+00:00,66.75,2 717 | 44,2020-07-25 02:00:00+00:00,67.5,2 718 | 44,2020-07-25 03:00:00+00:00,68.25,2 719 | 44,2020-07-25 04:00:00+00:00,69.0,2 720 | 44,2020-07-25 05:00:00+00:00,66.875,2 721 | 44,2020-07-25 06:00:00+00:00,64.75,2 722 | 44,2020-07-25 07:00:00+00:00,62.625,2 723 | 44,2020-07-25 08:00:00+00:00,60.5,2 724 | 44,2020-07-25 09:00:00+00:00,57.4375,2 725 | 44,2020-07-25 10:00:00+00:00,54.375,2 726 | 44,2020-07-25 11:00:00+00:00,51.3125,2 727 | 44,2020-07-25 12:00:00+00:00,48.25,2 728 | 44,2020-07-25 13:00:00+00:00,48.16666666666666,2 729 | 44,2020-07-25 14:00:00+00:00,48.08333333333334,2 730 | 44,2020-07-25 15:00:00+00:00,48.0,2 731 | 44,2020-07-25 16:00:00+00:00,49.5,2 732 | 44,2020-07-25 17:00:00+00:00,51.0,2 733 | 44,2020-07-25 18:00:00+00:00,52.5,2 734 | 44,2020-07-25 19:00:00+00:00,54.0,2 735 | 44,2020-07-25 20:00:00+00:00,56.25,2 736 | 44,2020-07-25 21:00:00+00:00,58.5,2 737 | 44,2020-07-25 22:00:00+00:00,60.75,2 738 | 44,2020-07-25 23:00:00+00:00,63.0,2 739 | 44,2020-07-26 00:00:00+00:00,64.625,2 740 | 44,2020-07-26 01:00:00+00:00,66.25,2 741 | 44,2020-07-26 02:00:00+00:00,67.875,2 742 | 44,2020-07-26 03:00:00+00:00,69.5,2 743 | 44,2020-07-26 04:00:00+00:00,70.25,2 744 | 44,2020-07-26 05:00:00+00:00,71.0,2 745 | 44,2020-07-26 06:00:00+00:00,71.75,2 746 | 44,2020-07-26 07:00:00+00:00,72.5,2 747 | 44,2020-07-26 08:00:00+00:00,71.75,2 748 | 44,2020-07-26 09:00:00+00:00,71.0,2 749 | 44,2020-07-26 10:00:00+00:00,70.25,2 750 | 44,2020-07-26 11:00:00+00:00,69.5,2 751 | 44,2020-07-26 12:00:00+00:00,70.125,2 752 | 44,2020-07-26 13:00:00+00:00,70.75,2 753 | 44,2020-07-26 14:00:00+00:00,71.375,2 754 | 44,2020-07-26 15:00:00+00:00,72.0,2 755 | 44,2020-07-26 16:00:00+00:00,69.5,2 756 | 44,2020-07-26 17:00:00+00:00,67.0,2 757 | 44,2020-07-26 18:00:00+00:00,64.5,2 758 | 44,2020-07-26 19:00:00+00:00,62.0,2 759 | 44,2020-07-26 20:00:00+00:00,63.25,2 760 | 44,2020-07-26 21:00:00+00:00,64.5,2 761 | 44,2020-07-26 22:00:00+00:00,65.75,2 762 | 44,2020-07-26 23:00:00+00:00,67.0,2 763 | 44,2020-07-27 00:00:00+00:00,68.5,2 764 | 44,2020-07-27 01:00:00+00:00,70.0,2 765 | 44,2020-07-27 02:00:00+00:00,71.5,2 766 | 44,2020-07-27 03:00:00+00:00,71.0,2 767 | 44,2020-07-27 04:00:00+00:00,70.5,2 768 | 44,2020-07-27 05:00:00+00:00,70.0,2 769 | 44,2020-07-27 06:00:00+00:00,69.5,2 770 | 44,2020-07-27 07:00:00+00:00,65.875,2 771 | 44,2020-07-27 08:00:00+00:00,62.25,2 772 | 44,2020-07-27 09:00:00+00:00,58.625,2 773 | 44,2020-07-27 10:00:00+00:00,55.0,2 774 | 44,2020-07-27 11:00:00+00:00,53.96153846153846,2 775 | 44,2020-07-27 12:00:00+00:00,52.92307692307693,2 776 | 44,2020-07-27 13:00:00+00:00,51.884615384615394,2 777 | 44,2020-07-27 14:00:00+00:00,50.84615384615386,2 778 | 44,2020-07-27 15:00:00+00:00,51.884615384615394,2 779 | 44,2020-07-27 16:00:00+00:00,52.92307692307693,2 780 | 44,2020-07-27 17:00:00+00:00,53.96153846153846,2 781 | 44,2020-07-27 18:00:00+00:00,55.0,2 782 | 44,2020-07-27 19:00:00+00:00,57.375,2 783 | 44,2020-07-27 20:00:00+00:00,59.75,2 784 | 44,2020-07-27 21:00:00+00:00,62.125,2 785 | 44,2020-07-27 22:00:00+00:00,64.5,2 786 | 44,2020-07-27 23:00:00+00:00,67.0,2 787 | 44,2020-07-28 00:00:00+00:00,69.5,2 788 | 44,2020-07-28 01:00:00+00:00,72.0,2 789 | 44,2020-07-28 02:00:00+00:00,74.5,2 790 | 44,2020-07-28 03:00:00+00:00,75.5,2 791 | 44,2020-07-28 04:00:00+00:00,76.5,2 792 | 44,2020-07-28 05:00:00+00:00,77.5,2 793 | 44,2020-07-28 06:00:00+00:00,78.5,2 794 | 44,2020-07-28 07:00:00+00:00,75.25,2 795 | 44,2020-07-28 08:00:00+00:00,72.0,2 796 | 44,2020-07-28 09:00:00+00:00,68.75,2 797 | 44,2020-07-28 10:00:00+00:00,65.5,2 798 | 44,2020-07-28 11:00:00+00:00,61.0,2 799 | 44,2020-07-28 12:00:00+00:00,56.5,2 800 | 44,2020-07-28 13:00:00+00:00,52.0,2 801 | 44,2020-07-28 14:00:00+00:00,47.5,2 802 | 44,2020-07-28 15:00:00+00:00,46.75,2 803 | 44,2020-07-28 16:00:00+00:00,46.0,2 804 | 44,2020-07-28 17:00:00+00:00,45.25,2 805 | 44,2020-07-28 18:00:00+00:00,44.5,2 806 | 44,2020-07-28 19:00:00+00:00,47.5,2 807 | 44,2020-07-28 20:00:00+00:00,50.5,2 808 | 44,2020-07-28 21:00:00+00:00,53.5,2 809 | 44,2020-07-28 22:00:00+00:00,55.75,2 810 | 44,2020-07-28 23:00:00+00:00,58.0,2 811 | 44,2020-07-29 00:00:00+00:00,60.25,2 812 | 44,2020-07-29 01:00:00+00:00,62.5,2 813 | 44,2020-07-29 02:00:00+00:00,63.625,2 814 | 44,2020-07-29 03:00:00+00:00,64.75,2 815 | 44,2020-07-29 04:00:00+00:00,65.875,2 816 | 44,2020-07-29 05:00:00+00:00,67.0,2 817 | 44,2020-07-29 06:00:00+00:00,64.875,2 818 | 44,2020-07-29 07:00:00+00:00,62.75,2 819 | 44,2020-07-29 08:00:00+00:00,60.625,2 820 | 44,2020-07-29 09:00:00+00:00,58.5,2 821 | 44,2020-07-29 10:00:00+00:00,56.43055555555557,2 822 | 44,2020-07-29 11:00:00+00:00,54.361111111111114,2 823 | 44,2020-07-29 12:00:00+00:00,52.29166666666666,2 824 | 44,2020-07-29 13:00:00+00:00,50.22222222222222,2 825 | 44,2020-07-29 14:00:00+00:00,51.79166666666666,2 826 | 44,2020-07-29 15:00:00+00:00,53.361111111111114,2 827 | 44,2020-07-29 16:00:00+00:00,54.93055555555557,2 828 | 44,2020-07-29 17:00:00+00:00,56.5,2 829 | 44,2020-07-29 18:00:00+00:00,58.375,2 830 | 44,2020-07-29 19:00:00+00:00,60.25,2 831 | 44,2020-07-29 20:00:00+00:00,62.125,2 832 | 44,2020-07-29 21:00:00+00:00,64.0,2 833 | 44,2020-07-29 22:00:00+00:00,64.75,2 834 | 44,2020-07-29 23:00:00+00:00,65.5,2 835 | 44,2020-07-30 00:00:00+00:00,66.25,2 836 | 44,2020-07-30 01:00:00+00:00,67.0,2 837 | 44,2020-07-30 02:00:00+00:00,68.0,2 838 | 44,2020-07-30 03:00:00+00:00,69.0,2 839 | 44,2020-07-30 04:00:00+00:00,70.0,2 840 | 44,2020-07-30 05:00:00+00:00,71.0,2 841 | 44,2020-07-30 06:00:00+00:00,70.66666666666667,2 842 | 44,2020-07-30 07:00:00+00:00,70.33333333333333,2 843 | 44,2020-07-30 08:00:00+00:00,70.0,2 844 | 44,2020-07-30 09:00:00+00:00,68.5,2 845 | 44,2020-07-30 10:00:00+00:00,67.0,2 846 | 44,2020-07-30 11:00:00+00:00,65.5,2 847 | 44,2020-07-30 12:00:00+00:00,64.0,2 848 | 44,2020-07-30 13:00:00+00:00,61.375,2 849 | 44,2020-07-30 14:00:00+00:00,58.75,2 850 | 44,2020-07-30 15:00:00+00:00,56.125,2 851 | 44,2020-07-30 16:00:00+00:00,53.5,2 852 | 44,2020-07-30 17:00:00+00:00,54.5,2 853 | 44,2020-07-30 18:00:00+00:00,55.5,2 854 | 44,2020-07-30 19:00:00+00:00,56.5,2 855 | 44,2020-07-30 20:00:00+00:00,57.5,2 856 | 44,2020-07-30 21:00:00+00:00,59.25,2 857 | 44,2020-07-30 22:00:00+00:00,61.0,2 858 | 44,2020-07-30 23:00:00+00:00,62.75,2 859 | 44,2020-07-31 00:00:00+00:00,64.5,2 860 | 44,2020-07-31 01:00:00+00:00,65.125,2 861 | 44,2020-07-31 02:00:00+00:00,65.75,2 862 | 44,2020-07-31 03:00:00+00:00,66.375,2 863 | 44,2020-07-31 04:00:00+00:00,67.0,2 864 | 44,2020-07-31 05:00:00+00:00,67.25,2 865 | 44,2020-07-31 06:00:00+00:00,67.5,2 866 | 44,2020-07-31 07:00:00+00:00,67.75,2 867 | 44,2020-07-31 08:00:00+00:00,68.0,2 868 | 44,2020-07-31 09:00:00+00:00,64.375,2 869 | 44,2020-07-31 10:00:00+00:00,60.75,2 870 | 44,2020-07-31 11:00:00+00:00,57.125,2 871 | 44,2020-07-31 12:00:00+00:00,53.5,2 872 | 44,2020-07-31 13:00:00+00:00,50.875,2 873 | 44,2020-07-31 14:00:00+00:00,48.25,2 874 | 44,2020-07-31 15:00:00+00:00,45.625,2 875 | 44,2020-07-31 16:00:00+00:00,43.0,2 876 | 44,2020-07-31 17:00:00+00:00,44.66666666666666,2 877 | 44,2020-07-31 18:00:00+00:00,46.33333333333334,2 878 | 44,2020-07-31 19:00:00+00:00,48.0,2 879 | 44,2020-07-31 20:00:00+00:00,50.125,2 880 | 44,2020-07-31 21:00:00+00:00,52.25,2 881 | 44,2020-07-31 22:00:00+00:00,54.375,2 882 | 44,2020-07-31 23:00:00+00:00,56.5,2 883 | 44,2020-08-01 00:00:00+00:00,58.625,2 884 | 44,2020-08-01 01:00:00+00:00,60.75,2 885 | 44,2020-08-01 02:00:00+00:00,62.875,2 886 | 44,2020-08-01 03:00:00+00:00,65.0,2 887 | 44,2020-08-01 04:00:00+00:00,63.125,2 888 | 44,2020-08-01 05:00:00+00:00,61.25,2 889 | 44,2020-08-01 06:00:00+00:00,59.375,2 890 | 44,2020-08-01 07:00:00+00:00,57.5,2 891 | 44,2020-08-01 08:00:00+00:00,53.375,2 892 | 44,2020-08-01 09:00:00+00:00,49.25,2 893 | 44,2020-08-01 10:00:00+00:00,45.125,2 894 | 44,2020-08-01 11:00:00+00:00,41.0,2 895 | 44,2020-08-01 12:00:00+00:00,40.625,2 896 | 44,2020-08-01 13:00:00+00:00,40.25,2 897 | 44,2020-08-01 14:00:00+00:00,39.875,2 898 | 44,2020-08-01 15:00:00+00:00,39.5,2 899 | 44,2020-08-01 16:00:00+00:00,41.125,2 900 | 44,2020-08-01 17:00:00+00:00,42.75,2 901 | 44,2020-08-01 18:00:00+00:00,44.375,2 902 | 44,2020-08-01 19:00:00+00:00,46.0,2 903 | 44,2020-08-01 20:00:00+00:00,48.375,2 904 | 44,2020-08-01 21:00:00+00:00,50.75,2 905 | 44,2020-08-01 22:00:00+00:00,53.125,2 906 | 44,2020-08-01 23:00:00+00:00,55.5,2 907 | 44,2020-08-02 00:00:00+00:00,56.875,2 908 | 44,2020-08-02 01:00:00+00:00,58.25,2 909 | 44,2020-08-02 02:00:00+00:00,59.625,2 910 | 44,2020-08-02 03:00:00+00:00,61.0,2 911 | 44,2020-08-02 04:00:00+00:00,62.66666666666666,2 912 | 44,2020-08-02 05:00:00+00:00,64.33333333333333,2 913 | 44,2020-08-02 06:00:00+00:00,66.0,2 914 | 44,2020-08-02 07:00:00+00:00,62.875,2 915 | 44,2020-08-02 08:00:00+00:00,59.75,2 916 | 44,2020-08-02 09:00:00+00:00,56.625,2 917 | 44,2020-08-02 10:00:00+00:00,53.5,2 918 | 44,2020-08-02 11:00:00+00:00,52.375,2 919 | 44,2020-08-02 12:00:00+00:00,51.25,2 920 | 44,2020-08-02 13:00:00+00:00,50.125,2 921 | 44,2020-08-02 14:00:00+00:00,49.0,2 922 | 44,2020-08-02 15:00:00+00:00,48.25,2 923 | 44,2020-08-02 16:00:00+00:00,47.5,2 924 | 44,2020-08-02 17:00:00+00:00,46.75,2 925 | 44,2020-08-02 18:00:00+00:00,46.0,2 926 | 44,2020-08-02 19:00:00+00:00,48.0,2 927 | 44,2020-08-02 20:00:00+00:00,50.0,2 928 | 44,2020-08-02 21:00:00+00:00,52.0,2 929 | 44,2020-08-02 22:00:00+00:00,54.0,2 930 | 44,2020-08-02 23:00:00+00:00,55.625,2 931 | 44,2020-08-03 00:00:00+00:00,57.25,2 932 | 44,2020-08-03 01:00:00+00:00,58.875,2 933 | 44,2020-08-03 02:00:00+00:00,60.5,2 934 | 44,2020-08-03 03:00:00+00:00,60.625,2 935 | 44,2020-08-03 04:00:00+00:00,60.75,2 936 | 44,2020-08-03 05:00:00+00:00,60.875,2 937 | 44,2020-08-03 06:00:00+00:00,61.0,2 938 | 44,2020-08-03 07:00:00+00:00,58.375,2 939 | 44,2020-08-03 08:00:00+00:00,55.75,2 940 | 44,2020-08-03 09:00:00+00:00,53.125,2 941 | 44,2020-08-03 10:00:00+00:00,50.5,2 942 | 44,2020-08-03 11:00:00+00:00,46.66666666666666,2 943 | 44,2020-08-03 12:00:00+00:00,42.833333333333336,2 944 | 44,2020-08-03 13:00:00+00:00,39.0,2 945 | 44,2020-08-03 14:00:00+00:00,38.25,2 946 | 44,2020-08-03 15:00:00+00:00,37.5,2 947 | 44,2020-08-03 16:00:00+00:00,36.75,2 948 | 44,2020-08-03 17:00:00+00:00,36.0,2 949 | 44,2020-08-03 18:00:00+00:00,38.625,2 950 | 44,2020-08-03 19:00:00+00:00,41.25,2 951 | 44,2020-08-03 20:00:00+00:00,43.875,2 952 | 44,2020-08-03 21:00:00+00:00,46.5,2 953 | 44,2020-08-03 22:00:00+00:00,49.25,2 954 | 44,2020-08-03 23:00:00+00:00,52.0,2 955 | 44,2020-08-04 00:00:00+00:00,54.75,2 956 | 44,2020-08-04 01:00:00+00:00,57.5,2 957 | 44,2020-08-04 02:00:00+00:00,58.5,2 958 | 44,2020-08-04 03:00:00+00:00,59.5,2 959 | 44,2020-08-04 04:00:00+00:00,60.5,2 960 | 44,2020-08-04 05:00:00+00:00,61.5,2 961 | 44,2020-08-04 06:00:00+00:00,58.375,2 962 | 44,2020-08-04 07:00:00+00:00,55.25,2 963 | 44,2020-08-04 08:00:00+00:00,52.125,2 964 | 44,2020-08-04 09:00:00+00:00,49.0,2 965 | 44,2020-08-04 10:00:00+00:00,46.25,2 966 | 44,2020-08-04 11:00:00+00:00,43.5,2 967 | 44,2020-08-04 12:00:00+00:00,40.75,2 968 | 44,2020-08-04 13:00:00+00:00,38.0,2 969 | 44,2020-08-04 14:00:00+00:00,37.0,2 970 | 44,2020-08-04 15:00:00+00:00,36.0,2 971 | 44,2020-08-04 16:00:00+00:00,35.0,2 972 | 44,2020-08-04 17:00:00+00:00,34.0,2 973 | 44,2020-08-04 18:00:00+00:00,36.125,2 974 | 44,2020-08-04 19:00:00+00:00,38.25,2 975 | 44,2020-08-04 20:00:00+00:00,40.375,2 976 | 44,2020-08-04 21:00:00+00:00,42.5,2 977 | 44,2020-08-04 22:00:00+00:00,46.66666666666666,2 978 | 44,2020-08-04 23:00:00+00:00,50.83333333333334,2 979 | 44,2020-08-05 00:00:00+00:00,55.0,2 980 | 44,2020-08-05 01:00:00+00:00,55.875,2 981 | 44,2020-08-05 02:00:00+00:00,56.75,2 982 | 44,2020-08-05 03:00:00+00:00,57.625,2 983 | 44,2020-08-05 04:00:00+00:00,58.5,2 984 | 44,2020-08-05 05:00:00+00:00,58.625,2 985 | 44,2020-08-05 06:00:00+00:00,58.75,2 986 | 44,2020-08-05 07:00:00+00:00,58.875,2 987 | 44,2020-08-05 08:00:00+00:00,59.0,2 988 | 44,2020-08-05 09:00:00+00:00,56.5,2 989 | 44,2020-08-05 10:00:00+00:00,54.0,2 990 | 44,2020-08-05 11:00:00+00:00,51.5,2 991 | 44,2020-08-05 12:00:00+00:00,49.0,2 992 | 44,2020-08-05 13:00:00+00:00,48.0,2 993 | 44,2020-08-05 14:00:00+00:00,47.0,2 994 | 44,2020-08-05 15:00:00+00:00,46.0,2 995 | 44,2020-08-05 16:00:00+00:00,45.0,2 996 | 44,2020-08-05 17:00:00+00:00,46.125,2 997 | 44,2020-08-05 18:00:00+00:00,47.25,2 998 | 44,2020-08-05 19:00:00+00:00,48.375,2 999 | 44,2020-08-05 20:00:00+00:00,49.5,2 1000 | 44,2020-08-05 21:00:00+00:00,50.875,2 1001 | 44,2020-08-05 22:00:00+00:00,52.25,2 1002 | 44,2020-08-05 23:00:00+00:00,53.625,2 1003 | 44,2020-08-06 00:00:00+00:00,55.0,2 1004 | 44,2020-08-06 01:00:00+00:00,56.25,2 1005 | 44,2020-08-06 02:00:00+00:00,57.5,2 1006 | 44,2020-08-06 03:00:00+00:00,58.75,2 1007 | 44,2020-08-06 04:00:00+00:00,60.0,2 1008 | 44,2020-08-06 05:00:00+00:00,57.125,2 1009 | 44,2020-08-06 06:00:00+00:00,54.25,2 1010 | 44,2020-08-06 07:00:00+00:00,51.375,2 1011 | 44,2020-08-06 08:00:00+00:00,48.5,2 1012 | 44,2020-08-06 09:00:00+00:00,43.5,2 1013 | 44,2020-08-06 10:00:00+00:00,38.5,2 1014 | 44,2020-08-06 11:00:00+00:00,33.5,2 1015 | 44,2020-08-06 12:00:00+00:00,33.375,2 1016 | 44,2020-08-06 13:00:00+00:00,33.25,2 1017 | 44,2020-08-06 14:00:00+00:00,33.125,2 1018 | 44,2020-08-06 15:00:00+00:00,33.0,2 1019 | 44,2020-08-06 16:00:00+00:00,34.0,2 1020 | 44,2020-08-06 17:00:00+00:00,35.0,2 1021 | 44,2020-08-06 18:00:00+00:00,36.0,2 1022 | 44,2020-08-06 19:00:00+00:00,37.0,2 1023 | 44,2020-08-06 20:00:00+00:00,39.5,2 1024 | 44,2020-08-06 21:00:00+00:00,42.0,2 1025 | 44,2020-08-06 22:00:00+00:00,44.5,2 1026 | 44,2020-08-06 23:00:00+00:00,47.0,2 1027 | 44,2020-08-07 00:00:00+00:00,48.5,2 1028 | 44,2020-08-07 01:00:00+00:00,50.0,2 1029 | 44,2020-08-07 02:00:00+00:00,51.5,2 1030 | 44,2020-08-07 03:00:00+00:00,53.0,2 1031 | 44,2020-08-07 04:00:00+00:00,51.625,2 1032 | 44,2020-08-07 05:00:00+00:00,50.25,2 1033 | 44,2020-08-07 06:00:00+00:00,48.875,2 1034 | 44,2020-08-07 07:00:00+00:00,47.5,2 1035 | 44,2020-08-07 08:00:00+00:00,44.125,2 1036 | 44,2020-08-07 09:00:00+00:00,40.75,2 1037 | 44,2020-08-07 10:00:00+00:00,37.375,2 1038 | 44,2020-08-07 11:00:00+00:00,34.0,2 1039 | 44,2020-08-07 12:00:00+00:00,33.0,2 1040 | 44,2020-08-07 13:00:00+00:00,32.0,2 1041 | 44,2020-08-07 14:00:00+00:00,31.0,2 1042 | 44,2020-08-07 15:00:00+00:00,30.0,2 1043 | 44,2020-08-07 16:00:00+00:00,30.5,2 1044 | 44,2020-08-07 17:00:00+00:00,31.0,2 1045 | 44,2020-08-07 18:00:00+00:00,31.5,2 1046 | 44,2020-08-07 19:00:00+00:00,34.0,2 1047 | 44,2020-08-07 20:00:00+00:00,36.5,2 1048 | 44,2020-08-07 21:00:00+00:00,39.0,2 1049 | 44,2020-08-07 22:00:00+00:00,41.5,2 1050 | 44,2020-08-07 23:00:00+00:00,43.5,2 1051 | 44,2020-08-08 00:00:00+00:00,45.5,2 1052 | 44,2020-08-08 01:00:00+00:00,47.5,2 1053 | 44,2020-08-08 02:00:00+00:00,49.5,2 1054 | 44,2020-08-08 03:00:00+00:00,50.0,2 1055 | 44,2020-08-08 04:00:00+00:00,50.5,2 1056 | 44,2020-08-08 05:00:00+00:00,51.0,2 1057 | 44,2020-08-08 06:00:00+00:00,51.5,2 1058 | 44,2020-08-08 07:00:00+00:00,47.875,2 1059 | 44,2020-08-08 08:00:00+00:00,44.25,2 1060 | 44,2020-08-08 09:00:00+00:00,40.625,2 1061 | 44,2020-08-08 10:00:00+00:00,37.0,2 1062 | 44,2020-08-08 11:00:00+00:00,35.375,2 1063 | 44,2020-08-08 12:00:00+00:00,33.75,2 1064 | 44,2020-08-08 13:00:00+00:00,32.125,2 1065 | 44,2020-08-08 14:00:00+00:00,30.5,2 1066 | 44,2020-08-08 15:00:00+00:00,30.875,2 1067 | 44,2020-08-08 16:00:00+00:00,31.25,2 1068 | 44,2020-08-08 17:00:00+00:00,31.625,2 1069 | 44,2020-08-08 18:00:00+00:00,32.0,2 1070 | 44,2020-08-08 19:00:00+00:00,34.125,2 1071 | 44,2020-08-08 20:00:00+00:00,36.25,2 1072 | 44,2020-08-08 21:00:00+00:00,38.375,2 1073 | 44,2020-08-08 22:00:00+00:00,40.5,2 1074 | 44,2020-08-08 23:00:00+00:00,44.0,2 1075 | 44,2020-08-09 00:00:00+00:00,47.5,2 1076 | 44,2020-08-09 01:00:00+00:00,51.0,2 1077 | 44,2020-08-09 02:00:00+00:00,52.375,2 1078 | 44,2020-08-09 03:00:00+00:00,53.75,2 1079 | 44,2020-08-09 04:00:00+00:00,55.125,2 1080 | 44,2020-08-09 05:00:00+00:00,56.5,2 1081 | 44,2020-08-09 06:00:00+00:00,51.75,2 1082 | 44,2020-08-09 07:00:00+00:00,47.0,2 1083 | 44,2020-08-09 08:00:00+00:00,42.25,2 1084 | 44,2020-08-09 09:00:00+00:00,37.5,2 1085 | 44,2020-08-09 10:00:00+00:00,35.375,2 1086 | 44,2020-08-09 11:00:00+00:00,33.25,2 1087 | 44,2020-08-09 12:00:00+00:00,31.125,2 1088 | 44,2020-08-09 13:00:00+00:00,29.0,2 1089 | 44,2020-08-09 14:00:00+00:00,29.125,2 1090 | 44,2020-08-09 15:00:00+00:00,29.25,2 1091 | 44,2020-08-09 16:00:00+00:00,29.375,2 1092 | 44,2020-08-09 17:00:00+00:00,29.5,2 1093 | 44,2020-08-09 18:00:00+00:00,31.75,2 1094 | 44,2020-08-09 19:00:00+00:00,34.0,2 1095 | 44,2020-08-09 20:00:00+00:00,36.25,2 1096 | 44,2020-08-09 21:00:00+00:00,38.5,2 1097 | 44,2020-08-09 22:00:00+00:00,40.875,2 1098 | 44,2020-08-09 23:00:00+00:00,43.25,2 1099 | 44,2020-08-10 00:00:00+00:00,45.625,2 1100 | 44,2020-08-10 01:00:00+00:00,48.0,2 1101 | 44,2020-08-10 02:00:00+00:00,50.875,2 1102 | 44,2020-08-10 03:00:00+00:00,53.75,2 1103 | 44,2020-08-10 04:00:00+00:00,56.625,2 1104 | 44,2020-08-10 05:00:00+00:00,59.5,2 1105 | 44,2020-08-10 06:00:00+00:00,55.25,2 1106 | 44,2020-08-10 07:00:00+00:00,51.0,2 1107 | 44,2020-08-10 08:00:00+00:00,46.75,2 1108 | 44,2020-08-10 09:00:00+00:00,42.5,2 1109 | 44,2020-08-10 10:00:00+00:00,40.833333333333336,2 1110 | 44,2020-08-10 11:00:00+00:00,39.16666666666666,2 1111 | 44,2020-08-10 12:00:00+00:00,37.5,2 1112 | 44,2020-08-10 13:00:00+00:00,39.25,2 1113 | 44,2020-08-10 14:00:00+00:00,41.0,2 1114 | 44,2020-08-10 15:00:00+00:00,42.75,2 1115 | 44,2020-08-10 16:00:00+00:00,44.5,2 1116 | 44,2020-08-10 17:00:00+00:00,46.5,2 1117 | 44,2020-08-10 18:00:00+00:00,48.5,2 1118 | 44,2020-08-10 19:00:00+00:00,50.5,2 1119 | 44,2020-08-10 20:00:00+00:00,52.5,2 1120 | 44,2020-08-10 21:00:00+00:00,54.0,2 1121 | 44,2020-08-10 22:00:00+00:00,55.5,2 1122 | 44,2020-08-10 23:00:00+00:00,57.0,2 1123 | 44,2020-08-11 00:00:00+00:00,58.5,2 1124 | 44,2020-08-11 01:00:00+00:00,60.75,2 1125 | 44,2020-08-11 02:00:00+00:00,63.0,2 1126 | 44,2020-08-11 03:00:00+00:00,65.25,2 1127 | 44,2020-08-11 04:00:00+00:00,67.5,2 1128 | 44,2020-08-11 05:00:00+00:00,63.875,2 1129 | 44,2020-08-11 06:00:00+00:00,60.25,2 1130 | 44,2020-08-11 07:00:00+00:00,56.625,2 1131 | 44,2020-08-11 08:00:00+00:00,53.0,2 1132 | 44,2020-08-11 09:00:00+00:00,50.125,2 1133 | 44,2020-08-11 10:00:00+00:00,47.25,2 1134 | 44,2020-08-11 11:00:00+00:00,44.375,2 1135 | 44,2020-08-11 12:00:00+00:00,41.5,2 1136 | 44,2020-08-11 13:00:00+00:00,41.0,2 1137 | 44,2020-08-11 14:00:00+00:00,40.5,2 1138 | 44,2020-08-11 15:00:00+00:00,40.0,2 1139 | 44,2020-08-11 16:00:00+00:00,39.5,2 1140 | 44,2020-08-11 17:00:00+00:00,41.16666666666666,2 1141 | 44,2020-08-11 18:00:00+00:00,42.833333333333336,2 1142 | 44,2020-08-11 19:00:00+00:00,44.5,2 1143 | 44,2020-08-11 20:00:00+00:00,47.875,2 1144 | 44,2020-08-11 21:00:00+00:00,51.25,2 1145 | 44,2020-08-11 22:00:00+00:00,54.625,2 1146 | 44,2020-08-11 23:00:00+00:00,58.0,2 1147 | 44,2020-08-12 00:00:00+00:00,60.375,2 1148 | 44,2020-08-12 01:00:00+00:00,62.75,2 1149 | 44,2020-08-12 02:00:00+00:00,65.125,2 1150 | 44,2020-08-12 03:00:00+00:00,67.5,2 1151 | 44,2020-08-12 04:00:00+00:00,65.5,2 1152 | 44,2020-08-12 05:00:00+00:00,63.5,2 1153 | 44,2020-08-12 06:00:00+00:00,61.5,2 1154 | 44,2020-08-12 07:00:00+00:00,59.5,2 1155 | 44,2020-08-12 08:00:00+00:00,55.375,2 1156 | 44,2020-08-12 09:00:00+00:00,51.25,2 1157 | 44,2020-08-12 10:00:00+00:00,47.125,2 1158 | 44,2020-08-12 11:00:00+00:00,43.0,2 1159 | 44,2020-08-12 12:00:00+00:00,40.625,2 1160 | 44,2020-08-12 13:00:00+00:00,38.25,2 1161 | 44,2020-08-12 14:00:00+00:00,35.875,2 1162 | 44,2020-08-12 15:00:00+00:00,33.5,2 1163 | 44,2020-08-12 16:00:00+00:00,35.0,2 1164 | 44,2020-08-12 17:00:00+00:00,36.5,2 1165 | 44,2020-08-12 18:00:00+00:00,38.0,2 1166 | 44,2020-08-12 19:00:00+00:00,39.5,2 1167 | 44,2020-08-12 20:00:00+00:00,42.0,2 1168 | 44,2020-08-12 21:00:00+00:00,44.5,2 1169 | 44,2020-08-12 22:00:00+00:00,47.0,2 1170 | 44,2020-08-12 23:00:00+00:00,49.5,2 1171 | 44,2020-08-13 00:00:00+00:00,51.875,2 1172 | 44,2020-08-13 01:00:00+00:00,54.25,2 1173 | 44,2020-08-13 02:00:00+00:00,56.625,2 1174 | 44,2020-08-13 03:00:00+00:00,59.0,2 1175 | 44,2020-08-13 04:00:00+00:00,58.33333333333334,2 1176 | 44,2020-08-13 05:00:00+00:00,57.66666666666666,2 1177 | 44,2020-08-13 06:00:00+00:00,57.0,2 1178 | 44,2020-08-13 07:00:00+00:00,53.125,2 1179 | 44,2020-08-13 08:00:00+00:00,49.25,2 1180 | 44,2020-08-13 09:00:00+00:00,45.375,2 1181 | 44,2020-08-13 10:00:00+00:00,41.5,2 1182 | 44,2020-08-13 11:00:00+00:00,39.0,2 1183 | 44,2020-08-13 12:00:00+00:00,36.5,2 1184 | 44,2020-08-13 13:00:00+00:00,34.0,2 1185 | 44,2020-08-13 14:00:00+00:00,31.5,2 1186 | 44,2020-08-13 15:00:00+00:00,32.375,2 1187 | 44,2020-08-13 16:00:00+00:00,33.25,2 1188 | 44,2020-08-13 17:00:00+00:00,34.125,2 1189 | 44,2020-08-13 18:00:00+00:00,35.0,2 1190 | 44,2020-08-13 19:00:00+00:00,37.75,2 1191 | 44,2020-08-13 20:00:00+00:00,40.5,2 1192 | 44,2020-08-13 21:00:00+00:00,43.25,2 1193 | 44,2020-08-13 22:00:00+00:00,46.0,2 1194 | 44,2020-08-13 23:00:00+00:00,48.75,2 1195 | 44,2020-08-14 00:00:00+00:00,51.5,2 1196 | 44,2020-08-14 01:00:00+00:00,54.25,2 1197 | 44,2020-08-14 02:00:00+00:00,57.0,2 1198 | 44,2020-08-14 03:00:00+00:00,56.875,2 1199 | 44,2020-08-14 04:00:00+00:00,56.75,2 1200 | 44,2020-08-14 05:00:00+00:00,56.625,2 1201 | 44,2020-08-14 06:00:00+00:00,56.5,2 1202 | 44,2020-08-14 07:00:00+00:00,49.75,2 1203 | 44,2020-08-14 08:00:00+00:00,43.0,2 1204 | 44,2020-08-14 09:00:00+00:00,36.25,2 1205 | 44,2020-08-14 10:00:00+00:00,29.5,2 1206 | 44,2020-08-14 11:00:00+00:00,28.75,2 1207 | 44,2020-08-14 12:00:00+00:00,28.0,2 1208 | 44,2020-08-14 13:00:00+00:00,27.25,2 1209 | 44,2020-08-14 14:00:00+00:00,26.5,2 1210 | 44,2020-08-14 15:00:00+00:00,27.16666666666667,2 1211 | 44,2020-08-14 16:00:00+00:00,27.83333333333333,2 1212 | 44,2020-08-14 17:00:00+00:00,28.5,2 1213 | 44,2020-08-14 18:00:00+00:00,31.375,2 1214 | 44,2020-08-14 19:00:00+00:00,34.25,2 1215 | 44,2020-08-14 20:00:00+00:00,37.125,2 1216 | 44,2020-08-14 21:00:00+00:00,40.0,2 1217 | 44,2020-08-14 22:00:00+00:00,43.0,2 1218 | 44,2020-08-14 23:00:00+00:00,46.0,2 1219 | 44,2020-08-15 00:00:00+00:00,49.0,2 1220 | 44,2020-08-15 01:00:00+00:00,52.0,2 1221 | 44,2020-08-15 02:00:00+00:00,54.25,2 1222 | 44,2020-08-15 03:00:00+00:00,56.5,2 1223 | 44,2020-08-15 04:00:00+00:00,58.75,2 1224 | 44,2020-08-15 05:00:00+00:00,61.0,2 1225 | 44,2020-08-15 06:00:00+00:00,55.0,2 1226 | 44,2020-08-15 07:00:00+00:00,49.0,2 1227 | 44,2020-08-15 08:00:00+00:00,43.0,2 1228 | 44,2020-08-15 09:00:00+00:00,37.0,2 1229 | 44,2020-08-15 10:00:00+00:00,34.5,2 1230 | 44,2020-08-15 11:00:00+00:00,32.0,2 1231 | 44,2020-08-15 12:00:00+00:00,29.5,2 1232 | 44,2020-08-15 13:00:00+00:00,27.0,2 1233 | 44,2020-08-15 14:00:00+00:00,27.75,2 1234 | 44,2020-08-15 15:00:00+00:00,28.5,2 1235 | 44,2020-08-15 16:00:00+00:00,29.25,2 1236 | 44,2020-08-15 17:00:00+00:00,30.0,2 1237 | 44,2020-08-15 18:00:00+00:00,32.75,2 1238 | 44,2020-08-15 19:00:00+00:00,35.5,2 1239 | 44,2020-08-15 20:00:00+00:00,38.25,2 1240 | 44,2020-08-15 21:00:00+00:00,41.0,2 1241 | 44,2020-08-15 22:00:00+00:00,44.16666666666666,2 1242 | 44,2020-08-15 23:00:00+00:00,47.33333333333334,2 1243 | 44,2020-08-16 00:00:00+00:00,50.5,2 1244 | 44,2020-08-16 01:00:00+00:00,52.5,2 1245 | 44,2020-08-16 02:00:00+00:00,54.5,2 1246 | 44,2020-08-16 03:00:00+00:00,56.5,2 1247 | 44,2020-08-16 04:00:00+00:00,58.5,2 1248 | 44,2020-08-16 05:00:00+00:00,54.0,2 1249 | 44,2020-08-16 06:00:00+00:00,49.5,2 1250 | 44,2020-08-16 07:00:00+00:00,45.0,2 1251 | 44,2020-08-16 08:00:00+00:00,40.5,2 1252 | 44,2020-08-16 09:00:00+00:00,38.0,2 1253 | 44,2020-08-16 10:00:00+00:00,35.5,2 1254 | 44,2020-08-16 11:00:00+00:00,33.0,2 1255 | 44,2020-08-16 12:00:00+00:00,30.5,2 1256 | 44,2020-08-16 13:00:00+00:00,29.75,2 1257 | 44,2020-08-16 14:00:00+00:00,29.0,2 1258 | 44,2020-08-16 15:00:00+00:00,28.25,2 1259 | 44,2020-08-16 16:00:00+00:00,27.5,2 1260 | 44,2020-08-16 17:00:00+00:00,29.5,2 1261 | 44,2020-08-16 18:00:00+00:00,31.5,2 1262 | 44,2020-08-16 19:00:00+00:00,33.5,2 1263 | 44,2020-08-16 20:00:00+00:00,35.5,2 1264 | 44,2020-08-16 21:00:00+00:00,38.125,2 1265 | 44,2020-08-16 22:00:00+00:00,40.75,2 1266 | 44,2020-08-16 23:00:00+00:00,43.375,2 1267 | 44,2020-08-17 00:00:00+00:00,46.0,2 1268 | 44,2020-08-17 01:00:00+00:00,48.5,2 1269 | 44,2020-08-17 02:00:00+00:00,51.0,2 1270 | 44,2020-08-17 03:00:00+00:00,53.5,2 1271 | 44,2020-08-17 04:00:00+00:00,56.0,2 1272 | 44,2020-08-17 05:00:00+00:00,53.125,2 1273 | 44,2020-08-17 06:00:00+00:00,50.25,2 1274 | 44,2020-08-17 07:00:00+00:00,47.375,2 1275 | 44,2020-08-17 08:00:00+00:00,44.5,2 1276 | 44,2020-08-17 09:00:00+00:00,40.16666666666666,2 1277 | 44,2020-08-17 10:00:00+00:00,35.833333333333336,2 1278 | 44,2020-08-17 11:00:00+00:00,31.5,2 1279 | 44,2020-08-17 12:00:00+00:00,30.375,2 1280 | 44,2020-08-17 13:00:00+00:00,29.25,2 1281 | 44,2020-08-17 14:00:00+00:00,28.125,2 1282 | 44,2020-08-17 15:00:00+00:00,27.0,2 1283 | 44,2020-08-17 16:00:00+00:00,28.5,2 1284 | 44,2020-08-17 17:00:00+00:00,30.0,2 1285 | 44,2020-08-17 18:00:00+00:00,31.5,2 1286 | 44,2020-08-17 19:00:00+00:00,33.0,2 1287 | 44,2020-08-17 20:00:00+00:00,35.5,2 1288 | 44,2020-08-17 21:00:00+00:00,38.0,2 1289 | 44,2020-08-17 22:00:00+00:00,40.5,2 1290 | 44,2020-08-17 23:00:00+00:00,43.0,2 1291 | 44,2020-08-18 00:00:00+00:00,46.5,2 1292 | 44,2020-08-18 01:00:00+00:00,50.0,2 1293 | 44,2020-08-18 02:00:00+00:00,53.5,2 1294 | 44,2020-08-18 03:00:00+00:00,57.0,2 1295 | 44,2020-08-18 04:00:00+00:00,56.75,2 1296 | 44,2020-08-18 05:00:00+00:00,56.5,2 1297 | 44,2020-08-18 06:00:00+00:00,56.25,2 1298 | 44,2020-08-18 07:00:00+00:00,56.0,2 1299 | 44,2020-08-18 08:00:00+00:00,52.0,2 1300 | 44,2020-08-18 09:00:00+00:00,48.0,2 1301 | 44,2020-08-18 10:00:00+00:00,44.0,2 1302 | -------------------------------------------------------------------------------- /DataLoader.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | from torch.utils.data import Dataset, DataLoader 3 | from sklearn.preprocessing import MinMaxScaler 4 | import os 5 | import torch 6 | import numpy as np 7 | import random 8 | import matplotlib.pyplot as plt 9 | from joblib import dump 10 | from icecream import ic 11 | 12 | class SensorDataset(Dataset): 13 | """Face Landmarks dataset.""" 14 | 15 | def __init__(self, csv_name, root_dir, training_length, forecast_window): 16 | """ 17 | Args: 18 | csv_file (string): Path to the csv file. 19 | root_dir (string): Directory 20 | """ 21 | 22 | # load raw data file 23 | csv_file = os.path.join(root_dir, csv_name) 24 | self.df = pd.read_csv(csv_file) 25 | self.root_dir = root_dir 26 | self.transform = MinMaxScaler() 27 | self.T = training_length 28 | self.S = forecast_window 29 | 30 | def __len__(self): 31 | # return number of sensors 32 | return len(self.df.groupby(by=["reindexed_id"])) 33 | 34 | # Will pull an index between 0 and __len__. 35 | def __getitem__(self, idx): 36 | 37 | # Sensors are indexed from 1 38 | idx = idx+1 39 | 40 | # np.random.seed(0) 41 | 42 | start = np.random.randint(0, len(self.df[self.df["reindexed_id"]==idx]) - self.T - self.S) 43 | sensor_number = str(self.df[self.df["reindexed_id"]==idx][["sensor_id"]][start:start+1].values.item()) 44 | index_in = torch.tensor([i for i in range(start, start+self.T)]) 45 | index_tar = torch.tensor([i for i in range(start + self.T, start + self.T + self.S)]) 46 | _input = torch.tensor(self.df[self.df["reindexed_id"]==idx][["humidity", "sin_hour", "cos_hour", "sin_day", "cos_day", "sin_month", "cos_month"]][start : start + self.T].values) 47 | target = torch.tensor(self.df[self.df["reindexed_id"]==idx][["humidity", "sin_hour", "cos_hour", "sin_day", "cos_day", "sin_month", "cos_month"]][start + self.T : start + self.T + self.S].values) 48 | 49 | # scalar is fit only to the input, to avoid the scaled values "leaking" information about the target range. 50 | # scalar is fit only for humidity, as the timestamps are already scaled 51 | # scalar input/output of shape: [n_samples, n_features]. 52 | scaler = self.transform 53 | 54 | scaler.fit(_input[:,0].unsqueeze(-1)) 55 | _input[:,0] = torch.tensor(scaler.transform(_input[:,0].unsqueeze(-1)).squeeze(-1)) 56 | target[:,0] = torch.tensor(scaler.transform(target[:,0].unsqueeze(-1)).squeeze(-1)) 57 | 58 | # save the scalar to be used later when inverse translating the data for plotting. 59 | dump(scaler, 'scalar_item.joblib') 60 | 61 | return index_in, index_tar, _input, target, sensor_number -------------------------------------------------------------------------------- /Preprocessing.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import time 3 | import numpy as np 4 | import datetime 5 | from icecream import ic 6 | 7 | # encoding the timestamp data cyclically. See Medium Article. 8 | def process_data(source): 9 | 10 | df = pd.read_csv(source) 11 | 12 | timestamps = [ts.split('+')[0] for ts in df['timestamp']] 13 | timestamps_hour = np.array([float(datetime.datetime.strptime(t, '%Y-%m-%d %H:%M:%S').hour) for t in timestamps]) 14 | timestamps_day = np.array([float(datetime.datetime.strptime(t, '%Y-%m-%d %H:%M:%S').day) for t in timestamps]) 15 | timestamps_month = np.array([float(datetime.datetime.strptime(t, '%Y-%m-%d %H:%M:%S').month) for t in timestamps]) 16 | 17 | hours_in_day = 24 18 | days_in_month = 30 19 | month_in_year = 12 20 | 21 | df['sin_hour'] = np.sin(2*np.pi*timestamps_hour/hours_in_day) 22 | df['cos_hour'] = np.cos(2*np.pi*timestamps_hour/hours_in_day) 23 | df['sin_day'] = np.sin(2*np.pi*timestamps_day/days_in_month) 24 | df['cos_day'] = np.cos(2*np.pi*timestamps_day/days_in_month) 25 | df['sin_month'] = np.sin(2*np.pi*timestamps_month/month_in_year) 26 | df['cos_month'] = np.cos(2*np.pi*timestamps_month/month_in_year) 27 | 28 | return df 29 | 30 | train_dataset = process_data('Data/train_raw.csv') 31 | test_dataset = process_data('Data/test_raw.csv') 32 | 33 | train_dataset.to_csv(r'Data/train_dataset.csv', index=False) 34 | test_dataset.to_csv(r'Data/test_dataset.csv', index=False) 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Attention Mechanisms for Time Series Forecasting 3 | 4 | Article: https://natasha-klingenbrunn.medium.com/transformer-implementation-for-time-series-forecasting-a9db2db5c820 5 | 6 | -------------------------------------------------------------------------------- /helpers.py: -------------------------------------------------------------------------------- 1 | import os, shutil 2 | 3 | # save train or validation loss 4 | def log_loss(loss_val : float, path_to_save_loss : str, train : bool = True): 5 | if train: 6 | file_name = "train_loss.txt" 7 | else: 8 | file_name = "val_loss.txt" 9 | 10 | path_to_file = path_to_save_loss+file_name 11 | os.makedirs(os.path.dirname(path_to_file), exist_ok=True) 12 | with open(path_to_file, "a") as f: 13 | f.write(str(loss_val)+"\n") 14 | f.close() 15 | 16 | # Exponential Moving Average, https://en.wikipedia.org/wiki/Moving_average 17 | def EMA(values, alpha=0.1): 18 | ema_values = [values[0]] 19 | for idx, item in enumerate(values[1:]): 20 | ema_values.append(alpha*item + (1-alpha)*ema_values[idx]) 21 | return ema_values 22 | 23 | # Remove all files from previous executions and re-run the model. 24 | def clean_directory(): 25 | 26 | if os.path.exists('save_loss'): 27 | shutil.rmtree('save_loss') 28 | if os.path.exists('save_model'): 29 | shutil.rmtree('save_model') 30 | if os.path.exists('save_predictions'): 31 | shutil.rmtree('save_predictions') 32 | os.mkdir("save_loss") 33 | os.mkdir("save_model") 34 | os.mkdir("save_predictions") -------------------------------------------------------------------------------- /inference.py: -------------------------------------------------------------------------------- 1 | from model import Transformer 2 | from torch.utils.data import DataLoader 3 | import torch 4 | import torch.nn as nn 5 | from DataLoader import SensorDataset 6 | import logging 7 | import time # debugging 8 | from plot import * 9 | from helpers import * 10 | from joblib import load 11 | from icecream import ic 12 | 13 | logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(name)s %(message)s", datefmt="[%Y-%m-%d %H:%M:%S]") 14 | logger = logging.getLogger(__name__) 15 | 16 | def inference(path_to_save_predictions, forecast_window, dataloader, device, path_to_save_model, best_model): 17 | 18 | device = torch.device(device) 19 | 20 | model = Transformer().double().to(device) 21 | model.load_state_dict(torch.load(path_to_save_model+best_model)) 22 | criterion = torch.nn.MSELoss() 23 | 24 | val_loss = 0 25 | with torch.no_grad(): 26 | 27 | model.eval() 28 | for plot in range(25): 29 | 30 | for index_in, index_tar, _input, target, sensor_number in dataloader: 31 | 32 | # starting from 1 so that src matches with target, but has same length as when training 33 | src = _input.permute(1,0,2).double().to(device)[1:, :, :] # 47, 1, 7: t1 -- t47 34 | target = target.permute(1,0,2).double().to(device) # t48 - t59 35 | 36 | next_input_model = src 37 | all_predictions = [] 38 | 39 | for i in range(forecast_window - 1): 40 | 41 | prediction = model(next_input_model, device) # 47,1,1: t2' - t48' 42 | 43 | if all_predictions == []: 44 | all_predictions = prediction # 47,1,1: t2' - t48' 45 | else: 46 | all_predictions = torch.cat((all_predictions, prediction[-1,:,:].unsqueeze(0))) # 47+,1,1: t2' - t48', t49', t50' 47 | 48 | pos_encoding_old_vals = src[i+1:, :, 1:] # 46, 1, 6, pop positional encoding first value: t2 -- t47 49 | pos_encoding_new_val = target[i + 1, :, 1:].unsqueeze(1) # 1, 1, 6, append positional encoding of last predicted value: t48 50 | pos_encodings = torch.cat((pos_encoding_old_vals, pos_encoding_new_val)) # 47, 1, 6 positional encodings matched with prediction: t2 -- t48 51 | 52 | next_input_model = torch.cat((src[i+1:, :, 0].unsqueeze(-1), prediction[-1,:,:].unsqueeze(0))) #t2 -- t47, t48' 53 | next_input_model = torch.cat((next_input_model, pos_encodings), dim = 2) # 47, 1, 7 input for next round 54 | 55 | true = torch.cat((src[1:,:,0],target[:-1,:,0])) 56 | loss = criterion(true, all_predictions[:,:,0]) 57 | val_loss += loss 58 | 59 | val_loss = val_loss/10 60 | scaler = load('scalar_item.joblib') 61 | src_humidity = scaler.inverse_transform(src[:,:,0].cpu()) 62 | target_humidity = scaler.inverse_transform(target[:,:,0].cpu()) 63 | prediction_humidity = scaler.inverse_transform(all_predictions[:,:,0].detach().cpu().numpy()) 64 | plot_prediction(plot, path_to_save_predictions, src_humidity, target_humidity, prediction_humidity, sensor_number, index_in, index_tar) 65 | 66 | logger.info(f"Loss On Unseen Dataset: {val_loss.item()}") -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | # from train_teacher_forcing import * 3 | from train_with_sampling import * 4 | from DataLoader import * 5 | from torch.utils.data import DataLoader 6 | import torch.nn as nn 7 | import torch 8 | from helpers import * 9 | from inference import * 10 | 11 | def main( 12 | epoch: int = 1000, 13 | k: int = 60, 14 | batch_size: int = 1, 15 | frequency: int = 100, 16 | training_length = 48, 17 | forecast_window = 24, 18 | train_csv = "train_dataset.csv", 19 | test_csv = "test_dataset.csv", 20 | path_to_save_model = "save_model/", 21 | path_to_save_loss = "save_loss/", 22 | path_to_save_predictions = "save_predictions/", 23 | device = "cpu" 24 | ): 25 | 26 | clean_directory() 27 | 28 | train_dataset = SensorDataset(csv_name = train_csv, root_dir = "Data/", training_length = training_length, forecast_window = forecast_window) 29 | train_dataloader = DataLoader(train_dataset, batch_size=1, shuffle=True) 30 | test_dataset = SensorDataset(csv_name = test_csv, root_dir = "Data/", training_length = training_length, forecast_window = forecast_window) 31 | test_dataloader = DataLoader(test_dataset, batch_size=1, shuffle=True) 32 | 33 | best_model = transformer(train_dataloader, epoch, k, frequency, path_to_save_model, path_to_save_loss, path_to_save_predictions, device) 34 | inference(path_to_save_predictions, forecast_window, test_dataloader, device, path_to_save_model, best_model) 35 | 36 | if __name__ == "__main__": 37 | parser = argparse.ArgumentParser() 38 | parser.add_argument("--epoch", type=int, default=1000) 39 | parser.add_argument("--k", type=int, default=60) 40 | parser.add_argument("--batch_size", type=int, default=1) 41 | parser.add_argument("--frequency", type=int, default=100) 42 | parser.add_argument("--path_to_save_model",type=str,default="save_model/") 43 | parser.add_argument("--path_to_save_loss",type=str,default="save_loss/") 44 | parser.add_argument("--path_to_save_predictions",type=str,default="save_predictions/") 45 | parser.add_argument("--device", type=str, default="cpu") 46 | args = parser.parse_args() 47 | 48 | main( 49 | epoch=args.epoch, 50 | k = args.k, 51 | batch_size=args.batch_size, 52 | frequency=args.frequency, 53 | path_to_save_model=args.path_to_save_model, 54 | path_to_save_loss=args.path_to_save_loss, 55 | path_to_save_predictions=args.path_to_save_predictions, 56 | device=args.device, 57 | ) 58 | 59 | -------------------------------------------------------------------------------- /model.py: -------------------------------------------------------------------------------- 1 | import torch.nn as nn 2 | import torch, math 3 | from icecream import ic 4 | import time 5 | """ 6 | The architecture is based on the paper “Attention Is All You Need”. 7 | Ashish Vaswani, Noam Shazeer, Niki Parmar, Jakob Uszkoreit, Llion Jones, Aidan N Gomez, Lukasz Kaiser, and Illia Polosukhin. 2017. 8 | """ 9 | 10 | class Transformer(nn.Module): 11 | # d_model : number of features 12 | def __init__(self,feature_size=7,num_layers=3,dropout=0): 13 | super(Transformer, self).__init__() 14 | 15 | self.encoder_layer = nn.TransformerEncoderLayer(d_model=feature_size, nhead=7, dropout=dropout) 16 | self.transformer_encoder = nn.TransformerEncoder(self.encoder_layer, num_layers=num_layers) 17 | self.decoder = nn.Linear(feature_size,1) 18 | self.init_weights() 19 | 20 | def init_weights(self): 21 | initrange = 0.1 22 | self.decoder.bias.data.zero_() 23 | self.decoder.weight.data.uniform_(-initrange, initrange) 24 | 25 | def _generate_square_subsequent_mask(self, sz): 26 | mask = (torch.triu(torch.ones(sz, sz)) == 1).transpose(0, 1) 27 | mask = mask.float().masked_fill(mask == 0, float('-inf')).masked_fill(mask == 1, float(0.0)) 28 | return mask 29 | 30 | def forward(self, src, device): 31 | 32 | mask = self._generate_square_subsequent_mask(len(src)).to(device) 33 | output = self.transformer_encoder(src,mask) 34 | output = self.decoder(output) 35 | return output 36 | 37 | 38 | -------------------------------------------------------------------------------- /plot.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | from helpers import EMA 3 | from icecream import ic 4 | import numpy as np 5 | import torch 6 | 7 | def plot_loss(path_to_save, train=True): 8 | plt.rcParams.update({'font.size': 10}) 9 | with open(path_to_save + "/train_loss.txt", 'r') as f: 10 | loss_list = [float(line) for line in f.readlines()] 11 | if train: 12 | title = "Train" 13 | else: 14 | title = "Validation" 15 | EMA_loss = EMA(loss_list) 16 | plt.plot(loss_list, label = "loss") 17 | plt.plot(EMA_loss, label="EMA loss") 18 | plt.xlabel("Epochs") 19 | plt.ylabel("Loss") 20 | plt.legend() 21 | plt.title(title+"_loss") 22 | plt.savefig(path_to_save+f"/{title}.png") 23 | plt.close() 24 | 25 | def plot_prediction(title, path_to_save, src, tgt, prediction, sensor_number, index_in, index_tar): 26 | 27 | idx_scr = index_in[0, 1:].tolist() 28 | idx_tgt = index_tar[0].tolist() 29 | idx_pred = [i for i in range(idx_scr[0] +1, idx_tgt[-1])] #t2 - t61 30 | 31 | plt.figure(figsize=(15,6)) 32 | plt.rcParams.update({"font.size" : 16}) 33 | 34 | # connect with last elemenet in src 35 | # tgt = np.append(src[-1], tgt.flatten()) 36 | # prediction = np.append(src[-1], prediction.flatten()) 37 | 38 | # plotting 39 | plt.plot(idx_scr, src, '-', color = 'blue', label = 'Input', linewidth=2) 40 | plt.plot(idx_tgt, tgt, '-', color = 'indigo', label = 'Target', linewidth=2) 41 | plt.plot(idx_pred, prediction,'--', color = 'limegreen', label = 'Forecast', linewidth=2) 42 | 43 | #formatting 44 | plt.grid(b=True, which='major', linestyle = 'solid') 45 | plt.minorticks_on() 46 | plt.grid(b=True, which='minor', linestyle = 'dashed', alpha=0.5) 47 | plt.xlabel("Time Elapsed") 48 | plt.ylabel("Humidity (%)") 49 | plt.legend() 50 | plt.title("Forecast from Sensor " + str(sensor_number[0])) 51 | 52 | # save 53 | plt.savefig(path_to_save+f"Prediction_{title}.png") 54 | plt.close() 55 | 56 | def plot_training(epoch, path_to_save, src, prediction, sensor_number, index_in, index_tar): 57 | 58 | # idx_scr = index_in.tolist()[0] 59 | # idx_tar = index_tar.tolist()[0] 60 | # idx_pred = idx_scr.append(idx_tar.append([idx_tar[-1] + 1])) 61 | 62 | idx_scr = [i for i in range(len(src))] 63 | idx_pred = [i for i in range(1, len(prediction)+1)] 64 | 65 | plt.figure(figsize=(15,6)) 66 | plt.rcParams.update({"font.size" : 18}) 67 | plt.grid(b=True, which='major', linestyle = '-') 68 | plt.grid(b=True, which='minor', linestyle = '--', alpha=0.5) 69 | plt.minorticks_on() 70 | 71 | plt.plot(idx_scr, src, 'o-.', color = 'blue', label = 'input sequence', linewidth=1) 72 | plt.plot(idx_pred, prediction, 'o-.', color = 'limegreen', label = 'prediction sequence', linewidth=1) 73 | 74 | plt.title("Teaching Forcing from Sensor " + str(sensor_number[0]) + ", Epoch " + str(epoch)) 75 | plt.xlabel("Time Elapsed") 76 | plt.ylabel("Humidity (%)") 77 | plt.legend() 78 | plt.savefig(path_to_save+f"/Epoch_{str(epoch)}.png") 79 | plt.close() 80 | 81 | def plot_training_3(epoch, path_to_save, src, sampled_src, prediction, sensor_number, index_in, index_tar): 82 | 83 | # idx_scr = index_in.tolist()[0] 84 | # idx_tar = index_tar.tolist()[0] 85 | # idx_pred = idx_scr.append(idx_tar.append([idx_tar[-1] + 1])) 86 | 87 | idx_scr = [i for i in range(len(src))] 88 | idx_pred = [i for i in range(1, len(prediction)+1)] 89 | idx_sampled_src = [i for i in range(len(sampled_src))] 90 | 91 | plt.figure(figsize=(15,6)) 92 | plt.rcParams.update({"font.size" : 18}) 93 | plt.grid(b=True, which='major', linestyle = '-') 94 | plt.grid(b=True, which='minor', linestyle = '--', alpha=0.5) 95 | plt.minorticks_on() 96 | 97 | ## REMOVE DROPOUT FOR THIS PLOT TO APPEAR AS EXPECTED !! DROPOUT INTERFERES WITH HOW THE SAMPLED SOURCES ARE PLOTTED 98 | plt.plot(idx_sampled_src, sampled_src, 'o-.', color='red', label = 'sampled source', linewidth=1, markersize=10) 99 | plt.plot(idx_scr, src, 'o-.', color = 'blue', label = 'input sequence', linewidth=1) 100 | plt.plot(idx_pred, prediction, 'o-.', color = 'limegreen', label = 'prediction sequence', linewidth=1) 101 | plt.title("Teaching Forcing from Sensor " + str(sensor_number[0]) + ", Epoch " + str(epoch)) 102 | plt.xlabel("Time Elapsed") 103 | plt.ylabel("Humidity (%)") 104 | plt.legend() 105 | plt.savefig(path_to_save+f"/Epoch_{str(epoch)}.png") 106 | plt.close() -------------------------------------------------------------------------------- /train_teacher_forcing.py: -------------------------------------------------------------------------------- 1 | from model import Transformer 2 | from torch.utils.data import DataLoader 3 | import torch 4 | import torch.nn as nn 5 | from DataLoader import SensorDataset 6 | import logging 7 | import time # debugging 8 | from plot import * 9 | from helpers import * 10 | from joblib import load 11 | from icecream import ic 12 | from torch.optim.lr_scheduler import ReduceLROnPlateau 13 | 14 | logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(name)s %(message)s", datefmt="[%Y-%m-%d %H:%M:%S]") 15 | logger = logging.getLogger(__name__) 16 | 17 | def transformer(dataloader, EPOCH, frequency, path_to_save_model, path_to_save_loss, path_to_save_predictions, device): 18 | 19 | device = torch.device(device) 20 | 21 | model = Transformer().double().to(device) 22 | optimizer = torch.optim.Adam(model.parameters()) 23 | # scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.1, patience=200) 24 | criterion = torch.nn.MSELoss() 25 | best_model = "" 26 | min_train_loss = float('inf') 27 | 28 | for epoch in range(EPOCH + 1): 29 | 30 | train_loss = 0 31 | val_loss = 0 32 | 33 | ## TRAIN -- TEACHER FORCING 34 | model.train() 35 | for index_in, index_tar, _input, target, sensor_number in dataloader: # for each data set 36 | 37 | optimizer.zero_grad() 38 | 39 | # Shape of _input : [batch, input_length, feature] 40 | # Desired input for model: [input_length, batch, feature] 41 | 42 | src = _input.permute(1,0,2).double().to(device)[:-1,:,:] # torch.Size([24, 1, 7]) 43 | target = _input.permute(1,0,2).double().to(device)[1:,:,:] # src shifted by 1. 44 | prediction = model(src, device) # torch.Size([24, 1, 7]) 45 | loss = criterion(prediction, target[:,:,0].unsqueeze(-1)) 46 | loss.backward() 47 | optimizer.step() 48 | # scheduler.step(loss.detach().item()) 49 | train_loss += loss.detach().item() 50 | 51 | if train_loss < min_train_loss: 52 | torch.save(model.state_dict(), path_to_save_model + f"best_train_{epoch}.pth") 53 | torch.save(optimizer.state_dict(), path_to_save_model + f"optimizer_{epoch}.pth") 54 | min_train_loss = train_loss 55 | best_model = f"best_train_{epoch}.pth" 56 | 57 | 58 | if epoch % 100 == 0: # Plot 1-Step Predictions 59 | 60 | logger.info(f"Epoch: {epoch}, Training loss: {train_loss}") 61 | scaler = load('scalar_item.joblib') 62 | src_humidity = scaler.inverse_transform(src[:,:,0].cpu()) #torch.Size([35, 1, 7]) 63 | target_humidity = scaler.inverse_transform(target[:,:,0].cpu()) #torch.Size([35, 1, 7]) 64 | prediction_humidity = scaler.inverse_transform(prediction[:,:,0].detach().cpu().numpy()) #torch.Size([35, 1, 7]) 65 | plot_training(epoch, path_to_save_predictions, src_humidity, prediction_humidity, sensor_number, index_in, index_tar) 66 | 67 | train_loss /= len(dataloader) 68 | log_loss(train_loss, path_to_save_loss, train=True) 69 | 70 | plot_loss(path_to_save_loss, train=True) 71 | return best_model -------------------------------------------------------------------------------- /train_with_sampling.py: -------------------------------------------------------------------------------- 1 | from model import Transformer 2 | from torch.utils.data import DataLoader 3 | import torch 4 | import torch.nn as nn 5 | from DataLoader import SensorDataset 6 | import logging 7 | import time # debugging 8 | from plot import * 9 | from helpers import * 10 | from joblib import load 11 | from icecream import ic 12 | from torch.optim.lr_scheduler import ReduceLROnPlateau 13 | import math, random 14 | 15 | logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(name)s %(message)s", datefmt="[%Y-%m-%d %H:%M:%S]") 16 | logger = logging.getLogger(__name__) 17 | 18 | def flip_from_probability(p): 19 | return True if random.random() < p else False 20 | 21 | def transformer(dataloader, EPOCH, k, frequency, path_to_save_model, path_to_save_loss, path_to_save_predictions, device): 22 | 23 | device = torch.device(device) 24 | 25 | model = Transformer().double().to(device) 26 | optimizer = torch.optim.Adam(model.parameters()) 27 | # scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.1, patience=200) 28 | criterion = torch.nn.MSELoss() 29 | best_model = "" 30 | min_train_loss = float('inf') 31 | 32 | for epoch in range(EPOCH + 1): 33 | train_loss = 0 34 | val_loss = 0 35 | 36 | ## TRAIN -- TEACHER FORCING 37 | model.train() 38 | for index_in, index_tar, _input, target, sensor_number in dataloader: 39 | 40 | # Shape of _input : [batch, input_length, feature] 41 | # Desired input for model: [input_length, batch, feature] 42 | 43 | optimizer.zero_grad() 44 | src = _input.permute(1,0,2).double().to(device)[:-1,:,:] # torch.Size([24, 1, 7]) 45 | target = _input.permute(1,0,2).double().to(device)[1:,:,:] # src shifted by 1. 46 | sampled_src = src[:1, :, :] #t0 torch.Size([1, 1, 7]) 47 | 48 | for i in range(len(target)-1): 49 | 50 | prediction = model(sampled_src, device) # torch.Size([1xw, 1, 1]) 51 | # for p1, p2 in zip(params, model.parameters()): 52 | # if p1.data.ne(p2.data).sum() > 0: 53 | # ic(False) 54 | # ic(True) 55 | # ic(i, sampled_src[:,:,0], prediction) 56 | # time.sleep(1) 57 | """ 58 | # to update model at every step 59 | # loss = criterion(prediction, target[:i+1,:,:1]) 60 | # loss.backward() 61 | # optimizer.step() 62 | """ 63 | 64 | if i < 24: # One day, enough data to make inferences about cycles 65 | prob_true_val = True 66 | else: 67 | ## coin flip 68 | v = k/(k+math.exp(epoch/k)) # probability of heads/tails depends on the epoch, evolves with time. 69 | prob_true_val = flip_from_probability(v) # starts with over 95 % probability of true val for each flip in epoch 0. 70 | ## if using true value as new value 71 | 72 | if prob_true_val: # Using true value as next value 73 | sampled_src = torch.cat((sampled_src.detach(), src[i+1, :, :].unsqueeze(0).detach())) 74 | else: ## using prediction as new value 75 | positional_encodings_new_val = src[i+1,:,1:].unsqueeze(0) 76 | predicted_humidity = torch.cat((prediction[-1,:,:].unsqueeze(0), positional_encodings_new_val), dim=2) 77 | sampled_src = torch.cat((sampled_src.detach(), predicted_humidity.detach())) 78 | 79 | """To update model after each sequence""" 80 | loss = criterion(target[:-1,:,0].unsqueeze(-1), prediction) 81 | loss.backward() 82 | optimizer.step() 83 | train_loss += loss.detach().item() 84 | 85 | if train_loss < min_train_loss: 86 | torch.save(model.state_dict(), path_to_save_model + f"best_train_{epoch}.pth") 87 | torch.save(optimizer.state_dict(), path_to_save_model + f"optimizer_{epoch}.pth") 88 | min_train_loss = train_loss 89 | best_model = f"best_train_{epoch}.pth" 90 | 91 | 92 | if epoch % 10 == 0: # Plot 1-Step Predictions 93 | 94 | logger.info(f"Epoch: {epoch}, Training loss: {train_loss}") 95 | scaler = load('scalar_item.joblib') 96 | sampled_src_humidity = scaler.inverse_transform(sampled_src[:,:,0].cpu()) #torch.Size([35, 1, 7]) 97 | src_humidity = scaler.inverse_transform(src[:,:,0].cpu()) #torch.Size([35, 1, 7]) 98 | target_humidity = scaler.inverse_transform(target[:,:,0].cpu()) #torch.Size([35, 1, 7]) 99 | prediction_humidity = scaler.inverse_transform(prediction[:,:,0].detach().cpu().numpy()) #torch.Size([35, 1, 7]) 100 | plot_training_3(epoch, path_to_save_predictions, src_humidity, sampled_src_humidity, prediction_humidity, sensor_number, index_in, index_tar) 101 | 102 | train_loss /= len(dataloader) 103 | log_loss(train_loss, path_to_save_loss, train=True) 104 | 105 | plot_loss(path_to_save_loss, train=True) 106 | return best_model --------------------------------------------------------------------------------