Update README.md
Browse files
README.md
CHANGED
|
@@ -1,3 +1,1804 @@
|
|
| 1 |
-
---
|
| 2 |
-
license: mit
|
| 3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: mit
|
| 3 |
+
tags:
|
| 4 |
+
- forecast
|
| 5 |
+
- weather
|
| 6 |
+
- lstm
|
| 7 |
+
- classification
|
| 8 |
+
- regression
|
| 9 |
+
- weather-forecast
|
| 10 |
+
- multitask
|
| 11 |
+
- harley-ml
|
| 12 |
+
- small
|
| 13 |
+
---
|
| 14 |
+
|
| 15 |
+
# Hweh-6M
|
| 16 |
+
|
| 17 |
+
## Summary
|
| 18 |
+
|
| 19 |
+
Task: Weather Forecasting
|
| 20 |
+
Inputs: 72 hours time-series
|
| 21 |
+
Outputs: 12h multivariate forecast
|
| 22 |
+
Params: 446k
|
| 23 |
+
Framework: PyTorch
|
| 24 |
+
Author: Paul Courneya (Harley-ml)
|
| 25 |
+
|
| 26 |
+
## Description
|
| 27 |
+
|
| 28 |
+
**Hweh-446k** is a **446-thousand-parameter LSTM model** distilisation of [Hweh-6M] (a 92% reduction in params!!), trained to predict the next **12 hours of weather**, including temperature, humidity, pressure, precipitation, and more, using the previous **72 hours of weather context**.
|
| 29 |
+
We recommend using this model as a backup to a weather API or for fast offline forecasting when internet access is unavailable.
|
| 30 |
+
|
| 31 |
+
We would also like to give a shoutout to [**Open-Meteo**](https://open-meteo.com/) for providing a **free-to-use weather forecasting API**.
|
| 32 |
+
|
| 33 |
+
### Why “Hweh”?
|
| 34 |
+
|
| 35 |
+
In Proto-Indo-European, the root ***h₂weh₁-** means “to blow.” We chose it as the name for a weather forecasting model because of its connection to wind and air.
|
| 36 |
+
|
| 37 |
+
## Architecture
|
| 38 |
+
|
| 39 |
+
The model uses a multitask LSTM setup:
|
| 40 |
+
|
| 41 |
+
| Parameter | Value |
|
| 42 |
+
| ----------------------- | ---------------------------------------------- |
|
| 43 |
+
| `input_dim` | `22` |
|
| 44 |
+
| `seq_len` | `72` |
|
| 45 |
+
| `num_predict` | `12` |
|
| 46 |
+
| `hidden_dim` | `128` |
|
| 47 |
+
| `num_layers` | `3` |
|
| 48 |
+
| `dropout` | `0.1` |
|
| 49 |
+
| `encoder_type` | `lstm` |
|
| 50 |
+
| `num_locations` | `82` |
|
| 51 |
+
| `location_emb_dim` | `32` |
|
| 52 |
+
| `num_weather_classes` | `7` |
|
| 53 |
+
|
| 54 |
+
## Training
|
| 55 |
+
|
| 56 |
+
We trained Hweh-446k on 4.06 million rows of weather data from 82 locations with the supervision of Hweh-6M for one epoch, using a batch size of 16 and gradient accumulation of 5. Training ran for 4.3 hours on an RTX 2060 6GB GPU.
|
| 57 |
+
|
| 58 |
+
### Input Features
|
| 59 |
+
|
| 60 |
+
1. `temperature_2m_norm`
|
| 61 |
+
2. `relative_humidity_2m_norm`
|
| 62 |
+
3. `apparent_temperature_norm`
|
| 63 |
+
4. `precipitation_log_norm`
|
| 64 |
+
5. `sea_level_pressure_norm`
|
| 65 |
+
6. `surface_pressure_norm`
|
| 66 |
+
7. `cloud_cover_total_norm`
|
| 67 |
+
8. `visibility_norm`
|
| 68 |
+
9. `wind_speed_10m_norm`
|
| 69 |
+
10. `wind_direction_10m_sin`
|
| 70 |
+
11. `wind_direction_10m_cos`
|
| 71 |
+
12. `hour_sin`
|
| 72 |
+
13. `hour_cos`
|
| 73 |
+
14. `day_of_year_sin`
|
| 74 |
+
15. `day_of_year_cos`
|
| 75 |
+
16. `weather_code_onehot_clear`
|
| 76 |
+
17. `weather_code_onehot_cloudy`
|
| 77 |
+
18. `weather_code_onehot_fog`
|
| 78 |
+
19. `weather_code_onehot_drizzle`
|
| 79 |
+
20. `weather_code_onehot_rain`
|
| 80 |
+
21. `weather_code_onehot_snow`
|
| 81 |
+
22. `weather_code_onehot_thunderstorm`
|
| 82 |
+
|
| 83 |
+
### Output Features
|
| 84 |
+
|
| 85 |
+
1. `y_temp_c`: continuous regression
|
| 86 |
+
2. `y_humidity`: continuous regression
|
| 87 |
+
3. `y_apparent_temperature`: continuous regression
|
| 88 |
+
4. `y_precipitation_mm`: continuous regression
|
| 89 |
+
5. `y_sea_level_pressure_hpa`: continuous regression
|
| 90 |
+
6. `y_surface_pressure_hpa`: continuous regression
|
| 91 |
+
7. `y_cloud_cover_total`: continuous regression
|
| 92 |
+
8. `y_wind_speed_10m`: continuous regression
|
| 93 |
+
9. `y_wind_direction_sin`: continuous regression
|
| 94 |
+
10. `y_wind_direction_cos`: continuous regression
|
| 95 |
+
11. `y_rain_prob`: binary classification
|
| 96 |
+
12. `y_weather_class`: multiclass classification
|
| 97 |
+
|
| 98 |
+
### Training Results
|
| 99 |
+
|
| 100 |
+
#### Training & Evaluation Metrics
|
| 101 |
+
|
| 102 |
+
| Step | Train Loss | Eval Loss | Weather Acc | Rain Acc | Rain Recall | Weather Recall |
|
| 103 |
+
| ----: | ---------: | --------: | ----------: | -------: | ----------: | -------------: |
|
| 104 |
+
| 1k | 8.4609 | 8.8471 | 0.6317 | 0.7451 | 0.7640 | 0.2574 |
|
| 105 |
+
| 5k | 5.1420 | 5.0602 | 0.6247 | 0.7531 | 0.8025 | 0.5648 |
|
| 106 |
+
| 10k | 4.1733 | 3.9198 | 0.6117 | 0.7876 | 0.8016 | 0.6297 |
|
| 107 |
+
| 15k | 3.8354 | 3.6310 | 0.6140 | 0.7920 | 0.8009 | 0.6187 |
|
| 108 |
+
| 20k | 3.6206 | 3.4365 | 0.6083 | 0.7881 | 0.8140 | 0.6179 |
|
| 109 |
+
| 25k | 3.5378 | 3.3251 | 0.6083 | 0.7859 | 0.8173 | 0.6245 |
|
| 110 |
+
| 30k | 3.4534 | 3.2846 | 0.6041 | 0.7812 | 0.8272 | 0.6398 |
|
| 111 |
+
| 35k | 3.4272 | 3.2324 | 0.6061 | 0.7860 | 0.8194 | 0.6289 |
|
| 112 |
+
| 40k | 3.4143 | 3.2230 | 0.6080 | 0.7862 | 0.8200 | 0.6339 |
|
| 113 |
+
| 42.6k | — | 3.2180 | 0.6081 | 0.7857 | 0.8212 | 0.6340 |
|
| 114 |
+
|
| 115 |
+
Note: Loss looks higher than Hweh-6M's because of KL + train/val loss.
|
| 116 |
+
#### Regression Error Metrics (MAE)
|
| 117 |
+
|
| 118 |
+
| Step | Apparent | Cloud | Humidity | Precip (mm) | Sea Level P | Surface P | Temp | Wind |
|
| 119 |
+
| ----: | -------: | ------: | -------: | ----------: | ----------: | --------: | -----: | ----: |
|
| 120 |
+
| 1k | 212.80 | 2179.70 | 1476.42 | 0.140 | 7571.45 | 83590.98 | 172.79 | 60.49 |
|
| 121 |
+
| 5k | 2.28 | 25.58 | 9.04 | 0.107 | 3.50 | 14.55 | 1.90 | 3.78 |
|
| 122 |
+
| 10k | 2.06 | 25.31 | 8.08 | 0.100 | 3.31 | 9.63 | 1.72 | 3.37 |
|
| 123 |
+
| 15k | 1.91 | 25.00 | 7.88 | 0.101 | 3.18 | 7.93 | 1.61 | 3.25 |
|
| 124 |
+
| 20k | 1.88 | 25.12 | 7.60 | 0.101 | 3.13 | 7.41 | 1.56 | 3.18 |
|
| 125 |
+
| 25k | 1.84 | 25.01 | 7.53 | 0.102 | 3.09 | 6.61 | 1.53 | 3.13 |
|
| 126 |
+
| 30k | 1.81 | 25.03 | 7.45 | 0.102 | 3.12 | 6.60 | 1.51 | 3.12 |
|
| 127 |
+
| 35k | 1.81 | 24.94 | 7.42 | 0.101 | 3.07 | 6.39 | 1.52 | 3.12 |
|
| 128 |
+
| 40k | 1.79 | 24.94 | 7.39 | 0.101 | 3.06 | 6.37 | 1.50 | 3.11 |
|
| 129 |
+
| 42.6k | 1.79 | 24.92 | 7.39 | 0.101 | 3.06 | 6.38 | 1.50 | 3.11 |
|
| 130 |
+
|
| 131 |
+
This model did better than the teacher on MAE and accuracy, but the real-world accuracy is 5-10% worse.
|
| 132 |
+
|
| 133 |
+
## Generation Examples
|
| 134 |
+
|
| 135 |
+
| ID | Class |
|
| 136 |
+
| -- | ------------ |
|
| 137 |
+
| 0 | clear |
|
| 138 |
+
| 1 | cloudy |
|
| 139 |
+
| 2 | fog |
|
| 140 |
+
| 3 | drizzle |
|
| 141 |
+
| 4 | rain |
|
| 142 |
+
| 5 | snow |
|
| 143 |
+
| 6 | thunderstorm |
|
| 144 |
+
|
| 145 |
+
City=Seattle
|
| 146 |
+
```
|
| 147 |
+
{
|
| 148 |
+
"city": "Seattle",
|
| 149 |
+
"location_id": "1",
|
| 150 |
+
"model_location_id": 0,
|
| 151 |
+
"data_source": "open-meteo forecast api (past-hours context only)",
|
| 152 |
+
"requested_at_utc": "2026-05-08T19:57:14.429521+00:00",
|
| 153 |
+
"context": {
|
| 154 |
+
"hours": 72,
|
| 155 |
+
"start_utc": "2026-05-05T19:00:00+00:00",
|
| 156 |
+
"end_utc": "2026-05-08T18:00:00+00:00",
|
| 157 |
+
"start_local": "2026-05-05T12:00:00-07:00",
|
| 158 |
+
"end_local": "2026-05-08T11:00:00-07:00"
|
| 159 |
+
},
|
| 160 |
+
"model": {
|
| 161 |
+
"encoder_type": "lstm",
|
| 162 |
+
"seq_len": 72,
|
| 163 |
+
"input_dim": 22,
|
| 164 |
+
"num_weather_classes": 7
|
| 165 |
+
},
|
| 166 |
+
"forecast": [
|
| 167 |
+
{
|
| 168 |
+
"lead_hours": 1,
|
| 169 |
+
"target_utc": "2026-05-08T19:00:00+00:00",
|
| 170 |
+
"target_local": "2026-05-08T12:00:00-07:00",
|
| 171 |
+
"temperature_2m_c": 12.21396255493164,
|
| 172 |
+
"relative_humidity_2m_pct": 72.33454895019531,
|
| 173 |
+
"apparent_temperature_c": 10.097986221313477,
|
| 174 |
+
"precipitation_mm": 0.015628309920430183,
|
| 175 |
+
"pressure_msl_hpa": 1022.0569458007812,
|
| 176 |
+
"surface_pressure_hpa": 1014.205078125,
|
| 177 |
+
"cloud_cover_pct": 94.34225463867188,
|
| 178 |
+
"wind_speed_10m_kmh": 12.568346977233887,
|
| 179 |
+
"rain_probability": 0.19356799125671387,
|
| 180 |
+
"weather_class": 1,
|
| 181 |
+
"weather_class_name": "class_1",
|
| 182 |
+
"weather_class_probabilities": {
|
| 183 |
+
"class_0": 0.020174680277705193,
|
| 184 |
+
"class_1": 0.9282320737838745,
|
| 185 |
+
"class_2": 0.0022441258188337088,
|
| 186 |
+
"class_3": 0.04022064805030823,
|
| 187 |
+
"class_4": 0.008552632294595242,
|
| 188 |
+
"class_5": 0.0005501594278030097,
|
| 189 |
+
"class_6": 2.556406798248645e-05
|
| 190 |
+
}
|
| 191 |
+
},
|
| 192 |
+
{
|
| 193 |
+
"lead_hours": 2,
|
| 194 |
+
"target_utc": "2026-05-08T20:00:00+00:00",
|
| 195 |
+
"target_local": "2026-05-08T13:00:00-07:00",
|
| 196 |
+
"temperature_2m_c": 12.8738374710083,
|
| 197 |
+
"relative_humidity_2m_pct": 70.51017761230469,
|
| 198 |
+
"apparent_temperature_c": 10.80291748046875,
|
| 199 |
+
"precipitation_mm": 0.011432276107370853,
|
| 200 |
+
"pressure_msl_hpa": 1022.0043334960938,
|
| 201 |
+
"surface_pressure_hpa": 1014.2881469726562,
|
| 202 |
+
"cloud_cover_pct": 89.5630111694336,
|
| 203 |
+
"wind_speed_10m_kmh": 12.822803497314453,
|
| 204 |
+
"rain_probability": 0.2689012587070465,
|
| 205 |
+
"weather_class": 1,
|
| 206 |
+
"weather_class_name": "class_1",
|
| 207 |
+
"weather_class_probabilities": {
|
| 208 |
+
"class_0": 0.04770936816930771,
|
| 209 |
+
"class_1": 0.8698592185974121,
|
| 210 |
+
"class_2": 0.0019157826900482178,
|
| 211 |
+
"class_3": 0.057819921523332596,
|
| 212 |
+
"class_4": 0.02183685451745987,
|
| 213 |
+
"class_5": 0.0008237561560235918,
|
| 214 |
+
"class_6": 3.5158725950168446e-05
|
| 215 |
+
}
|
| 216 |
+
},
|
| 217 |
+
{
|
| 218 |
+
"lead_hours": 3,
|
| 219 |
+
"target_utc": "2026-05-08T21:00:00+00:00",
|
| 220 |
+
"target_local": "2026-05-08T14:00:00-07:00",
|
| 221 |
+
"temperature_2m_c": 13.51952075958252,
|
| 222 |
+
"relative_humidity_2m_pct": 68.44591522216797,
|
| 223 |
+
"apparent_temperature_c": 11.500271797180176,
|
| 224 |
+
"precipitation_mm": 0.006943895947188139,
|
| 225 |
+
"pressure_msl_hpa": 1021.80859375,
|
| 226 |
+
"surface_pressure_hpa": 1014.2529296875,
|
| 227 |
+
"cloud_cover_pct": 84.49480438232422,
|
| 228 |
+
"wind_speed_10m_kmh": 12.941960334777832,
|
| 229 |
+
"rain_probability": 0.30342426896095276,
|
| 230 |
+
"weather_class": 1,
|
| 231 |
+
"weather_class_name": "class_1",
|
| 232 |
+
"weather_class_probabilities": {
|
| 233 |
+
"class_0": 0.07170139998197556,
|
| 234 |
+
"class_1": 0.8286910057067871,
|
| 235 |
+
"class_2": 0.0013093570014461875,
|
| 236 |
+
"class_3": 0.06433302909135818,
|
| 237 |
+
"class_4": 0.03300558775663376,
|
| 238 |
+
"class_5": 0.0009036734118126333,
|
| 239 |
+
"class_6": 5.590655928244814e-05
|
| 240 |
+
}
|
| 241 |
+
},
|
| 242 |
+
{
|
| 243 |
+
"lead_hours": 4,
|
| 244 |
+
"target_utc": "2026-05-08T22:00:00+00:00",
|
| 245 |
+
"target_local": "2026-05-08T15:00:00-07:00",
|
| 246 |
+
"temperature_2m_c": 13.970871925354004,
|
| 247 |
+
"relative_humidity_2m_pct": 66.8187026977539,
|
| 248 |
+
"apparent_temperature_c": 11.959537506103516,
|
| 249 |
+
"precipitation_mm": 0.009790810756385326,
|
| 250 |
+
"pressure_msl_hpa": 1021.4691162109375,
|
| 251 |
+
"surface_pressure_hpa": 1014.1052856445312,
|
| 252 |
+
"cloud_cover_pct": 80.34271240234375,
|
| 253 |
+
"wind_speed_10m_kmh": 13.050889015197754,
|
| 254 |
+
"rain_probability": 0.33110707998275757,
|
| 255 |
+
"weather_class": 1,
|
| 256 |
+
"weather_class_name": "class_1",
|
| 257 |
+
"weather_class_probabilities": {
|
| 258 |
+
"class_0": 0.10919982939958572,
|
| 259 |
+
"class_1": 0.7759758830070496,
|
| 260 |
+
"class_2": 0.0011831748997792602,
|
| 261 |
+
"class_3": 0.07015678286552429,
|
| 262 |
+
"class_4": 0.042580746114254,
|
| 263 |
+
"class_5": 0.000857028178870678,
|
| 264 |
+
"class_6": 4.6529316023224965e-05
|
| 265 |
+
}
|
| 266 |
+
},
|
| 267 |
+
{
|
| 268 |
+
"lead_hours": 5,
|
| 269 |
+
"target_utc": "2026-05-08T23:00:00+00:00",
|
| 270 |
+
"target_local": "2026-05-08T16:00:00-07:00",
|
| 271 |
+
"temperature_2m_c": 14.132287979125977,
|
| 272 |
+
"relative_humidity_2m_pct": 66.1208267211914,
|
| 273 |
+
"apparent_temperature_c": 12.156023025512695,
|
| 274 |
+
"precipitation_mm": 0.008600466884672642,
|
| 275 |
+
"pressure_msl_hpa": 1021.0518188476562,
|
| 276 |
+
"surface_pressure_hpa": 1013.7891845703125,
|
| 277 |
+
"cloud_cover_pct": 76.06925201416016,
|
| 278 |
+
"wind_speed_10m_kmh": 12.926268577575684,
|
| 279 |
+
"rain_probability": 0.3409281373023987,
|
| 280 |
+
"weather_class": 1,
|
| 281 |
+
"weather_class_name": "class_1",
|
| 282 |
+
"weather_class_probabilities": {
|
| 283 |
+
"class_0": 0.1305426061153412,
|
| 284 |
+
"class_1": 0.7395681142807007,
|
| 285 |
+
"class_2": 0.0007046378450468183,
|
| 286 |
+
"class_3": 0.07573042809963226,
|
| 287 |
+
"class_4": 0.052331216633319855,
|
| 288 |
+
"class_5": 0.0010767169296741486,
|
| 289 |
+
"class_6": 4.629969771485776e-05
|
| 290 |
+
}
|
| 291 |
+
},
|
| 292 |
+
{
|
| 293 |
+
"lead_hours": 6,
|
| 294 |
+
"target_utc": "2026-05-09T00:00:00+00:00",
|
| 295 |
+
"target_local": "2026-05-08T17:00:00-07:00",
|
| 296 |
+
"temperature_2m_c": 13.963343620300293,
|
| 297 |
+
"relative_humidity_2m_pct": 66.67638397216797,
|
| 298 |
+
"apparent_temperature_c": 11.971813201904297,
|
| 299 |
+
"precipitation_mm": 0.010375693440437317,
|
| 300 |
+
"pressure_msl_hpa": 1020.6505126953125,
|
| 301 |
+
"surface_pressure_hpa": 1013.4520874023438,
|
| 302 |
+
"cloud_cover_pct": 73.21341705322266,
|
| 303 |
+
"wind_speed_10m_kmh": 12.721481323242188,
|
| 304 |
+
"rain_probability": 0.35606324672698975,
|
| 305 |
+
"weather_class": 1,
|
| 306 |
+
"weather_class_name": "class_1",
|
| 307 |
+
"weather_class_probabilities": {
|
| 308 |
+
"class_0": 0.15235546231269836,
|
| 309 |
+
"class_1": 0.7133304476737976,
|
| 310 |
+
"class_2": 0.0007980632944963872,
|
| 311 |
+
"class_3": 0.07519367337226868,
|
| 312 |
+
"class_4": 0.05724283307790756,
|
| 313 |
+
"class_5": 0.0010369947412982583,
|
| 314 |
+
"class_6": 4.249428093316965e-05
|
| 315 |
+
}
|
| 316 |
+
},
|
| 317 |
+
{
|
| 318 |
+
"lead_hours": 7,
|
| 319 |
+
"target_utc": "2026-05-09T01:00:00+00:00",
|
| 320 |
+
"target_local": "2026-05-08T18:00:00-07:00",
|
| 321 |
+
"temperature_2m_c": 13.449448585510254,
|
| 322 |
+
"relative_humidity_2m_pct": 68.29602813720703,
|
| 323 |
+
"apparent_temperature_c": 11.426795959472656,
|
| 324 |
+
"precipitation_mm": 0.012202607467770576,
|
| 325 |
+
"pressure_msl_hpa": 1020.3434448242188,
|
| 326 |
+
"surface_pressure_hpa": 1013.139892578125,
|
| 327 |
+
"cloud_cover_pct": 70.92017364501953,
|
| 328 |
+
"wind_speed_10m_kmh": 12.359071731567383,
|
| 329 |
+
"rain_probability": 0.3651714026927948,
|
| 330 |
+
"weather_class": 1,
|
| 331 |
+
"weather_class_name": "class_1",
|
| 332 |
+
"weather_class_probabilities": {
|
| 333 |
+
"class_0": 0.16448773443698883,
|
| 334 |
+
"class_1": 0.695494532585144,
|
| 335 |
+
"class_2": 0.0008648976217955351,
|
| 336 |
+
"class_3": 0.07075871527194977,
|
| 337 |
+
"class_4": 0.06722015887498856,
|
| 338 |
+
"class_5": 0.0011408632853999734,
|
| 339 |
+
"class_6": 3.3135267585748807e-05
|
| 340 |
+
}
|
| 341 |
+
},
|
| 342 |
+
{
|
| 343 |
+
"lead_hours": 8,
|
| 344 |
+
"target_utc": "2026-05-09T02:00:00+00:00",
|
| 345 |
+
"target_local": "2026-05-08T19:00:00-07:00",
|
| 346 |
+
"temperature_2m_c": 12.755823135375977,
|
| 347 |
+
"relative_humidity_2m_pct": 70.44146728515625,
|
| 348 |
+
"apparent_temperature_c": 10.662925720214844,
|
| 349 |
+
"precipitation_mm": 0.014662384055554867,
|
| 350 |
+
"pressure_msl_hpa": 1020.1875610351562,
|
| 351 |
+
"surface_pressure_hpa": 1012.8895874023438,
|
| 352 |
+
"cloud_cover_pct": 69.15129852294922,
|
| 353 |
+
"wind_speed_10m_kmh": 11.787208557128906,
|
| 354 |
+
"rain_probability": 0.3489035665988922,
|
| 355 |
+
"weather_class": 1,
|
| 356 |
+
"weather_class_name": "class_1",
|
| 357 |
+
"weather_class_probabilities": {
|
| 358 |
+
"class_0": 0.19570188224315643,
|
| 359 |
+
"class_1": 0.6735588908195496,
|
| 360 |
+
"class_2": 0.000978420372121036,
|
| 361 |
+
"class_3": 0.06184739992022514,
|
| 362 |
+
"class_4": 0.0664038360118866,
|
| 363 |
+
"class_5": 0.0014616982080042362,
|
| 364 |
+
"class_6": 4.789666854776442e-05
|
| 365 |
+
}
|
| 366 |
+
},
|
| 367 |
+
{
|
| 368 |
+
"lead_hours": 9,
|
| 369 |
+
"target_utc": "2026-05-09T03:00:00+00:00",
|
| 370 |
+
"target_local": "2026-05-08T20:00:00-07:00",
|
| 371 |
+
"temperature_2m_c": 11.955390930175781,
|
| 372 |
+
"relative_humidity_2m_pct": 73.05667877197266,
|
| 373 |
+
"apparent_temperature_c": 9.77428913116455,
|
| 374 |
+
"precipitation_mm": 0.015376528725028038,
|
| 375 |
+
"pressure_msl_hpa": 1020.2242431640625,
|
| 376 |
+
"surface_pressure_hpa": 1012.7984619140625,
|
| 377 |
+
"cloud_cover_pct": 67.46344757080078,
|
| 378 |
+
"wind_speed_10m_kmh": 11.127586364746094,
|
| 379 |
+
"rain_probability": 0.36496502161026,
|
| 380 |
+
"weather_class": 1,
|
| 381 |
+
"weather_class_name": "class_1",
|
| 382 |
+
"weather_class_probabilities": {
|
| 383 |
+
"class_0": 0.20349998772144318,
|
| 384 |
+
"class_1": 0.6480608582496643,
|
| 385 |
+
"class_2": 0.0010103220120072365,
|
| 386 |
+
"class_3": 0.06373731791973114,
|
| 387 |
+
"class_4": 0.08206527680158615,
|
| 388 |
+
"class_5": 0.0015911461086943746,
|
| 389 |
+
"class_6": 3.510143869789317e-05
|
| 390 |
+
}
|
| 391 |
+
},
|
| 392 |
+
{
|
| 393 |
+
"lead_hours": 10,
|
| 394 |
+
"target_utc": "2026-05-09T04:00:00+00:00",
|
| 395 |
+
"target_local": "2026-05-08T21:00:00-07:00",
|
| 396 |
+
"temperature_2m_c": 11.182319641113281,
|
| 397 |
+
"relative_humidity_2m_pct": 75.5196304321289,
|
| 398 |
+
"apparent_temperature_c": 8.978246688842773,
|
| 399 |
+
"precipitation_mm": 0.016823438927531242,
|
| 400 |
+
"pressure_msl_hpa": 1020.421875,
|
| 401 |
+
"surface_pressure_hpa": 1012.8126831054688,
|
| 402 |
+
"cloud_cover_pct": 65.73115539550781,
|
| 403 |
+
"wind_speed_10m_kmh": 10.359850883483887,
|
| 404 |
+
"rain_probability": 0.35924479365348816,
|
| 405 |
+
"weather_class": 1,
|
| 406 |
+
"weather_class_name": "class_1",
|
| 407 |
+
"weather_class_probabilities": {
|
| 408 |
+
"class_0": 0.21845510601997375,
|
| 409 |
+
"class_1": 0.6389062404632568,
|
| 410 |
+
"class_2": 0.0018773162737488747,
|
| 411 |
+
"class_3": 0.059891991317272186,
|
| 412 |
+
"class_4": 0.07879848033189774,
|
| 413 |
+
"class_5": 0.002034474164247513,
|
| 414 |
+
"class_6": 3.633901724242605e-05
|
| 415 |
+
}
|
| 416 |
+
},
|
| 417 |
+
{
|
| 418 |
+
"lead_hours": 11,
|
| 419 |
+
"target_utc": "2026-05-09T05:00:00+00:00",
|
| 420 |
+
"target_local": "2026-05-08T22:00:00-07:00",
|
| 421 |
+
"temperature_2m_c": 10.499757766723633,
|
| 422 |
+
"relative_humidity_2m_pct": 77.536865234375,
|
| 423 |
+
"apparent_temperature_c": 8.306406021118164,
|
| 424 |
+
"precipitation_mm": 0.01860857754945755,
|
| 425 |
+
"pressure_msl_hpa": 1020.7318725585938,
|
| 426 |
+
"surface_pressure_hpa": 1012.9368896484375,
|
| 427 |
+
"cloud_cover_pct": 65.10720825195312,
|
| 428 |
+
"wind_speed_10m_kmh": 9.62015151977539,
|
| 429 |
+
"rain_probability": 0.3694237470626831,
|
| 430 |
+
"weather_class": 1,
|
| 431 |
+
"weather_class_name": "class_1",
|
| 432 |
+
"weather_class_probabilities": {
|
| 433 |
+
"class_0": 0.22774139046669006,
|
| 434 |
+
"class_1": 0.6242526173591614,
|
| 435 |
+
"class_2": 0.0028147574048489332,
|
| 436 |
+
"class_3": 0.06025313213467598,
|
| 437 |
+
"class_4": 0.0822005346417427,
|
| 438 |
+
"class_5": 0.0026846849359571934,
|
| 439 |
+
"class_6": 5.289047476253472e-05
|
| 440 |
+
}
|
| 441 |
+
},
|
| 442 |
+
{
|
| 443 |
+
"lead_hours": 12,
|
| 444 |
+
"target_utc": "2026-05-09T06:00:00+00:00",
|
| 445 |
+
"target_local": "2026-05-08T23:00:00-07:00",
|
| 446 |
+
"temperature_2m_c": 9.956731796264648,
|
| 447 |
+
"relative_humidity_2m_pct": 79.21904754638672,
|
| 448 |
+
"apparent_temperature_c": 7.87125301361084,
|
| 449 |
+
"precipitation_mm": 0.017959173768758774,
|
| 450 |
+
"pressure_msl_hpa": 1021.0579833984375,
|
| 451 |
+
"surface_pressure_hpa": 1013.093994140625,
|
| 452 |
+
"cloud_cover_pct": 64.14817810058594,
|
| 453 |
+
"wind_speed_10m_kmh": 8.923616409301758,
|
| 454 |
+
"rain_probability": 0.3691202700138092,
|
| 455 |
+
"weather_class": 1,
|
| 456 |
+
"weather_class_name": "class_1",
|
| 457 |
+
"weather_class_probabilities": {
|
| 458 |
+
"class_0": 0.23541118204593658,
|
| 459 |
+
"class_1": 0.618242621421814,
|
| 460 |
+
"class_2": 0.0044443667866289616,
|
| 461 |
+
"class_3": 0.06440076231956482,
|
| 462 |
+
"class_4": 0.0741729885339737,
|
| 463 |
+
"class_5": 0.003270090091973543,
|
| 464 |
+
"class_6": 5.8019890275318176e-05
|
| 465 |
+
}
|
| 466 |
+
}
|
| 467 |
+
],
|
| 468 |
+
"sanity": {
|
| 469 |
+
"sequence_shape": [
|
| 470 |
+
72,
|
| 471 |
+
22
|
| 472 |
+
],
|
| 473 |
+
"finite_features": true
|
| 474 |
+
}
|
| 475 |
+
}
|
| 476 |
+
PS C:\Users\Paulc> python3.12 weather_infer.py --model_dir "C:\Users\Paulc\weather_model\student_distilled" --city Seattle
|
| 477 |
+
Warning: unexpected keys while loading checkpoint: ['distill_proj.weight']
|
| 478 |
+
{
|
| 479 |
+
"city": "Seattle",
|
| 480 |
+
"location_id": "1",
|
| 481 |
+
"model_location_id": 0,
|
| 482 |
+
"data_source": "open-meteo forecast api (past-hours context only)",
|
| 483 |
+
"requested_at_utc": "2026-05-08T19:57:47.439276+00:00",
|
| 484 |
+
"context": {
|
| 485 |
+
"hours": 72,
|
| 486 |
+
"start_utc": "2026-05-05T19:00:00+00:00",
|
| 487 |
+
"end_utc": "2026-05-08T18:00:00+00:00",
|
| 488 |
+
"start_local": "2026-05-05T12:00:00-07:00",
|
| 489 |
+
"end_local": "2026-05-08T11:00:00-07:00"
|
| 490 |
+
},
|
| 491 |
+
"model": {
|
| 492 |
+
"encoder_type": "lstm",
|
| 493 |
+
"seq_len": 72,
|
| 494 |
+
"input_dim": 22,
|
| 495 |
+
"num_weather_classes": 7
|
| 496 |
+
},
|
| 497 |
+
"forecast": [
|
| 498 |
+
{
|
| 499 |
+
"lead_hours": 1,
|
| 500 |
+
"target_utc": "2026-05-08T19:00:00+00:00",
|
| 501 |
+
"target_local": "2026-05-08T12:00:00-07:00",
|
| 502 |
+
"temperature_2m_c": 13.681238174438477,
|
| 503 |
+
"relative_humidity_2m_pct": 69.90876770019531,
|
| 504 |
+
"apparent_temperature_c": 11.687149047851562,
|
| 505 |
+
"precipitation_mm": 0.0012515264097601175,
|
| 506 |
+
"pressure_msl_hpa": 1019.3030395507812,
|
| 507 |
+
"surface_pressure_hpa": 1018.5359497070312,
|
| 508 |
+
"cloud_cover_pct": 88.76920318603516,
|
| 509 |
+
"wind_speed_10m_kmh": 13.126839637756348,
|
| 510 |
+
"rain_probability": 0.1457637995481491,
|
| 511 |
+
"weather_class": 1,
|
| 512 |
+
"weather_class_name": "class_1",
|
| 513 |
+
"weather_class_probabilities": {
|
| 514 |
+
"class_0": 0.02097843959927559,
|
| 515 |
+
"class_1": 0.9304905533790588,
|
| 516 |
+
"class_2": 0.0025352241937071085,
|
| 517 |
+
"class_3": 0.03495039418339729,
|
| 518 |
+
"class_4": 0.01054275780916214,
|
| 519 |
+
"class_5": 0.0004654920194298029,
|
| 520 |
+
"class_6": 3.7044908822281286e-05
|
| 521 |
+
}
|
| 522 |
+
},
|
| 523 |
+
{
|
| 524 |
+
"lead_hours": 2,
|
| 525 |
+
"target_utc": "2026-05-08T20:00:00+00:00",
|
| 526 |
+
"target_local": "2026-05-08T13:00:00-07:00",
|
| 527 |
+
"temperature_2m_c": 14.486506462097168,
|
| 528 |
+
"relative_humidity_2m_pct": 67.52698516845703,
|
| 529 |
+
"apparent_temperature_c": 12.55270767211914,
|
| 530 |
+
"precipitation_mm": 0.0008608415955677629,
|
| 531 |
+
"pressure_msl_hpa": 1019.0198364257812,
|
| 532 |
+
"surface_pressure_hpa": 1018.4589233398438,
|
| 533 |
+
"cloud_cover_pct": 84.31889343261719,
|
| 534 |
+
"wind_speed_10m_kmh": 13.241435050964355,
|
| 535 |
+
"rain_probability": 0.19527363777160645,
|
| 536 |
+
"weather_class": 1,
|
| 537 |
+
"weather_class_name": "class_1",
|
| 538 |
+
"weather_class_probabilities": {
|
| 539 |
+
"class_0": 0.053049832582473755,
|
| 540 |
+
"class_1": 0.8794819712638855,
|
| 541 |
+
"class_2": 0.0021074640098959208,
|
| 542 |
+
"class_3": 0.0436088852584362,
|
| 543 |
+
"class_4": 0.02111213095486164,
|
| 544 |
+
"class_5": 0.0005800225771963596,
|
| 545 |
+
"class_6": 5.971627979306504e-05
|
| 546 |
+
}
|
| 547 |
+
},
|
| 548 |
+
{
|
| 549 |
+
"lead_hours": 3,
|
| 550 |
+
"target_utc": "2026-05-08T21:00:00+00:00",
|
| 551 |
+
"target_local": "2026-05-08T14:00:00-07:00",
|
| 552 |
+
"temperature_2m_c": 15.089279174804688,
|
| 553 |
+
"relative_humidity_2m_pct": 65.6773681640625,
|
| 554 |
+
"apparent_temperature_c": 13.181319236755371,
|
| 555 |
+
"precipitation_mm": 0.002190209459513426,
|
| 556 |
+
"pressure_msl_hpa": 1018.709716796875,
|
| 557 |
+
"surface_pressure_hpa": 1018.2867431640625,
|
| 558 |
+
"cloud_cover_pct": 80.14619445800781,
|
| 559 |
+
"wind_speed_10m_kmh": 13.32516860961914,
|
| 560 |
+
"rain_probability": 0.21867528557777405,
|
| 561 |
+
"weather_class": 1,
|
| 562 |
+
"weather_class_name": "class_1",
|
| 563 |
+
"weather_class_probabilities": {
|
| 564 |
+
"class_0": 0.08254168927669525,
|
| 565 |
+
"class_1": 0.8380688428878784,
|
| 566 |
+
"class_2": 0.0014072611229494214,
|
| 567 |
+
"class_3": 0.04709410294890404,
|
| 568 |
+
"class_4": 0.030200183391571045,
|
| 569 |
+
"class_5": 0.0006088378722779453,
|
| 570 |
+
"class_6": 7.912428554845974e-05
|
| 571 |
+
}
|
| 572 |
+
},
|
| 573 |
+
{
|
| 574 |
+
"lead_hours": 4,
|
| 575 |
+
"target_utc": "2026-05-08T22:00:00+00:00",
|
| 576 |
+
"target_local": "2026-05-08T15:00:00-07:00",
|
| 577 |
+
"temperature_2m_c": 15.403922080993652,
|
| 578 |
+
"relative_humidity_2m_pct": 64.67561340332031,
|
| 579 |
+
"apparent_temperature_c": 13.48654556274414,
|
| 580 |
+
"precipitation_mm": 0.0021571130491793156,
|
| 581 |
+
"pressure_msl_hpa": 1018.3944702148438,
|
| 582 |
+
"surface_pressure_hpa": 1018.0625,
|
| 583 |
+
"cloud_cover_pct": 76.4104995727539,
|
| 584 |
+
"wind_speed_10m_kmh": 13.275524139404297,
|
| 585 |
+
"rain_probability": 0.2299734503030777,
|
| 586 |
+
"weather_class": 1,
|
| 587 |
+
"weather_class_name": "class_1",
|
| 588 |
+
"weather_class_probabilities": {
|
| 589 |
+
"class_0": 0.11604393273591995,
|
| 590 |
+
"class_1": 0.7922014594078064,
|
| 591 |
+
"class_2": 0.0011422870447859168,
|
| 592 |
+
"class_3": 0.05158008262515068,
|
| 593 |
+
"class_4": 0.03833876550197601,
|
| 594 |
+
"class_5": 0.000621610670350492,
|
| 595 |
+
"class_6": 7.179530075518414e-05
|
| 596 |
+
}
|
| 597 |
+
},
|
| 598 |
+
{
|
| 599 |
+
"lead_hours": 5,
|
| 600 |
+
"target_utc": "2026-05-08T23:00:00+00:00",
|
| 601 |
+
"target_local": "2026-05-08T16:00:00-07:00",
|
| 602 |
+
"temperature_2m_c": 15.407997131347656,
|
| 603 |
+
"relative_humidity_2m_pct": 64.65668487548828,
|
| 604 |
+
"apparent_temperature_c": 13.48292350769043,
|
| 605 |
+
"precipitation_mm": 0.0026813943404704332,
|
| 606 |
+
"pressure_msl_hpa": 1018.1220703125,
|
| 607 |
+
"surface_pressure_hpa": 1017.7960205078125,
|
| 608 |
+
"cloud_cover_pct": 72.77561950683594,
|
| 609 |
+
"wind_speed_10m_kmh": 13.133893966674805,
|
| 610 |
+
"rain_probability": 0.23628145456314087,
|
| 611 |
+
"weather_class": 1,
|
| 612 |
+
"weather_class_name": "class_1",
|
| 613 |
+
"weather_class_probabilities": {
|
| 614 |
+
"class_0": 0.14982207119464874,
|
| 615 |
+
"class_1": 0.7523030638694763,
|
| 616 |
+
"class_2": 0.0008282885537482798,
|
| 617 |
+
"class_3": 0.05172016844153404,
|
| 618 |
+
"class_4": 0.04454538971185684,
|
| 619 |
+
"class_5": 0.0007084720418788493,
|
| 620 |
+
"class_6": 7.257604011101648e-05
|
| 621 |
+
}
|
| 622 |
+
},
|
| 623 |
+
{
|
| 624 |
+
"lead_hours": 6,
|
| 625 |
+
"target_utc": "2026-05-09T00:00:00+00:00",
|
| 626 |
+
"target_local": "2026-05-08T17:00:00-07:00",
|
| 627 |
+
"temperature_2m_c": 15.139252662658691,
|
| 628 |
+
"relative_humidity_2m_pct": 65.5518798828125,
|
| 629 |
+
"apparent_temperature_c": 13.192585945129395,
|
| 630 |
+
"precipitation_mm": 0.0026606114115566015,
|
| 631 |
+
"pressure_msl_hpa": 1017.9351196289062,
|
| 632 |
+
"surface_pressure_hpa": 1017.5604858398438,
|
| 633 |
+
"cloud_cover_pct": 69.60166931152344,
|
| 634 |
+
"wind_speed_10m_kmh": 12.789706230163574,
|
| 635 |
+
"rain_probability": 0.23617199063301086,
|
| 636 |
+
"weather_class": 1,
|
| 637 |
+
"weather_class_name": "class_1",
|
| 638 |
+
"weather_class_probabilities": {
|
| 639 |
+
"class_0": 0.17920561134815216,
|
| 640 |
+
"class_1": 0.7213184237480164,
|
| 641 |
+
"class_2": 0.0008871846948750317,
|
| 642 |
+
"class_3": 0.05144878104329109,
|
| 643 |
+
"class_4": 0.046307649463415146,
|
| 644 |
+
"class_5": 0.0007639037212356925,
|
| 645 |
+
"class_6": 6.843609298812225e-05
|
| 646 |
+
}
|
| 647 |
+
},
|
| 648 |
+
{
|
| 649 |
+
"lead_hours": 7,
|
| 650 |
+
"target_utc": "2026-05-09T01:00:00+00:00",
|
| 651 |
+
"target_local": "2026-05-08T18:00:00-07:00",
|
| 652 |
+
"temperature_2m_c": 14.66390609741211,
|
| 653 |
+
"relative_humidity_2m_pct": 67.1559066772461,
|
| 654 |
+
"apparent_temperature_c": 12.692171096801758,
|
| 655 |
+
"precipitation_mm": 0.002722225384786725,
|
| 656 |
+
"pressure_msl_hpa": 1017.8424072265625,
|
| 657 |
+
"surface_pressure_hpa": 1017.3685913085938,
|
| 658 |
+
"cloud_cover_pct": 66.97268676757812,
|
| 659 |
+
"wind_speed_10m_kmh": 12.329818725585938,
|
| 660 |
+
"rain_probability": 0.23410728573799133,
|
| 661 |
+
"weather_class": 1,
|
| 662 |
+
"weather_class_name": "class_1",
|
| 663 |
+
"weather_class_probabilities": {
|
| 664 |
+
"class_0": 0.20177967846393585,
|
| 665 |
+
"class_1": 0.697116494178772,
|
| 666 |
+
"class_2": 0.001064434414729476,
|
| 667 |
+
"class_3": 0.04921679198741913,
|
| 668 |
+
"class_4": 0.049886710941791534,
|
| 669 |
+
"class_5": 0.0008780939970165491,
|
| 670 |
+
"class_6": 5.7844863476930186e-05
|
| 671 |
+
}
|
| 672 |
+
},
|
| 673 |
+
{
|
| 674 |
+
"lead_hours": 8,
|
| 675 |
+
"target_utc": "2026-05-09T02:00:00+00:00",
|
| 676 |
+
"target_local": "2026-05-08T19:00:00-07:00",
|
| 677 |
+
"temperature_2m_c": 14.042488098144531,
|
| 678 |
+
"relative_humidity_2m_pct": 69.15681457519531,
|
| 679 |
+
"apparent_temperature_c": 12.045327186584473,
|
| 680 |
+
"precipitation_mm": 0.003981542307883501,
|
| 681 |
+
"pressure_msl_hpa": 1017.853759765625,
|
| 682 |
+
"surface_pressure_hpa": 1017.2957763671875,
|
| 683 |
+
"cloud_cover_pct": 64.85920715332031,
|
| 684 |
+
"wind_speed_10m_kmh": 11.780016899108887,
|
| 685 |
+
"rain_probability": 0.23837216198444366,
|
| 686 |
+
"weather_class": 1,
|
| 687 |
+
"weather_class_name": "class_1",
|
| 688 |
+
"weather_class_probabilities": {
|
| 689 |
+
"class_0": 0.23561197519302368,
|
| 690 |
+
"class_1": 0.6629505753517151,
|
| 691 |
+
"class_2": 0.0012489539803937078,
|
| 692 |
+
"class_3": 0.04817439988255501,
|
| 693 |
+
"class_4": 0.050942711532115936,
|
| 694 |
+
"class_5": 0.0010061608627438545,
|
| 695 |
+
"class_6": 6.52461385470815e-05
|
| 696 |
+
}
|
| 697 |
+
},
|
| 698 |
+
{
|
| 699 |
+
"lead_hours": 9,
|
| 700 |
+
"target_utc": "2026-05-09T03:00:00+00:00",
|
| 701 |
+
"target_local": "2026-05-08T20:00:00-07:00",
|
| 702 |
+
"temperature_2m_c": 13.325971603393555,
|
| 703 |
+
"relative_humidity_2m_pct": 71.42361450195312,
|
| 704 |
+
"apparent_temperature_c": 11.300540924072266,
|
| 705 |
+
"precipitation_mm": 0.0030152045655995607,
|
| 706 |
+
"pressure_msl_hpa": 1017.9505004882812,
|
| 707 |
+
"surface_pressure_hpa": 1017.2774047851562,
|
| 708 |
+
"cloud_cover_pct": 63.037109375,
|
| 709 |
+
"wind_speed_10m_kmh": 11.165238380432129,
|
| 710 |
+
"rain_probability": 0.23051044344902039,
|
| 711 |
+
"weather_class": 1,
|
| 712 |
+
"weather_class_name": "class_1",
|
| 713 |
+
"weather_class_probabilities": {
|
| 714 |
+
"class_0": 0.24986012279987335,
|
| 715 |
+
"class_1": 0.6375465989112854,
|
| 716 |
+
"class_2": 0.0016154011245816946,
|
| 717 |
+
"class_3": 0.04874761775135994,
|
| 718 |
+
"class_4": 0.06096767634153366,
|
| 719 |
+
"class_5": 0.0012142135528847575,
|
| 720 |
+
"class_6": 4.836557855014689e-05
|
| 721 |
+
}
|
| 722 |
+
},
|
| 723 |
+
{
|
| 724 |
+
"lead_hours": 10,
|
| 725 |
+
"target_utc": "2026-05-09T04:00:00+00:00",
|
| 726 |
+
"target_local": "2026-05-08T21:00:00-07:00",
|
| 727 |
+
"temperature_2m_c": 12.574642181396484,
|
| 728 |
+
"relative_humidity_2m_pct": 73.7841796875,
|
| 729 |
+
"apparent_temperature_c": 10.549814224243164,
|
| 730 |
+
"precipitation_mm": 0.004971037618815899,
|
| 731 |
+
"pressure_msl_hpa": 1018.10400390625,
|
| 732 |
+
"surface_pressure_hpa": 1017.2828979492188,
|
| 733 |
+
"cloud_cover_pct": 61.4162483215332,
|
| 734 |
+
"wind_speed_10m_kmh": 10.5538911819458,
|
| 735 |
+
"rain_probability": 0.23788221180438995,
|
| 736 |
+
"weather_class": 1,
|
| 737 |
+
"weather_class_name": "class_1",
|
| 738 |
+
"weather_class_probabilities": {
|
| 739 |
+
"class_0": 0.27152255177497864,
|
| 740 |
+
"class_1": 0.6182448863983154,
|
| 741 |
+
"class_2": 0.0025821358431130648,
|
| 742 |
+
"class_3": 0.04885515570640564,
|
| 743 |
+
"class_4": 0.05706281587481499,
|
| 744 |
+
"class_5": 0.0016854261048138142,
|
| 745 |
+
"class_6": 4.704758248408325e-05
|
| 746 |
+
}
|
| 747 |
+
},
|
| 748 |
+
{
|
| 749 |
+
"lead_hours": 11,
|
| 750 |
+
"target_utc": "2026-05-09T05:00:00+00:00",
|
| 751 |
+
"target_local": "2026-05-08T22:00:00-07:00",
|
| 752 |
+
"temperature_2m_c": 11.85836124420166,
|
| 753 |
+
"relative_humidity_2m_pct": 75.99488830566406,
|
| 754 |
+
"apparent_temperature_c": 9.845465660095215,
|
| 755 |
+
"precipitation_mm": 0.0059099141508340836,
|
| 756 |
+
"pressure_msl_hpa": 1018.2722778320312,
|
| 757 |
+
"surface_pressure_hpa": 1017.3274536132812,
|
| 758 |
+
"cloud_cover_pct": 60.944053649902344,
|
| 759 |
+
"wind_speed_10m_kmh": 10.019789695739746,
|
| 760 |
+
"rain_probability": 0.24793456494808197,
|
| 761 |
+
"weather_class": 1,
|
| 762 |
+
"weather_class_name": "class_1",
|
| 763 |
+
"weather_class_probabilities": {
|
| 764 |
+
"class_0": 0.27306604385375977,
|
| 765 |
+
"class_1": 0.6107510328292847,
|
| 766 |
+
"class_2": 0.004449337720870972,
|
| 767 |
+
"class_3": 0.0498417466878891,
|
| 768 |
+
"class_4": 0.05973493307828903,
|
| 769 |
+
"class_5": 0.002092213137075305,
|
| 770 |
+
"class_6": 6.465442857006565e-05
|
| 771 |
+
}
|
| 772 |
+
},
|
| 773 |
+
{
|
| 774 |
+
"lead_hours": 12,
|
| 775 |
+
"target_utc": "2026-05-09T06:00:00+00:00",
|
| 776 |
+
"target_local": "2026-05-08T23:00:00-07:00",
|
| 777 |
+
"temperature_2m_c": 11.196554183959961,
|
| 778 |
+
"relative_humidity_2m_pct": 78.09349060058594,
|
| 779 |
+
"apparent_temperature_c": 9.231935501098633,
|
| 780 |
+
"precipitation_mm": 0.00701399240642786,
|
| 781 |
+
"pressure_msl_hpa": 1018.4185791015625,
|
| 782 |
+
"surface_pressure_hpa": 1017.3386840820312,
|
| 783 |
+
"cloud_cover_pct": 60.26295471191406,
|
| 784 |
+
"wind_speed_10m_kmh": 9.483912467956543,
|
| 785 |
+
"rain_probability": 0.2565533518791199,
|
| 786 |
+
"weather_class": 1,
|
| 787 |
+
"weather_class_name": "class_1",
|
| 788 |
+
"weather_class_probabilities": {
|
| 789 |
+
"class_0": 0.27720507979393005,
|
| 790 |
+
"class_1": 0.6052833795547485,
|
| 791 |
+
"class_2": 0.007175811566412449,
|
| 792 |
+
"class_3": 0.04983551800251007,
|
| 793 |
+
"class_4": 0.05781771242618561,
|
| 794 |
+
"class_5": 0.0026247103232890368,
|
| 795 |
+
"class_6": 5.782112566521391e-05
|
| 796 |
+
}
|
| 797 |
+
}
|
| 798 |
+
],
|
| 799 |
+
"sanity": {
|
| 800 |
+
"sequence_shape": [
|
| 801 |
+
72,
|
| 802 |
+
22
|
| 803 |
+
],
|
| 804 |
+
"finite_features": true
|
| 805 |
+
}
|
| 806 |
+
}
|
| 807 |
+
```
|
| 808 |
+
|
| 809 |
+
City=Nuuk
|
| 810 |
+
```
|
| 811 |
+
{
|
| 812 |
+
"city": "Nuuk",
|
| 813 |
+
"location_id": "83",
|
| 814 |
+
"model_location_id": 0,
|
| 815 |
+
"data_source": "open-meteo forecast api (past-hours context only)",
|
| 816 |
+
"requested_at_utc": "2026-05-08T20:40:35.109779+00:00",
|
| 817 |
+
"context": {
|
| 818 |
+
"hours": 72,
|
| 819 |
+
"start_utc": "2026-05-05T20:00:00+00:00",
|
| 820 |
+
"end_utc": "2026-05-08T19:00:00+00:00",
|
| 821 |
+
"start_local": "2026-05-05T19:00:00-01:00",
|
| 822 |
+
"end_local": "2026-05-08T18:00:00-01:00"
|
| 823 |
+
},
|
| 824 |
+
"model": {
|
| 825 |
+
"encoder_type": "lstm",
|
| 826 |
+
"seq_len": 72,
|
| 827 |
+
"input_dim": 22,
|
| 828 |
+
"num_weather_classes": 7
|
| 829 |
+
},
|
| 830 |
+
"forecast": [
|
| 831 |
+
{
|
| 832 |
+
"lead_hours": 1,
|
| 833 |
+
"target_utc": "2026-05-08T20:00:00+00:00",
|
| 834 |
+
"target_local": "2026-05-08T19:00:00-01:00",
|
| 835 |
+
"temperature_2m_c": 5.2753753662109375,
|
| 836 |
+
"relative_humidity_2m_pct": 93.01068115234375,
|
| 837 |
+
"apparent_temperature_c": 1.6396684646606445,
|
| 838 |
+
"precipitation_mm": 0.3556472063064575,
|
| 839 |
+
"pressure_msl_hpa": 1005.5432739257812,
|
| 840 |
+
"surface_pressure_hpa": 973.415771484375,
|
| 841 |
+
"cloud_cover_pct": 98.54638671875,
|
| 842 |
+
"wind_speed_10m_kmh": 13.717008590698242,
|
| 843 |
+
"rain_probability": 0.9789170026779175,
|
| 844 |
+
"weather_class": 3,
|
| 845 |
+
"weather_class_name": "class_3",
|
| 846 |
+
"weather_class_probabilities": {
|
| 847 |
+
"class_0": 0.000619232130702585,
|
| 848 |
+
"class_1": 0.057769663631916046,
|
| 849 |
+
"class_2": 0.003395488252863288,
|
| 850 |
+
"class_3": 0.401492714881897,
|
| 851 |
+
"class_4": 0.18206973373889923,
|
| 852 |
+
"class_5": 0.3545896112918854,
|
| 853 |
+
"class_6": 6.364739965647459e-05
|
| 854 |
+
}
|
| 855 |
+
},
|
| 856 |
+
{
|
| 857 |
+
"lead_hours": 2,
|
| 858 |
+
"target_utc": "2026-05-08T21:00:00+00:00",
|
| 859 |
+
"target_local": "2026-05-08T20:00:00-01:00",
|
| 860 |
+
"temperature_2m_c": 4.986588478088379,
|
| 861 |
+
"relative_humidity_2m_pct": 93.84243774414062,
|
| 862 |
+
"apparent_temperature_c": 1.352757453918457,
|
| 863 |
+
"precipitation_mm": 0.2776345908641815,
|
| 864 |
+
"pressure_msl_hpa": 1005.599853515625,
|
| 865 |
+
"surface_pressure_hpa": 973.536376953125,
|
| 866 |
+
"cloud_cover_pct": 98.45586395263672,
|
| 867 |
+
"wind_speed_10m_kmh": 13.445389747619629,
|
| 868 |
+
"rain_probability": 0.9556259512901306,
|
| 869 |
+
"weather_class": 5,
|
| 870 |
+
"weather_class_name": "class_5",
|
| 871 |
+
"weather_class_probabilities": {
|
| 872 |
+
"class_0": 0.00150326790753752,
|
| 873 |
+
"class_1": 0.09517476707696915,
|
| 874 |
+
"class_2": 0.004558710381388664,
|
| 875 |
+
"class_3": 0.32409900426864624,
|
| 876 |
+
"class_4": 0.1846529245376587,
|
| 877 |
+
"class_5": 0.38996437191963196,
|
| 878 |
+
"class_6": 4.702423757407814e-05
|
| 879 |
+
}
|
| 880 |
+
},
|
| 881 |
+
{
|
| 882 |
+
"lead_hours": 3,
|
| 883 |
+
"target_utc": "2026-05-08T22:00:00+00:00",
|
| 884 |
+
"target_local": "2026-05-08T21:00:00-01:00",
|
| 885 |
+
"temperature_2m_c": 4.788308143615723,
|
| 886 |
+
"relative_humidity_2m_pct": 94.0885238647461,
|
| 887 |
+
"apparent_temperature_c": 1.1667909622192383,
|
| 888 |
+
"precipitation_mm": 0.23039932548999786,
|
| 889 |
+
"pressure_msl_hpa": 1005.703857421875,
|
| 890 |
+
"surface_pressure_hpa": 973.5965576171875,
|
| 891 |
+
"cloud_cover_pct": 97.65797424316406,
|
| 892 |
+
"wind_speed_10m_kmh": 13.209211349487305,
|
| 893 |
+
"rain_probability": 0.9299042820930481,
|
| 894 |
+
"weather_class": 5,
|
| 895 |
+
"weather_class_name": "class_5",
|
| 896 |
+
"weather_class_probabilities": {
|
| 897 |
+
"class_0": 0.002542331349104643,
|
| 898 |
+
"class_1": 0.12809209525585175,
|
| 899 |
+
"class_2": 0.0058285691775381565,
|
| 900 |
+
"class_3": 0.3043138086795807,
|
| 901 |
+
"class_4": 0.17225369811058044,
|
| 902 |
+
"class_5": 0.3869440257549286,
|
| 903 |
+
"class_6": 2.5515650122542866e-05
|
| 904 |
+
}
|
| 905 |
+
},
|
| 906 |
+
{
|
| 907 |
+
"lead_hours": 4,
|
| 908 |
+
"target_utc": "2026-05-08T23:00:00+00:00",
|
| 909 |
+
"target_local": "2026-05-08T22:00:00-01:00",
|
| 910 |
+
"temperature_2m_c": 4.660131454467773,
|
| 911 |
+
"relative_humidity_2m_pct": 94.03594970703125,
|
| 912 |
+
"apparent_temperature_c": 1.0469179153442383,
|
| 913 |
+
"precipitation_mm": 0.19706439971923828,
|
| 914 |
+
"pressure_msl_hpa": 1005.7493896484375,
|
| 915 |
+
"surface_pressure_hpa": 973.7083740234375,
|
| 916 |
+
"cloud_cover_pct": 97.17306518554688,
|
| 917 |
+
"wind_speed_10m_kmh": 13.017566680908203,
|
| 918 |
+
"rain_probability": 0.9050359129905701,
|
| 919 |
+
"weather_class": 5,
|
| 920 |
+
"weather_class_name": "class_5",
|
| 921 |
+
"weather_class_probabilities": {
|
| 922 |
+
"class_0": 0.004407276399433613,
|
| 923 |
+
"class_1": 0.15539932250976562,
|
| 924 |
+
"class_2": 0.009657401591539383,
|
| 925 |
+
"class_3": 0.2794102430343628,
|
| 926 |
+
"class_4": 0.1521354615688324,
|
| 927 |
+
"class_5": 0.3989632725715637,
|
| 928 |
+
"class_6": 2.7043566660722718e-05
|
| 929 |
+
}
|
| 930 |
+
},
|
| 931 |
+
{
|
| 932 |
+
"lead_hours": 5,
|
| 933 |
+
"target_utc": "2026-05-09T00:00:00+00:00",
|
| 934 |
+
"target_local": "2026-05-08T23:00:00-01:00",
|
| 935 |
+
"temperature_2m_c": 4.5112457275390625,
|
| 936 |
+
"relative_humidity_2m_pct": 93.88682556152344,
|
| 937 |
+
"apparent_temperature_c": 0.9274702072143555,
|
| 938 |
+
"precipitation_mm": 0.1685791015625,
|
| 939 |
+
"pressure_msl_hpa": 1005.7725830078125,
|
| 940 |
+
"surface_pressure_hpa": 973.7322387695312,
|
| 941 |
+
"cloud_cover_pct": 96.03288269042969,
|
| 942 |
+
"wind_speed_10m_kmh": 12.944330215454102,
|
| 943 |
+
"rain_probability": 0.8804075121879578,
|
| 944 |
+
"weather_class": 5,
|
| 945 |
+
"weather_class_name": "class_5",
|
| 946 |
+
"weather_class_probabilities": {
|
| 947 |
+
"class_0": 0.006306177470833063,
|
| 948 |
+
"class_1": 0.17262385785579681,
|
| 949 |
+
"class_2": 0.00996350683271885,
|
| 950 |
+
"class_3": 0.2658991515636444,
|
| 951 |
+
"class_4": 0.1401163786649704,
|
| 952 |
+
"class_5": 0.4050598442554474,
|
| 953 |
+
"class_6": 3.1046529329614714e-05
|
| 954 |
+
}
|
| 955 |
+
},
|
| 956 |
+
{
|
| 957 |
+
"lead_hours": 6,
|
| 958 |
+
"target_utc": "2026-05-09T01:00:00+00:00",
|
| 959 |
+
"target_local": "2026-05-09T00:00:00-01:00",
|
| 960 |
+
"temperature_2m_c": 4.33610725402832,
|
| 961 |
+
"relative_humidity_2m_pct": 94.00520324707031,
|
| 962 |
+
"apparent_temperature_c": 0.7778654098510742,
|
| 963 |
+
"precipitation_mm": 0.14649224281311035,
|
| 964 |
+
"pressure_msl_hpa": 1005.8167114257812,
|
| 965 |
+
"surface_pressure_hpa": 973.7780151367188,
|
| 966 |
+
"cloud_cover_pct": 95.56141662597656,
|
| 967 |
+
"wind_speed_10m_kmh": 12.845012664794922,
|
| 968 |
+
"rain_probability": 0.8599434494972229,
|
| 969 |
+
"weather_class": 5,
|
| 970 |
+
"weather_class_name": "class_5",
|
| 971 |
+
"weather_class_probabilities": {
|
| 972 |
+
"class_0": 0.007768102455884218,
|
| 973 |
+
"class_1": 0.18894362449645996,
|
| 974 |
+
"class_2": 0.011767406016588211,
|
| 975 |
+
"class_3": 0.2329735904932022,
|
| 976 |
+
"class_4": 0.12322919070720673,
|
| 977 |
+
"class_5": 0.43529438972473145,
|
| 978 |
+
"class_6": 2.3752647393848747e-05
|
| 979 |
+
}
|
| 980 |
+
},
|
| 981 |
+
{
|
| 982 |
+
"lead_hours": 7,
|
| 983 |
+
"target_utc": "2026-05-09T02:00:00+00:00",
|
| 984 |
+
"target_local": "2026-05-09T01:00:00-01:00",
|
| 985 |
+
"temperature_2m_c": 4.140122413635254,
|
| 986 |
+
"relative_humidity_2m_pct": 94.25415802001953,
|
| 987 |
+
"apparent_temperature_c": 0.5866508483886719,
|
| 988 |
+
"precipitation_mm": 0.13218756020069122,
|
| 989 |
+
"pressure_msl_hpa": 1005.855712890625,
|
| 990 |
+
"surface_pressure_hpa": 973.7844848632812,
|
| 991 |
+
"cloud_cover_pct": 95.55270385742188,
|
| 992 |
+
"wind_speed_10m_kmh": 12.77564811706543,
|
| 993 |
+
"rain_probability": 0.8421469330787659,
|
| 994 |
+
"weather_class": 5,
|
| 995 |
+
"weather_class_name": "class_5",
|
| 996 |
+
"weather_class_probabilities": {
|
| 997 |
+
"class_0": 0.009295819327235222,
|
| 998 |
+
"class_1": 0.20261473953723907,
|
| 999 |
+
"class_2": 0.012845687568187714,
|
| 1000 |
+
"class_3": 0.21367891132831573,
|
| 1001 |
+
"class_4": 0.11506513506174088,
|
| 1002 |
+
"class_5": 0.4464803636074066,
|
| 1003 |
+
"class_6": 1.9363311366760172e-05
|
| 1004 |
+
}
|
| 1005 |
+
},
|
| 1006 |
+
{
|
| 1007 |
+
"lead_hours": 8,
|
| 1008 |
+
"target_utc": "2026-05-09T03:00:00+00:00",
|
| 1009 |
+
"target_local": "2026-05-09T02:00:00-01:00",
|
| 1010 |
+
"temperature_2m_c": 3.953939437866211,
|
| 1011 |
+
"relative_humidity_2m_pct": 94.34648895263672,
|
| 1012 |
+
"apparent_temperature_c": 0.3805828094482422,
|
| 1013 |
+
"precipitation_mm": 0.11994519084692001,
|
| 1014 |
+
"pressure_msl_hpa": 1005.9537353515625,
|
| 1015 |
+
"surface_pressure_hpa": 973.9803466796875,
|
| 1016 |
+
"cloud_cover_pct": 95.32868957519531,
|
| 1017 |
+
"wind_speed_10m_kmh": 12.735028266906738,
|
| 1018 |
+
"rain_probability": 0.8208134174346924,
|
| 1019 |
+
"weather_class": 5,
|
| 1020 |
+
"weather_class_name": "class_5",
|
| 1021 |
+
"weather_class_probabilities": {
|
| 1022 |
+
"class_0": 0.011135051026940346,
|
| 1023 |
+
"class_1": 0.21503449976444244,
|
| 1024 |
+
"class_2": 0.015187171287834644,
|
| 1025 |
+
"class_3": 0.18286095559597015,
|
| 1026 |
+
"class_4": 0.1143169179558754,
|
| 1027 |
+
"class_5": 0.46144354343414307,
|
| 1028 |
+
"class_6": 2.182190291932784e-05
|
| 1029 |
+
}
|
| 1030 |
+
},
|
| 1031 |
+
{
|
| 1032 |
+
"lead_hours": 9,
|
| 1033 |
+
"target_utc": "2026-05-09T04:00:00+00:00",
|
| 1034 |
+
"target_local": "2026-05-09T03:00:00-01:00",
|
| 1035 |
+
"temperature_2m_c": 3.826430320739746,
|
| 1036 |
+
"relative_humidity_2m_pct": 94.16539001464844,
|
| 1037 |
+
"apparent_temperature_c": 0.16225242614746094,
|
| 1038 |
+
"precipitation_mm": 0.11211992800235748,
|
| 1039 |
+
"pressure_msl_hpa": 1006.1436767578125,
|
| 1040 |
+
"surface_pressure_hpa": 974.2029418945312,
|
| 1041 |
+
"cloud_cover_pct": 94.6148681640625,
|
| 1042 |
+
"wind_speed_10m_kmh": 12.761141777038574,
|
| 1043 |
+
"rain_probability": 0.8099679350852966,
|
| 1044 |
+
"weather_class": 5,
|
| 1045 |
+
"weather_class_name": "class_5",
|
| 1046 |
+
"weather_class_probabilities": {
|
| 1047 |
+
"class_0": 0.013121353462338448,
|
| 1048 |
+
"class_1": 0.23102521896362305,
|
| 1049 |
+
"class_2": 0.017765367403626442,
|
| 1050 |
+
"class_3": 0.1780213713645935,
|
| 1051 |
+
"class_4": 0.12005121260881424,
|
| 1052 |
+
"class_5": 0.4399879574775696,
|
| 1053 |
+
"class_6": 2.7478810807224363e-05
|
| 1054 |
+
}
|
| 1055 |
+
},
|
| 1056 |
+
{
|
| 1057 |
+
"lead_hours": 10,
|
| 1058 |
+
"target_utc": "2026-05-09T05:00:00+00:00",
|
| 1059 |
+
"target_local": "2026-05-09T04:00:00-01:00",
|
| 1060 |
+
"temperature_2m_c": 3.8089590072631836,
|
| 1061 |
+
"relative_humidity_2m_pct": 93.53528594970703,
|
| 1062 |
+
"apparent_temperature_c": 0.12103080749511719,
|
| 1063 |
+
"precipitation_mm": 0.10691206157207489,
|
| 1064 |
+
"pressure_msl_hpa": 1006.42529296875,
|
| 1065 |
+
"surface_pressure_hpa": 974.4669189453125,
|
| 1066 |
+
"cloud_cover_pct": 93.8226318359375,
|
| 1067 |
+
"wind_speed_10m_kmh": 12.700864791870117,
|
| 1068 |
+
"rain_probability": 0.797008216381073,
|
| 1069 |
+
"weather_class": 5,
|
| 1070 |
+
"weather_class_name": "class_5",
|
| 1071 |
+
"weather_class_probabilities": {
|
| 1072 |
+
"class_0": 0.014465805143117905,
|
| 1073 |
+
"class_1": 0.22260957956314087,
|
| 1074 |
+
"class_2": 0.018675586208701134,
|
| 1075 |
+
"class_3": 0.15951745212078094,
|
| 1076 |
+
"class_4": 0.10494350641965866,
|
| 1077 |
+
"class_5": 0.47975844144821167,
|
| 1078 |
+
"class_6": 2.9636566978297196e-05
|
| 1079 |
+
}
|
| 1080 |
+
},
|
| 1081 |
+
{
|
| 1082 |
+
"lead_hours": 11,
|
| 1083 |
+
"target_utc": "2026-05-09T06:00:00+00:00",
|
| 1084 |
+
"target_local": "2026-05-09T05:00:00-01:00",
|
| 1085 |
+
"temperature_2m_c": 3.9785900115966797,
|
| 1086 |
+
"relative_humidity_2m_pct": 92.22869110107422,
|
| 1087 |
+
"apparent_temperature_c": 0.24558448791503906,
|
| 1088 |
+
"precipitation_mm": 0.10196752846240997,
|
| 1089 |
+
"pressure_msl_hpa": 1006.7659301757812,
|
| 1090 |
+
"surface_pressure_hpa": 974.8555297851562,
|
| 1091 |
+
"cloud_cover_pct": 92.74380493164062,
|
| 1092 |
+
"wind_speed_10m_kmh": 12.71017837524414,
|
| 1093 |
+
"rain_probability": 0.7881969213485718,
|
| 1094 |
+
"weather_class": 5,
|
| 1095 |
+
"weather_class_name": "class_5",
|
| 1096 |
+
"weather_class_probabilities": {
|
| 1097 |
+
"class_0": 0.01727476716041565,
|
| 1098 |
+
"class_1": 0.232261523604393,
|
| 1099 |
+
"class_2": 0.019182473421096802,
|
| 1100 |
+
"class_3": 0.15716883540153503,
|
| 1101 |
+
"class_4": 0.10425136238336563,
|
| 1102 |
+
"class_5": 0.46981269121170044,
|
| 1103 |
+
"class_6": 4.833983985008672e-05
|
| 1104 |
+
}
|
| 1105 |
+
},
|
| 1106 |
+
{
|
| 1107 |
+
"lead_hours": 12,
|
| 1108 |
+
"target_utc": "2026-05-09T07:00:00+00:00",
|
| 1109 |
+
"target_local": "2026-05-09T06:00:00-01:00",
|
| 1110 |
+
"temperature_2m_c": 4.317435264587402,
|
| 1111 |
+
"relative_humidity_2m_pct": 90.45832824707031,
|
| 1112 |
+
"apparent_temperature_c": 0.6276102066040039,
|
| 1113 |
+
"precipitation_mm": 0.09439859539270401,
|
| 1114 |
+
"pressure_msl_hpa": 1007.0864868164062,
|
| 1115 |
+
"surface_pressure_hpa": 975.1940307617188,
|
| 1116 |
+
"cloud_cover_pct": 91.2315673828125,
|
| 1117 |
+
"wind_speed_10m_kmh": 12.740204811096191,
|
| 1118 |
+
"rain_probability": 0.7812836170196533,
|
| 1119 |
+
"weather_class": 5,
|
| 1120 |
+
"weather_class_name": "class_5",
|
| 1121 |
+
"weather_class_probabilities": {
|
| 1122 |
+
"class_0": 0.019589632749557495,
|
| 1123 |
+
"class_1": 0.23847728967666626,
|
| 1124 |
+
"class_2": 0.020689163357019424,
|
| 1125 |
+
"class_3": 0.159035325050354,
|
| 1126 |
+
"class_4": 0.08879318088293076,
|
| 1127 |
+
"class_5": 0.47335243225097656,
|
| 1128 |
+
"class_6": 6.291128374869004e-05
|
| 1129 |
+
}
|
| 1130 |
+
}
|
| 1131 |
+
],
|
| 1132 |
+
"sanity": {
|
| 1133 |
+
"sequence_shape": [
|
| 1134 |
+
72,
|
| 1135 |
+
22
|
| 1136 |
+
],
|
| 1137 |
+
"finite_features": true
|
| 1138 |
+
}
|
| 1139 |
+
}
|
| 1140 |
+
```
|
| 1141 |
+
|
| 1142 |
+
### Note
|
| 1143 |
+
In observed outputs, the model is often within **1°C** of the actual value, which is **0.7** more than Hweh-6M.
|
| 1144 |
+
|
| 1145 |
+
Furthermore, you can pass locations that are not present in the model’s location embedding table. We’ve observed that the model can generalize to out-of-distribution (OOD) cities, with an estimated accuracy drop of only about 2–5%. However, this figure is an estimate and does not reflect a true ground-truth measurement.
|
| 1146 |
+
|
| 1147 |
+
## Use Cases
|
| 1148 |
+
|
| 1149 |
+
Intended for:
|
| 1150 |
+
|
| 1151 |
+
1. Backup to API
|
| 1152 |
+
2. Offline forecasting if you have the data
|
| 1153 |
+
3. Research
|
| 1154 |
+
4. Or more simply, for fun
|
| 1155 |
+
|
| 1156 |
+
Not intended for:
|
| 1157 |
+
|
| 1158 |
+
1. Safety-critical forecasting (aviation, emergency response)
|
| 1159 |
+
2. Replacing meteorological or API services
|
| 1160 |
+
|
| 1161 |
+
## Limitations
|
| 1162 |
+
|
| 1163 |
+
1. The model is not perfectly accurate and will produce approximate forecasts rather than exact real-world weather conditions.
|
| 1164 |
+
2. Prediction accuracy decreases as the forecast horizon increases up to 12 hours.
|
| 1165 |
+
3. Performance may degrade on unseen or underrepresented geographic regions and climate types.
|
| 1166 |
+
4. The model does not enforce physical laws of atmospheric dynamics and may produce physically inconsistent outputs.
|
| 1167 |
+
5. Forecast quality is sensitive to the quality and completeness of input weather data.
|
| 1168 |
+
6. Rare or extreme weather events are underrepresented in training data and may be poorly predicted.
|
| 1169 |
+
7. Weather class outputs are simplified and do not capture fine-grained meteorological distinctions.
|
| 1170 |
+
|
| 1171 |
+
# Inference
|
| 1172 |
+
|
| 1173 |
+
```python
|
| 1174 |
+
#!/usr/bin/env python3
|
| 1175 |
+
from __future__ import annotations
|
| 1176 |
+
|
| 1177 |
+
import json
|
| 1178 |
+
import time
|
| 1179 |
+
from pathlib import Path
|
| 1180 |
+
from typing import Any
|
| 1181 |
+
|
| 1182 |
+
import numpy as np
|
| 1183 |
+
import pandas as pd
|
| 1184 |
+
import requests
|
| 1185 |
+
import torch
|
| 1186 |
+
from transformers import AutoConfig, AutoModel
|
| 1187 |
+
from zoneinfo import ZoneInfo
|
| 1188 |
+
|
| 1189 |
+
# ----------------------------
|
| 1190 |
+
# Change these values here
|
| 1191 |
+
# ----------------------------
|
| 1192 |
+
MODEL_ID = r"Harley-ml/Hweh-446k" # HF repo id or local path
|
| 1193 |
+
CITY = "New York"
|
| 1194 |
+
SEQUENCE_META_PATH = "Harley-ml/Hweh-446k/weather_sequences.metadata.json"
|
| 1195 |
+
CONTEXT_HOURS = 72
|
| 1196 |
+
FORECAST_HOURS = 12
|
| 1197 |
+
DEVICE = None # "cpu", "cuda", "cuda:0", or None for auto
|
| 1198 |
+
|
| 1199 |
+
API_BASE_URL = "https://api.open-meteo.com/v1/forecast"
|
| 1200 |
+
MAX_RETRIES = 6
|
| 1201 |
+
REQUEST_TIMEOUT_S = 60
|
| 1202 |
+
|
| 1203 |
+
HOURLY_VARS = [
|
| 1204 |
+
"temperature_2m",
|
| 1205 |
+
"relative_humidity_2m",
|
| 1206 |
+
"apparent_temperature",
|
| 1207 |
+
"precipitation",
|
| 1208 |
+
"weather_code",
|
| 1209 |
+
"pressure_msl",
|
| 1210 |
+
"surface_pressure",
|
| 1211 |
+
"cloud_cover",
|
| 1212 |
+
"visibility",
|
| 1213 |
+
"wind_speed_10m",
|
| 1214 |
+
"wind_direction_10m",
|
| 1215 |
+
]
|
| 1216 |
+
|
| 1217 |
+
WEATHER_CODE_BUCKETS = 7
|
| 1218 |
+
TEMP_SCALE = 50.0
|
| 1219 |
+
HUMIDITY_SCALE = 100.0
|
| 1220 |
+
WIND_SCALE = 100.0
|
| 1221 |
+
|
| 1222 |
+
# ----------------------------
|
| 1223 |
+
# City metadata (82 locations)
|
| 1224 |
+
# ----------------------------
|
| 1225 |
+
CITY_SPECS: dict[str, dict[str, Any]] = {
|
| 1226 |
+
"Seattle": {"location_id": "1", "latitude": 47.6062, "longitude": -122.3321, "continent": "North America", "climate_tag": "temperate_oceanic", "elevation": 56},
|
| 1227 |
+
"Portland": {"location_id": "2", "latitude": 45.5152, "longitude": -122.6784, "continent": "North America", "climate_tag": "temperate_oceanic", "elevation": 15},
|
| 1228 |
+
"San Francisco": {"location_id": "3", "latitude": 37.7749, "longitude": -122.4194, "continent": "North America", "climate_tag": "foggy_mediterranean", "elevation": 16},
|
| 1229 |
+
"Los Angeles": {"location_id": "4", "latitude": 34.0522, "longitude": -118.2437, "continent": "North America", "climate_tag": "sunny_mediterranean", "elevation": 71},
|
| 1230 |
+
"Denver": {"location_id": "5", "latitude": 39.7392, "longitude": -104.9903, "continent": "North America", "climate_tag": "semi_arid_highland", "elevation": 1609},
|
| 1231 |
+
"Chicago": {"location_id": "6", "latitude": 41.8781, "longitude": -87.6298, "continent": "North America", "climate_tag": "humid_continental", "elevation": 181},
|
| 1232 |
+
"Dallas": {"location_id": "7", "latitude": 32.7767, "longitude": -96.7970, "continent": "North America", "climate_tag": "hot_subhumid", "elevation": 131},
|
| 1233 |
+
"Atlanta": {"location_id": "8", "latitude": 33.7490, "longitude": -84.3880, "continent": "North America", "climate_tag": "humid_subtropical", "elevation": 320},
|
| 1234 |
+
"New York": {"location_id": "9", "latitude": 40.7128, "longitude": -74.0060, "continent": "North America", "climate_tag": "humid_subtropical", "elevation": 10},
|
| 1235 |
+
"Miami": {"location_id": "10", "latitude": 25.7617, "longitude": -80.1918, "continent": "North America", "climate_tag": "tropical_humid", "elevation": 2},
|
| 1236 |
+
"Phoenix": {"location_id": "11", "latitude": 33.4484, "longitude": -112.0740, "continent": "North America", "climate_tag": "hot_arid", "elevation": 331},
|
| 1237 |
+
"Salt Lake City": {"location_id": "12", "latitude": 40.7608, "longitude": -111.8910, "continent": "North America", "climate_tag": "semi_arid", "elevation": 1288},
|
| 1238 |
+
"Anchorage": {"location_id": "13", "latitude": 61.2181, "longitude": -149.9003, "continent": "North America", "climate_tag": "subarctic_snowy", "elevation": 31},
|
| 1239 |
+
"Minneapolis": {"location_id": "14", "latitude": 44.9778, "longitude": -93.2650, "continent": "North America", "climate_tag": "cold_snowy", "elevation": 264},
|
| 1240 |
+
"Toronto": {"location_id": "15", "latitude": 43.6532, "longitude": -79.3832, "continent": "North America", "climate_tag": "humid_continental", "elevation": 76},
|
| 1241 |
+
"Montreal": {"location_id": "16", "latitude": 45.5017, "longitude": -73.5673, "continent": "North America", "climate_tag": "cold_snowy", "elevation": 233},
|
| 1242 |
+
"Vancouver": {"location_id": "17", "latitude": 49.2827, "longitude": -123.1207, "continent": "North America", "climate_tag": "temperate_oceanic", "elevation": 70},
|
| 1243 |
+
"Mexico City": {"location_id": "18", "latitude": 19.4326, "longitude": -99.1332, "continent": "North America", "climate_tag": "highland_subtropical", "elevation": 2240},
|
| 1244 |
+
"Havana": {"location_id": "19", "latitude": 23.1136, "longitude": -82.3666, "continent": "North America", "climate_tag": "tropical_humid", "elevation": 59},
|
| 1245 |
+
"San Juan": {"location_id": "20", "latitude": 18.4655, "longitude": -66.1057, "continent": "North America", "climate_tag": "tropical_humid", "elevation": 8},
|
| 1246 |
+
|
| 1247 |
+
"Lima": {"location_id": "21", "latitude": -12.0464, "longitude": -77.0428, "continent": "South America", "climate_tag": "coastal_arid", "elevation": 154},
|
| 1248 |
+
"Santiago": {"location_id": "22", "latitude": -33.4489, "longitude": -70.6693, "continent": "South America", "climate_tag": "mediterranean", "elevation": 520},
|
| 1249 |
+
"Buenos Aires": {"location_id": "23", "latitude": -34.6037, "longitude": -58.3816, "continent": "South America", "climate_tag": "humid_subtropical", "elevation": 25},
|
| 1250 |
+
"Bogotá": {"location_id": "24", "latitude": 4.7110, "longitude": -74.0721, "continent": "South America", "climate_tag": "highland_cool", "elevation": 2640},
|
| 1251 |
+
"Quito": {"location_id": "25", "latitude": -0.1807, "longitude": -78.4678, "continent": "South America", "climate_tag": "highland_equatorial", "elevation": 2850},
|
| 1252 |
+
"Caracas": {"location_id": "26", "latitude": 10.4806, "longitude": -66.9036, "continent": "South America", "climate_tag": "tropical_humid", "elevation": 900},
|
| 1253 |
+
"Rio de Janeiro": {"location_id": "27", "latitude": -22.9068, "longitude": -43.1729, "continent": "South America", "climate_tag": "tropical_humid", "elevation": 5},
|
| 1254 |
+
"São Paulo": {"location_id": "28", "latitude": -23.5505, "longitude": -46.6333, "continent": "South America", "climate_tag": "humid_subtropical", "elevation": 760},
|
| 1255 |
+
"La Paz": {"location_id": "29", "latitude": -16.4897, "longitude": -68.1193, "continent": "South America", "climate_tag": "highland_cold", "elevation": 3640},
|
| 1256 |
+
"Cusco": {"location_id": "30", "latitude": -13.5319, "longitude": -71.9675, "continent": "South America", "climate_tag": "highland_cool", "elevation": 3399},
|
| 1257 |
+
"Montevideo": {"location_id": "31", "latitude": -34.9011, "longitude": -56.1645, "continent": "South America", "climate_tag": "temperate_oceanic", "elevation": 43},
|
| 1258 |
+
"Asunción": {"location_id": "32", "latitude": -25.2637, "longitude": -57.5759, "continent": "South America", "climate_tag": "humid_subtropical", "elevation": 43},
|
| 1259 |
+
"Manaus": {"location_id": "33", "latitude": -3.1190, "longitude": -60.0217, "continent": "South America", "climate_tag": "tropical_humid", "elevation": 92},
|
| 1260 |
+
"Recife": {"location_id": "34", "latitude": -8.0476, "longitude": -34.8770, "continent": "South America", "climate_tag": "tropical_coastal", "elevation": 4},
|
| 1261 |
+
"Punta Arenas": {"location_id": "35", "latitude": -53.1638, "longitude": -70.9171, "continent": "South America", "climate_tag": "cold_windy", "elevation": 34},
|
| 1262 |
+
|
| 1263 |
+
"London": {"location_id": "36", "latitude": 51.5074, "longitude": -0.1278, "continent": "Europe", "climate_tag": "temperate_oceanic", "elevation": 11},
|
| 1264 |
+
"Paris": {"location_id": "37", "latitude": 48.8566, "longitude": 2.3522, "continent": "Europe", "climate_tag": "temperate_oceanic", "elevation": 35},
|
| 1265 |
+
"Madrid": {"location_id": "38", "latitude": 40.4168, "longitude": -3.7038, "continent": "Europe", "climate_tag": "hot_summer_mediterranean", "elevation": 667},
|
| 1266 |
+
"Rome": {"location_id": "39", "latitude": 41.9028, "longitude": 12.4964, "continent": "Europe", "climate_tag": "hot_summer_mediterranean", "elevation": 21},
|
| 1267 |
+
"Berlin": {"location_id": "40", "latitude": 52.52, "longitude": 13.4050, "continent": "Europe", "climate_tag": "temperate_continental", "elevation": 34},
|
| 1268 |
+
"Stockholm": {"location_id": "41", "latitude": 59.3293, "longitude": 18.0686, "continent": "Europe", "climate_tag": "cold_marine", "elevation": 28},
|
| 1269 |
+
"Oslo": {"location_id": "42", "latitude": 59.9139, "longitude": 10.7522, "continent": "Europe", "climate_tag": "cold_snowy", "elevation": 23},
|
| 1270 |
+
"Helsinki": {"location_id": "43", "latitude": 60.1699, "longitude": 24.9384, "continent": "Europe", "climate_tag": "cold_snowy", "elevation": 25},
|
| 1271 |
+
"Reykjavik": {"location_id": "44", "latitude": 64.1466, "longitude": -21.9426, "continent": "Europe", "climate_tag": "cold_windy", "elevation": 12},
|
| 1272 |
+
"Kyiv": {"location_id": "45", "latitude": 50.4501, "longitude": 30.5234, "continent": "Europe", "climate_tag": "humid_continental", "elevation": 179},
|
| 1273 |
+
"Lisbon": {"location_id": "46", "latitude": 38.7223, "longitude": -9.1393, "continent": "Europe", "climate_tag": "sunny_mediterranean", "elevation": 7},
|
| 1274 |
+
"Athens": {"location_id": "47", "latitude": 37.9838, "longitude": 23.7275, "continent": "Europe", "climate_tag": "sunny_mediterranean", "elevation": 70},
|
| 1275 |
+
"Zurich": {"location_id": "48", "latitude": 47.3769, "longitude": 8.5417, "continent": "Europe", "climate_tag": "temperate_continental", "elevation": 408},
|
| 1276 |
+
"Dublin": {"location_id": "49", "latitude": 53.3498, "longitude": -6.2603, "continent": "Europe", "climate_tag": "temperate_oceanic", "elevation": 20},
|
| 1277 |
+
"Vienna": {"location_id": "50", "latitude": 48.2082, "longitude": 16.3738, "continent": "Europe", "climate_tag": "temperate_continental", "elevation": 171},
|
| 1278 |
+
|
| 1279 |
+
"Dubai": {"location_id": "51", "latitude": 25.2048, "longitude": 55.2708, "continent": "Asia", "climate_tag": "hot_arid", "elevation": 16},
|
| 1280 |
+
"Riyadh": {"location_id": "52", "latitude": 24.7136, "longitude": 46.6753, "continent": "Asia", "climate_tag": "hot_arid", "elevation": 612},
|
| 1281 |
+
"Delhi": {"location_id": "53", "latitude": 28.7041, "longitude": 77.1025, "continent": "Asia", "climate_tag": "hot_semi_arid", "elevation": 216},
|
| 1282 |
+
"Mumbai": {"location_id": "54", "latitude": 19.0760, "longitude": 72.8777, "continent": "Asia", "climate_tag": "tropical_humid", "elevation": 14},
|
| 1283 |
+
"Bangkok": {"location_id": "55", "latitude": 13.7563, "longitude": 100.5018, "continent": "Asia", "climate_tag": "tropical_monsoon", "elevation": 2},
|
| 1284 |
+
"Singapore": {"location_id": "56", "latitude": 1.3521, "longitude": 103.8198, "continent": "Asia", "climate_tag": "tropical_humid", "elevation": 15},
|
| 1285 |
+
"Tokyo": {"location_id": "57", "latitude": 35.6762, "longitude": 139.6503, "continent": "Asia", "climate_tag": "humid_subtropical", "elevation": 40},
|
| 1286 |
+
"Seoul": {"location_id": "58", "latitude": 37.5665, "longitude": 126.9780, "continent": "Asia", "climate_tag": "humid_continental", "elevation": 38},
|
| 1287 |
+
"Ulaanbaatar": {"location_id": "59", "latitude": 47.8864, "longitude": 106.9057, "continent": "Asia", "climate_tag": "cold_steppe", "elevation": 1350},
|
| 1288 |
+
"Kathmandu": {"location_id": "60", "latitude": 27.7172, "longitude": 85.3240, "continent": "Asia", "climate_tag": "highland_subtropical", "elevation": 1400},
|
| 1289 |
+
"Chiang Mai": {"location_id": "61", "latitude": 18.7883, "longitude": 98.9853, "continent": "Asia", "climate_tag": "tropical_seasonal", "elevation": 300},
|
| 1290 |
+
"Lhasa": {"location_id": "62", "latitude": 29.6520, "longitude": 91.1721, "continent": "Asia", "climate_tag": "high_altitude_cold", "elevation": 3656},
|
| 1291 |
+
"Jakarta": {"location_id": "63", "latitude": -6.2088, "longitude": 106.8456, "continent": "Asia", "climate_tag": "tropical_humid", "elevation": 8},
|
| 1292 |
+
"Manila": {"location_id": "64", "latitude": 14.5995, "longitude": 120.9842, "continent": "Asia", "climate_tag": "tropical_humid", "elevation": 16},
|
| 1293 |
+
"Karachi": {"location_id": "65", "latitude": 24.8607, "longitude": 67.0011, "continent": "Asia", "climate_tag": "hot_arid", "elevation": 10},
|
| 1294 |
+
|
| 1295 |
+
"Cairo": {"location_id": "66", "latitude": 30.0444, "longitude": 31.2357, "continent": "Africa", "climate_tag": "hot_arid", "elevation": 23},
|
| 1296 |
+
"Alexandria": {"location_id": "67", "latitude": 31.2001, "longitude": 29.9187, "continent": "Africa", "climate_tag": "coastal_mediterranean", "elevation": 5},
|
| 1297 |
+
"Casablanca": {"location_id": "68", "latitude": 33.5731, "longitude": -7.5898, "continent": "Africa", "climate_tag": "coastal_mediterranean", "elevation": 56},
|
| 1298 |
+
"Marrakech": {"location_id": "69", "latitude": 31.6295, "longitude": -7.9811, "continent": "Africa", "climate_tag": "hot_semi_arid", "elevation": 466},
|
| 1299 |
+
"Lagos": {"location_id": "70", "latitude": 6.5244, "longitude": 3.3792, "continent": "Africa", "climate_tag": "tropical_humid", "elevation": 41},
|
| 1300 |
+
"Nairobi": {"location_id": "71", "latitude": -1.2921, "longitude": 36.8219, "continent": "Africa", "climate_tag": "temperate_highland", "elevation": 1795},
|
| 1301 |
+
"Addis Ababa": {"location_id": "72", "latitude": 8.9806, "longitude": 38.7578, "continent": "Africa", "climate_tag": "temperate_highland", "elevation": 2355},
|
| 1302 |
+
"Cape Town": {"location_id": "73", "latitude": -33.9249, "longitude": 18.4241, "continent": "Africa", "climate_tag": "mediterranean", "elevation": 25},
|
| 1303 |
+
"Johannesburg": {"location_id": "74", "latitude": -26.2041, "longitude": 28.0473, "continent": "Africa", "climate_tag": "subtropical_highland", "elevation": 1753},
|
| 1304 |
+
"Windhoek": {"location_id": "75", "latitude": -22.5609, "longitude": 17.0658, "continent": "Africa", "climate_tag": "semi_arid", "elevation": 1650},
|
| 1305 |
+
"Accra": {"location_id": "76", "latitude": 5.6037, "longitude": -0.1870, "continent": "Africa", "climate_tag": "tropical_humid", "elevation": 61},
|
| 1306 |
+
"Kigali": {"location_id": "77", "latitude": -1.9441, "longitude": 30.0619, "continent": "Africa", "climate_tag": "highland_tropical", "elevation": 1567},
|
| 1307 |
+
"Tunis": {"location_id": "78", "latitude": 36.8065, "longitude": 10.1815, "continent": "Africa", "climate_tag": "mediterranean", "elevation": 4},
|
| 1308 |
+
"Dakar": {"location_id": "79", "latitude": -14.7167, "longitude": -17.4677, "continent": "Africa", "climate_tag": "hot_coastal", "elevation": 25},
|
| 1309 |
+
"Mombasa": {"location_id": "80", "latitude": -4.0435, "longitude": 39.6682, "continent": "Africa", "climate_tag": "tropical_coastal", "elevation": 17},
|
| 1310 |
+
|
| 1311 |
+
"Sydney": {"location_id": "81", "latitude": -33.8688, "longitude": 151.2093, "continent": "Oceania", "climate_tag": "humid_subtropical", "elevation": 58},
|
| 1312 |
+
"Melbourne": {"location_id": "82", "latitude": -37.8136, "longitude": 144.9631, "continent": "Oceania", "climate_tag": "temperate_oceanic", "elevation": 31},
|
| 1313 |
+
}
|
| 1314 |
+
|
| 1315 |
+
CITY_TIMEZONES: dict[str, str] = {
|
| 1316 |
+
"Seattle": "America/Los_Angeles",
|
| 1317 |
+
"Portland": "America/Los_Angeles",
|
| 1318 |
+
"San Francisco": "America/Los_Angeles",
|
| 1319 |
+
"Los Angeles": "America/Los_Angeles",
|
| 1320 |
+
"Denver": "America/Denver",
|
| 1321 |
+
"Chicago": "America/Chicago",
|
| 1322 |
+
"Dallas": "America/Chicago",
|
| 1323 |
+
"Atlanta": "America/New_York",
|
| 1324 |
+
"New York": "America/New_York",
|
| 1325 |
+
"Miami": "America/New_York",
|
| 1326 |
+
"Phoenix": "America/Phoenix",
|
| 1327 |
+
"Salt Lake City": "America/Denver",
|
| 1328 |
+
"Anchorage": "America/Anchorage",
|
| 1329 |
+
"Minneapolis": "America/Chicago",
|
| 1330 |
+
"Toronto": "America/Toronto",
|
| 1331 |
+
"Montreal": "America/Toronto",
|
| 1332 |
+
"Vancouver": "America/Vancouver",
|
| 1333 |
+
"Mexico City": "America/Mexico_City",
|
| 1334 |
+
"Havana": "America/Havana",
|
| 1335 |
+
"San Juan": "America/Puerto_Rico",
|
| 1336 |
+
"Lima": "America/Lima",
|
| 1337 |
+
"Santiago": "America/Santiago",
|
| 1338 |
+
"Buenos Aires": "America/Argentina/Buenos_Aires",
|
| 1339 |
+
"Bogotá": "America/Bogota",
|
| 1340 |
+
"Quito": "America/Guayaquil",
|
| 1341 |
+
"Caracas": "America/Caracas",
|
| 1342 |
+
"Rio de Janeiro": "America/Sao_Paulo",
|
| 1343 |
+
"São Paulo": "America/Sao_Paulo",
|
| 1344 |
+
"La Paz": "America/La_Paz",
|
| 1345 |
+
"Cusco": "America/Lima",
|
| 1346 |
+
"Montevideo": "America/Montevideo",
|
| 1347 |
+
"Asunción": "America/Asuncion",
|
| 1348 |
+
"Manaus": "America/Manaus",
|
| 1349 |
+
"Recife": "America/Recife",
|
| 1350 |
+
"Punta Arenas": "America/Punta_Arenas",
|
| 1351 |
+
"London": "Europe/London",
|
| 1352 |
+
"Paris": "Europe/Paris",
|
| 1353 |
+
"Madrid": "Europe/Madrid",
|
| 1354 |
+
"Rome": "Europe/Rome",
|
| 1355 |
+
"Berlin": "Europe/Berlin",
|
| 1356 |
+
"Stockholm": "Europe/Stockholm",
|
| 1357 |
+
"Oslo": "Europe/Oslo",
|
| 1358 |
+
"Helsinki": "Europe/Helsinki",
|
| 1359 |
+
"Reykjavik": "Atlantic/Reykjavik",
|
| 1360 |
+
"Kyiv": "Europe/Kyiv",
|
| 1361 |
+
"Lisbon": "Europe/Lisbon",
|
| 1362 |
+
"Athens": "Europe/Athens",
|
| 1363 |
+
"Zurich": "Europe/Zurich",
|
| 1364 |
+
"Dublin": "Europe/Dublin",
|
| 1365 |
+
"Vienna": "Europe/Vienna",
|
| 1366 |
+
"Dubai": "Asia/Dubai",
|
| 1367 |
+
"Riyadh": "Asia/Riyadh",
|
| 1368 |
+
"Delhi": "Asia/Kolkata",
|
| 1369 |
+
"Mumbai": "Asia/Kolkata",
|
| 1370 |
+
"Bangkok": "Asia/Bangkok",
|
| 1371 |
+
"Singapore": "Asia/Singapore",
|
| 1372 |
+
"Tokyo": "Asia/Tokyo",
|
| 1373 |
+
"Seoul": "Asia/Seoul",
|
| 1374 |
+
"Ulaanbaatar": "Asia/Ulaanbaatar",
|
| 1375 |
+
"Kathmandu": "Asia/Kathmandu",
|
| 1376 |
+
"Chiang Mai": "Asia/Bangkok",
|
| 1377 |
+
"Lhasa": "Asia/Shanghai",
|
| 1378 |
+
"Jakarta": "Asia/Jakarta",
|
| 1379 |
+
"Manila": "Asia/Manila",
|
| 1380 |
+
"Karachi": "Asia/Karachi",
|
| 1381 |
+
"Cairo": "Africa/Cairo",
|
| 1382 |
+
"Alexandria": "Africa/Cairo",
|
| 1383 |
+
"Casablanca": "Africa/Casablanca",
|
| 1384 |
+
"Marrakech": "Africa/Casablanca",
|
| 1385 |
+
"Lagos": "Africa/Lagos",
|
| 1386 |
+
"Nairobi": "Africa/Nairobi",
|
| 1387 |
+
"Addis Ababa": "Africa/Addis_Ababa",
|
| 1388 |
+
"Cape Town": "Africa/Johannesburg",
|
| 1389 |
+
"Johannesburg": "Africa/Johannesburg",
|
| 1390 |
+
"Windhoek": "Africa/Windhoek",
|
| 1391 |
+
"Accra": "Africa/Accra",
|
| 1392 |
+
"Kigali": "Africa/Kigali",
|
| 1393 |
+
"Tunis": "Africa/Tunis",
|
| 1394 |
+
"Dakar": "Africa/Dakar",
|
| 1395 |
+
"Mombasa": "Africa/Nairobi",
|
| 1396 |
+
"Sydney": "Australia/Sydney",
|
| 1397 |
+
"Melbourne": "Australia/Melbourne",
|
| 1398 |
+
}
|
| 1399 |
+
|
| 1400 |
+
# ----------------------------
|
| 1401 |
+
# Helpers
|
| 1402 |
+
# ----------------------------
|
| 1403 |
+
def weather_code_to_bucket(code) -> int:
|
| 1404 |
+
if code is None:
|
| 1405 |
+
return 1
|
| 1406 |
+
try:
|
| 1407 |
+
if pd.isna(code):
|
| 1408 |
+
return 1
|
| 1409 |
+
except Exception:
|
| 1410 |
+
pass
|
| 1411 |
+
|
| 1412 |
+
code = int(code)
|
| 1413 |
+
if code == 0:
|
| 1414 |
+
return 0
|
| 1415 |
+
if code in (1, 2, 3):
|
| 1416 |
+
return 1
|
| 1417 |
+
if code in (45, 48):
|
| 1418 |
+
return 2
|
| 1419 |
+
if code in (51, 53, 55, 56, 57):
|
| 1420 |
+
return 3
|
| 1421 |
+
if code in (61, 63, 65, 66, 67, 80, 81, 82):
|
| 1422 |
+
return 4
|
| 1423 |
+
if code in (71, 73, 75, 77, 85, 86):
|
| 1424 |
+
return 5
|
| 1425 |
+
if code in (95, 96, 99):
|
| 1426 |
+
return 6
|
| 1427 |
+
return 1
|
| 1428 |
+
|
| 1429 |
+
|
| 1430 |
+
def cyc(x: np.ndarray, period: float) -> tuple[np.ndarray, np.ndarray]:
|
| 1431 |
+
angle = 2.0 * np.pi * (x / period)
|
| 1432 |
+
return np.sin(angle), np.cos(angle)
|
| 1433 |
+
|
| 1434 |
+
|
| 1435 |
+
def clamp_array(x: np.ndarray, lo: float | None = None, hi: float | None = None) -> np.ndarray:
|
| 1436 |
+
return np.clip(x, lo, hi)
|
| 1437 |
+
|
| 1438 |
+
|
| 1439 |
+
def request_with_backoff(session: requests.Session, url: str, params: dict[str, Any]) -> dict[str, Any]:
|
| 1440 |
+
last_exc: Exception | None = None
|
| 1441 |
+
for attempt in range(MAX_RETRIES):
|
| 1442 |
+
try:
|
| 1443 |
+
resp = session.get(url, params=params, timeout=REQUEST_TIMEOUT_S)
|
| 1444 |
+
if resp.status_code == 429:
|
| 1445 |
+
retry_after = resp.headers.get("Retry-After")
|
| 1446 |
+
sleep_s = float(retry_after) if retry_after else min(60.0, 2**attempt)
|
| 1447 |
+
print(f"Rate limited. Sleeping {sleep_s:.1f}s and retrying.", flush=True)
|
| 1448 |
+
time.sleep(sleep_s)
|
| 1449 |
+
continue
|
| 1450 |
+
resp.raise_for_status()
|
| 1451 |
+
return resp.json()
|
| 1452 |
+
except Exception as e:
|
| 1453 |
+
last_exc = e
|
| 1454 |
+
sleep_s = min(60.0, 2**attempt)
|
| 1455 |
+
print(f"Request failed: {e}. Sleeping {sleep_s:.1f}s and retrying.", flush=True)
|
| 1456 |
+
time.sleep(sleep_s)
|
| 1457 |
+
raise RuntimeError(f"Failed after {MAX_RETRIES} retries: {params}") from last_exc
|
| 1458 |
+
|
| 1459 |
+
|
| 1460 |
+
def load_sequence_meta(path: str) -> dict[str, Any]:
|
| 1461 |
+
p = Path(path)
|
| 1462 |
+
if not p.exists():
|
| 1463 |
+
return {"location_to_id": {}}
|
| 1464 |
+
with open(p, "r", encoding="utf-8") as f:
|
| 1465 |
+
meta = json.load(f)
|
| 1466 |
+
meta.setdefault("location_to_id", {})
|
| 1467 |
+
return meta
|
| 1468 |
+
|
| 1469 |
+
|
| 1470 |
+
def load_model():
|
| 1471 |
+
config = AutoConfig.from_pretrained(MODEL_ID, trust_remote_code=True)
|
| 1472 |
+
model = AutoModel.from_pretrained(MODEL_ID, config=config, trust_remote_code=True)
|
| 1473 |
+
model.eval()
|
| 1474 |
+
return model, config
|
| 1475 |
+
|
| 1476 |
+
|
| 1477 |
+
def fetch_recent_history(city: str, context_hours: int) -> pd.DataFrame:
|
| 1478 |
+
if city not in CITY_SPECS:
|
| 1479 |
+
raise ValueError(f"Unknown city: {city}")
|
| 1480 |
+
|
| 1481 |
+
spec = CITY_SPECS[city]
|
| 1482 |
+
session = requests.Session()
|
| 1483 |
+
session.headers.update({"User-Agent": "Mozilla/5.0"})
|
| 1484 |
+
|
| 1485 |
+
params = {
|
| 1486 |
+
"latitude": spec["latitude"],
|
| 1487 |
+
"longitude": spec["longitude"],
|
| 1488 |
+
"hourly": ",".join(HOURLY_VARS),
|
| 1489 |
+
"timezone": "UTC",
|
| 1490 |
+
"temperature_unit": "celsius",
|
| 1491 |
+
"wind_speed_unit": "kmh",
|
| 1492 |
+
"precipitation_unit": "mm",
|
| 1493 |
+
"past_hours": int(context_hours) + 2,
|
| 1494 |
+
"forecast_hours": 0,
|
| 1495 |
+
}
|
| 1496 |
+
|
| 1497 |
+
data = request_with_backoff(session, API_BASE_URL, params=params)
|
| 1498 |
+
hourly = data.get("hourly", {})
|
| 1499 |
+
if "time" not in hourly:
|
| 1500 |
+
raise ValueError(f"No hourly data returned for {city}: {data}")
|
| 1501 |
+
|
| 1502 |
+
df = pd.DataFrame(hourly)
|
| 1503 |
+
if df.empty:
|
| 1504 |
+
raise ValueError(f"Empty hourly response for {city}.")
|
| 1505 |
+
|
| 1506 |
+
df["time"] = pd.to_datetime(df["time"], errors="coerce", utc=True)
|
| 1507 |
+
df = df.dropna(subset=["time"]).sort_values("time").drop_duplicates(subset=["time"]).reset_index(drop=True)
|
| 1508 |
+
|
| 1509 |
+
needed = HOURLY_VARS
|
| 1510 |
+
missing = [c for c in needed if c not in df.columns]
|
| 1511 |
+
if missing:
|
| 1512 |
+
raise ValueError(f"Missing hourly columns in API response: {missing}")
|
| 1513 |
+
|
| 1514 |
+
for c in needed:
|
| 1515 |
+
df[c] = pd.to_numeric(df[c], errors="coerce")
|
| 1516 |
+
|
| 1517 |
+
df["weather_code"] = df["weather_code"].fillna(1)
|
| 1518 |
+
df["precipitation"] = df["precipitation"].fillna(0.0)
|
| 1519 |
+
|
| 1520 |
+
for c in [
|
| 1521 |
+
"temperature_2m",
|
| 1522 |
+
"relative_humidity_2m",
|
| 1523 |
+
"apparent_temperature",
|
| 1524 |
+
"precipitation",
|
| 1525 |
+
"pressure_msl",
|
| 1526 |
+
"surface_pressure",
|
| 1527 |
+
"cloud_cover",
|
| 1528 |
+
"visibility",
|
| 1529 |
+
"wind_speed_10m",
|
| 1530 |
+
"wind_direction_10m",
|
| 1531 |
+
]:
|
| 1532 |
+
df[c] = df[c].interpolate(limit_direction="both").ffill().bfill()
|
| 1533 |
+
|
| 1534 |
+
now_utc = pd.Timestamp.now(tz="UTC")
|
| 1535 |
+
df = df[df["time"] <= now_utc].copy()
|
| 1536 |
+
|
| 1537 |
+
if len(df) < context_hours:
|
| 1538 |
+
raise ValueError(f"Not enough observed rows: got {len(df)}, need {context_hours}")
|
| 1539 |
+
|
| 1540 |
+
return df.tail(context_hours).reset_index(drop=True)
|
| 1541 |
+
|
| 1542 |
+
|
| 1543 |
+
def build_single_sequence(df: pd.DataFrame) -> np.ndarray:
|
| 1544 |
+
hour = df["time"].dt.hour.to_numpy()
|
| 1545 |
+
doy = df["time"].dt.dayofyear.to_numpy()
|
| 1546 |
+
|
| 1547 |
+
hour_sin, hour_cos = cyc(hour.astype(float), 24.0)
|
| 1548 |
+
doy_sin, doy_cos = cyc(doy.astype(float), 365.25)
|
| 1549 |
+
|
| 1550 |
+
temp = np.nan_to_num(df["temperature_2m"].astype(float).to_numpy(), nan=0.0)
|
| 1551 |
+
humidity = np.nan_to_num(df["relative_humidity_2m"].astype(float).to_numpy(), nan=0.0)
|
| 1552 |
+
apparent = np.nan_to_num(df["apparent_temperature"].astype(float).to_numpy(), nan=0.0)
|
| 1553 |
+
precip = np.nan_to_num(df["precipitation"].astype(float).to_numpy(), nan=0.0)
|
| 1554 |
+
pressure = np.nan_to_num(df["pressure_msl"].astype(float).to_numpy(), nan=0.0)
|
| 1555 |
+
surface_pressure = np.nan_to_num(df["surface_pressure"].astype(float).to_numpy(), nan=0.0)
|
| 1556 |
+
cloud_cover = np.nan_to_num(df["cloud_cover"].astype(float).to_numpy(), nan=0.0)
|
| 1557 |
+
visibility = np.nan_to_num(df["visibility"].astype(float).to_numpy(), nan=0.0)
|
| 1558 |
+
wind = np.nan_to_num(df["wind_speed_10m"].astype(float).to_numpy(), nan=0.0)
|
| 1559 |
+
wind_dir = np.nan_to_num(df["wind_direction_10m"].astype(float).to_numpy(), nan=0.0)
|
| 1560 |
+
|
| 1561 |
+
humidity = clamp_array(humidity, 0.0, 100.0)
|
| 1562 |
+
cloud_cover = clamp_array(cloud_cover, 0.0, 100.0)
|
| 1563 |
+
precip = clamp_array(precip, 0.0, None)
|
| 1564 |
+
wind = clamp_array(wind, 0.0, None)
|
| 1565 |
+
visibility = clamp_array(visibility, 0.0, None)
|
| 1566 |
+
|
| 1567 |
+
wind_dir_sin, wind_dir_cos = cyc(wind_dir, 360.0)
|
| 1568 |
+
weather_bucket = df["weather_code"].fillna(1).apply(weather_code_to_bucket).to_numpy(dtype=np.int64)
|
| 1569 |
+
|
| 1570 |
+
rows = []
|
| 1571 |
+
for i in range(len(df)):
|
| 1572 |
+
wc_oh = np.zeros(WEATHER_CODE_BUCKETS, dtype=np.float32)
|
| 1573 |
+
wc_oh[weather_bucket[i]] = 1.0
|
| 1574 |
+
|
| 1575 |
+
row = np.concatenate(
|
| 1576 |
+
[
|
| 1577 |
+
np.array(
|
| 1578 |
+
[
|
| 1579 |
+
temp[i] / TEMP_SCALE,
|
| 1580 |
+
humidity[i] / HUMIDITY_SCALE,
|
| 1581 |
+
apparent[i] / TEMP_SCALE,
|
| 1582 |
+
np.log1p(max(precip[i], 0.0)) / 3.0,
|
| 1583 |
+
pressure[i] / 1100.0,
|
| 1584 |
+
surface_pressure[i] / 1100.0,
|
| 1585 |
+
cloud_cover[i] / 100.0,
|
| 1586 |
+
visibility[i] / 50000.0,
|
| 1587 |
+
wind[i] / WIND_SCALE,
|
| 1588 |
+
wind_dir_sin[i],
|
| 1589 |
+
wind_dir_cos[i],
|
| 1590 |
+
hour_sin[i],
|
| 1591 |
+
hour_cos[i],
|
| 1592 |
+
doy_sin[i],
|
| 1593 |
+
doy_cos[i],
|
| 1594 |
+
],
|
| 1595 |
+
dtype=np.float32,
|
| 1596 |
+
),
|
| 1597 |
+
wc_oh,
|
| 1598 |
+
]
|
| 1599 |
+
)
|
| 1600 |
+
rows.append(row)
|
| 1601 |
+
|
| 1602 |
+
seq = np.asarray(rows, dtype=np.float32)
|
| 1603 |
+
|
| 1604 |
+
if not np.isfinite(seq).all():
|
| 1605 |
+
bad = np.argwhere(~np.isfinite(seq))
|
| 1606 |
+
raise ValueError(f"Non-finite values remain in sequence at positions like: {bad[:10].tolist()}")
|
| 1607 |
+
|
| 1608 |
+
return seq
|
| 1609 |
+
|
| 1610 |
+
|
| 1611 |
+
def to_iso(ts: pd.Timestamp, tz_name: str | None = None) -> str:
|
| 1612 |
+
if tz_name:
|
| 1613 |
+
try:
|
| 1614 |
+
return ts.tz_convert(ZoneInfo(tz_name)).isoformat()
|
| 1615 |
+
except Exception:
|
| 1616 |
+
pass
|
| 1617 |
+
return ts.isoformat()
|
| 1618 |
+
|
| 1619 |
+
|
| 1620 |
+
def get_logits(out):
|
| 1621 |
+
if isinstance(out, dict) and "logits" in out:
|
| 1622 |
+
return out["logits"]
|
| 1623 |
+
if hasattr(out, "logits"):
|
| 1624 |
+
return out.logits
|
| 1625 |
+
return out
|
| 1626 |
+
|
| 1627 |
+
|
| 1628 |
+
def resolve_location_index(seq_meta: dict[str, Any], city_location_id: str) -> int:
|
| 1629 |
+
location_to_id = seq_meta.get("location_to_id", {})
|
| 1630 |
+
|
| 1631 |
+
if city_location_id in location_to_id:
|
| 1632 |
+
return int(location_to_id[city_location_id])
|
| 1633 |
+
|
| 1634 |
+
try:
|
| 1635 |
+
as_int = int(city_location_id)
|
| 1636 |
+
if as_int in location_to_id:
|
| 1637 |
+
return int(location_to_id[as_int])
|
| 1638 |
+
if str(as_int) in location_to_id:
|
| 1639 |
+
return int(location_to_id[str(as_int)])
|
| 1640 |
+
except Exception:
|
| 1641 |
+
pass
|
| 1642 |
+
|
| 1643 |
+
for unk_key in ("UNK", "<UNK>", "unknown", "UNKNOWN"):
|
| 1644 |
+
if unk_key in location_to_id:
|
| 1645 |
+
return int(location_to_id[unk_key])
|
| 1646 |
+
|
| 1647 |
+
return 0
|
| 1648 |
+
|
| 1649 |
+
|
| 1650 |
+
def predict():
|
| 1651 |
+
seq_meta = load_sequence_meta(SEQUENCE_META_PATH)
|
| 1652 |
+
model, config = load_model()
|
| 1653 |
+
|
| 1654 |
+
if CITY not in CITY_SPECS:
|
| 1655 |
+
raise ValueError(f"Unknown city: {CITY}")
|
| 1656 |
+
|
| 1657 |
+
if CONTEXT_HOURS <= 0:
|
| 1658 |
+
raise ValueError("CONTEXT_HOURS must be > 0")
|
| 1659 |
+
|
| 1660 |
+
if hasattr(config, "seq_len") and int(config.seq_len) != CONTEXT_HOURS:
|
| 1661 |
+
raise ValueError(f"Set CONTEXT_HOURS to {int(config.seq_len)} for this model.")
|
| 1662 |
+
|
| 1663 |
+
city_spec = CITY_SPECS[CITY]
|
| 1664 |
+
city_tz = CITY_TIMEZONES.get(CITY, "UTC")
|
| 1665 |
+
model_location_id = resolve_location_index(seq_meta, str(city_spec["location_id"]))
|
| 1666 |
+
|
| 1667 |
+
df = fetch_recent_history(CITY, CONTEXT_HOURS)
|
| 1668 |
+
seq = build_single_sequence(df)
|
| 1669 |
+
|
| 1670 |
+
X = torch.from_numpy(seq).unsqueeze(0)
|
| 1671 |
+
loc = torch.tensor([model_location_id], dtype=torch.long)
|
| 1672 |
+
|
| 1673 |
+
target_device = torch.device(
|
| 1674 |
+
DEVICE if DEVICE else ("cuda" if torch.cuda.is_available() else "cpu")
|
| 1675 |
+
)
|
| 1676 |
+
model = model.to(target_device)
|
| 1677 |
+
X = X.to(target_device)
|
| 1678 |
+
loc = loc.to(target_device)
|
| 1679 |
+
|
| 1680 |
+
weather_class_names = getattr(config, "weather_class_names", None)
|
| 1681 |
+
if not weather_class_names:
|
| 1682 |
+
weather_class_names = [f"class_{i}" for i in range(int(getattr(config, "num_weather_classes", 7)))]
|
| 1683 |
+
|
| 1684 |
+
with torch.no_grad():
|
| 1685 |
+
out = model(X=X, location_id=loc)
|
| 1686 |
+
logits = get_logits(out)
|
| 1687 |
+
|
| 1688 |
+
(
|
| 1689 |
+
temp_pred,
|
| 1690 |
+
humidity_pred,
|
| 1691 |
+
apparent_pred,
|
| 1692 |
+
precip_pred,
|
| 1693 |
+
sea_level_pressure_pred,
|
| 1694 |
+
surface_pressure_pred,
|
| 1695 |
+
cloud_cover_pred,
|
| 1696 |
+
wind_pred,
|
| 1697 |
+
wind_dir_sin_pred,
|
| 1698 |
+
wind_dir_cos_pred,
|
| 1699 |
+
rain_logit,
|
| 1700 |
+
weather_logits,
|
| 1701 |
+
) = logits
|
| 1702 |
+
|
| 1703 |
+
temp_pred = temp_pred.squeeze(0).detach().cpu().numpy()
|
| 1704 |
+
humidity_pred = humidity_pred.squeeze(0).detach().cpu().numpy()
|
| 1705 |
+
apparent_pred = apparent_pred.squeeze(0).detach().cpu().numpy()
|
| 1706 |
+
precip_pred = precip_pred.squeeze(0).detach().cpu().numpy()
|
| 1707 |
+
sea_level_pressure_pred = sea_level_pressure_pred.squeeze(0).detach().cpu().numpy()
|
| 1708 |
+
surface_pressure_pred = surface_pressure_pred.squeeze(0).detach().cpu().numpy()
|
| 1709 |
+
cloud_cover_pred = cloud_cover_pred.squeeze(0).detach().cpu().numpy()
|
| 1710 |
+
wind_pred = wind_pred.squeeze(0).detach().cpu().numpy()
|
| 1711 |
+
rain_prob = torch.sigmoid(rain_logit).squeeze(0).detach().cpu().numpy()
|
| 1712 |
+
weather_probs = torch.softmax(weather_logits, dim=-1).squeeze(0).detach().cpu().numpy()
|
| 1713 |
+
weather_idx = np.argmax(weather_probs, axis=-1).astype(np.int64)
|
| 1714 |
+
|
| 1715 |
+
humidity_pred = np.clip(humidity_pred, 0.0, 100.0)
|
| 1716 |
+
cloud_cover_pred = np.clip(cloud_cover_pred, 0.0, 100.0)
|
| 1717 |
+
precip_pred = np.clip(precip_pred, 0.0, None)
|
| 1718 |
+
wind_pred = np.clip(wind_pred, 0.0, None)
|
| 1719 |
+
rain_prob = np.clip(rain_prob, 0.0, 1.0)
|
| 1720 |
+
|
| 1721 |
+
context_start = df["time"].iloc[0]
|
| 1722 |
+
context_end = df["time"].iloc[-1]
|
| 1723 |
+
requested_at_utc = pd.Timestamp.now(tz="UTC")
|
| 1724 |
+
|
| 1725 |
+
horizon = min(
|
| 1726 |
+
int(FORECAST_HOURS),
|
| 1727 |
+
int(temp_pred.shape[0]),
|
| 1728 |
+
int(humidity_pred.shape[0]),
|
| 1729 |
+
int(weather_idx.shape[0]),
|
| 1730 |
+
)
|
| 1731 |
+
|
| 1732 |
+
forecast = []
|
| 1733 |
+
for lead in range(1, horizon + 1):
|
| 1734 |
+
target_time = context_end + pd.Timedelta(hours=lead)
|
| 1735 |
+
idx = lead - 1
|
| 1736 |
+
w_idx = int(weather_idx[idx])
|
| 1737 |
+
|
| 1738 |
+
forecast.append(
|
| 1739 |
+
{
|
| 1740 |
+
"lead_hours": lead,
|
| 1741 |
+
"target_utc": target_time.isoformat(),
|
| 1742 |
+
"target_local": to_iso(target_time, city_tz),
|
| 1743 |
+
"temperature_2m_c": float(temp_pred[idx]),
|
| 1744 |
+
"relative_humidity_2m_pct": float(humidity_pred[idx]),
|
| 1745 |
+
"apparent_temperature_c": float(apparent_pred[idx]),
|
| 1746 |
+
"precipitation_mm": float(precip_pred[idx]),
|
| 1747 |
+
"pressure_msl_hpa": float(sea_level_pressure_pred[idx]),
|
| 1748 |
+
"surface_pressure_hpa": float(surface_pressure_pred[idx]),
|
| 1749 |
+
"cloud_cover_pct": float(cloud_cover_pred[idx]),
|
| 1750 |
+
"wind_speed_10m_kmh": float(wind_pred[idx]),
|
| 1751 |
+
"rain_probability": float(rain_prob[idx]),
|
| 1752 |
+
"weather_class": w_idx,
|
| 1753 |
+
"weather_class_name": weather_class_names[w_idx] if w_idx < len(weather_class_names) else f"class_{w_idx}",
|
| 1754 |
+
"weather_class_probabilities": {
|
| 1755 |
+
name: float(prob) for name, prob in zip(weather_class_names, weather_probs[idx])
|
| 1756 |
+
},
|
| 1757 |
+
}
|
| 1758 |
+
)
|
| 1759 |
+
|
| 1760 |
+
result = {
|
| 1761 |
+
"city": CITY,
|
| 1762 |
+
"location_id": str(city_spec["location_id"]),
|
| 1763 |
+
"model_location_id": int(model_location_id),
|
| 1764 |
+
"data_source": "open-meteo forecast api (past-hours context only)",
|
| 1765 |
+
"requested_at_utc": requested_at_utc.isoformat(),
|
| 1766 |
+
"context": {
|
| 1767 |
+
"hours": int(len(df)),
|
| 1768 |
+
"start_utc": context_start.isoformat(),
|
| 1769 |
+
"end_utc": context_end.isoformat(),
|
| 1770 |
+
"start_local": to_iso(context_start, city_tz),
|
| 1771 |
+
"end_local": to_iso(context_end, city_tz),
|
| 1772 |
+
},
|
| 1773 |
+
"model": {
|
| 1774 |
+
"model_id": MODEL_ID,
|
| 1775 |
+
"encoder_type": getattr(config, "encoder_type", None),
|
| 1776 |
+
"seq_len": int(getattr(config, "seq_len", CONTEXT_HOURS)),
|
| 1777 |
+
"input_dim": int(getattr(config, "input_dim", seq.shape[1])),
|
| 1778 |
+
"num_weather_classes": int(getattr(config, "num_weather_classes", len(weather_class_names))),
|
| 1779 |
+
},
|
| 1780 |
+
"forecast": forecast,
|
| 1781 |
+
"sanity": {
|
| 1782 |
+
"sequence_shape": list(seq.shape),
|
| 1783 |
+
"finite_features": bool(np.isfinite(seq).all()),
|
| 1784 |
+
},
|
| 1785 |
+
}
|
| 1786 |
+
|
| 1787 |
+
print(json.dumps(result, indent=2))
|
| 1788 |
+
|
| 1789 |
+
|
| 1790 |
+
if __name__ == "__main__":
|
| 1791 |
+
predict()
|
| 1792 |
+
```
|
| 1793 |
+
|
| 1794 |
+
|
| 1795 |
+
## Citation
|
| 1796 |
+
|
| 1797 |
+
```bibtex
|
| 1798 |
+
@misc{Hweh-6m,
|
| 1799 |
+
title = {Hweh-446k: Knowledge Distillation in Short-Term Multivariate Weather Forecasting},
|
| 1800 |
+
author = {Paul Courneya; Harley-ml},
|
| 1801 |
+
year = {2026},
|
| 1802 |
+
url = {https://huggingface.co/Harley-ml/DistilHweh-446k}
|
| 1803 |
+
}
|
| 1804 |
+
```
|