Time Series Forecasting
Transformers
Safetensors
fela-ts
feature-extraction
fela
fourier-neural-operator
fno
cpu
on-device
edge
time-series
forecasting
energy
electricity
custom_code
Instructions to use lowdown-labs/fela-timeseries with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use lowdown-labs/fela-timeseries with Transformers:
# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("lowdown-labs/fela-timeseries", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
Commit ·
3a6f8cc
0
Parent(s):
initial commit
Browse files- .gitattributes +1 -0
- .gitignore +6 -0
- LICENSE +474 -0
- README.md +161 -0
- config.json +32 -0
- configuration_ts.py +27 -0
- model.safetensors +3 -0
- modeling.py +157 -0
- modeling_ts.py +56 -0
- streaming/manifest.json +14 -0
- streaming/model_fp16.safetensors +3 -0
- train.py +137 -0
.gitattributes
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
.gitignore
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
.ruff_cache/
|
| 2 |
+
.venv/
|
| 3 |
+
__pycache__/
|
| 4 |
+
*.swp
|
| 5 |
+
*.kate-swp
|
| 6 |
+
*~
|
LICENSE
ADDED
|
@@ -0,0 +1,474 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Lowdown Labs Lovely License 1.0 (LLLL-1.0)
|
| 2 |
+
|
| 3 |
+
Everything in this repository (the model weights, the configuration, and the code) is
|
| 4 |
+
released by Lowdown Labs under two licenses that apply at the same time. To use this work
|
| 5 |
+
you must comply with BOTH of them. Where a term in one is stricter than the other, the
|
| 6 |
+
stricter term controls. "Lowdown Labs Lovely License 1.0" is a convenience name for this
|
| 7 |
+
exact pair; it is not a new legal instrument.
|
| 8 |
+
|
| 9 |
+
SPDX-License-Identifier: CC-BY-NC-4.0 AND LicenseRef-Hippocratic-3.0
|
| 10 |
+
|
| 11 |
+
Commercial licensing. The grant below is non-commercial only. Commercial licenses are
|
| 12 |
+
sold separately by Lowdown Labs on a per-customer basis. To use this work, its weights, or
|
| 13 |
+
its outputs for any commercial purpose, contact Lowdown Labs to purchase a commercial
|
| 14 |
+
license. A commercial license does not remove the Hippocratic ethical-use obligations in
|
| 15 |
+
Part 2; those apply to commercial licensees as well.
|
| 16 |
+
|
| 17 |
+
==============================================================================
|
| 18 |
+
Part 1 of 2. Creative Commons Attribution-NonCommercial 4.0 International (CC BY-NC 4.0)
|
| 19 |
+
==============================================================================
|
| 20 |
+
|
| 21 |
+
You may share and adapt this work for non-commercial purposes, with attribution to
|
| 22 |
+
Lowdown Labs. Commercial use is not granted under this license.
|
| 23 |
+
|
| 24 |
+
Full legal text: https://creativecommons.org/licenses/by-nc/4.0/legalcode
|
| 25 |
+
Plain-language summary: https://creativecommons.org/licenses/by-nc/4.0/
|
| 26 |
+
SPDX-License-Identifier: CC-BY-NC-4.0
|
| 27 |
+
|
| 28 |
+
==============================================================================
|
| 29 |
+
Part 2 of 2. The Hippocratic License 3.0 (ethical use)
|
| 30 |
+
==============================================================================
|
| 31 |
+
|
| 32 |
+
Module set enabled: bds, cl, eco, extr, ffd, law, media, mil, my, soc, sup, sv, usta.
|
| 33 |
+
Canonical build: https://firstdonoharm.dev/build/?modules=bds,cl,eco,extr,ffd,law,media,mil,my,soc,sup,sv,usta
|
| 34 |
+
|
| 35 |
+
The verbatim official Hippocratic License 3.0 text for exactly this module set follows,
|
| 36 |
+
between the markers.
|
| 37 |
+
|
| 38 |
+
--------------------- BEGIN OFFICIAL HIPPOCRATIC LICENSE 3.0 TEXT ---------------------
|
| 39 |
+
|
| 40 |
+
HIPPOCRATIC LICENSE
|
| 41 |
+
|
| 42 |
+
Version 3.0, October 2021
|
| 43 |
+
|
| 44 |
+
https://firstdonoharm.dev/version/3/0/bds-cl-eco-extr-ffd-law-media-mil-my-soc-sup-sv-usta.txt
|
| 45 |
+
|
| 46 |
+
TERMS AND CONDITIONS
|
| 47 |
+
|
| 48 |
+
TERMS AND CONDITIONS FOR USE, COPY, MODIFICATION, PREPARATION OF DERIVATIVE
|
| 49 |
+
WORK, REPRODUCTION, AND DISTRIBUTION:
|
| 50 |
+
|
| 51 |
+
1. DEFINITIONS:
|
| 52 |
+
|
| 53 |
+
This section defines certain terms used throughout this license agreement.
|
| 54 |
+
|
| 55 |
+
1.1. “License” means the terms and conditions, as stated herein, for use, copy,
|
| 56 |
+
modification, preparation of derivative work, reproduction, and distribution of
|
| 57 |
+
Software (as defined below).
|
| 58 |
+
|
| 59 |
+
1.2. “Licensor” means the copyright and/or patent owner or entity authorized by
|
| 60 |
+
the copyright and/or patent owner that is granting the License.
|
| 61 |
+
|
| 62 |
+
1.3. “Licensee” means the individual or entity exercising permissions granted by
|
| 63 |
+
this License, including the use, copy, modification, preparation of derivative
|
| 64 |
+
work, reproduction, and distribution of Software (as defined below).
|
| 65 |
+
|
| 66 |
+
1.4. “Software” means any copyrighted work, including but not limited to
|
| 67 |
+
software code, authored by Licensor and made available under this License.
|
| 68 |
+
|
| 69 |
+
1.5. “Supply Chain” means the sequence of processes involved in the production
|
| 70 |
+
and/or distribution of a commodity, good, or service offered by the Licensee.
|
| 71 |
+
|
| 72 |
+
1.6. “Supply Chain Impacted Party” or “Supply Chain Impacted Parties” means any
|
| 73 |
+
person(s) directly impacted by any of Licensee’s Supply Chain, including the
|
| 74 |
+
practices of all persons or entities within the Supply Chain prior to a good or
|
| 75 |
+
service reaching the Licensee.
|
| 76 |
+
|
| 77 |
+
1.7. “Duty of Care” is defined by its use in tort law, delict law, and/or
|
| 78 |
+
similar bodies of law closely related to tort and/or delict law, including
|
| 79 |
+
without limitation, a requirement to act with the watchfulness, attention,
|
| 80 |
+
caution, and prudence that a reasonable person in the same or similar
|
| 81 |
+
circumstances would use towards any Supply Chain Impacted Party.
|
| 82 |
+
|
| 83 |
+
1.8. “Worker” is defined to include any and all permanent, temporary, and agency
|
| 84 |
+
workers, as well as piece-rate, salaried, hourly paid, legal young (minors),
|
| 85 |
+
part-time, night, and migrant workers.
|
| 86 |
+
|
| 87 |
+
2. INTELLECTUAL PROPERTY GRANTS:
|
| 88 |
+
|
| 89 |
+
This section identifies intellectual property rights granted to a Licensee.
|
| 90 |
+
|
| 91 |
+
2.1. Grant of Copyright License: Subject to the terms and conditions of this
|
| 92 |
+
License, Licensor hereby grants to Licensee a worldwide, non-exclusive,
|
| 93 |
+
no-charge, royalty-free copyright license to use, copy, modify, prepare
|
| 94 |
+
derivative work, reproduce, or distribute the Software, Licensor authored
|
| 95 |
+
modified software, or other work derived from the Software.
|
| 96 |
+
|
| 97 |
+
2.2. Grant of Patent License: Subject to the terms and conditions of this
|
| 98 |
+
License, Licensor hereby grants Licensee a worldwide, non-exclusive, no-charge,
|
| 99 |
+
royalty-free patent license to make, have made, use, offer to sell, sell,
|
| 100 |
+
import, and otherwise transfer Software.
|
| 101 |
+
|
| 102 |
+
3. ETHICAL STANDARDS:
|
| 103 |
+
|
| 104 |
+
This section lists conditions the Licensee must comply with in order to have
|
| 105 |
+
rights under this License.
|
| 106 |
+
|
| 107 |
+
The rights granted to the Licensee by this License are expressly made subject to
|
| 108 |
+
the Licensee’s ongoing compliance with the following conditions:
|
| 109 |
+
|
| 110 |
+
* 3.1. The Licensee SHALL NOT, whether directly or indirectly, through agents
|
| 111 |
+
or assigns:
|
| 112 |
+
|
| 113 |
+
* 3.1.1. Infringe upon any person’s right to life or security of person,
|
| 114 |
+
engage in extrajudicial killings, or commit murder, without lawful cause
|
| 115 |
+
(See Article 3, United Nations Universal Declaration of Human Rights;
|
| 116 |
+
Article 6, International Covenant on Civil and Political Rights)
|
| 117 |
+
|
| 118 |
+
* 3.1.2. Hold any person in slavery, servitude, or forced labor (See Article
|
| 119 |
+
4, United Nations Universal Declaration of Human Rights; Article 8,
|
| 120 |
+
International Covenant on Civil and Political Rights);
|
| 121 |
+
|
| 122 |
+
* 3.1.3. Contribute to the institution of slavery, slave trading, forced
|
| 123 |
+
labor, or unlawful child labor (See Article 4, United Nations Universal
|
| 124 |
+
Declaration of Human Rights; Article 8, International Covenant on Civil and
|
| 125 |
+
Political Rights);
|
| 126 |
+
|
| 127 |
+
* 3.1.4. Torture or subject any person to cruel, inhumane, or degrading
|
| 128 |
+
treatment or punishment (See Article 5, United Nations Universal
|
| 129 |
+
Declaration of Human Rights; Article 7, International Covenant on Civil and
|
| 130 |
+
Political Rights);
|
| 131 |
+
|
| 132 |
+
* 3.1.5. Discriminate on the basis of sex, gender, sexual orientation, race,
|
| 133 |
+
ethnicity, nationality, religion, caste, age, medical disability or
|
| 134 |
+
impairment, and/or any other like circumstances (See Article 7, United
|
| 135 |
+
Nations Universal Declaration of Human Rights; Article 2, International
|
| 136 |
+
Covenant on Economic, Social and Cultural Rights; Article 26, International
|
| 137 |
+
Covenant on Civil and Political Rights);
|
| 138 |
+
|
| 139 |
+
* 3.1.6. Prevent any person from exercising his/her/their right to seek an
|
| 140 |
+
effective remedy by a competent court or national tribunal (including
|
| 141 |
+
domestic judicial systems, international courts, arbitration bodies, and
|
| 142 |
+
other adjudicating bodies) for actions violating the fundamental rights
|
| 143 |
+
granted to him/her/them by applicable constitutions, applicable laws, or by
|
| 144 |
+
this License (See Article 8, United Nations Universal Declaration of Human
|
| 145 |
+
Rights; Articles 9 and 14, International Covenant on Civil and Political
|
| 146 |
+
Rights);
|
| 147 |
+
|
| 148 |
+
* 3.1.7. Subject any person to arbitrary arrest, detention, or exile (See
|
| 149 |
+
Article 9, United Nations Universal Declaration of Human Rights; Article 9,
|
| 150 |
+
International Covenant on Civil and Political Rights);
|
| 151 |
+
|
| 152 |
+
* 3.1.8. Subject any person to arbitrary interference with a person’s
|
| 153 |
+
privacy, family, home, or correspondence without the express written
|
| 154 |
+
consent of the person (See Article 12, United Nations Universal Declaration
|
| 155 |
+
of Human Rights; Article 17, International Covenant on Civil and Political
|
| 156 |
+
Rights);
|
| 157 |
+
|
| 158 |
+
* 3.1.9. Arbitrarily deprive any person of his/her/their property (See
|
| 159 |
+
Article 17, United Nations Universal Declaration of Human Rights);
|
| 160 |
+
|
| 161 |
+
* 3.1.10. Forcibly remove indigenous peoples from their lands or territories
|
| 162 |
+
or take any action with the aim or effect of dispossessing indigenous
|
| 163 |
+
peoples from their lands, territories, or resources, including without
|
| 164 |
+
limitation the intellectual property or traditional knowledge of indigenous
|
| 165 |
+
peoples, without the free, prior, and informed consent of indigenous
|
| 166 |
+
peoples concerned (See Articles 8 and 10, United Nations Declaration on the
|
| 167 |
+
Rights of Indigenous Peoples);
|
| 168 |
+
* 3.1.11. Fossil Fuel Divestment: Be an individual or entity, or a
|
| 169 |
+
representative, agent, affiliate, successor, attorney, or assign of an
|
| 170 |
+
individual or entity, on the FFI Solutions Carbon Underground 200 list
|
| 171 |
+
[https://www.ffisolutions.com/research-analytics-index-solutions/research-screening/the-carbon-underground-200/?cn-reloaded=1];
|
| 172 |
+
|
| 173 |
+
* 3.1.12. Ecocide: Commit ecocide:
|
| 174 |
+
|
| 175 |
+
* 3.1.12.1. For the purpose of this section, “ecocide” means unlawful or
|
| 176 |
+
wanton acts committed with knowledge that there is a substantial
|
| 177 |
+
likelihood of severe and either widespread or long-term damage to the
|
| 178 |
+
environment being caused by those acts;
|
| 179 |
+
|
| 180 |
+
* 3.1.12.2. For the purpose of further defining ecocide and the terms
|
| 181 |
+
contained in the previous paragraph:
|
| 182 |
+
|
| 183 |
+
* 3.1.12.2.1. “Wanton” means with reckless disregard for damage which
|
| 184 |
+
would be clearly excessive in relation to the social and economic
|
| 185 |
+
benefits anticipated;
|
| 186 |
+
|
| 187 |
+
* 3.1.12.2.2. “Severe” means damage which involves very serious adverse
|
| 188 |
+
changes, disruption, or harm to any element of the environment,
|
| 189 |
+
including grave impacts on human life or natural, cultural, or
|
| 190 |
+
economic resources;
|
| 191 |
+
|
| 192 |
+
* 3.1.12.2.3. “Widespread” means damage which extends beyond a limited
|
| 193 |
+
geographic area, crosses state boundaries, or is suffered by an entire
|
| 194 |
+
ecosystem or species or a large number of human beings;
|
| 195 |
+
|
| 196 |
+
* 3.1.12.2.4. “Long-term” means damage which is irreversible or which
|
| 197 |
+
cannot be redressed through natural recovery within a reasonable
|
| 198 |
+
period of time; and
|
| 199 |
+
|
| 200 |
+
* 3.1.12.2.5. “Environment” means the earth, its biosphere, cryosphere,
|
| 201 |
+
lithosphere, hydrosphere, and atmosphere, as well as outer space
|
| 202 |
+
|
| 203 |
+
(See Section II, Independent Expert Panel for the Legal Definition of
|
| 204 |
+
Ecocide, Stop Ecocide Foundation and the Promise Institute for Human
|
| 205 |
+
Rights at UCLA School of Law, June 2021);
|
| 206 |
+
|
| 207 |
+
* 3.1.13. Extractive Industries: Be an individual or entity, or a
|
| 208 |
+
representative, agent, affiliate, successor, attorney, or assign of an
|
| 209 |
+
individual or entity, that engages in fossil fuel or mineral exploration,
|
| 210 |
+
extraction, development, or sale;
|
| 211 |
+
|
| 212 |
+
* 3.1.14. Boycott / Divestment / Sanctions: Be an individual or entity, or a
|
| 213 |
+
representative, agent, affiliate, successor, attorney, or assign of an
|
| 214 |
+
individual or entity, identified by the Boycott, Divestment, Sanctions
|
| 215 |
+
(“BDS”) movement on its website (https://bdsmovement.net/
|
| 216 |
+
[https://bdsmovement.net/] and
|
| 217 |
+
https://bdsmovement.net/get-involved/what-to-boycott
|
| 218 |
+
[https://bdsmovement.net/get-involved/what-to-boycott]) as a target for
|
| 219 |
+
boycott;
|
| 220 |
+
|
| 221 |
+
* 3.1.15. Myanmar: Be an individual or entity that:
|
| 222 |
+
|
| 223 |
+
* 3.1.15.1. engages in any commercial transactions with the
|
| 224 |
+
Myanmar/Burmese military junta; or
|
| 225 |
+
|
| 226 |
+
* 3.1.15.2. is a representative, agent, affiliate, successor, attorney, or
|
| 227 |
+
assign of the Myanmar/Burmese government;
|
| 228 |
+
|
| 229 |
+
* 3.1.16. US Tariff Act: Be an individual or entity:
|
| 230 |
+
|
| 231 |
+
* 3.1.16.1. which U.S. Customs and Border Protection (CBP) has currently
|
| 232 |
+
issued a Withhold Release Order (WRO) or finding against based on
|
| 233 |
+
reasonable suspicion of forced labor; or
|
| 234 |
+
|
| 235 |
+
* 3.1.16.2. that is a representative, agent, affiliate, successor,
|
| 236 |
+
attorney, or assign of an individual or entity that does business with
|
| 237 |
+
an individual or entity which currently has a WRO or finding from CBP
|
| 238 |
+
issued against it based on reasonable suspicion of forced labor;
|
| 239 |
+
|
| 240 |
+
* 3.1.17. Mass Surveillance: Be a government agency or multinational
|
| 241 |
+
corporation, or a representative, agent, affiliate, successor, attorney,
|
| 242 |
+
or assign of a government or multinational corporation, which participates
|
| 243 |
+
in mass surveillance programs;
|
| 244 |
+
|
| 245 |
+
* 3.1.18. Military Activities: Be an entity or a representative, agent,
|
| 246 |
+
affiliate, successor, attorney, or assign of an entity which conducts
|
| 247 |
+
military activities;
|
| 248 |
+
|
| 249 |
+
* 3.1.19. Law Enforcement: Be an individual or entity, or a representative,
|
| 250 |
+
agent, affiliate, successor, attorney, or assign of an individual or
|
| 251 |
+
entity, that provides good or services to, or otherwise enters into any
|
| 252 |
+
commercial contracts with, any local, state, or federal law enforcement
|
| 253 |
+
agency;
|
| 254 |
+
|
| 255 |
+
* 3.1.20. Media: Be an individual or entity, or a representative, agent,
|
| 256 |
+
affiliate, successor, attorney, or assign of an individual or entity, that
|
| 257 |
+
broadcasts messages promoting killing, torture, or other forms of extreme
|
| 258 |
+
violence;
|
| 259 |
+
|
| 260 |
+
* 3.1.21. Interfere with Workers’ free exercise of the right to organize and
|
| 261 |
+
associate (See Article 20, United Nations Universal Declaration of Human
|
| 262 |
+
Rights; C087 - Freedom of Association and Protection of the Right to
|
| 263 |
+
Organise Convention, 1948 (No. 87), International Labour Organization;
|
| 264 |
+
Article 8, International Covenant on Economic, Social and Cultural Rights);
|
| 265 |
+
and
|
| 266 |
+
|
| 267 |
+
* 3.1.22. Harm the environment in a manner inconsistent with local, state,
|
| 268 |
+
national, or international law.
|
| 269 |
+
|
| 270 |
+
* 3.2. The Licensee SHALL:
|
| 271 |
+
|
| 272 |
+
* 3.2.1. Social Auditing: Only use social auditing mechanisms that adhere to
|
| 273 |
+
Worker-Driven Social Responsibility Network’s Statement of Principles
|
| 274 |
+
(https://wsr-network.org/what-is-wsr/statement-of-principles/
|
| 275 |
+
[https://wsr-network.org/what-is-wsr/statement-of-principles/]) over
|
| 276 |
+
traditional social auditing mechanisms, to the extent the Licensee uses
|
| 277 |
+
any social auditing mechanisms at all;
|
| 278 |
+
|
| 279 |
+
* 3.2.2. Supply Chain: Provide clear, accessible supply chain data to the
|
| 280 |
+
public in accordance with the following conditions:
|
| 281 |
+
|
| 282 |
+
* 3.2.2.1. All data will be on Licensee’s website and/or, to the extent
|
| 283 |
+
Licensee is a representative, agent, affiliate, successor, attorney,
|
| 284 |
+
subsidiary, or assign, on Licensee’s principal’s or parent’s website or
|
| 285 |
+
some other online platform accessible to the public via an internet
|
| 286 |
+
search on a common internet search engine; and
|
| 287 |
+
|
| 288 |
+
* 3.2.2.2. Data published will include, where applicable, manufacturers,
|
| 289 |
+
top tier suppliers, subcontractors, cooperatives, component parts
|
| 290 |
+
producers, and farms;
|
| 291 |
+
|
| 292 |
+
* 3.2.3. Provide equal pay for equal work where the performance of such work
|
| 293 |
+
requires equal skill, effort, and responsibility, and which are performed
|
| 294 |
+
under similar working conditions, except where such payment is made
|
| 295 |
+
pursuant to:
|
| 296 |
+
|
| 297 |
+
* 3.2.3.1. A seniority system;
|
| 298 |
+
|
| 299 |
+
* 3.2.3.2. A merit system;
|
| 300 |
+
|
| 301 |
+
* 3.2.3.3. A system which measures earnings by quantity or quality of
|
| 302 |
+
production; or
|
| 303 |
+
|
| 304 |
+
* 3.2.3.4. A differential based on any other factor other than sex, gender,
|
| 305 |
+
sexual orientation, race, ethnicity, nationality, religion, caste, age,
|
| 306 |
+
medical disability or impairment, and/or any other like circumstances
|
| 307 |
+
(See 29 U.S.C.A. § 206(d)(1); Article 23, United Nations Universal
|
| 308 |
+
Declaration of Human Rights; Article 7, International Covenant on
|
| 309 |
+
Economic, Social and Cultural Rights; Article 26, International Covenant
|
| 310 |
+
on Civil and Political Rights); and
|
| 311 |
+
|
| 312 |
+
* 3.2.4. Allow for reasonable limitation of working hours and periodic
|
| 313 |
+
holidays with pay (See Article 24, United Nations Universal Declaration of
|
| 314 |
+
Human Rights; Article 7, International Covenant on Economic, Social and
|
| 315 |
+
Cultural Rights).
|
| 316 |
+
|
| 317 |
+
4. SUPPLY CHAIN IMPACTED PARTIES:
|
| 318 |
+
|
| 319 |
+
This section identifies additional individuals or entities that a Licensee could
|
| 320 |
+
harm as a result of violating the Ethical Standards section, the condition that
|
| 321 |
+
the Licensee must voluntarily accept a Duty of Care for those individuals or
|
| 322 |
+
entities, and the right to a private right of action that those individuals or
|
| 323 |
+
entities possess as a result of violations of the Ethical Standards section.
|
| 324 |
+
|
| 325 |
+
4.1. In addition to the above Ethical Standards, Licensee voluntarily accepts a
|
| 326 |
+
Duty of Care for Supply Chain Impacted Parties of this License, including
|
| 327 |
+
individuals and communities impacted by violations of the Ethical Standards. The
|
| 328 |
+
Duty of Care is breached when a provision within the Ethical Standards section
|
| 329 |
+
is violated by a Licensee, one of its successors or assigns, or by an individual
|
| 330 |
+
or entity that exists within the Supply Chain prior to a good or service
|
| 331 |
+
reaching the Licensee.
|
| 332 |
+
|
| 333 |
+
4.2. Breaches of the Duty of Care, as stated within this section, shall create a
|
| 334 |
+
private right of action, allowing any Supply Chain Impacted Party harmed by the
|
| 335 |
+
Licensee to take legal action against the Licensee in accordance with applicable
|
| 336 |
+
negligence laws, whether they be in tort law, delict law, and/or similar bodies
|
| 337 |
+
of law closely related to tort and/or delict law, regardless if Licensee is
|
| 338 |
+
directly responsible for the harms suffered by a Supply Chain Impacted Party.
|
| 339 |
+
Nothing in this section shall be interpreted to include acts committed by
|
| 340 |
+
individuals outside of the scope of his/her/their employment.
|
| 341 |
+
|
| 342 |
+
5. NOTICE: This section explains when a Licensee must notify others of the
|
| 343 |
+
License.
|
| 344 |
+
|
| 345 |
+
5.1. Distribution of Notice: Licensee must ensure that everyone who receives a
|
| 346 |
+
copy of or uses any part of Software from Licensee, with or without changes,
|
| 347 |
+
also receives the License and the copyright notice included with Software (and
|
| 348 |
+
if included by the Licensor, patent, trademark, and attribution notice).
|
| 349 |
+
Licensee must ensure that License is prominently displayed so that any
|
| 350 |
+
individual or entity seeking to download, copy, use, or otherwise receive any
|
| 351 |
+
part of Software from Licensee is notified of this License and its terms and
|
| 352 |
+
conditions. Licensee must cause any modified versions of the Software to carry
|
| 353 |
+
prominent notices stating that Licensee changed the Software.
|
| 354 |
+
|
| 355 |
+
5.2. Modified Software: Licensee is free to create modifications of the Software
|
| 356 |
+
and distribute only the modified portion created by Licensee, however, any
|
| 357 |
+
derivative work stemming from the Software or its code must be distributed
|
| 358 |
+
pursuant to this License, including this Notice provision.
|
| 359 |
+
|
| 360 |
+
5.3. Recipients as Licensees: Any individual or entity that uses, copies,
|
| 361 |
+
modifies, reproduces, distributes, or prepares derivative work based upon the
|
| 362 |
+
Software, all or part of the Software’s code, or a derivative work developed by
|
| 363 |
+
using the Software, including a portion of its code, is a Licensee as defined
|
| 364 |
+
above and is subject to the terms and conditions of this License.
|
| 365 |
+
|
| 366 |
+
6. REPRESENTATIONS AND WARRANTIES:
|
| 367 |
+
|
| 368 |
+
6.1. Disclaimer of Warranty: TO THE FULL EXTENT ALLOWED BY LAW, THIS SOFTWARE
|
| 369 |
+
COMES “AS IS,” WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED, AND LICENSOR SHALL NOT
|
| 370 |
+
BE LIABLE TO ANY PERSON OR ENTITY FOR ANY DAMAGES OR OTHER LIABILITY ARISING
|
| 371 |
+
FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THIS LICENSE, UNDER ANY
|
| 372 |
+
LEGAL CLAIM.
|
| 373 |
+
|
| 374 |
+
6.2. Limitation of Liability: LICENSEE SHALL HOLD LICENSOR HARMLESS AGAINST ANY
|
| 375 |
+
AND ALL CLAIMS, DEBTS, DUES, LIABILITIES, LIENS, CAUSES OF ACTION, DEMANDS,
|
| 376 |
+
OBLIGATIONS, DISPUTES, DAMAGES, LOSSES, EXPENSES, ATTORNEYS’ FEES, COSTS,
|
| 377 |
+
LIABILITIES, AND ALL OTHER CLAIMS OF EVERY KIND AND NATURE WHATSOEVER, WHETHER
|
| 378 |
+
KNOWN OR UNKNOWN, ANTICIPATED OR UNANTICIPATED, FORESEEN OR UNFORESEEN, ACCRUED
|
| 379 |
+
OR UNACCRUED, DISCLOSED OR UNDISCLOSED, ARISING OUT OF OR RELATING TO LICENSEE’S
|
| 380 |
+
USE OF THE SOFTWARE. NOTHING IN THIS SECTION SHOULD BE INTERPRETED TO REQUIRE
|
| 381 |
+
LICENSEE TO INDEMNIFY LICENSOR, NOR REQUIRE LICENSOR TO INDEMNIFY LICENSEE.
|
| 382 |
+
|
| 383 |
+
7. TERMINATION
|
| 384 |
+
|
| 385 |
+
7.1. Violations of Ethical Standards or Breaching Duty of Care: If Licensee
|
| 386 |
+
violates the Ethical Standards section or Licensee, or any other person or
|
| 387 |
+
entity within the Supply Chain prior to a good or service reaching the Licensee,
|
| 388 |
+
breaches its Duty of Care to Supply Chain Impacted Parties, Licensee must remedy
|
| 389 |
+
the violation or harm caused by Licensee within 30 days of being notified of the
|
| 390 |
+
violation or harm. If Licensee fails to remedy the violation or harm within 30
|
| 391 |
+
days, all rights in the Software granted to Licensee by License will be null and
|
| 392 |
+
void as between Licensor and Licensee.
|
| 393 |
+
|
| 394 |
+
7.2. Failure of Notice: If any person or entity notifies Licensee in writing
|
| 395 |
+
that Licensee has not complied with the Notice section of this License, Licensee
|
| 396 |
+
can keep this License by taking all practical steps to comply within 30 days
|
| 397 |
+
after the notice of noncompliance. If Licensee does not do so, Licensee’s
|
| 398 |
+
License (and all rights licensed hereunder) will end immediately.
|
| 399 |
+
|
| 400 |
+
7.3. Judicial Findings: In the event Licensee is found by a civil, criminal,
|
| 401 |
+
administrative, or other court of competent jurisdiction, or some other
|
| 402 |
+
adjudicating body with legal authority, to have committed actions which are in
|
| 403 |
+
violation of the Ethical Standards or Supply Chain Impacted Party sections of
|
| 404 |
+
this License, all rights granted to Licensee by this License will terminate
|
| 405 |
+
immediately.
|
| 406 |
+
|
| 407 |
+
7.4. Patent Litigation: If Licensee institutes patent litigation against any
|
| 408 |
+
entity (including a cross-claim or counterclaim in a suit) alleging that the
|
| 409 |
+
Software, all or part of the Software’s code, or a derivative work developed
|
| 410 |
+
using the Software, including a portion of its code, constitutes direct or
|
| 411 |
+
contributory patent infringement, then any patent license, along with all other
|
| 412 |
+
rights, granted to Licensee under this License will terminate as of the date
|
| 413 |
+
such litigation is filed.
|
| 414 |
+
|
| 415 |
+
7.5. Additional Remedies: Termination of the License by failing to remedy harms
|
| 416 |
+
in no way prevents Licensor or Supply Chain Impacted Party from seeking
|
| 417 |
+
appropriate remedies at law or in equity.
|
| 418 |
+
|
| 419 |
+
8. MISCELLANEOUS:
|
| 420 |
+
|
| 421 |
+
8.1. Conditions: Sections 3, 4.1, 5.1, 5.2, 7.1, 7.2, 7.3, and 7.4 are
|
| 422 |
+
conditions of the rights granted to Licensee in the License.
|
| 423 |
+
|
| 424 |
+
8.2. Equitable Relief: Licensor and any Supply Chain Impacted Party shall be
|
| 425 |
+
entitled to equitable relief, including injunctive relief or specific
|
| 426 |
+
performance of the terms hereof, in addition to any other remedy to which they
|
| 427 |
+
are entitled at law or in equity.
|
| 428 |
+
|
| 429 |
+
8.3. Copyleft: Modified software, source code, or other derivative work must be
|
| 430 |
+
licensed, in its entirety, under the exact same conditions as this License.
|
| 431 |
+
|
| 432 |
+
8.4. Severability: If any term or provision of this License is determined to be
|
| 433 |
+
invalid, illegal, or unenforceable by a court of competent jurisdiction, any
|
| 434 |
+
such determination of invalidity, illegality, or unenforceability shall not
|
| 435 |
+
affect any other term or provision of this License or invalidate or render
|
| 436 |
+
unenforceable such term or provision in any other jurisdiction. If the
|
| 437 |
+
determination of invalidity, illegality, or unenforceability by a court of
|
| 438 |
+
competent jurisdiction pertains to the terms or provisions contained in the
|
| 439 |
+
Ethical Standards section of this License, all rights in the Software granted to
|
| 440 |
+
Licensee shall be deemed null and void as between Licensor and Licensee.
|
| 441 |
+
|
| 442 |
+
8.5. Section Titles: Section titles are solely written for organizational
|
| 443 |
+
purposes and should not be used to interpret the language within each section.
|
| 444 |
+
|
| 445 |
+
8.6. Citations: Citations are solely written to provide context for the source
|
| 446 |
+
of the provisions in the Ethical Standards.
|
| 447 |
+
|
| 448 |
+
8.7. Section Summaries: Some sections have a brief italicized description which
|
| 449 |
+
is provided for the sole purpose of briefly describing the section and should
|
| 450 |
+
not be used to interpret the terms of the License.
|
| 451 |
+
|
| 452 |
+
8.8. Entire License: This is the entire License between the Licensor and
|
| 453 |
+
Licensee with respect to the claims released herein and that the consideration
|
| 454 |
+
stated herein is the only consideration or compensation to be paid or exchanged
|
| 455 |
+
between them for this License. This License cannot be modified or amended except
|
| 456 |
+
in a writing signed by Licensor and Licensee.
|
| 457 |
+
|
| 458 |
+
8.9. Successors and Assigns: This License shall be binding upon and inure to the
|
| 459 |
+
benefit of the Licensor’s and Licensee’s respective heirs, successors, and
|
| 460 |
+
assigns.
|
| 461 |
+
---------------------- END OFFICIAL HIPPOCRATIC LICENSE 3.0 TEXT ----------------------
|
| 462 |
+
|
| 463 |
+
==============================================================================
|
| 464 |
+
Attribution, commercial use, and warranty
|
| 465 |
+
==============================================================================
|
| 466 |
+
|
| 467 |
+
Attribution: cite this work as described in the model card (README.md), section
|
| 468 |
+
"How to cite". Attribution to Lowdown Labs is required under CC BY-NC 4.0.
|
| 469 |
+
|
| 470 |
+
Commercial use: CC BY-NC 4.0 does not grant commercial rights. Commercial licenses are
|
| 471 |
+
sold by Lowdown Labs; contact Lowdown Labs to purchase one.
|
| 472 |
+
|
| 473 |
+
No warranty: this work is provided as is, without warranty of any kind. See the model card
|
| 474 |
+
for the intended use, the evaluated conditions, and the known limitations.
|
README.md
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: other
|
| 3 |
+
license_name: lowdown-labs-lovely-license-1.0
|
| 4 |
+
license_link: LICENSE
|
| 5 |
+
tags:
|
| 6 |
+
- fela
|
| 7 |
+
- fourier-neural-operator
|
| 8 |
+
- fno
|
| 9 |
+
- cpu
|
| 10 |
+
- on-device
|
| 11 |
+
- edge
|
| 12 |
+
- time-series
|
| 13 |
+
- forecasting
|
| 14 |
+
- energy
|
| 15 |
+
- electricity
|
| 16 |
+
library_name: transformers
|
| 17 |
+
pipeline_tag: time-series-forecasting
|
| 18 |
+
---
|
| 19 |
+
|
| 20 |
+
# DISCLAIMER
|
| 21 |
+
|
| 22 |
+
This model is a research preview. It is released by Lowdown Labs in the interest of advancing
|
| 23 |
+
public science and demonstrating that a Fourier Neural Operator can forecast on a plain CPU with
|
| 24 |
+
a constant memory footprint. The dataset behind this
|
| 25 |
+
one (UCI electricity load) is CC BY 4.0 and could permit commercial use with attribution; see the
|
| 26 |
+
license notes below before deploying.
|
| 27 |
+
|
| 28 |
+
# FELA-TS edge: On device electricity load forecaster
|
| 29 |
+
|
| 30 |
+
FELA-TS edge reads a window of recent load history and forecasts the next 96 steps ahead. It is
|
| 31 |
+
tiny, about 1.76M parameters, and runs on a plain CPU with no GPU. Its working memory does not grow with how long the stream has been running, so you can drop
|
| 32 |
+
it into a meter or a building controller and let it forecast a live feed for years without the
|
| 33 |
+
memory climbing due to the model expanding its usage.
|
| 34 |
+
|
| 35 |
+
The shipped checkpoint is trained on the standard 321 channel electricity load benchmark, but the
|
| 36 |
+
architecture underneath is a generic multi channel forecaster for long horizons.
|
| 37 |
+
|
| 38 |
+
# What goes in, what comes out
|
| 39 |
+
|
| 40 |
+
- Input: one history window of shape `(1, 512, 321)`: 512 past time steps across 321 load
|
| 41 |
+
channels, per channel standardized on the training statistics. RevIN handles the instance
|
| 42 |
+
normalization inside the model, so you pass the standardized history and the model manages the
|
| 43 |
+
per window mean and scale itself.
|
| 44 |
+
- Output: a forecast of shape `(1, 96, 321)`: the next 96 steps for all 321 channels, returned in
|
| 45 |
+
the original (denormalized) units.
|
| 46 |
+
- In plain terms: "here are the last 512 hours of load for these meters" goes in, and "here is the
|
| 47 |
+
next 96 hours for each of them" comes out.
|
| 48 |
+
|
| 49 |
+
The edge/on device unit runs a single load stream at a time (one channel), which is the
|
| 50 |
+
sub millisecond, constant memory path described under Performance.
|
| 51 |
+
|
| 52 |
+
# Why we built it this way
|
| 53 |
+
|
| 54 |
+
The sequence mixer is a Fourier Neural Operator, a filter the model learns and then applies in the
|
| 55 |
+
frequency domain. Electricity load runs on strong daily and weekly cycles, and those cycles are
|
| 56 |
+
what a frequency domain filter reads best, so the method fits the signal. The model is pure FNO
|
| 57 |
+
with a patch embedding, and it normalizes each history window internally (a step called RevIN) so
|
| 58 |
+
you do not have to hand tune it. It is pure FNO, with none of the gated memory or attention layers
|
| 59 |
+
that some sibling FELA models add.
|
| 60 |
+
|
| 61 |
+
Because it carries no attention and no KV cache, the working memory stays small and fixed no matter
|
| 62 |
+
how much history has streamed through it. The live single stream path keeps its history in a 512
|
| 63 |
+
sample ring buffer, about 2 KB, and one forward pass runs on roughly 126 KB of activations. That
|
| 64 |
+
flat footprint is the whole point at the edge: a full history attention model would keep growing its
|
| 65 |
+
memory until it ran out, while this one does not move.
|
| 66 |
+
|
| 67 |
+
# Performance
|
| 68 |
+
|
| 69 |
+
Speed and footprint, measured on CPU (single core, single load stream).
|
| 70 |
+
|
| 71 |
+
| Format | Size on disk | Notes |
|
| 72 |
+
|---|---|---|
|
| 73 |
+
| fp32 | 9.96 MB | full model weights |
|
| 74 |
+
| int8 (PyTorch/ONNX) | 7.29 MB | deployable edge unit |
|
| 75 |
+
| TFLite float16 | 4.9 MB | smallest deployable export |
|
| 76 |
+
|
| 77 |
+
- Full 321 channel forecast: median 165.7 ms on one CPU core.
|
| 78 |
+
- Single channel edge unit forecast: median 0.863 ms on one CPU core.
|
| 79 |
+
- int8 ONNX single stream update: about 0.56 ms per update (roughly 1,700 updates per second) on
|
| 80 |
+
one core.
|
| 81 |
+
- Live working RAM (constant, independent of history length): a 2 KB ring buffer holds the entire
|
| 82 |
+
retained history, plus about 126 KB of activations, for a working set under 200 KB excluding
|
| 83 |
+
weights.
|
| 84 |
+
|
| 85 |
+
Constant memory is verified: the O(1) ring buffer streaming path was checked against recomputing
|
| 86 |
+
the forecast on the explicit window and matched exactly (mean absolute difference 0.0 over 1,800
|
| 87 |
+
streamed steps).
|
| 88 |
+
|
| 89 |
+
The model fits comfortably on a Raspberry Pi 4/5 or Pi Zero 2 W (Cortex-A class,
|
| 90 |
+
ONNX path); it probably could not fit a small microcontroller (the 5 to 7 MB model is larger than typical
|
| 91 |
+
MCU flash) without explicitly targeting those constraints, so the realistic edge target is a Cortex-A single board computer, not a Cortex-M part.
|
| 92 |
+
|
| 93 |
+
# Accuracy
|
| 94 |
+
|
| 95 |
+
Protocol: UCI ElectricityLoadDiagrams20112014 ("electricity" / ECL benchmark), the standard
|
| 96 |
+
Informer chronological 70/10/20 train/validation/test split, lookback L = 512, forecast horizon
|
| 97 |
+
H = 96, over all 321 channels. Metric is mean squared error (MSE) and mean absolute error (MAE) on
|
| 98 |
+
the z normalized test windows, the standard long horizon ECL protocol.
|
| 99 |
+
|
| 100 |
+
| Benchmark | Metric | This model | Baseline (named) |
|
| 101 |
+
|---|---|---|---|
|
| 102 |
+
| Electricity, horizon 96 | MSE | 0.1325 | PatchTST ~0.129 |
|
| 103 |
+
| Electricity, horizon 96 | MAE | 0.2233 | iTransformer MSE ~0.148, DLinear MSE ~0.140 |
|
| 104 |
+
|
| 105 |
+
The card MSE/MAE of 0.1325 / 0.2233 reproduced at 0.1344 / 0.2254 on a fresh held out evaluation
|
| 106 |
+
(1.76M parameters). PatchTST leads on accuracy by a small margin at this
|
| 107 |
+
horizon; iTransformer and DLinear are behind. However, sub millisecond single stream forecasts on one CPU core with a flat, sub 200 KB working set are provably attainable, vs a full history attention model whose memory climbs with the length of the stream.
|
| 108 |
+
|
| 109 |
+
# How to run it
|
| 110 |
+
|
| 111 |
+
The short version:
|
| 112 |
+
|
| 113 |
+
```python
|
| 114 |
+
import torch
|
| 115 |
+
from modeling import load_model, forecast
|
| 116 |
+
|
| 117 |
+
m = load_model("/path/to/weights_dir") # a dir with model.safetensors + config.json
|
| 118 |
+
# x: a (1, 512, 321) history window, per channel standardized on training stats
|
| 119 |
+
y = forecast(m, x) # -> (1, 96, 321) forecast in original units
|
| 120 |
+
```
|
| 121 |
+
|
| 122 |
+
`load_model` also accepts the `model.safetensors` path directly or a Hugging Face repo id. The fp32
|
| 123 |
+
weights ship as `model.safetensors`; the loader builds the architecture from `config.json` and
|
| 124 |
+
loads the state dict.
|
| 125 |
+
|
| 126 |
+
# Training data and license
|
| 127 |
+
|
| 128 |
+
- Dataset: UCI ElectricityLoadDiagrams20112014 ("electricity" / ECL), the 321 client hourly
|
| 129 |
+
variant used across the Informer / Autoformer / PatchTST time series literature (26,304 hourly
|
| 130 |
+
timesteps x 321 client load streams). Source: UCI Machine Learning Repository, dataset 321
|
| 131 |
+
(DOI 10.24432/C58C86). The training split, windowing, and the audited train window count are
|
| 132 |
+
reproduced in `train.py` (`--smoke` rebuilds the split and asserts 17,805 train windows).
|
| 133 |
+
- License: Creative Commons Attribution 4.0 International (CC BY 4.0), as listed on the UCI dataset
|
| 134 |
+
page. Commercial use is ALLOWED, contingent only on attribution and preserving the license terms.
|
| 135 |
+
This is the one dataset in the FELA industrial family with an unambiguous, commercially usable
|
| 136 |
+
license. Attribution: cite the UCI ElectricityLoadDiagrams20112014 dataset (DOI 10.24432/C58C86).
|
| 137 |
+
|
| 138 |
+
# Intended use, limitations, and safety
|
| 139 |
+
|
| 140 |
+
What it is for: the forecasting core inside an edge or on premises energy product, running on a CPU
|
| 141 |
+
or a single board computer. Fit includes live load forecasting on a meter or gateway, building and
|
| 142 |
+
microgrid controllers, and any long running multi channel forecast where the memory must stay flat
|
| 143 |
+
while history accumulates.
|
| 144 |
+
|
| 145 |
+
What it is not for: this is a forecasting model, not a control system or a guarantee. It was
|
| 146 |
+
trained and evaluated only on the UCI electricity benchmark; generalization to other load profiles,
|
| 147 |
+
sampling rates, sensors, and populations is not established and must be validated before any
|
| 148 |
+
operational use. Accuracy is at parity with, not ahead of, the strongest published transformer
|
| 149 |
+
forecaster (PatchTST leads by a small margin); the model wins on footprint and constant memory, not
|
| 150 |
+
on top line accuracy. Continuous stream benchmarks beyond the verified streaming equals batch check
|
| 151 |
+
(for example multi day real time factor on a specific physical board) are not yet measured.
|
| 152 |
+
|
| 153 |
+
# Model family
|
| 154 |
+
|
| 155 |
+
This is part of the FELA family from Lowdown Labs: one Fourier Neural Operator architecture across
|
| 156 |
+
many modalities, all CPU native and subquadratic. Sibling repos share no weights, so none carries a
|
| 157 |
+
`base_model` link.
|
| 158 |
+
|
| 159 |
+
# License
|
| 160 |
+
|
| 161 |
+
Released under the Lowdown Labs Lovely License 1.0 (CC BY-NC 4.0 plus Hippocratic License 3.0). See LICENSE. For most LL models, a commercial license may be available; contact Lowdown Labs.
|
config.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"model_type": "fela-ts",
|
| 3 |
+
"architectures": [
|
| 4 |
+
"FelaTsModel"
|
| 5 |
+
],
|
| 6 |
+
"auto_map": {
|
| 7 |
+
"AutoConfig": "configuration_ts.FelaTsConfig",
|
| 8 |
+
"AutoModel": "modeling_ts.FelaTsModel"
|
| 9 |
+
},
|
| 10 |
+
"library_name": "pytorch",
|
| 11 |
+
"arch": "FELA_TS",
|
| 12 |
+
"note": "FELA time series forecaster, about 1.76M params. RevIN, patch embedding, FNO spectral mixer blocks, linear head. Trained on electricity, 321 channels, L=512, H=96.",
|
| 13 |
+
"C": 321,
|
| 14 |
+
"L": 512,
|
| 15 |
+
"H": 96,
|
| 16 |
+
"patch": 16,
|
| 17 |
+
"stride": 8,
|
| 18 |
+
"D": 128,
|
| 19 |
+
"modes": 16,
|
| 20 |
+
"nblk": 3,
|
| 21 |
+
"input_shape": [
|
| 22 |
+
1,
|
| 23 |
+
512,
|
| 24 |
+
321
|
| 25 |
+
],
|
| 26 |
+
"input_desc": "history window shape (1, 512, 321): 512 past steps of 321 channels, standardized per channel on training statistics. RevIN normalizes instances inside the model.",
|
| 27 |
+
"complex_keys": [
|
| 28 |
+
"blocks.0.fno.w",
|
| 29 |
+
"blocks.1.fno.w",
|
| 30 |
+
"blocks.2.fno.w"
|
| 31 |
+
]
|
| 32 |
+
}
|
configuration_ts.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from transformers import PretrainedConfig
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
class FelaTsConfig(PretrainedConfig):
|
| 5 |
+
model_type = "fela-ts"
|
| 6 |
+
|
| 7 |
+
def __init__(
|
| 8 |
+
self,
|
| 9 |
+
C=321,
|
| 10 |
+
L=512,
|
| 11 |
+
H=96,
|
| 12 |
+
patch=16,
|
| 13 |
+
stride=8,
|
| 14 |
+
D=128,
|
| 15 |
+
modes=16,
|
| 16 |
+
nblk=3,
|
| 17 |
+
**kwargs,
|
| 18 |
+
):
|
| 19 |
+
self.C = C
|
| 20 |
+
self.L = L
|
| 21 |
+
self.H = H
|
| 22 |
+
self.patch = patch
|
| 23 |
+
self.stride = stride
|
| 24 |
+
self.D = D
|
| 25 |
+
self.modes = modes
|
| 26 |
+
self.nblk = nblk
|
| 27 |
+
super().__init__(**kwargs)
|
model.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:4f4fbc05634862cbdf2cc8bc35906426785750d491b71d25cae39ea20389b0be
|
| 3 |
+
size 10199640
|
modeling.py
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
import json
|
| 3 |
+
import os
|
| 4 |
+
from dataclasses import dataclass
|
| 5 |
+
import torch
|
| 6 |
+
import torch.nn as nn
|
| 7 |
+
import torch.nn.functional as F
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
@dataclass
|
| 11 |
+
class TSConfig:
|
| 12 |
+
C: int = 321
|
| 13 |
+
L: int = 512
|
| 14 |
+
H: int = 96
|
| 15 |
+
patch: int = 16
|
| 16 |
+
stride: int = 8
|
| 17 |
+
D: int = 128
|
| 18 |
+
modes: int = 16
|
| 19 |
+
nblk: int = 3
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
class RevIN(nn.Module):
|
| 23 |
+
def __init__(self, C):
|
| 24 |
+
super().__init__()
|
| 25 |
+
self.g = nn.Parameter(torch.ones(C))
|
| 26 |
+
self.b = nn.Parameter(torch.zeros(C))
|
| 27 |
+
|
| 28 |
+
def norm(self, x):
|
| 29 |
+
self.m = x.mean(1, keepdim=True)
|
| 30 |
+
self.s = x.std(1, keepdim=True) + 1e-05
|
| 31 |
+
return (x - self.m) / self.s * self.g + self.b
|
| 32 |
+
|
| 33 |
+
def denorm(self, x):
|
| 34 |
+
return (x - self.b) / self.g * self.s + self.m
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
class FNO1D(nn.Module):
|
| 38 |
+
def __init__(self, D, m):
|
| 39 |
+
super().__init__()
|
| 40 |
+
self.m = m
|
| 41 |
+
self.w = nn.Parameter(1 / (D * D) * torch.rand(m, D, D, dtype=torch.cfloat))
|
| 42 |
+
|
| 43 |
+
def forward(self, x):
|
| 44 |
+
P = x.shape[1]
|
| 45 |
+
xf = torch.fft.rfft(x, dim=1)
|
| 46 |
+
mm = min(self.m, xf.shape[1])
|
| 47 |
+
o = torch.zeros_like(xf)
|
| 48 |
+
o[:, :mm] = torch.einsum("bpd,pde->bpe", xf[:, :mm], self.w[:mm])
|
| 49 |
+
return torch.fft.irfft(o, n=P, dim=1)
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
class Block(nn.Module):
|
| 53 |
+
def __init__(self, D, m, ff=2, drop=0.2):
|
| 54 |
+
super().__init__()
|
| 55 |
+
self.n1 = nn.LayerNorm(D)
|
| 56 |
+
self.fno = FNO1D(D, m)
|
| 57 |
+
self.d1 = nn.Dropout(drop)
|
| 58 |
+
self.n2 = nn.LayerNorm(D)
|
| 59 |
+
self.ff = nn.Sequential(
|
| 60 |
+
nn.Linear(D, D * ff), nn.GELU(), nn.Dropout(drop), nn.Linear(D * ff, D)
|
| 61 |
+
)
|
| 62 |
+
|
| 63 |
+
def forward(self, x):
|
| 64 |
+
x = x + self.d1(self.fno(self.n1(x)))
|
| 65 |
+
return x + self.ff(self.n2(x))
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
class FELA_TS(nn.Module):
|
| 69 |
+
def __init__(self, C, L, H, patch=16, stride=8, D=128, modes=16, nblk=3):
|
| 70 |
+
super().__init__()
|
| 71 |
+
self.C, self.L, self.H, self.patch, self.stride = (C, L, H, patch, stride)
|
| 72 |
+
self.revin = RevIN(C)
|
| 73 |
+
self.np_ = (L - patch) // stride + 1
|
| 74 |
+
self.embed = nn.Linear(patch, D)
|
| 75 |
+
self.blocks = nn.ModuleList([Block(D, modes) for _ in range(nblk)])
|
| 76 |
+
self.head = nn.Linear(self.np_ * D, H)
|
| 77 |
+
|
| 78 |
+
def forward(self, x):
|
| 79 |
+
x = self.revin.norm(x)
|
| 80 |
+
x = x.permute(0, 2, 1).reshape(-1, self.L)
|
| 81 |
+
x = x.unfold(1, self.patch, self.stride)
|
| 82 |
+
h = self.embed(x)
|
| 83 |
+
for b in self.blocks:
|
| 84 |
+
h = b(h)
|
| 85 |
+
y = self.head(h.flatten(1)).reshape(-1, self.C, self.H).permute(0, 2, 1)
|
| 86 |
+
return self.revin.denorm(y)
|
| 87 |
+
|
| 88 |
+
|
| 89 |
+
_CONFIG_FIELDS = set(TSConfig.__dataclass_fields__.keys())
|
| 90 |
+
|
| 91 |
+
|
| 92 |
+
def _read_json(path):
|
| 93 |
+
with open(path) as f:
|
| 94 |
+
return json.load(f)
|
| 95 |
+
|
| 96 |
+
|
| 97 |
+
def _cfg_from_dict(d):
|
| 98 |
+
return TSConfig(**{k: v for k, v in d.items() if k in _CONFIG_FIELDS})
|
| 99 |
+
|
| 100 |
+
|
| 101 |
+
def validate_history(x: torch.Tensor, cfg: TSConfig):
|
| 102 |
+
if x.dim() != 3:
|
| 103 |
+
raise ValueError(f"expected a 3D tensor (B, L, C); got {tuple(x.shape)}")
|
| 104 |
+
if x.size(1) != cfg.L or x.size(2) != cfg.C:
|
| 105 |
+
raise ValueError(
|
| 106 |
+
f"expected history of shape (B, {cfg.L}, {cfg.C}); got {tuple(x.shape)}"
|
| 107 |
+
)
|
| 108 |
+
|
| 109 |
+
|
| 110 |
+
def load_model(path_or_repo: str):
|
| 111 |
+
if os.path.isdir(path_or_repo):
|
| 112 |
+
cfg_dict = _read_json(os.path.join(path_or_repo, "config.json"))
|
| 113 |
+
weights = os.path.join(path_or_repo, "model.safetensors")
|
| 114 |
+
elif os.path.isfile(path_or_repo) and path_or_repo.endswith(".safetensors"):
|
| 115 |
+
cfg_dict = _read_json(
|
| 116 |
+
os.path.join(os.path.dirname(path_or_repo), "config.json")
|
| 117 |
+
)
|
| 118 |
+
weights = path_or_repo
|
| 119 |
+
elif os.path.isfile(path_or_repo):
|
| 120 |
+
cfg_dict = _read_json(
|
| 121 |
+
os.path.join(os.path.dirname(path_or_repo) or ".", "config.json")
|
| 122 |
+
)
|
| 123 |
+
weights = path_or_repo
|
| 124 |
+
else:
|
| 125 |
+
from huggingface_hub import hf_hub_download
|
| 126 |
+
|
| 127 |
+
cfg_dict = _read_json(hf_hub_download(path_or_repo, "config.json"))
|
| 128 |
+
weights = hf_hub_download(path_or_repo, "model.safetensors")
|
| 129 |
+
cfg = _cfg_from_dict(cfg_dict)
|
| 130 |
+
model = FELA_TS(
|
| 131 |
+
cfg.C, cfg.L, cfg.H, cfg.patch, cfg.stride, cfg.D, cfg.modes, cfg.nblk
|
| 132 |
+
).eval()
|
| 133 |
+
if weights.endswith(".safetensors"):
|
| 134 |
+
from safetensors.torch import load_file
|
| 135 |
+
|
| 136 |
+
state = load_file(weights)
|
| 137 |
+
cplx = set(cfg_dict.get("complex_keys", []))
|
| 138 |
+
state = {
|
| 139 |
+
k: (torch.view_as_complex(v.contiguous()) if k in cplx else v)
|
| 140 |
+
for k, v in state.items()
|
| 141 |
+
}
|
| 142 |
+
else:
|
| 143 |
+
state = torch.load(weights, map_location="cpu", weights_only=False)
|
| 144 |
+
if isinstance(state, dict) and "state_dict" in state:
|
| 145 |
+
state = state["state_dict"]
|
| 146 |
+
model.load_state_dict(state)
|
| 147 |
+
model.cfg = cfg
|
| 148 |
+
return model
|
| 149 |
+
|
| 150 |
+
|
| 151 |
+
from_pretrained = load_model
|
| 152 |
+
|
| 153 |
+
|
| 154 |
+
@torch.no_grad()
|
| 155 |
+
def forecast(model, x: torch.Tensor) -> torch.Tensor:
|
| 156 |
+
validate_history(x, model.cfg)
|
| 157 |
+
return model(x)
|
modeling_ts.py
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import sys
|
| 3 |
+
import types
|
| 4 |
+
|
| 5 |
+
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
| 6 |
+
import torch
|
| 7 |
+
import torch.nn as nn
|
| 8 |
+
from transformers import PreTrainedModel
|
| 9 |
+
from transformers.modeling_outputs import CausalLMOutput
|
| 10 |
+
|
| 11 |
+
from .configuration_ts import FelaTsConfig
|
| 12 |
+
from .modeling import FELA_TS, FNO1D
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
def _fno1d_forward(self, x):
|
| 16 |
+
w = torch.view_as_complex(self.w)
|
| 17 |
+
P = x.shape[1]
|
| 18 |
+
xf = torch.fft.rfft(x, dim=1)
|
| 19 |
+
mm = min(self.m, xf.shape[1])
|
| 20 |
+
o = torch.zeros_like(xf)
|
| 21 |
+
o[:, :mm] = torch.einsum("bpd,pde->bpe", xf[:, :mm], w[:mm])
|
| 22 |
+
return torch.fft.irfft(o, n=P, dim=1)
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
def _realify(model):
|
| 26 |
+
for m in model.modules():
|
| 27 |
+
if isinstance(m, FNO1D):
|
| 28 |
+
m.w = nn.Parameter(torch.view_as_real(m.w.detach()).contiguous())
|
| 29 |
+
m.forward = types.MethodType(_fno1d_forward, m)
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
class FelaTsModel(PreTrainedModel):
|
| 33 |
+
config_class = FelaTsConfig
|
| 34 |
+
base_model_prefix = "model"
|
| 35 |
+
main_input_name = "x"
|
| 36 |
+
|
| 37 |
+
def __init__(self, config):
|
| 38 |
+
super().__init__(config)
|
| 39 |
+
self.model = FELA_TS(
|
| 40 |
+
config.C,
|
| 41 |
+
config.L,
|
| 42 |
+
config.H,
|
| 43 |
+
config.patch,
|
| 44 |
+
config.stride,
|
| 45 |
+
config.D,
|
| 46 |
+
config.modes,
|
| 47 |
+
config.nblk,
|
| 48 |
+
)
|
| 49 |
+
_realify(self.model)
|
| 50 |
+
self.post_init()
|
| 51 |
+
|
| 52 |
+
def forward(self, x=None, input_values=None, **kwargs):
|
| 53 |
+
if x is None:
|
| 54 |
+
x = input_values
|
| 55 |
+
out = self.model(x)
|
| 56 |
+
return CausalLMOutput(logits=out)
|
streaming/manifest.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"model": "ts-edge",
|
| 3 |
+
"format": "fp16-streaming",
|
| 4 |
+
"note": "load order is smallest-first for progressive/streaming load",
|
| 5 |
+
"files": [
|
| 6 |
+
{
|
| 7 |
+
"file": "model_fp16.safetensors",
|
| 8 |
+
"source": "model.safetensors",
|
| 9 |
+
"dtype": "fp16",
|
| 10 |
+
"bytes": 5101188,
|
| 11 |
+
"approx_mb": 4.865
|
| 12 |
+
}
|
| 13 |
+
]
|
| 14 |
+
}
|
streaming/model_fp16.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:11ca25fba43652d89559fc17bd610ded2f920b2cb742046bc3d7482f57e59332
|
| 3 |
+
size 5101188
|
train.py
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import sys, numpy as np, pandas as pd, torch, torch.nn as nn, torch.nn.functional as F
|
| 2 |
+
|
| 3 |
+
dev = "cuda" if torch.cuda.is_available() else "cpu"
|
| 4 |
+
torch.manual_seed(0)
|
| 5 |
+
np.random.seed(0)
|
| 6 |
+
csv, L, H = ("/workspace/data/electricity.csv", 512, 96)
|
| 7 |
+
smoke = "--smoke" in sys.argv
|
| 8 |
+
save = (
|
| 9 |
+
sys.argv[sys.argv.index("--save") + 1]
|
| 10 |
+
if "--save" in sys.argv
|
| 11 |
+
else "/workspace/ts_demo/fela_ts_electricity.pt"
|
| 12 |
+
)
|
| 13 |
+
epochs = int(sys.argv[sys.argv.index("--epochs") + 1]) if "--epochs" in sys.argv else 30
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
class RevIN(nn.Module):
|
| 17 |
+
def __init__(s, C):
|
| 18 |
+
super().__init__()
|
| 19 |
+
s.g = nn.Parameter(torch.ones(C))
|
| 20 |
+
s.b = nn.Parameter(torch.zeros(C))
|
| 21 |
+
|
| 22 |
+
def norm(s, x):
|
| 23 |
+
s.m = x.mean(1, keepdim=True)
|
| 24 |
+
s.s = x.std(1, keepdim=True) + 1e-05
|
| 25 |
+
return (x - s.m) / s.s * s.g + s.b
|
| 26 |
+
|
| 27 |
+
def denorm(s, x):
|
| 28 |
+
return (x - s.b) / s.g * s.s + s.m
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
class FNO1D(nn.Module):
|
| 32 |
+
def __init__(s, D, m):
|
| 33 |
+
super().__init__()
|
| 34 |
+
s.m = m
|
| 35 |
+
s.w = nn.Parameter(1 / (D * D) * torch.rand(m, D, D, dtype=torch.cfloat))
|
| 36 |
+
|
| 37 |
+
def forward(s, x):
|
| 38 |
+
P = x.shape[1]
|
| 39 |
+
xf = torch.fft.rfft(x, dim=1)
|
| 40 |
+
mm = min(s.m, xf.shape[1])
|
| 41 |
+
o = torch.zeros_like(xf)
|
| 42 |
+
o[:, :mm] = torch.einsum("bpd,pde->bpe", xf[:, :mm], s.w[:mm])
|
| 43 |
+
return torch.fft.irfft(o, n=P, dim=1)
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
class Block(nn.Module):
|
| 47 |
+
def __init__(s, D, m, ff=2, drop=0.2):
|
| 48 |
+
super().__init__()
|
| 49 |
+
s.n1 = nn.LayerNorm(D)
|
| 50 |
+
s.fno = FNO1D(D, m)
|
| 51 |
+
s.d1 = nn.Dropout(drop)
|
| 52 |
+
s.n2 = nn.LayerNorm(D)
|
| 53 |
+
s.ff = nn.Sequential(
|
| 54 |
+
nn.Linear(D, D * ff), nn.GELU(), nn.Dropout(drop), nn.Linear(D * ff, D)
|
| 55 |
+
)
|
| 56 |
+
|
| 57 |
+
def forward(s, x):
|
| 58 |
+
x = x + s.d1(s.fno(s.n1(x)))
|
| 59 |
+
return x + s.ff(s.n2(x))
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
class FELA_TS(nn.Module):
|
| 63 |
+
def __init__(s, C, L, H, patch=16, stride=8, D=128, modes=16, nblk=3):
|
| 64 |
+
super().__init__()
|
| 65 |
+
s.C, s.L, s.H, s.patch, s.stride = (C, L, H, patch, stride)
|
| 66 |
+
s.revin = RevIN(C)
|
| 67 |
+
s.np_ = (L - patch) // stride + 1
|
| 68 |
+
s.embed = nn.Linear(patch, D)
|
| 69 |
+
s.blocks = nn.ModuleList([Block(D, modes) for _ in range(nblk)])
|
| 70 |
+
s.head = nn.Linear(s.np_ * D, H)
|
| 71 |
+
|
| 72 |
+
def forward(s, x):
|
| 73 |
+
x = s.revin.norm(x)
|
| 74 |
+
x = x.permute(0, 2, 1).reshape(-1, s.L)
|
| 75 |
+
x = x.unfold(1, s.patch, s.stride)
|
| 76 |
+
h = s.embed(x)
|
| 77 |
+
for b in s.blocks:
|
| 78 |
+
h = b(h)
|
| 79 |
+
y = s.head(h.flatten(1)).reshape(-1, s.C, s.H).permute(0, 2, 1)
|
| 80 |
+
return s.revin.denorm(y)
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
df = pd.read_csv(csv)
|
| 84 |
+
cols = [c for c in df.columns if c != "date"]
|
| 85 |
+
data = df[cols].values.astype(np.float32)
|
| 86 |
+
n = len(data)
|
| 87 |
+
ntr, nva = (int(n * 0.7), int(n * 0.1))
|
| 88 |
+
mu = data[:ntr].mean(0)
|
| 89 |
+
sd = data[:ntr].std(0) + 1e-08
|
| 90 |
+
data = (data - mu) / sd
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
def win(a):
|
| 94 |
+
xs, ys = ([], [])
|
| 95 |
+
for i in range(0, len(a) - L - H + 1, 1):
|
| 96 |
+
xs.append(a[i : i + L])
|
| 97 |
+
ys.append(a[i + L : i + L + H])
|
| 98 |
+
return (torch.tensor(np.array(xs)), torch.tensor(np.array(ys)))
|
| 99 |
+
|
| 100 |
+
|
| 101 |
+
Xtr, Ytr = win(data[:ntr])
|
| 102 |
+
Xte, Yte = win(data[ntr + nva :])
|
| 103 |
+
C = data.shape[1]
|
| 104 |
+
assert len(Xtr) == 17805
|
| 105 |
+
if smoke:
|
| 106 |
+
print(
|
| 107 |
+
f"Electricity C={C} n={n} ntr={ntr} nva={nva} train {len(Xtr)} test {len(Xte)}"
|
| 108 |
+
)
|
| 109 |
+
sys.exit()
|
| 110 |
+
m = FELA_TS(C, L, H).to(dev)
|
| 111 |
+
opt = torch.optim.Adam(m.parameters(), lr=0.001)
|
| 112 |
+
sch = torch.optim.lr_scheduler.CosineAnnealingLR(opt, epochs)
|
| 113 |
+
bs = 64
|
| 114 |
+
print(f"[Ts] electricity C={C} train {len(Xtr)} test {len(Xte)}")
|
| 115 |
+
for ep in range(epochs):
|
| 116 |
+
m.train()
|
| 117 |
+
p = torch.randperm(len(Xtr))
|
| 118 |
+
for i in range(0, len(Xtr) - bs, bs):
|
| 119 |
+
idx = p[i : i + bs]
|
| 120 |
+
loss = F.l1_loss(m(Xtr[idx].to(dev)), Ytr[idx].to(dev))
|
| 121 |
+
opt.zero_grad()
|
| 122 |
+
loss.backward()
|
| 123 |
+
opt.step()
|
| 124 |
+
sch.step()
|
| 125 |
+
m.eval()
|
| 126 |
+
se = ae = cnt = 0
|
| 127 |
+
with torch.no_grad():
|
| 128 |
+
for i in range(0, len(Xte), 256):
|
| 129 |
+
pr = m(Xte[i : i + 256].to(dev))
|
| 130 |
+
y = Yte[i : i + 256].to(dev)
|
| 131 |
+
se += F.mse_loss(pr, y, reduction="sum").item()
|
| 132 |
+
ae += (pr - y).abs().sum().item()
|
| 133 |
+
cnt += y.numel()
|
| 134 |
+
mse, mae = (se / cnt, ae / cnt)
|
| 135 |
+
print(f"[Ts] electricity/96 TEST MSE {mse:.4f} MAE {mae:.4f}")
|
| 136 |
+
torch.save(m.state_dict(), save)
|
| 137 |
+
print(f"SAVED {save}")
|