Tabular Classification
Transformers
Safetensors
felatab
feature-extraction
fela
tabular
in-context-learning
prior-fitted-network
foundation-model
delta-rule
cpu
on-device
custom_code
Eval Results (legacy)
Instructions to use lowdown-labs/fela-tab with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use lowdown-labs/fela-tab with Transformers:
# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("lowdown-labs/fela-tab", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
Commit ·
c902bdf
0
Parent(s):
initial commit
Browse files- .gitattributes +1 -0
- .gitignore +6 -0
- LICENSE +202 -0
- README.md +210 -0
- config.json +26 -0
- config_big.json +19 -0
- config_small.json +19 -0
- configuration_felatab.py +35 -0
- model.safetensors.index.json +552 -0
- model_big.safetensors +3 -0
- model_big_int8.safetensors +3 -0
- model_small.safetensors +3 -0
- model_small_int8.safetensors +3 -0
- modeling.py +404 -0
- modeling_felatab.py +28 -0
- prior.py +194 -0
- quickstart/README.md +43 -0
- quickstart/requirements.txt +5 -0
- quickstart/run.py +71 -0
- requirements.txt +4 -0
- space/README.md +36 -0
- space/app.py +100 -0
- space/requirements.txt +6 -0
- train.py +172 -0
- verify.py +82 -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,202 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
Apache License
|
| 3 |
+
Version 2.0, January 2004
|
| 4 |
+
http://www.apache.org/licenses/
|
| 5 |
+
|
| 6 |
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
| 7 |
+
|
| 8 |
+
1. Definitions.
|
| 9 |
+
|
| 10 |
+
"License" shall mean the terms and conditions for use, reproduction,
|
| 11 |
+
and distribution as defined by Sections 1 through 9 of this document.
|
| 12 |
+
|
| 13 |
+
"Licensor" shall mean the copyright owner or entity authorized by
|
| 14 |
+
the copyright owner that is granting the License.
|
| 15 |
+
|
| 16 |
+
"Legal Entity" shall mean the union of the acting entity and all
|
| 17 |
+
other entities that control, are controlled by, or are under common
|
| 18 |
+
control with that entity. For the purposes of this definition,
|
| 19 |
+
"control" means (i) the power, direct or indirect, to cause the
|
| 20 |
+
direction or management of such entity, whether by contract or
|
| 21 |
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
| 22 |
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
| 23 |
+
|
| 24 |
+
"You" (or "Your") shall mean an individual or Legal Entity
|
| 25 |
+
exercising permissions granted by this License.
|
| 26 |
+
|
| 27 |
+
"Source" form shall mean the preferred form for making modifications,
|
| 28 |
+
including but not limited to software source code, documentation
|
| 29 |
+
source, and configuration files.
|
| 30 |
+
|
| 31 |
+
"Object" form shall mean any form resulting from mechanical
|
| 32 |
+
transformation or translation of a Source form, including but
|
| 33 |
+
not limited to compiled object code, generated documentation,
|
| 34 |
+
and conversions to other media types.
|
| 35 |
+
|
| 36 |
+
"Work" shall mean the work of authorship, whether in Source or
|
| 37 |
+
Object form, made available under the License, as indicated by a
|
| 38 |
+
copyright notice that is included in or attached to the work
|
| 39 |
+
(an example is provided in the Appendix below).
|
| 40 |
+
|
| 41 |
+
"Derivative Works" shall mean any work, whether in Source or Object
|
| 42 |
+
form, that is based on (or derived from) the Work and for which the
|
| 43 |
+
editorial revisions, annotations, elaborations, or other modifications
|
| 44 |
+
represent, as a whole, an original work of authorship. For the purposes
|
| 45 |
+
of this License, Derivative Works shall not include works that remain
|
| 46 |
+
separable from, or merely link (or bind by name) to the interfaces of,
|
| 47 |
+
the Work and Derivative Works thereof.
|
| 48 |
+
|
| 49 |
+
"Contribution" shall mean any work of authorship, including
|
| 50 |
+
the original version of the Work and any modifications or additions
|
| 51 |
+
to that Work or Derivative Works thereof, that is intentionally
|
| 52 |
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
| 53 |
+
or by an individual or Legal Entity authorized to submit on behalf of
|
| 54 |
+
the copyright owner. For the purposes of this definition, "submitted"
|
| 55 |
+
means any form of electronic, verbal, or written communication sent
|
| 56 |
+
to the Licensor or its representatives, including but not limited to
|
| 57 |
+
communication on electronic mailing lists, source code control systems,
|
| 58 |
+
and issue tracking systems that are managed by, or on behalf of, the
|
| 59 |
+
Licensor for the purpose of discussing and improving the Work, but
|
| 60 |
+
excluding communication that is conspicuously marked or otherwise
|
| 61 |
+
designated in writing by the copyright owner as "Not a Contribution."
|
| 62 |
+
|
| 63 |
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
| 64 |
+
on behalf of whom a Contribution has been received by Licensor and
|
| 65 |
+
subsequently incorporated within the Work.
|
| 66 |
+
|
| 67 |
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
| 68 |
+
this License, each Contributor hereby grants to You a perpetual,
|
| 69 |
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
| 70 |
+
copyright license to reproduce, prepare Derivative Works of,
|
| 71 |
+
publicly display, publicly perform, sublicense, and distribute the
|
| 72 |
+
Work and such Derivative Works in Source or Object form.
|
| 73 |
+
|
| 74 |
+
3. Grant of Patent License. Subject to the terms and conditions of
|
| 75 |
+
this License, each Contributor hereby grants to You a perpetual,
|
| 76 |
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
| 77 |
+
(except as stated in this section) patent license to make, have made,
|
| 78 |
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
| 79 |
+
where such license applies only to those patent claims licensable
|
| 80 |
+
by such Contributor that are necessarily infringed by their
|
| 81 |
+
Contribution(s) alone or by combination of their Contribution(s)
|
| 82 |
+
with the Work to which such Contribution(s) was submitted. If You
|
| 83 |
+
institute patent litigation against any entity (including a
|
| 84 |
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
| 85 |
+
or a Contribution incorporated within the Work constitutes direct
|
| 86 |
+
or contributory patent infringement, then any patent licenses
|
| 87 |
+
granted to You under this License for that Work shall terminate
|
| 88 |
+
as of the date such litigation is filed.
|
| 89 |
+
|
| 90 |
+
4. Redistribution. You may reproduce and distribute copies of the
|
| 91 |
+
Work or Derivative Works thereof in any medium, with or without
|
| 92 |
+
modifications, and in Source or Object form, provided that You
|
| 93 |
+
meet the following conditions:
|
| 94 |
+
|
| 95 |
+
(a) You must give any other recipients of the Work or
|
| 96 |
+
Derivative Works a copy of this License; and
|
| 97 |
+
|
| 98 |
+
(b) You must cause any modified files to carry prominent notices
|
| 99 |
+
stating that You changed the files; and
|
| 100 |
+
|
| 101 |
+
(c) You must retain, in the Source form of any Derivative Works
|
| 102 |
+
that You distribute, all copyright, patent, trademark, and
|
| 103 |
+
attribution notices from the Source form of the Work,
|
| 104 |
+
excluding those notices that do not pertain to any part of
|
| 105 |
+
the Derivative Works; and
|
| 106 |
+
|
| 107 |
+
(d) If the Work includes a "NOTICE" text file as part of its
|
| 108 |
+
distribution, then any Derivative Works that You distribute must
|
| 109 |
+
include a readable copy of the attribution notices contained
|
| 110 |
+
within such NOTICE file, excluding those notices that do not
|
| 111 |
+
pertain to any part of the Derivative Works, in at least one
|
| 112 |
+
of the following places: within a NOTICE text file distributed
|
| 113 |
+
as part of the Derivative Works; within the Source form or
|
| 114 |
+
documentation, if provided along with the Derivative Works; or,
|
| 115 |
+
within a display generated by the Derivative Works, if and
|
| 116 |
+
wherever such third-party notices normally appear. The contents
|
| 117 |
+
of the NOTICE file are for informational purposes only and
|
| 118 |
+
do not modify the License. You may add Your own attribution
|
| 119 |
+
notices within Derivative Works that You distribute, alongside
|
| 120 |
+
or as an addendum to the NOTICE text from the Work, provided
|
| 121 |
+
that such additional attribution notices cannot be construed
|
| 122 |
+
as modifying the License.
|
| 123 |
+
|
| 124 |
+
You may add Your own copyright statement to Your modifications and
|
| 125 |
+
may provide additional or different license terms and conditions
|
| 126 |
+
for use, reproduction, or distribution of Your modifications, or
|
| 127 |
+
for any such Derivative Works as a whole, provided Your use,
|
| 128 |
+
reproduction, and distribution of the Work otherwise complies with
|
| 129 |
+
the conditions stated in this License.
|
| 130 |
+
|
| 131 |
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
| 132 |
+
any Contribution intentionally submitted for inclusion in the Work
|
| 133 |
+
by You to the Licensor shall be under the terms and conditions of
|
| 134 |
+
this License, without any additional terms or conditions.
|
| 135 |
+
Notwithstanding the above, nothing herein shall supersede or modify
|
| 136 |
+
the terms of any separate license agreement you may have executed
|
| 137 |
+
with Licensor regarding such Contributions.
|
| 138 |
+
|
| 139 |
+
6. Trademarks. This License does not grant permission to use the trade
|
| 140 |
+
names, trademarks, service marks, or product names of the Licensor,
|
| 141 |
+
except as required for reasonable and customary use in describing the
|
| 142 |
+
origin of the Work and reproducing the content of the NOTICE file.
|
| 143 |
+
|
| 144 |
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
| 145 |
+
agreed to in writing, Licensor provides the Work (and each
|
| 146 |
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
| 147 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
| 148 |
+
implied, including, without limitation, any warranties or conditions
|
| 149 |
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
| 150 |
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
| 151 |
+
appropriateness of using or redistributing the Work and assume any
|
| 152 |
+
risks associated with Your exercise of permissions under this License.
|
| 153 |
+
|
| 154 |
+
8. Limitation of Liability. In no event and under no legal theory,
|
| 155 |
+
whether in tort (including negligence), contract, or otherwise,
|
| 156 |
+
unless required by applicable law (such as deliberate and grossly
|
| 157 |
+
negligent acts) or agreed to in writing, shall any Contributor be
|
| 158 |
+
liable to You for damages, including any direct, indirect, special,
|
| 159 |
+
incidental, or consequential damages of any character arising as a
|
| 160 |
+
result of this License or out of the use or inability to use the
|
| 161 |
+
Work (including but not limited to damages for loss of goodwill,
|
| 162 |
+
work stoppage, computer failure or malfunction, or any and all
|
| 163 |
+
other commercial damages or losses), even if such Contributor
|
| 164 |
+
has been advised of the possibility of such damages.
|
| 165 |
+
|
| 166 |
+
9. Accepting Warranty or Additional Liability. While redistributing
|
| 167 |
+
the Work or Derivative Works thereof, You may choose to offer,
|
| 168 |
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
| 169 |
+
or other liability obligations and/or rights consistent with this
|
| 170 |
+
License. However, in accepting such obligations, You may act only
|
| 171 |
+
on Your own behalf and on Your sole responsibility, not on behalf
|
| 172 |
+
of any other Contributor, and only if You agree to indemnify,
|
| 173 |
+
defend, and hold each Contributor harmless for any liability
|
| 174 |
+
incurred by, or claims asserted against, such Contributor by reason
|
| 175 |
+
of your accepting any such warranty or additional liability.
|
| 176 |
+
|
| 177 |
+
END OF TERMS AND CONDITIONS
|
| 178 |
+
|
| 179 |
+
APPENDIX: How to apply the Apache License to your work.
|
| 180 |
+
|
| 181 |
+
To apply the Apache License to your work, attach the following
|
| 182 |
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
| 183 |
+
replaced with your own identifying information. (Don't include
|
| 184 |
+
the brackets!) The text should be enclosed in the appropriate
|
| 185 |
+
comment syntax for the file format. We also recommend that a
|
| 186 |
+
file or class name and description of purpose be included on the
|
| 187 |
+
same "printed page" as the copyright notice for easier
|
| 188 |
+
identification within third-party archives.
|
| 189 |
+
|
| 190 |
+
Copyright 2026 Lowdown Labs
|
| 191 |
+
|
| 192 |
+
Licensed under the Apache License, Version 2.0 (the "License");
|
| 193 |
+
you may not use this file except in compliance with the License.
|
| 194 |
+
You may obtain a copy of the License at
|
| 195 |
+
|
| 196 |
+
http://www.apache.org/licenses/LICENSE-2.0
|
| 197 |
+
|
| 198 |
+
Unless required by applicable law or agreed to in writing, software
|
| 199 |
+
distributed under the License is distributed on an "AS IS" BASIS,
|
| 200 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 201 |
+
See the License for the specific language governing permissions and
|
| 202 |
+
limitations under the License.
|
README.md
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: apache-2.0
|
| 3 |
+
tags:
|
| 4 |
+
- fela
|
| 5 |
+
- felatab
|
| 6 |
+
- tabular
|
| 7 |
+
- in-context-learning
|
| 8 |
+
- prior-fitted-network
|
| 9 |
+
- foundation-model
|
| 10 |
+
- delta-rule
|
| 11 |
+
- cpu
|
| 12 |
+
- on-device
|
| 13 |
+
library_name: transformers
|
| 14 |
+
pipeline_tag: tabular-classification
|
| 15 |
+
model-index:
|
| 16 |
+
- name: fela-tab
|
| 17 |
+
results:
|
| 18 |
+
- task:
|
| 19 |
+
type: tabular-classification
|
| 20 |
+
name: Tabular classification
|
| 21 |
+
dataset:
|
| 22 |
+
type: openml
|
| 23 |
+
name: OpenML (8 datasets)
|
| 24 |
+
metrics:
|
| 25 |
+
- type: accuracy
|
| 26 |
+
value: 0.819
|
| 27 |
+
name: mean accuracy (zero shot)
|
| 28 |
+
---
|
| 29 |
+
|
| 30 |
+
# DISCLAIMER
|
| 31 |
+
|
| 32 |
+
This model is a research preview. It is offered for advancing public science and for evaluation.
|
| 33 |
+
It is not a substitute for a domain expert, and it is not a certified decision system.
|
| 34 |
+
|
| 35 |
+
# FelaTab: point at any table in context tabular model
|
| 36 |
+
|
| 37 |
+
FelaTab reads a small table you already have and predicts the missing cells. You give it some
|
| 38 |
+
example rows with their answers (the support rows) and one or more rows you want filled in (the
|
| 39 |
+
query rows); it learns the pattern from your examples in a single pass and returns the answer with
|
| 40 |
+
a calibrated confidence range. There is no per table training, no fitting, and no setup: you point
|
| 41 |
+
it at a table and it predicts. It runs on a plain CPU with no GPU.
|
| 42 |
+
|
| 43 |
+
It is a prior fitted network (a "foundation model for tables"), trained on millions of synthetic
|
| 44 |
+
tables so that it generalizes zero shot to real tables it has never seen.
|
| 45 |
+
|
| 46 |
+
# What goes in, what comes out
|
| 47 |
+
|
| 48 |
+
- Input: one table, split into SUPPORT rows (features + a known label) and QUERY rows (features
|
| 49 |
+
only). Features are plain numbers; the model standardizes them for you. Up to 100 feature
|
| 50 |
+
columns and, for classification, up to 10 classes.
|
| 51 |
+
- Output:
|
| 52 |
+
- Classification: a probability for each class on every query row (they sum to one). Pick the
|
| 53 |
+
top class as the prediction and read the probability as the confidence.
|
| 54 |
+
- Regression: a predicted value plus a standard deviation on every query row, an honest error
|
| 55 |
+
bar in the original units of your label, not just a point estimate.
|
| 56 |
+
- In plain terms: "these rows look labelled like this; fill the blank ones and tell me how sure
|
| 57 |
+
you are."
|
| 58 |
+
|
| 59 |
+
# Why we built it this way
|
| 60 |
+
|
| 61 |
+
The "sequence" the model attends over is the SET of rows of your table. Support rows carry their
|
| 62 |
+
label and write into a fixed size working state; query rows are read only (they never write the
|
| 63 |
+
state and never see each other, so there is no test time leakage). The mixer is a delta rule
|
| 64 |
+
linear attention (an overwrite update that fixes the recall weakness of plain linear attention)
|
| 65 |
+
plus a variable chunk landmark attention over pooled support rows. Both are linear in the number
|
| 66 |
+
of rows with a fixed working state, so the model scales past the quadratic roughly 10k row cap of
|
| 67 |
+
full attention tabular models, and its memory stays flat as the support set grows. That is what
|
| 68 |
+
lets it run on a low power CPU and index large tables without a GPU.
|
| 69 |
+
|
| 70 |
+
## The two tiers (one model, pick your size)
|
| 71 |
+
|
| 72 |
+
FelaTab ships two tiers from ONE MatFormer nested training run. The small model is a strict
|
| 73 |
+
top left prefix slice of the big model's weights (nesting verified bit exact at full
|
| 74 |
+
granularity), so you get both from a single set of weights and can pick your size/accuracy
|
| 75 |
+
tradeoff.
|
| 76 |
+
|
| 77 |
+
| Tier | dim | layers | heads | params | fp32 file | int8 file |
|
| 78 |
+
|-------|-----|--------|-------|--------|-----------|-----------|
|
| 79 |
+
| big | 1024 | 28 | 16 | 411.9M | `model_big.safetensors` (1.65 GB) | `model_big_int8.safetensors` (416 MB) |
|
| 80 |
+
| small | 512 | 14 | 8 | 51.6M | `model_small.safetensors` (206 MB) | `model_small_int8.safetensors` (52 MB) |
|
| 81 |
+
|
| 82 |
+
int8 is close to lossless here (see below), so the int8 files are the recommended deploy
|
| 83 |
+
artifact. The in browser demo runs the small int8 tier.
|
| 84 |
+
|
| 85 |
+
# Performance and footprint
|
| 86 |
+
|
| 87 |
+
Measured on CPU. The working memory is flat as the support set grows: on the OpenML `adult`
|
| 88 |
+
dataset the big model's resident set stays at about **3.79 GB from 500 support rows all the way to
|
| 89 |
+
10,000** support rows (the model carries a fixed size state, not a growing key value cache), while
|
| 90 |
+
a full attention model would grow quadratically. Row throughput is linear in the support size.
|
| 91 |
+
|
| 92 |
+
# Accuracy (held out OpenML)
|
| 93 |
+
|
| 94 |
+
Protocol: zero shot, TabPFN style. The train split of a real OpenML dataset is fed as support
|
| 95 |
+
rows, the test split as query rows, in one in context forward, no per dataset training. The
|
| 96 |
+
reported battery is 8 classification and 5 regression datasets. Field bars are untuned
|
| 97 |
+
scikit-learn and a TUNED LightGBM; the "full ensemble" is FelaTab combined with gradient boosted
|
| 98 |
+
trees and ridge. The numbers below are measured on the shipped weights.
|
| 99 |
+
|
| 100 |
+
## Classification (8 datasets, mean accuracy)
|
| 101 |
+
|
| 102 |
+
| System | Accuracy |
|
| 103 |
+
|---|---|
|
| 104 |
+
| FelaTab big, single pass | 0.819 |
|
| 105 |
+
| FelaTab small, single pass | 0.810 |
|
| 106 |
+
| tuned LightGBM | 0.827 |
|
| 107 |
+
| untuned scikit-learn, best | 0.834 |
|
| 108 |
+
| full ensemble (FelaTab + GBT + ridge, stacked) | 0.840 |
|
| 109 |
+
|
| 110 |
+
- With no tuning, FelaTab alone matches or beats a **tuned** LightGBM on **5 of the 8** datasets.
|
| 111 |
+
- FelaTab alone reaches about **97%** of the full ensemble's accuracy (0.819 vs 0.840).
|
| 112 |
+
- Calibration is good: expected calibration error about **0.051** for FelaTab, and a conformal
|
| 113 |
+
wrapper hits its target coverage (empirical coverage about **0.91** for FelaTab and about **0.92**
|
| 114 |
+
for the ensemble at a 0.90 guarantee).
|
| 115 |
+
- Inference time bagging (averaging the frozen model over permuted feature orders and a reshuffled
|
| 116 |
+
support set) did not improve the big tier on this battery (it measured 0.811, below the single
|
| 117 |
+
pass), so the single pass is the number to use.
|
| 118 |
+
|
| 119 |
+
## Regression (5 datasets)
|
| 120 |
+
|
| 121 |
+
On regression accuracy FelaTab alone beats neither untuned scikit-learn nor a tuned LightGBM on any
|
| 122 |
+
of the 5 datasets (**0 of 5**) but it's not off by far; its mean R2 is 0.813 versus 0.880 for a tuned LightGBM.
|
| 123 |
+
|
| 124 |
+
This is a training budget limit of the current model, not a bug. What
|
| 125 |
+
FelaTab ships for regression is, however, calibrated uncertainty: a Gaussian mean and standard
|
| 126 |
+
deviation per row, plus a conformal wrapper that reaches its coverage target (empirical coverage
|
| 127 |
+
about 0.91 at a 0.90 guarantee). If you need maximum regression accuracy, use a gradient boosted
|
| 128 |
+
tree; use FelaTab's regression head for a fast zero shot estimate with a trustworthy error bar.
|
| 129 |
+
|
| 130 |
+
## int8 is close to lossless
|
| 131 |
+
|
| 132 |
+
Dynamic int8 on the bulk linear layers barely moves accuracy: classification 0.819 fp32 vs 0.816
|
| 133 |
+
int8 for the big tier and 0.810 vs 0.809 for the small tier, regression within 0.002 R2 either
|
| 134 |
+
way. The int8 files are 4x smaller and are the recommended deploy format.
|
| 135 |
+
|
| 136 |
+
|
| 137 |
+
# How to run it
|
| 138 |
+
|
| 139 |
+
See `quickstart/` for a runnable example on public sklearn datasets. The short version:
|
| 140 |
+
|
| 141 |
+
```python
|
| 142 |
+
from modeling import load_model, predict
|
| 143 |
+
|
| 144 |
+
model = load_model("/path/to/repo_dir", tier="small") # or "big"; or a HF repo id
|
| 145 |
+
# Xtr, ytr = your labelled support rows; Xte = the rows to predict
|
| 146 |
+
probs = predict(model, Xtr, ytr, Xte, task="classification", n_classes=3) # [n_query, 3]
|
| 147 |
+
mean, std = predict(model, Xtr, ytr, Xte, task="regression") # error bars
|
| 148 |
+
```
|
| 149 |
+
|
| 150 |
+
The loader ships `config_big.json` / `config_small.json` (a top level `config.json` mirrors the
|
| 151 |
+
big tier) and a self contained `modeling.py` with `load_model` / `from_pretrained`. It
|
| 152 |
+
auto detects the int8 bundles and dequantizes them, so you always get a plain fp32 model back. For
|
| 153 |
+
an interactive playground, see the Hugging Face Space in `space/`.
|
| 154 |
+
|
| 155 |
+
## Serving artifacts
|
| 156 |
+
|
| 157 |
+
- `model_<tier>.safetensors` (fp32) and `model_<tier>_int8.safetensors` (int8), plus the matching
|
| 158 |
+
`config_<tier>.json`.
|
| 159 |
+
- `verify.py` runs two fixed bundled tasks (one classification, one regression), checks the output
|
| 160 |
+
shapes, that the regression standard deviations are positive, and that the small tier
|
| 161 |
+
predictions match a stored reference within the shipped int8 tolerance.
|
| 162 |
+
- `modeling.py` also exposes `predict_bagged` (the inference bagging path) and the full
|
| 163 |
+
architecture for standard tooling.
|
| 164 |
+
|
| 165 |
+
FelaTab is embedded natively in the CPU FELA server and in a PostgreSQL extension (`fela_classify`
|
| 166 |
+
in database), and runs client side in the browser via WebAssembly (the small int8 tier). Those
|
| 167 |
+
paths reproduce the Python predictions to within the int8 tolerance.
|
| 168 |
+
|
| 169 |
+
## Training data
|
| 170 |
+
|
| 171 |
+
FelaTab is a prior fitted network: trained on synthetic tables from a structural causal model prior
|
| 172 |
+
(about 85% of the stream) with a small mix in of teacher baked real public OpenML tables (about
|
| 173 |
+
15%), and evaluated zero shot on held out real OpenML datasets that are excluded from training by
|
| 174 |
+
dataset id and name. No customer data and no benchmarked test set is in the training stream. The
|
| 175 |
+
synthetic prior is in `prior.py` and the training objective is in `train.py`, which reproduces the
|
| 176 |
+
method (`python train.py --smoke`).
|
| 177 |
+
|
| 178 |
+
# Intended use, limitations, and safety
|
| 179 |
+
|
| 180 |
+
What it is for: fast, zero shot predictions and autofill on small to medium tables where you do
|
| 181 |
+
not want to set up and tune a model: spreadsheet autofill, in database prediction, quick
|
| 182 |
+
what if estimates, and calibrated triage where the confidence matters as much as the answer. It is
|
| 183 |
+
a good first pass and a strong no tuning baseline.
|
| 184 |
+
|
| 185 |
+
What it is not: it is not a replacement for a tuned gradient boosted tree when you want maximum
|
| 186 |
+
accuracy, especially on regression, where it is behind trees and ships error bars instead of
|
| 187 |
+
headline accuracy. It is capped at 100 features and 10 classes. It is trained and validated on
|
| 188 |
+
standard public tabular benchmarks; generalization to a very different distribution should be
|
| 189 |
+
checked on your own held out data before you rely on it. Do not use it as the sole basis for a
|
| 190 |
+
consequential decision.
|
| 191 |
+
|
| 192 |
+
# How to cite
|
| 193 |
+
|
| 194 |
+
```bibtex
|
| 195 |
+
@misc{lowdownlabs_felatab,
|
| 196 |
+
title = {FelaTab: an in context tabular foundation model on the FELA linear attention base},
|
| 197 |
+
author = {Lowdown Labs},
|
| 198 |
+
year = {2026},
|
| 199 |
+
note = {Model card}
|
| 200 |
+
}
|
| 201 |
+
```
|
| 202 |
+
|
| 203 |
+
# Model family
|
| 204 |
+
|
| 205 |
+
This is part of the FELA family from Lowdown Labs: one linear attention architecture across many
|
| 206 |
+
modalities, all CPU native and subquadratic. Sibling repos share no weights, so none carries a
|
| 207 |
+
`base_model` link.
|
| 208 |
+
|
| 209 |
+
# License
|
| 210 |
+
Apache-2.0. The model weights and the code are both under Apache-2.0 (see LICENSE): no separate model license and no non commercial restriction. Trained on synthetic data; the OpenML datasets are used only for evaluation, not training. We distribute weights only.
|
config.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"model_type": "felatab",
|
| 3 |
+
"library_name": "transformers",
|
| 4 |
+
"architectures": [
|
| 5 |
+
"FelaTabModel"
|
| 6 |
+
],
|
| 7 |
+
"auto_map": {
|
| 8 |
+
"AutoConfig": "configuration_felatab.FelaTabConfig",
|
| 9 |
+
"AutoModel": "modeling_felatab.FelaTabModel"
|
| 10 |
+
},
|
| 11 |
+
"arch": "FelaTab",
|
| 12 |
+
"tier": "big",
|
| 13 |
+
"params_millions": 411.86,
|
| 14 |
+
"max_features": 100,
|
| 15 |
+
"max_classes": 10,
|
| 16 |
+
"dim": 1024,
|
| 17 |
+
"n_layers": 28,
|
| 18 |
+
"n_heads": 16,
|
| 19 |
+
"head_dim": 64,
|
| 20 |
+
"chunk": 64,
|
| 21 |
+
"ffn_mult": 3,
|
| 22 |
+
"use_landmark": true,
|
| 23 |
+
"n_landmarks": 48,
|
| 24 |
+
"ln_eps": 1e-05,
|
| 25 |
+
"note": "Reads support rows (features plus label) then query rows; returns class probabilities or mean and std error bars."
|
| 26 |
+
}
|
config_big.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"model_type": "felatab",
|
| 3 |
+
"library_name": "pytorch",
|
| 4 |
+
"arch": "FelaTab",
|
| 5 |
+
"tier": "big",
|
| 6 |
+
"params_millions": 411.86,
|
| 7 |
+
"max_features": 100,
|
| 8 |
+
"max_classes": 10,
|
| 9 |
+
"dim": 1024,
|
| 10 |
+
"n_layers": 28,
|
| 11 |
+
"n_heads": 16,
|
| 12 |
+
"head_dim": 64,
|
| 13 |
+
"chunk": 64,
|
| 14 |
+
"ffn_mult": 3,
|
| 15 |
+
"use_landmark": true,
|
| 16 |
+
"n_landmarks": 48,
|
| 17 |
+
"ln_eps": 1e-05,
|
| 18 |
+
"note": "Reads support rows (features plus label) then query rows; returns class probabilities or mean and std error bars."
|
| 19 |
+
}
|
config_small.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"model_type": "felatab",
|
| 3 |
+
"library_name": "pytorch",
|
| 4 |
+
"arch": "FelaTab",
|
| 5 |
+
"tier": "small",
|
| 6 |
+
"params_millions": 51.56,
|
| 7 |
+
"max_features": 100,
|
| 8 |
+
"max_classes": 10,
|
| 9 |
+
"dim": 512,
|
| 10 |
+
"n_layers": 14,
|
| 11 |
+
"n_heads": 8,
|
| 12 |
+
"head_dim": 64,
|
| 13 |
+
"chunk": 64,
|
| 14 |
+
"ffn_mult": 3,
|
| 15 |
+
"use_landmark": true,
|
| 16 |
+
"n_landmarks": 48,
|
| 17 |
+
"ln_eps": 1e-05,
|
| 18 |
+
"note": "Reads support rows (features plus label) then query rows; returns class probabilities or mean and std error bars."
|
| 19 |
+
}
|
configuration_felatab.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from transformers import PretrainedConfig
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
class FelaTabConfig(PretrainedConfig):
|
| 5 |
+
model_type = "felatab"
|
| 6 |
+
|
| 7 |
+
def __init__(
|
| 8 |
+
self,
|
| 9 |
+
max_features=100,
|
| 10 |
+
max_classes=10,
|
| 11 |
+
dim=1024,
|
| 12 |
+
n_layers=28,
|
| 13 |
+
n_heads=16,
|
| 14 |
+
head_dim=64,
|
| 15 |
+
chunk=64,
|
| 16 |
+
ffn_mult=3,
|
| 17 |
+
dropout=0.0,
|
| 18 |
+
use_landmark=True,
|
| 19 |
+
n_landmarks=48,
|
| 20 |
+
ln_eps=1e-05,
|
| 21 |
+
**kwargs,
|
| 22 |
+
):
|
| 23 |
+
self.max_features = max_features
|
| 24 |
+
self.max_classes = max_classes
|
| 25 |
+
self.dim = dim
|
| 26 |
+
self.n_layers = n_layers
|
| 27 |
+
self.n_heads = n_heads
|
| 28 |
+
self.head_dim = head_dim
|
| 29 |
+
self.chunk = chunk
|
| 30 |
+
self.ffn_mult = ffn_mult
|
| 31 |
+
self.dropout = dropout
|
| 32 |
+
self.use_landmark = use_landmark
|
| 33 |
+
self.n_landmarks = n_landmarks
|
| 34 |
+
self.ln_eps = ln_eps
|
| 35 |
+
super().__init__(**kwargs)
|
model.safetensors.index.json
ADDED
|
@@ -0,0 +1,552 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"metadata": {
|
| 3 |
+
"total_size": 1647454116
|
| 4 |
+
},
|
| 5 |
+
"weight_map": {
|
| 6 |
+
"blocks.0.attn.b.bias": "model_big.safetensors",
|
| 7 |
+
"blocks.0.attn.b.weight": "model_big.safetensors",
|
| 8 |
+
"blocks.0.attn.k.weight": "model_big.safetensors",
|
| 9 |
+
"blocks.0.attn.o.weight": "model_big.safetensors",
|
| 10 |
+
"blocks.0.attn.q.weight": "model_big.safetensors",
|
| 11 |
+
"blocks.0.attn.v.weight": "model_big.safetensors",
|
| 12 |
+
"blocks.0.ff.0.bias": "model_big.safetensors",
|
| 13 |
+
"blocks.0.ff.0.weight": "model_big.safetensors",
|
| 14 |
+
"blocks.0.ff.2.bias": "model_big.safetensors",
|
| 15 |
+
"blocks.0.ff.2.weight": "model_big.safetensors",
|
| 16 |
+
"blocks.0.landmark.gate": "model_big.safetensors",
|
| 17 |
+
"blocks.0.landmark.k.weight": "model_big.safetensors",
|
| 18 |
+
"blocks.0.landmark.o.weight": "model_big.safetensors",
|
| 19 |
+
"blocks.0.landmark.q.weight": "model_big.safetensors",
|
| 20 |
+
"blocks.0.landmark.v.weight": "model_big.safetensors",
|
| 21 |
+
"blocks.0.n1.bias": "model_big.safetensors",
|
| 22 |
+
"blocks.0.n1.weight": "model_big.safetensors",
|
| 23 |
+
"blocks.0.n2.bias": "model_big.safetensors",
|
| 24 |
+
"blocks.0.n2.weight": "model_big.safetensors",
|
| 25 |
+
"blocks.1.attn.b.bias": "model_big.safetensors",
|
| 26 |
+
"blocks.1.attn.b.weight": "model_big.safetensors",
|
| 27 |
+
"blocks.1.attn.k.weight": "model_big.safetensors",
|
| 28 |
+
"blocks.1.attn.o.weight": "model_big.safetensors",
|
| 29 |
+
"blocks.1.attn.q.weight": "model_big.safetensors",
|
| 30 |
+
"blocks.1.attn.v.weight": "model_big.safetensors",
|
| 31 |
+
"blocks.1.ff.0.bias": "model_big.safetensors",
|
| 32 |
+
"blocks.1.ff.0.weight": "model_big.safetensors",
|
| 33 |
+
"blocks.1.ff.2.bias": "model_big.safetensors",
|
| 34 |
+
"blocks.1.ff.2.weight": "model_big.safetensors",
|
| 35 |
+
"blocks.1.landmark.gate": "model_big.safetensors",
|
| 36 |
+
"blocks.1.landmark.k.weight": "model_big.safetensors",
|
| 37 |
+
"blocks.1.landmark.o.weight": "model_big.safetensors",
|
| 38 |
+
"blocks.1.landmark.q.weight": "model_big.safetensors",
|
| 39 |
+
"blocks.1.landmark.v.weight": "model_big.safetensors",
|
| 40 |
+
"blocks.1.n1.bias": "model_big.safetensors",
|
| 41 |
+
"blocks.1.n1.weight": "model_big.safetensors",
|
| 42 |
+
"blocks.1.n2.bias": "model_big.safetensors",
|
| 43 |
+
"blocks.1.n2.weight": "model_big.safetensors",
|
| 44 |
+
"blocks.10.attn.b.bias": "model_big.safetensors",
|
| 45 |
+
"blocks.10.attn.b.weight": "model_big.safetensors",
|
| 46 |
+
"blocks.10.attn.k.weight": "model_big.safetensors",
|
| 47 |
+
"blocks.10.attn.o.weight": "model_big.safetensors",
|
| 48 |
+
"blocks.10.attn.q.weight": "model_big.safetensors",
|
| 49 |
+
"blocks.10.attn.v.weight": "model_big.safetensors",
|
| 50 |
+
"blocks.10.ff.0.bias": "model_big.safetensors",
|
| 51 |
+
"blocks.10.ff.0.weight": "model_big.safetensors",
|
| 52 |
+
"blocks.10.ff.2.bias": "model_big.safetensors",
|
| 53 |
+
"blocks.10.ff.2.weight": "model_big.safetensors",
|
| 54 |
+
"blocks.10.landmark.gate": "model_big.safetensors",
|
| 55 |
+
"blocks.10.landmark.k.weight": "model_big.safetensors",
|
| 56 |
+
"blocks.10.landmark.o.weight": "model_big.safetensors",
|
| 57 |
+
"blocks.10.landmark.q.weight": "model_big.safetensors",
|
| 58 |
+
"blocks.10.landmark.v.weight": "model_big.safetensors",
|
| 59 |
+
"blocks.10.n1.bias": "model_big.safetensors",
|
| 60 |
+
"blocks.10.n1.weight": "model_big.safetensors",
|
| 61 |
+
"blocks.10.n2.bias": "model_big.safetensors",
|
| 62 |
+
"blocks.10.n2.weight": "model_big.safetensors",
|
| 63 |
+
"blocks.11.attn.b.bias": "model_big.safetensors",
|
| 64 |
+
"blocks.11.attn.b.weight": "model_big.safetensors",
|
| 65 |
+
"blocks.11.attn.k.weight": "model_big.safetensors",
|
| 66 |
+
"blocks.11.attn.o.weight": "model_big.safetensors",
|
| 67 |
+
"blocks.11.attn.q.weight": "model_big.safetensors",
|
| 68 |
+
"blocks.11.attn.v.weight": "model_big.safetensors",
|
| 69 |
+
"blocks.11.ff.0.bias": "model_big.safetensors",
|
| 70 |
+
"blocks.11.ff.0.weight": "model_big.safetensors",
|
| 71 |
+
"blocks.11.ff.2.bias": "model_big.safetensors",
|
| 72 |
+
"blocks.11.ff.2.weight": "model_big.safetensors",
|
| 73 |
+
"blocks.11.landmark.gate": "model_big.safetensors",
|
| 74 |
+
"blocks.11.landmark.k.weight": "model_big.safetensors",
|
| 75 |
+
"blocks.11.landmark.o.weight": "model_big.safetensors",
|
| 76 |
+
"blocks.11.landmark.q.weight": "model_big.safetensors",
|
| 77 |
+
"blocks.11.landmark.v.weight": "model_big.safetensors",
|
| 78 |
+
"blocks.11.n1.bias": "model_big.safetensors",
|
| 79 |
+
"blocks.11.n1.weight": "model_big.safetensors",
|
| 80 |
+
"blocks.11.n2.bias": "model_big.safetensors",
|
| 81 |
+
"blocks.11.n2.weight": "model_big.safetensors",
|
| 82 |
+
"blocks.12.attn.b.bias": "model_big.safetensors",
|
| 83 |
+
"blocks.12.attn.b.weight": "model_big.safetensors",
|
| 84 |
+
"blocks.12.attn.k.weight": "model_big.safetensors",
|
| 85 |
+
"blocks.12.attn.o.weight": "model_big.safetensors",
|
| 86 |
+
"blocks.12.attn.q.weight": "model_big.safetensors",
|
| 87 |
+
"blocks.12.attn.v.weight": "model_big.safetensors",
|
| 88 |
+
"blocks.12.ff.0.bias": "model_big.safetensors",
|
| 89 |
+
"blocks.12.ff.0.weight": "model_big.safetensors",
|
| 90 |
+
"blocks.12.ff.2.bias": "model_big.safetensors",
|
| 91 |
+
"blocks.12.ff.2.weight": "model_big.safetensors",
|
| 92 |
+
"blocks.12.landmark.gate": "model_big.safetensors",
|
| 93 |
+
"blocks.12.landmark.k.weight": "model_big.safetensors",
|
| 94 |
+
"blocks.12.landmark.o.weight": "model_big.safetensors",
|
| 95 |
+
"blocks.12.landmark.q.weight": "model_big.safetensors",
|
| 96 |
+
"blocks.12.landmark.v.weight": "model_big.safetensors",
|
| 97 |
+
"blocks.12.n1.bias": "model_big.safetensors",
|
| 98 |
+
"blocks.12.n1.weight": "model_big.safetensors",
|
| 99 |
+
"blocks.12.n2.bias": "model_big.safetensors",
|
| 100 |
+
"blocks.12.n2.weight": "model_big.safetensors",
|
| 101 |
+
"blocks.13.attn.b.bias": "model_big.safetensors",
|
| 102 |
+
"blocks.13.attn.b.weight": "model_big.safetensors",
|
| 103 |
+
"blocks.13.attn.k.weight": "model_big.safetensors",
|
| 104 |
+
"blocks.13.attn.o.weight": "model_big.safetensors",
|
| 105 |
+
"blocks.13.attn.q.weight": "model_big.safetensors",
|
| 106 |
+
"blocks.13.attn.v.weight": "model_big.safetensors",
|
| 107 |
+
"blocks.13.ff.0.bias": "model_big.safetensors",
|
| 108 |
+
"blocks.13.ff.0.weight": "model_big.safetensors",
|
| 109 |
+
"blocks.13.ff.2.bias": "model_big.safetensors",
|
| 110 |
+
"blocks.13.ff.2.weight": "model_big.safetensors",
|
| 111 |
+
"blocks.13.landmark.gate": "model_big.safetensors",
|
| 112 |
+
"blocks.13.landmark.k.weight": "model_big.safetensors",
|
| 113 |
+
"blocks.13.landmark.o.weight": "model_big.safetensors",
|
| 114 |
+
"blocks.13.landmark.q.weight": "model_big.safetensors",
|
| 115 |
+
"blocks.13.landmark.v.weight": "model_big.safetensors",
|
| 116 |
+
"blocks.13.n1.bias": "model_big.safetensors",
|
| 117 |
+
"blocks.13.n1.weight": "model_big.safetensors",
|
| 118 |
+
"blocks.13.n2.bias": "model_big.safetensors",
|
| 119 |
+
"blocks.13.n2.weight": "model_big.safetensors",
|
| 120 |
+
"blocks.14.attn.b.bias": "model_big.safetensors",
|
| 121 |
+
"blocks.14.attn.b.weight": "model_big.safetensors",
|
| 122 |
+
"blocks.14.attn.k.weight": "model_big.safetensors",
|
| 123 |
+
"blocks.14.attn.o.weight": "model_big.safetensors",
|
| 124 |
+
"blocks.14.attn.q.weight": "model_big.safetensors",
|
| 125 |
+
"blocks.14.attn.v.weight": "model_big.safetensors",
|
| 126 |
+
"blocks.14.ff.0.bias": "model_big.safetensors",
|
| 127 |
+
"blocks.14.ff.0.weight": "model_big.safetensors",
|
| 128 |
+
"blocks.14.ff.2.bias": "model_big.safetensors",
|
| 129 |
+
"blocks.14.ff.2.weight": "model_big.safetensors",
|
| 130 |
+
"blocks.14.landmark.gate": "model_big.safetensors",
|
| 131 |
+
"blocks.14.landmark.k.weight": "model_big.safetensors",
|
| 132 |
+
"blocks.14.landmark.o.weight": "model_big.safetensors",
|
| 133 |
+
"blocks.14.landmark.q.weight": "model_big.safetensors",
|
| 134 |
+
"blocks.14.landmark.v.weight": "model_big.safetensors",
|
| 135 |
+
"blocks.14.n1.bias": "model_big.safetensors",
|
| 136 |
+
"blocks.14.n1.weight": "model_big.safetensors",
|
| 137 |
+
"blocks.14.n2.bias": "model_big.safetensors",
|
| 138 |
+
"blocks.14.n2.weight": "model_big.safetensors",
|
| 139 |
+
"blocks.15.attn.b.bias": "model_big.safetensors",
|
| 140 |
+
"blocks.15.attn.b.weight": "model_big.safetensors",
|
| 141 |
+
"blocks.15.attn.k.weight": "model_big.safetensors",
|
| 142 |
+
"blocks.15.attn.o.weight": "model_big.safetensors",
|
| 143 |
+
"blocks.15.attn.q.weight": "model_big.safetensors",
|
| 144 |
+
"blocks.15.attn.v.weight": "model_big.safetensors",
|
| 145 |
+
"blocks.15.ff.0.bias": "model_big.safetensors",
|
| 146 |
+
"blocks.15.ff.0.weight": "model_big.safetensors",
|
| 147 |
+
"blocks.15.ff.2.bias": "model_big.safetensors",
|
| 148 |
+
"blocks.15.ff.2.weight": "model_big.safetensors",
|
| 149 |
+
"blocks.15.landmark.gate": "model_big.safetensors",
|
| 150 |
+
"blocks.15.landmark.k.weight": "model_big.safetensors",
|
| 151 |
+
"blocks.15.landmark.o.weight": "model_big.safetensors",
|
| 152 |
+
"blocks.15.landmark.q.weight": "model_big.safetensors",
|
| 153 |
+
"blocks.15.landmark.v.weight": "model_big.safetensors",
|
| 154 |
+
"blocks.15.n1.bias": "model_big.safetensors",
|
| 155 |
+
"blocks.15.n1.weight": "model_big.safetensors",
|
| 156 |
+
"blocks.15.n2.bias": "model_big.safetensors",
|
| 157 |
+
"blocks.15.n2.weight": "model_big.safetensors",
|
| 158 |
+
"blocks.16.attn.b.bias": "model_big.safetensors",
|
| 159 |
+
"blocks.16.attn.b.weight": "model_big.safetensors",
|
| 160 |
+
"blocks.16.attn.k.weight": "model_big.safetensors",
|
| 161 |
+
"blocks.16.attn.o.weight": "model_big.safetensors",
|
| 162 |
+
"blocks.16.attn.q.weight": "model_big.safetensors",
|
| 163 |
+
"blocks.16.attn.v.weight": "model_big.safetensors",
|
| 164 |
+
"blocks.16.ff.0.bias": "model_big.safetensors",
|
| 165 |
+
"blocks.16.ff.0.weight": "model_big.safetensors",
|
| 166 |
+
"blocks.16.ff.2.bias": "model_big.safetensors",
|
| 167 |
+
"blocks.16.ff.2.weight": "model_big.safetensors",
|
| 168 |
+
"blocks.16.landmark.gate": "model_big.safetensors",
|
| 169 |
+
"blocks.16.landmark.k.weight": "model_big.safetensors",
|
| 170 |
+
"blocks.16.landmark.o.weight": "model_big.safetensors",
|
| 171 |
+
"blocks.16.landmark.q.weight": "model_big.safetensors",
|
| 172 |
+
"blocks.16.landmark.v.weight": "model_big.safetensors",
|
| 173 |
+
"blocks.16.n1.bias": "model_big.safetensors",
|
| 174 |
+
"blocks.16.n1.weight": "model_big.safetensors",
|
| 175 |
+
"blocks.16.n2.bias": "model_big.safetensors",
|
| 176 |
+
"blocks.16.n2.weight": "model_big.safetensors",
|
| 177 |
+
"blocks.17.attn.b.bias": "model_big.safetensors",
|
| 178 |
+
"blocks.17.attn.b.weight": "model_big.safetensors",
|
| 179 |
+
"blocks.17.attn.k.weight": "model_big.safetensors",
|
| 180 |
+
"blocks.17.attn.o.weight": "model_big.safetensors",
|
| 181 |
+
"blocks.17.attn.q.weight": "model_big.safetensors",
|
| 182 |
+
"blocks.17.attn.v.weight": "model_big.safetensors",
|
| 183 |
+
"blocks.17.ff.0.bias": "model_big.safetensors",
|
| 184 |
+
"blocks.17.ff.0.weight": "model_big.safetensors",
|
| 185 |
+
"blocks.17.ff.2.bias": "model_big.safetensors",
|
| 186 |
+
"blocks.17.ff.2.weight": "model_big.safetensors",
|
| 187 |
+
"blocks.17.landmark.gate": "model_big.safetensors",
|
| 188 |
+
"blocks.17.landmark.k.weight": "model_big.safetensors",
|
| 189 |
+
"blocks.17.landmark.o.weight": "model_big.safetensors",
|
| 190 |
+
"blocks.17.landmark.q.weight": "model_big.safetensors",
|
| 191 |
+
"blocks.17.landmark.v.weight": "model_big.safetensors",
|
| 192 |
+
"blocks.17.n1.bias": "model_big.safetensors",
|
| 193 |
+
"blocks.17.n1.weight": "model_big.safetensors",
|
| 194 |
+
"blocks.17.n2.bias": "model_big.safetensors",
|
| 195 |
+
"blocks.17.n2.weight": "model_big.safetensors",
|
| 196 |
+
"blocks.18.attn.b.bias": "model_big.safetensors",
|
| 197 |
+
"blocks.18.attn.b.weight": "model_big.safetensors",
|
| 198 |
+
"blocks.18.attn.k.weight": "model_big.safetensors",
|
| 199 |
+
"blocks.18.attn.o.weight": "model_big.safetensors",
|
| 200 |
+
"blocks.18.attn.q.weight": "model_big.safetensors",
|
| 201 |
+
"blocks.18.attn.v.weight": "model_big.safetensors",
|
| 202 |
+
"blocks.18.ff.0.bias": "model_big.safetensors",
|
| 203 |
+
"blocks.18.ff.0.weight": "model_big.safetensors",
|
| 204 |
+
"blocks.18.ff.2.bias": "model_big.safetensors",
|
| 205 |
+
"blocks.18.ff.2.weight": "model_big.safetensors",
|
| 206 |
+
"blocks.18.landmark.gate": "model_big.safetensors",
|
| 207 |
+
"blocks.18.landmark.k.weight": "model_big.safetensors",
|
| 208 |
+
"blocks.18.landmark.o.weight": "model_big.safetensors",
|
| 209 |
+
"blocks.18.landmark.q.weight": "model_big.safetensors",
|
| 210 |
+
"blocks.18.landmark.v.weight": "model_big.safetensors",
|
| 211 |
+
"blocks.18.n1.bias": "model_big.safetensors",
|
| 212 |
+
"blocks.18.n1.weight": "model_big.safetensors",
|
| 213 |
+
"blocks.18.n2.bias": "model_big.safetensors",
|
| 214 |
+
"blocks.18.n2.weight": "model_big.safetensors",
|
| 215 |
+
"blocks.19.attn.b.bias": "model_big.safetensors",
|
| 216 |
+
"blocks.19.attn.b.weight": "model_big.safetensors",
|
| 217 |
+
"blocks.19.attn.k.weight": "model_big.safetensors",
|
| 218 |
+
"blocks.19.attn.o.weight": "model_big.safetensors",
|
| 219 |
+
"blocks.19.attn.q.weight": "model_big.safetensors",
|
| 220 |
+
"blocks.19.attn.v.weight": "model_big.safetensors",
|
| 221 |
+
"blocks.19.ff.0.bias": "model_big.safetensors",
|
| 222 |
+
"blocks.19.ff.0.weight": "model_big.safetensors",
|
| 223 |
+
"blocks.19.ff.2.bias": "model_big.safetensors",
|
| 224 |
+
"blocks.19.ff.2.weight": "model_big.safetensors",
|
| 225 |
+
"blocks.19.landmark.gate": "model_big.safetensors",
|
| 226 |
+
"blocks.19.landmark.k.weight": "model_big.safetensors",
|
| 227 |
+
"blocks.19.landmark.o.weight": "model_big.safetensors",
|
| 228 |
+
"blocks.19.landmark.q.weight": "model_big.safetensors",
|
| 229 |
+
"blocks.19.landmark.v.weight": "model_big.safetensors",
|
| 230 |
+
"blocks.19.n1.bias": "model_big.safetensors",
|
| 231 |
+
"blocks.19.n1.weight": "model_big.safetensors",
|
| 232 |
+
"blocks.19.n2.bias": "model_big.safetensors",
|
| 233 |
+
"blocks.19.n2.weight": "model_big.safetensors",
|
| 234 |
+
"blocks.2.attn.b.bias": "model_big.safetensors",
|
| 235 |
+
"blocks.2.attn.b.weight": "model_big.safetensors",
|
| 236 |
+
"blocks.2.attn.k.weight": "model_big.safetensors",
|
| 237 |
+
"blocks.2.attn.o.weight": "model_big.safetensors",
|
| 238 |
+
"blocks.2.attn.q.weight": "model_big.safetensors",
|
| 239 |
+
"blocks.2.attn.v.weight": "model_big.safetensors",
|
| 240 |
+
"blocks.2.ff.0.bias": "model_big.safetensors",
|
| 241 |
+
"blocks.2.ff.0.weight": "model_big.safetensors",
|
| 242 |
+
"blocks.2.ff.2.bias": "model_big.safetensors",
|
| 243 |
+
"blocks.2.ff.2.weight": "model_big.safetensors",
|
| 244 |
+
"blocks.2.landmark.gate": "model_big.safetensors",
|
| 245 |
+
"blocks.2.landmark.k.weight": "model_big.safetensors",
|
| 246 |
+
"blocks.2.landmark.o.weight": "model_big.safetensors",
|
| 247 |
+
"blocks.2.landmark.q.weight": "model_big.safetensors",
|
| 248 |
+
"blocks.2.landmark.v.weight": "model_big.safetensors",
|
| 249 |
+
"blocks.2.n1.bias": "model_big.safetensors",
|
| 250 |
+
"blocks.2.n1.weight": "model_big.safetensors",
|
| 251 |
+
"blocks.2.n2.bias": "model_big.safetensors",
|
| 252 |
+
"blocks.2.n2.weight": "model_big.safetensors",
|
| 253 |
+
"blocks.20.attn.b.bias": "model_big.safetensors",
|
| 254 |
+
"blocks.20.attn.b.weight": "model_big.safetensors",
|
| 255 |
+
"blocks.20.attn.k.weight": "model_big.safetensors",
|
| 256 |
+
"blocks.20.attn.o.weight": "model_big.safetensors",
|
| 257 |
+
"blocks.20.attn.q.weight": "model_big.safetensors",
|
| 258 |
+
"blocks.20.attn.v.weight": "model_big.safetensors",
|
| 259 |
+
"blocks.20.ff.0.bias": "model_big.safetensors",
|
| 260 |
+
"blocks.20.ff.0.weight": "model_big.safetensors",
|
| 261 |
+
"blocks.20.ff.2.bias": "model_big.safetensors",
|
| 262 |
+
"blocks.20.ff.2.weight": "model_big.safetensors",
|
| 263 |
+
"blocks.20.landmark.gate": "model_big.safetensors",
|
| 264 |
+
"blocks.20.landmark.k.weight": "model_big.safetensors",
|
| 265 |
+
"blocks.20.landmark.o.weight": "model_big.safetensors",
|
| 266 |
+
"blocks.20.landmark.q.weight": "model_big.safetensors",
|
| 267 |
+
"blocks.20.landmark.v.weight": "model_big.safetensors",
|
| 268 |
+
"blocks.20.n1.bias": "model_big.safetensors",
|
| 269 |
+
"blocks.20.n1.weight": "model_big.safetensors",
|
| 270 |
+
"blocks.20.n2.bias": "model_big.safetensors",
|
| 271 |
+
"blocks.20.n2.weight": "model_big.safetensors",
|
| 272 |
+
"blocks.21.attn.b.bias": "model_big.safetensors",
|
| 273 |
+
"blocks.21.attn.b.weight": "model_big.safetensors",
|
| 274 |
+
"blocks.21.attn.k.weight": "model_big.safetensors",
|
| 275 |
+
"blocks.21.attn.o.weight": "model_big.safetensors",
|
| 276 |
+
"blocks.21.attn.q.weight": "model_big.safetensors",
|
| 277 |
+
"blocks.21.attn.v.weight": "model_big.safetensors",
|
| 278 |
+
"blocks.21.ff.0.bias": "model_big.safetensors",
|
| 279 |
+
"blocks.21.ff.0.weight": "model_big.safetensors",
|
| 280 |
+
"blocks.21.ff.2.bias": "model_big.safetensors",
|
| 281 |
+
"blocks.21.ff.2.weight": "model_big.safetensors",
|
| 282 |
+
"blocks.21.landmark.gate": "model_big.safetensors",
|
| 283 |
+
"blocks.21.landmark.k.weight": "model_big.safetensors",
|
| 284 |
+
"blocks.21.landmark.o.weight": "model_big.safetensors",
|
| 285 |
+
"blocks.21.landmark.q.weight": "model_big.safetensors",
|
| 286 |
+
"blocks.21.landmark.v.weight": "model_big.safetensors",
|
| 287 |
+
"blocks.21.n1.bias": "model_big.safetensors",
|
| 288 |
+
"blocks.21.n1.weight": "model_big.safetensors",
|
| 289 |
+
"blocks.21.n2.bias": "model_big.safetensors",
|
| 290 |
+
"blocks.21.n2.weight": "model_big.safetensors",
|
| 291 |
+
"blocks.22.attn.b.bias": "model_big.safetensors",
|
| 292 |
+
"blocks.22.attn.b.weight": "model_big.safetensors",
|
| 293 |
+
"blocks.22.attn.k.weight": "model_big.safetensors",
|
| 294 |
+
"blocks.22.attn.o.weight": "model_big.safetensors",
|
| 295 |
+
"blocks.22.attn.q.weight": "model_big.safetensors",
|
| 296 |
+
"blocks.22.attn.v.weight": "model_big.safetensors",
|
| 297 |
+
"blocks.22.ff.0.bias": "model_big.safetensors",
|
| 298 |
+
"blocks.22.ff.0.weight": "model_big.safetensors",
|
| 299 |
+
"blocks.22.ff.2.bias": "model_big.safetensors",
|
| 300 |
+
"blocks.22.ff.2.weight": "model_big.safetensors",
|
| 301 |
+
"blocks.22.landmark.gate": "model_big.safetensors",
|
| 302 |
+
"blocks.22.landmark.k.weight": "model_big.safetensors",
|
| 303 |
+
"blocks.22.landmark.o.weight": "model_big.safetensors",
|
| 304 |
+
"blocks.22.landmark.q.weight": "model_big.safetensors",
|
| 305 |
+
"blocks.22.landmark.v.weight": "model_big.safetensors",
|
| 306 |
+
"blocks.22.n1.bias": "model_big.safetensors",
|
| 307 |
+
"blocks.22.n1.weight": "model_big.safetensors",
|
| 308 |
+
"blocks.22.n2.bias": "model_big.safetensors",
|
| 309 |
+
"blocks.22.n2.weight": "model_big.safetensors",
|
| 310 |
+
"blocks.23.attn.b.bias": "model_big.safetensors",
|
| 311 |
+
"blocks.23.attn.b.weight": "model_big.safetensors",
|
| 312 |
+
"blocks.23.attn.k.weight": "model_big.safetensors",
|
| 313 |
+
"blocks.23.attn.o.weight": "model_big.safetensors",
|
| 314 |
+
"blocks.23.attn.q.weight": "model_big.safetensors",
|
| 315 |
+
"blocks.23.attn.v.weight": "model_big.safetensors",
|
| 316 |
+
"blocks.23.ff.0.bias": "model_big.safetensors",
|
| 317 |
+
"blocks.23.ff.0.weight": "model_big.safetensors",
|
| 318 |
+
"blocks.23.ff.2.bias": "model_big.safetensors",
|
| 319 |
+
"blocks.23.ff.2.weight": "model_big.safetensors",
|
| 320 |
+
"blocks.23.landmark.gate": "model_big.safetensors",
|
| 321 |
+
"blocks.23.landmark.k.weight": "model_big.safetensors",
|
| 322 |
+
"blocks.23.landmark.o.weight": "model_big.safetensors",
|
| 323 |
+
"blocks.23.landmark.q.weight": "model_big.safetensors",
|
| 324 |
+
"blocks.23.landmark.v.weight": "model_big.safetensors",
|
| 325 |
+
"blocks.23.n1.bias": "model_big.safetensors",
|
| 326 |
+
"blocks.23.n1.weight": "model_big.safetensors",
|
| 327 |
+
"blocks.23.n2.bias": "model_big.safetensors",
|
| 328 |
+
"blocks.23.n2.weight": "model_big.safetensors",
|
| 329 |
+
"blocks.24.attn.b.bias": "model_big.safetensors",
|
| 330 |
+
"blocks.24.attn.b.weight": "model_big.safetensors",
|
| 331 |
+
"blocks.24.attn.k.weight": "model_big.safetensors",
|
| 332 |
+
"blocks.24.attn.o.weight": "model_big.safetensors",
|
| 333 |
+
"blocks.24.attn.q.weight": "model_big.safetensors",
|
| 334 |
+
"blocks.24.attn.v.weight": "model_big.safetensors",
|
| 335 |
+
"blocks.24.ff.0.bias": "model_big.safetensors",
|
| 336 |
+
"blocks.24.ff.0.weight": "model_big.safetensors",
|
| 337 |
+
"blocks.24.ff.2.bias": "model_big.safetensors",
|
| 338 |
+
"blocks.24.ff.2.weight": "model_big.safetensors",
|
| 339 |
+
"blocks.24.landmark.gate": "model_big.safetensors",
|
| 340 |
+
"blocks.24.landmark.k.weight": "model_big.safetensors",
|
| 341 |
+
"blocks.24.landmark.o.weight": "model_big.safetensors",
|
| 342 |
+
"blocks.24.landmark.q.weight": "model_big.safetensors",
|
| 343 |
+
"blocks.24.landmark.v.weight": "model_big.safetensors",
|
| 344 |
+
"blocks.24.n1.bias": "model_big.safetensors",
|
| 345 |
+
"blocks.24.n1.weight": "model_big.safetensors",
|
| 346 |
+
"blocks.24.n2.bias": "model_big.safetensors",
|
| 347 |
+
"blocks.24.n2.weight": "model_big.safetensors",
|
| 348 |
+
"blocks.25.attn.b.bias": "model_big.safetensors",
|
| 349 |
+
"blocks.25.attn.b.weight": "model_big.safetensors",
|
| 350 |
+
"blocks.25.attn.k.weight": "model_big.safetensors",
|
| 351 |
+
"blocks.25.attn.o.weight": "model_big.safetensors",
|
| 352 |
+
"blocks.25.attn.q.weight": "model_big.safetensors",
|
| 353 |
+
"blocks.25.attn.v.weight": "model_big.safetensors",
|
| 354 |
+
"blocks.25.ff.0.bias": "model_big.safetensors",
|
| 355 |
+
"blocks.25.ff.0.weight": "model_big.safetensors",
|
| 356 |
+
"blocks.25.ff.2.bias": "model_big.safetensors",
|
| 357 |
+
"blocks.25.ff.2.weight": "model_big.safetensors",
|
| 358 |
+
"blocks.25.landmark.gate": "model_big.safetensors",
|
| 359 |
+
"blocks.25.landmark.k.weight": "model_big.safetensors",
|
| 360 |
+
"blocks.25.landmark.o.weight": "model_big.safetensors",
|
| 361 |
+
"blocks.25.landmark.q.weight": "model_big.safetensors",
|
| 362 |
+
"blocks.25.landmark.v.weight": "model_big.safetensors",
|
| 363 |
+
"blocks.25.n1.bias": "model_big.safetensors",
|
| 364 |
+
"blocks.25.n1.weight": "model_big.safetensors",
|
| 365 |
+
"blocks.25.n2.bias": "model_big.safetensors",
|
| 366 |
+
"blocks.25.n2.weight": "model_big.safetensors",
|
| 367 |
+
"blocks.26.attn.b.bias": "model_big.safetensors",
|
| 368 |
+
"blocks.26.attn.b.weight": "model_big.safetensors",
|
| 369 |
+
"blocks.26.attn.k.weight": "model_big.safetensors",
|
| 370 |
+
"blocks.26.attn.o.weight": "model_big.safetensors",
|
| 371 |
+
"blocks.26.attn.q.weight": "model_big.safetensors",
|
| 372 |
+
"blocks.26.attn.v.weight": "model_big.safetensors",
|
| 373 |
+
"blocks.26.ff.0.bias": "model_big.safetensors",
|
| 374 |
+
"blocks.26.ff.0.weight": "model_big.safetensors",
|
| 375 |
+
"blocks.26.ff.2.bias": "model_big.safetensors",
|
| 376 |
+
"blocks.26.ff.2.weight": "model_big.safetensors",
|
| 377 |
+
"blocks.26.landmark.gate": "model_big.safetensors",
|
| 378 |
+
"blocks.26.landmark.k.weight": "model_big.safetensors",
|
| 379 |
+
"blocks.26.landmark.o.weight": "model_big.safetensors",
|
| 380 |
+
"blocks.26.landmark.q.weight": "model_big.safetensors",
|
| 381 |
+
"blocks.26.landmark.v.weight": "model_big.safetensors",
|
| 382 |
+
"blocks.26.n1.bias": "model_big.safetensors",
|
| 383 |
+
"blocks.26.n1.weight": "model_big.safetensors",
|
| 384 |
+
"blocks.26.n2.bias": "model_big.safetensors",
|
| 385 |
+
"blocks.26.n2.weight": "model_big.safetensors",
|
| 386 |
+
"blocks.27.attn.b.bias": "model_big.safetensors",
|
| 387 |
+
"blocks.27.attn.b.weight": "model_big.safetensors",
|
| 388 |
+
"blocks.27.attn.k.weight": "model_big.safetensors",
|
| 389 |
+
"blocks.27.attn.o.weight": "model_big.safetensors",
|
| 390 |
+
"blocks.27.attn.q.weight": "model_big.safetensors",
|
| 391 |
+
"blocks.27.attn.v.weight": "model_big.safetensors",
|
| 392 |
+
"blocks.27.ff.0.bias": "model_big.safetensors",
|
| 393 |
+
"blocks.27.ff.0.weight": "model_big.safetensors",
|
| 394 |
+
"blocks.27.ff.2.bias": "model_big.safetensors",
|
| 395 |
+
"blocks.27.ff.2.weight": "model_big.safetensors",
|
| 396 |
+
"blocks.27.landmark.gate": "model_big.safetensors",
|
| 397 |
+
"blocks.27.landmark.k.weight": "model_big.safetensors",
|
| 398 |
+
"blocks.27.landmark.o.weight": "model_big.safetensors",
|
| 399 |
+
"blocks.27.landmark.q.weight": "model_big.safetensors",
|
| 400 |
+
"blocks.27.landmark.v.weight": "model_big.safetensors",
|
| 401 |
+
"blocks.27.n1.bias": "model_big.safetensors",
|
| 402 |
+
"blocks.27.n1.weight": "model_big.safetensors",
|
| 403 |
+
"blocks.27.n2.bias": "model_big.safetensors",
|
| 404 |
+
"blocks.27.n2.weight": "model_big.safetensors",
|
| 405 |
+
"blocks.3.attn.b.bias": "model_big.safetensors",
|
| 406 |
+
"blocks.3.attn.b.weight": "model_big.safetensors",
|
| 407 |
+
"blocks.3.attn.k.weight": "model_big.safetensors",
|
| 408 |
+
"blocks.3.attn.o.weight": "model_big.safetensors",
|
| 409 |
+
"blocks.3.attn.q.weight": "model_big.safetensors",
|
| 410 |
+
"blocks.3.attn.v.weight": "model_big.safetensors",
|
| 411 |
+
"blocks.3.ff.0.bias": "model_big.safetensors",
|
| 412 |
+
"blocks.3.ff.0.weight": "model_big.safetensors",
|
| 413 |
+
"blocks.3.ff.2.bias": "model_big.safetensors",
|
| 414 |
+
"blocks.3.ff.2.weight": "model_big.safetensors",
|
| 415 |
+
"blocks.3.landmark.gate": "model_big.safetensors",
|
| 416 |
+
"blocks.3.landmark.k.weight": "model_big.safetensors",
|
| 417 |
+
"blocks.3.landmark.o.weight": "model_big.safetensors",
|
| 418 |
+
"blocks.3.landmark.q.weight": "model_big.safetensors",
|
| 419 |
+
"blocks.3.landmark.v.weight": "model_big.safetensors",
|
| 420 |
+
"blocks.3.n1.bias": "model_big.safetensors",
|
| 421 |
+
"blocks.3.n1.weight": "model_big.safetensors",
|
| 422 |
+
"blocks.3.n2.bias": "model_big.safetensors",
|
| 423 |
+
"blocks.3.n2.weight": "model_big.safetensors",
|
| 424 |
+
"blocks.4.attn.b.bias": "model_big.safetensors",
|
| 425 |
+
"blocks.4.attn.b.weight": "model_big.safetensors",
|
| 426 |
+
"blocks.4.attn.k.weight": "model_big.safetensors",
|
| 427 |
+
"blocks.4.attn.o.weight": "model_big.safetensors",
|
| 428 |
+
"blocks.4.attn.q.weight": "model_big.safetensors",
|
| 429 |
+
"blocks.4.attn.v.weight": "model_big.safetensors",
|
| 430 |
+
"blocks.4.ff.0.bias": "model_big.safetensors",
|
| 431 |
+
"blocks.4.ff.0.weight": "model_big.safetensors",
|
| 432 |
+
"blocks.4.ff.2.bias": "model_big.safetensors",
|
| 433 |
+
"blocks.4.ff.2.weight": "model_big.safetensors",
|
| 434 |
+
"blocks.4.landmark.gate": "model_big.safetensors",
|
| 435 |
+
"blocks.4.landmark.k.weight": "model_big.safetensors",
|
| 436 |
+
"blocks.4.landmark.o.weight": "model_big.safetensors",
|
| 437 |
+
"blocks.4.landmark.q.weight": "model_big.safetensors",
|
| 438 |
+
"blocks.4.landmark.v.weight": "model_big.safetensors",
|
| 439 |
+
"blocks.4.n1.bias": "model_big.safetensors",
|
| 440 |
+
"blocks.4.n1.weight": "model_big.safetensors",
|
| 441 |
+
"blocks.4.n2.bias": "model_big.safetensors",
|
| 442 |
+
"blocks.4.n2.weight": "model_big.safetensors",
|
| 443 |
+
"blocks.5.attn.b.bias": "model_big.safetensors",
|
| 444 |
+
"blocks.5.attn.b.weight": "model_big.safetensors",
|
| 445 |
+
"blocks.5.attn.k.weight": "model_big.safetensors",
|
| 446 |
+
"blocks.5.attn.o.weight": "model_big.safetensors",
|
| 447 |
+
"blocks.5.attn.q.weight": "model_big.safetensors",
|
| 448 |
+
"blocks.5.attn.v.weight": "model_big.safetensors",
|
| 449 |
+
"blocks.5.ff.0.bias": "model_big.safetensors",
|
| 450 |
+
"blocks.5.ff.0.weight": "model_big.safetensors",
|
| 451 |
+
"blocks.5.ff.2.bias": "model_big.safetensors",
|
| 452 |
+
"blocks.5.ff.2.weight": "model_big.safetensors",
|
| 453 |
+
"blocks.5.landmark.gate": "model_big.safetensors",
|
| 454 |
+
"blocks.5.landmark.k.weight": "model_big.safetensors",
|
| 455 |
+
"blocks.5.landmark.o.weight": "model_big.safetensors",
|
| 456 |
+
"blocks.5.landmark.q.weight": "model_big.safetensors",
|
| 457 |
+
"blocks.5.landmark.v.weight": "model_big.safetensors",
|
| 458 |
+
"blocks.5.n1.bias": "model_big.safetensors",
|
| 459 |
+
"blocks.5.n1.weight": "model_big.safetensors",
|
| 460 |
+
"blocks.5.n2.bias": "model_big.safetensors",
|
| 461 |
+
"blocks.5.n2.weight": "model_big.safetensors",
|
| 462 |
+
"blocks.6.attn.b.bias": "model_big.safetensors",
|
| 463 |
+
"blocks.6.attn.b.weight": "model_big.safetensors",
|
| 464 |
+
"blocks.6.attn.k.weight": "model_big.safetensors",
|
| 465 |
+
"blocks.6.attn.o.weight": "model_big.safetensors",
|
| 466 |
+
"blocks.6.attn.q.weight": "model_big.safetensors",
|
| 467 |
+
"blocks.6.attn.v.weight": "model_big.safetensors",
|
| 468 |
+
"blocks.6.ff.0.bias": "model_big.safetensors",
|
| 469 |
+
"blocks.6.ff.0.weight": "model_big.safetensors",
|
| 470 |
+
"blocks.6.ff.2.bias": "model_big.safetensors",
|
| 471 |
+
"blocks.6.ff.2.weight": "model_big.safetensors",
|
| 472 |
+
"blocks.6.landmark.gate": "model_big.safetensors",
|
| 473 |
+
"blocks.6.landmark.k.weight": "model_big.safetensors",
|
| 474 |
+
"blocks.6.landmark.o.weight": "model_big.safetensors",
|
| 475 |
+
"blocks.6.landmark.q.weight": "model_big.safetensors",
|
| 476 |
+
"blocks.6.landmark.v.weight": "model_big.safetensors",
|
| 477 |
+
"blocks.6.n1.bias": "model_big.safetensors",
|
| 478 |
+
"blocks.6.n1.weight": "model_big.safetensors",
|
| 479 |
+
"blocks.6.n2.bias": "model_big.safetensors",
|
| 480 |
+
"blocks.6.n2.weight": "model_big.safetensors",
|
| 481 |
+
"blocks.7.attn.b.bias": "model_big.safetensors",
|
| 482 |
+
"blocks.7.attn.b.weight": "model_big.safetensors",
|
| 483 |
+
"blocks.7.attn.k.weight": "model_big.safetensors",
|
| 484 |
+
"blocks.7.attn.o.weight": "model_big.safetensors",
|
| 485 |
+
"blocks.7.attn.q.weight": "model_big.safetensors",
|
| 486 |
+
"blocks.7.attn.v.weight": "model_big.safetensors",
|
| 487 |
+
"blocks.7.ff.0.bias": "model_big.safetensors",
|
| 488 |
+
"blocks.7.ff.0.weight": "model_big.safetensors",
|
| 489 |
+
"blocks.7.ff.2.bias": "model_big.safetensors",
|
| 490 |
+
"blocks.7.ff.2.weight": "model_big.safetensors",
|
| 491 |
+
"blocks.7.landmark.gate": "model_big.safetensors",
|
| 492 |
+
"blocks.7.landmark.k.weight": "model_big.safetensors",
|
| 493 |
+
"blocks.7.landmark.o.weight": "model_big.safetensors",
|
| 494 |
+
"blocks.7.landmark.q.weight": "model_big.safetensors",
|
| 495 |
+
"blocks.7.landmark.v.weight": "model_big.safetensors",
|
| 496 |
+
"blocks.7.n1.bias": "model_big.safetensors",
|
| 497 |
+
"blocks.7.n1.weight": "model_big.safetensors",
|
| 498 |
+
"blocks.7.n2.bias": "model_big.safetensors",
|
| 499 |
+
"blocks.7.n2.weight": "model_big.safetensors",
|
| 500 |
+
"blocks.8.attn.b.bias": "model_big.safetensors",
|
| 501 |
+
"blocks.8.attn.b.weight": "model_big.safetensors",
|
| 502 |
+
"blocks.8.attn.k.weight": "model_big.safetensors",
|
| 503 |
+
"blocks.8.attn.o.weight": "model_big.safetensors",
|
| 504 |
+
"blocks.8.attn.q.weight": "model_big.safetensors",
|
| 505 |
+
"blocks.8.attn.v.weight": "model_big.safetensors",
|
| 506 |
+
"blocks.8.ff.0.bias": "model_big.safetensors",
|
| 507 |
+
"blocks.8.ff.0.weight": "model_big.safetensors",
|
| 508 |
+
"blocks.8.ff.2.bias": "model_big.safetensors",
|
| 509 |
+
"blocks.8.ff.2.weight": "model_big.safetensors",
|
| 510 |
+
"blocks.8.landmark.gate": "model_big.safetensors",
|
| 511 |
+
"blocks.8.landmark.k.weight": "model_big.safetensors",
|
| 512 |
+
"blocks.8.landmark.o.weight": "model_big.safetensors",
|
| 513 |
+
"blocks.8.landmark.q.weight": "model_big.safetensors",
|
| 514 |
+
"blocks.8.landmark.v.weight": "model_big.safetensors",
|
| 515 |
+
"blocks.8.n1.bias": "model_big.safetensors",
|
| 516 |
+
"blocks.8.n1.weight": "model_big.safetensors",
|
| 517 |
+
"blocks.8.n2.bias": "model_big.safetensors",
|
| 518 |
+
"blocks.8.n2.weight": "model_big.safetensors",
|
| 519 |
+
"blocks.9.attn.b.bias": "model_big.safetensors",
|
| 520 |
+
"blocks.9.attn.b.weight": "model_big.safetensors",
|
| 521 |
+
"blocks.9.attn.k.weight": "model_big.safetensors",
|
| 522 |
+
"blocks.9.attn.o.weight": "model_big.safetensors",
|
| 523 |
+
"blocks.9.attn.q.weight": "model_big.safetensors",
|
| 524 |
+
"blocks.9.attn.v.weight": "model_big.safetensors",
|
| 525 |
+
"blocks.9.ff.0.bias": "model_big.safetensors",
|
| 526 |
+
"blocks.9.ff.0.weight": "model_big.safetensors",
|
| 527 |
+
"blocks.9.ff.2.bias": "model_big.safetensors",
|
| 528 |
+
"blocks.9.ff.2.weight": "model_big.safetensors",
|
| 529 |
+
"blocks.9.landmark.gate": "model_big.safetensors",
|
| 530 |
+
"blocks.9.landmark.k.weight": "model_big.safetensors",
|
| 531 |
+
"blocks.9.landmark.o.weight": "model_big.safetensors",
|
| 532 |
+
"blocks.9.landmark.q.weight": "model_big.safetensors",
|
| 533 |
+
"blocks.9.landmark.v.weight": "model_big.safetensors",
|
| 534 |
+
"blocks.9.n1.bias": "model_big.safetensors",
|
| 535 |
+
"blocks.9.n1.weight": "model_big.safetensors",
|
| 536 |
+
"blocks.9.n2.bias": "model_big.safetensors",
|
| 537 |
+
"blocks.9.n2.weight": "model_big.safetensors",
|
| 538 |
+
"cls_head.bias": "model_big.safetensors",
|
| 539 |
+
"cls_head.weight": "model_big.safetensors",
|
| 540 |
+
"cls_label_emb.weight": "model_big.safetensors",
|
| 541 |
+
"feat_enc.bias": "model_big.safetensors",
|
| 542 |
+
"feat_enc.weight": "model_big.safetensors",
|
| 543 |
+
"norm.bias": "model_big.safetensors",
|
| 544 |
+
"norm.weight": "model_big.safetensors",
|
| 545 |
+
"reg_head.bias": "model_big.safetensors",
|
| 546 |
+
"reg_head.weight": "model_big.safetensors",
|
| 547 |
+
"reg_label.bias": "model_big.safetensors",
|
| 548 |
+
"reg_label.weight": "model_big.safetensors",
|
| 549 |
+
"reg_label_gate": "model_big.safetensors",
|
| 550 |
+
"type_emb.weight": "model_big.safetensors"
|
| 551 |
+
}
|
| 552 |
+
}
|
model_big.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:d9560e0d033172ab26ff43e94bceffc7a9277d2b64031ae3b554011e71414b47
|
| 3 |
+
size 1647506252
|
model_big_int8.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:e210edaff81b0c23876722f10bb6fe49eb8ff237fa61f2fe81946da9010f2411
|
| 3 |
+
size 415479124
|
model_small.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:0a448bb4aef008af34730e09a8c2aad3d599751e65b178b83226d6a1ac56c586
|
| 3 |
+
size 206272140
|
model_small_int8.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6018b2ec8968751d47c8ba30178b13d99e10df6fd61c71c2b08893b054416ffc
|
| 3 |
+
size 52336084
|
modeling.py
ADDED
|
@@ -0,0 +1,404 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
import json
|
| 3 |
+
import math
|
| 4 |
+
import os
|
| 5 |
+
from dataclasses import dataclass
|
| 6 |
+
import numpy as np
|
| 7 |
+
import torch
|
| 8 |
+
import torch.nn as nn
|
| 9 |
+
import torch.nn.functional as F
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
@dataclass
|
| 13 |
+
class FelaTabConfig:
|
| 14 |
+
max_features: int = 100
|
| 15 |
+
max_classes: int = 10
|
| 16 |
+
dim: int = 1024
|
| 17 |
+
n_layers: int = 28
|
| 18 |
+
n_heads: int = 16
|
| 19 |
+
head_dim: int = 64
|
| 20 |
+
chunk: int = 64
|
| 21 |
+
ffn_mult: int = 3
|
| 22 |
+
dropout: float = 0.0
|
| 23 |
+
use_landmark: bool = True
|
| 24 |
+
n_landmarks: int = 48
|
| 25 |
+
ln_eps: float = 1e-05
|
| 26 |
+
|
| 27 |
+
def __post_init__(self):
|
| 28 |
+
assert self.dim % self.n_heads == 0 or self.n_heads * self.head_dim > 0
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
def delta_rule_chunk(q, k, v, beta, chunk):
|
| 32 |
+
B, H, T, D = q.shape
|
| 33 |
+
dev, dt = (q.device, q.dtype)
|
| 34 |
+
pad = (chunk - T % chunk) % chunk
|
| 35 |
+
if pad:
|
| 36 |
+
q = F.pad(q, (0, 0, 0, pad))
|
| 37 |
+
k = F.pad(k, (0, 0, 0, pad))
|
| 38 |
+
v = F.pad(v, (0, 0, 0, pad))
|
| 39 |
+
beta = F.pad(beta, (0, pad))
|
| 40 |
+
Tp = T + pad
|
| 41 |
+
nC = Tp // chunk
|
| 42 |
+
q = q.view(B, H, nC, chunk, D)
|
| 43 |
+
k = k.view(B, H, nC, chunk, D)
|
| 44 |
+
v = v.view(B, H, nC, chunk, D)
|
| 45 |
+
beta = beta.view(B, H, nC, chunk)
|
| 46 |
+
tri = torch.tril(torch.ones(chunk, chunk, device=dev, dtype=dt), -1)
|
| 47 |
+
eye = torch.eye(chunk, device=dev, dtype=dt)
|
| 48 |
+
S = torch.zeros(B, H, D, D, device=dev, dtype=dt)
|
| 49 |
+
outs = []
|
| 50 |
+
for c in range(nC):
|
| 51 |
+
kc = k[:, :, c]
|
| 52 |
+
vc = v[:, :, c]
|
| 53 |
+
qc = q[:, :, c]
|
| 54 |
+
bc = beta[:, :, c]
|
| 55 |
+
KK = torch.einsum("bhtd,bhsd->bhts", kc, kc)
|
| 56 |
+
A = bc.unsqueeze(-1) * KK * tri
|
| 57 |
+
kS0 = torch.einsum("bhtd,bhde->bhte", kc, S)
|
| 58 |
+
RHS = bc.unsqueeze(-1) * (vc - kS0)
|
| 59 |
+
M = eye + A
|
| 60 |
+
U = torch.linalg.solve_triangular(M, RHS, upper=False, unitriangular=True)
|
| 61 |
+
qS0 = torch.einsum("bhtd,bhde->bhte", qc, S)
|
| 62 |
+
QK = torch.einsum("bhtd,bhsd->bhts", qc, kc) * tri
|
| 63 |
+
o = qS0 + torch.einsum("bhts,bhse->bhte", QK, U)
|
| 64 |
+
outs.append(o)
|
| 65 |
+
S = S + torch.einsum("bhtd,bhte->bhde", kc, U)
|
| 66 |
+
o = torch.cat(outs, dim=2).view(B, H, Tp, D)[:, :, :T]
|
| 67 |
+
return (o, S)
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def pool_landmarks(x, wm, G):
|
| 71 |
+
B, T, C = x.shape
|
| 72 |
+
ns = wm.sum(1).clamp(min=1)
|
| 73 |
+
gs = torch.ceil(ns / G).clamp(min=1)
|
| 74 |
+
pos = torch.arange(T, device=x.device)[None, :].expand(B, T)
|
| 75 |
+
gid = torch.minimum((pos / gs[:, None]).floor().long(), torch.full_like(pos, G - 1))
|
| 76 |
+
valid = wm > 0
|
| 77 |
+
flat = (torch.arange(B, device=x.device)[:, None] * G + gid)[valid]
|
| 78 |
+
src = x[valid]
|
| 79 |
+
land = torch.zeros(B * G, C, device=x.device, dtype=x.dtype)
|
| 80 |
+
cnt = torch.zeros(B * G, device=x.device, dtype=x.dtype)
|
| 81 |
+
land.index_add_(0, flat, src)
|
| 82 |
+
cnt.index_add_(0, flat, torch.ones(src.shape[0], device=x.device, dtype=x.dtype))
|
| 83 |
+
land = land / cnt.clamp(min=1)[:, None]
|
| 84 |
+
return (land.view(B, G, C), (cnt > 0).view(B, G))
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
class DeltaAttn(nn.Module):
|
| 88 |
+
def __init__(self, cfg):
|
| 89 |
+
super().__init__()
|
| 90 |
+
self.H, self.D, self.chunk = (cfg.n_heads, cfg.head_dim, cfg.chunk)
|
| 91 |
+
inner = cfg.n_heads * cfg.head_dim
|
| 92 |
+
self.q = nn.Linear(cfg.dim, inner, bias=False)
|
| 93 |
+
self.k = nn.Linear(cfg.dim, inner, bias=False)
|
| 94 |
+
self.v = nn.Linear(cfg.dim, inner, bias=False)
|
| 95 |
+
self.b = nn.Linear(cfg.dim, cfg.n_heads)
|
| 96 |
+
self.o = nn.Linear(inner, cfg.dim, bias=False)
|
| 97 |
+
|
| 98 |
+
def forward(self, x, write_mask):
|
| 99 |
+
B, T, _ = x.shape
|
| 100 |
+
H, D = (self.H, self.D)
|
| 101 |
+
q = self.q(x).view(B, T, H, D).transpose(1, 2)
|
| 102 |
+
k = self.k(x).view(B, T, H, D).transpose(1, 2)
|
| 103 |
+
v = self.v(x).view(B, T, H, D).transpose(1, 2)
|
| 104 |
+
q = F.normalize(q, dim=-1)
|
| 105 |
+
k = F.normalize(k, dim=-1)
|
| 106 |
+
beta = torch.sigmoid(self.b(x)).transpose(1, 2)
|
| 107 |
+
beta = beta * write_mask.unsqueeze(1)
|
| 108 |
+
o, _ = delta_rule_chunk(q, k, v, beta, self.chunk)
|
| 109 |
+
o = o.transpose(1, 2).reshape(B, T, H * D)
|
| 110 |
+
return self.o(o)
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
class LandmarkAttn(nn.Module):
|
| 114 |
+
def __init__(self, cfg):
|
| 115 |
+
super().__init__()
|
| 116 |
+
self.H, self.D, self.G = (cfg.n_heads, cfg.head_dim, cfg.n_landmarks)
|
| 117 |
+
inner = cfg.n_heads * cfg.head_dim
|
| 118 |
+
self.q = nn.Linear(cfg.dim, inner, bias=False)
|
| 119 |
+
self.k = nn.Linear(cfg.dim, inner, bias=False)
|
| 120 |
+
self.v = nn.Linear(cfg.dim, inner, bias=False)
|
| 121 |
+
self.o = nn.Linear(inner, cfg.dim, bias=False)
|
| 122 |
+
self.gate = nn.Parameter(torch.zeros(1))
|
| 123 |
+
|
| 124 |
+
def forward(self, x, wm):
|
| 125 |
+
B, T, _ = x.shape
|
| 126 |
+
H, D, G = (self.H, self.D, self.G)
|
| 127 |
+
land, lmask = pool_landmarks(x, wm, G)
|
| 128 |
+
q = self.q(x).view(B, T, H, D).transpose(1, 2)
|
| 129 |
+
k = self.k(land).view(B, G, H, D).transpose(1, 2)
|
| 130 |
+
v = self.v(land).view(B, G, H, D).transpose(1, 2)
|
| 131 |
+
att = torch.einsum("bhtd,bhgd->bhtg", q, k) / math.sqrt(D)
|
| 132 |
+
att = att.masked_fill(~lmask[:, None, None, :], -1000000000.0)
|
| 133 |
+
att = att.softmax(-1)
|
| 134 |
+
o = torch.einsum("bhtg,bhgd->bhtd", att, v).transpose(1, 2).reshape(B, T, H * D)
|
| 135 |
+
return self.o(o) * torch.tanh(self.gate)
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
class Block(nn.Module):
|
| 139 |
+
def __init__(self, cfg):
|
| 140 |
+
super().__init__()
|
| 141 |
+
self.n1 = nn.LayerNorm(cfg.dim, eps=cfg.ln_eps)
|
| 142 |
+
self.attn = DeltaAttn(cfg)
|
| 143 |
+
self.landmark = LandmarkAttn(cfg) if cfg.use_landmark else None
|
| 144 |
+
self.n2 = nn.LayerNorm(cfg.dim, eps=cfg.ln_eps)
|
| 145 |
+
hid = cfg.dim * cfg.ffn_mult
|
| 146 |
+
self.ff = nn.Sequential(
|
| 147 |
+
nn.Linear(cfg.dim, hid), nn.GELU(), nn.Linear(hid, cfg.dim)
|
| 148 |
+
)
|
| 149 |
+
|
| 150 |
+
def forward(self, x, wm):
|
| 151 |
+
h = self.n1(x)
|
| 152 |
+
a = self.attn(h, wm)
|
| 153 |
+
if self.landmark is not None:
|
| 154 |
+
a = a + self.landmark(h, wm)
|
| 155 |
+
x = x + a
|
| 156 |
+
x = x + self.ff(self.n2(x))
|
| 157 |
+
return x
|
| 158 |
+
|
| 159 |
+
|
| 160 |
+
class FelaTab(nn.Module):
|
| 161 |
+
def __init__(self, cfg: FelaTabConfig):
|
| 162 |
+
super().__init__()
|
| 163 |
+
self.cfg = cfg
|
| 164 |
+
self.feat_enc = nn.Linear(cfg.max_features, cfg.dim)
|
| 165 |
+
self.cls_label_emb = nn.Embedding(cfg.max_classes + 1, cfg.dim)
|
| 166 |
+
self.reg_label = nn.Linear(1, cfg.dim)
|
| 167 |
+
self.reg_label_gate = nn.Parameter(torch.ones(1))
|
| 168 |
+
self.type_emb = nn.Embedding(2, cfg.dim)
|
| 169 |
+
self.blocks = nn.ModuleList([Block(cfg) for _ in range(cfg.n_layers)])
|
| 170 |
+
self.norm = nn.LayerNorm(cfg.dim, eps=cfg.ln_eps)
|
| 171 |
+
self.cls_head = nn.Linear(cfg.dim, cfg.max_classes)
|
| 172 |
+
self.reg_head = nn.Linear(cfg.dim, 2)
|
| 173 |
+
|
| 174 |
+
def encode_tokens(self, X, y, n_support, task_type_id):
|
| 175 |
+
B, T, _ = X.shape
|
| 176 |
+
tok = self.feat_enc(X)
|
| 177 |
+
tok = tok + self.type_emb(task_type_id).view(1, 1, -1)
|
| 178 |
+
idx = torch.arange(T, device=X.device).unsqueeze(0)
|
| 179 |
+
wm = (idx < n_support.unsqueeze(1)).float()
|
| 180 |
+
if int(task_type_id) == 0:
|
| 181 |
+
yl = y.clamp(min=0).long()
|
| 182 |
+
lab = self.cls_label_emb(yl) * wm.unsqueeze(-1)
|
| 183 |
+
tok = tok + lab
|
| 184 |
+
else:
|
| 185 |
+
lab = (
|
| 186 |
+
self.reg_label(y.unsqueeze(-1).float())
|
| 187 |
+
* wm.unsqueeze(-1)
|
| 188 |
+
* self.reg_label_gate
|
| 189 |
+
)
|
| 190 |
+
tok = tok + lab
|
| 191 |
+
return (tok, wm)
|
| 192 |
+
|
| 193 |
+
def forward(self, X, y, n_support, task_type_id):
|
| 194 |
+
tok, wm = self.encode_tokens(X, y, n_support, task_type_id)
|
| 195 |
+
h = tok
|
| 196 |
+
for blk in self.blocks:
|
| 197 |
+
h = blk(h, wm)
|
| 198 |
+
h = self.norm(h)
|
| 199 |
+
if int(task_type_id) == 0:
|
| 200 |
+
return self.cls_head(h)
|
| 201 |
+
return self.reg_head(h)
|
| 202 |
+
|
| 203 |
+
|
| 204 |
+
_CONFIG_FIELDS = set(FelaTabConfig.__dataclass_fields__.keys())
|
| 205 |
+
TIERS = {
|
| 206 |
+
"big": dict(dim=1024, n_layers=28, n_heads=16, head_dim=64),
|
| 207 |
+
"small": dict(dim=512, n_layers=14, n_heads=8, head_dim=64),
|
| 208 |
+
}
|
| 209 |
+
|
| 210 |
+
|
| 211 |
+
def _to_config(cfg_dict: dict) -> FelaTabConfig:
|
| 212 |
+
return FelaTabConfig(**{k: v for k, v in cfg_dict.items() if k in _CONFIG_FIELDS})
|
| 213 |
+
|
| 214 |
+
|
| 215 |
+
def _read_json(path: str) -> dict:
|
| 216 |
+
with open(path) as f:
|
| 217 |
+
return json.load(f)
|
| 218 |
+
|
| 219 |
+
|
| 220 |
+
def _dequant_state_dict(tensors: dict) -> dict:
|
| 221 |
+
sd = {}
|
| 222 |
+
for k, v in tensors.items():
|
| 223 |
+
if k.endswith(".scale"):
|
| 224 |
+
continue
|
| 225 |
+
if v.dtype == torch.int8:
|
| 226 |
+
scale = tensors[k + ".scale"]
|
| 227 |
+
sd[k] = v.float() * scale[:, None]
|
| 228 |
+
else:
|
| 229 |
+
sd[k] = v.float()
|
| 230 |
+
return sd
|
| 231 |
+
|
| 232 |
+
|
| 233 |
+
def load_model(path_or_repo: str = ".", tier: str = "big", config: dict = None):
|
| 234 |
+
from safetensors.torch import load_file
|
| 235 |
+
|
| 236 |
+
def _pick(dir_path):
|
| 237 |
+
for base in (
|
| 238 |
+
f"model_{tier}_int8.safetensors",
|
| 239 |
+
f"model_{tier}.safetensors",
|
| 240 |
+
"model_int8.safetensors",
|
| 241 |
+
"model.safetensors",
|
| 242 |
+
):
|
| 243 |
+
p = os.path.join(dir_path, base)
|
| 244 |
+
if os.path.isfile(p):
|
| 245 |
+
return p
|
| 246 |
+
raise FileNotFoundError(f"no model safetensors for tier '{tier}' in {dir_path}")
|
| 247 |
+
|
| 248 |
+
def _cfg(dir_path):
|
| 249 |
+
for base in (f"config_{tier}.json", "config.json"):
|
| 250 |
+
p = os.path.join(dir_path, base)
|
| 251 |
+
if os.path.isfile(p):
|
| 252 |
+
return _read_json(p)
|
| 253 |
+
return dict(TIERS[tier])
|
| 254 |
+
|
| 255 |
+
if os.path.isfile(path_or_repo) and path_or_repo.endswith(".safetensors"):
|
| 256 |
+
weights_path = path_or_repo
|
| 257 |
+
cfg_dict = config or _cfg(os.path.dirname(path_or_repo) or ".")
|
| 258 |
+
elif os.path.isdir(path_or_repo):
|
| 259 |
+
weights_path = _pick(path_or_repo)
|
| 260 |
+
cfg_dict = config or _cfg(path_or_repo)
|
| 261 |
+
else:
|
| 262 |
+
from huggingface_hub import hf_hub_download
|
| 263 |
+
|
| 264 |
+
cfg_dict = config
|
| 265 |
+
if cfg_dict is None:
|
| 266 |
+
for base in (f"config_{tier}.json", "config.json"):
|
| 267 |
+
try:
|
| 268 |
+
cfg_dict = _read_json(hf_hub_download(path_or_repo, base))
|
| 269 |
+
break
|
| 270 |
+
except Exception:
|
| 271 |
+
continue
|
| 272 |
+
cfg_dict = cfg_dict or dict(TIERS[tier])
|
| 273 |
+
weights_path = None
|
| 274 |
+
for base in (f"model_{tier}_int8.safetensors", f"model_{tier}.safetensors"):
|
| 275 |
+
try:
|
| 276 |
+
weights_path = hf_hub_download(path_or_repo, base)
|
| 277 |
+
break
|
| 278 |
+
except Exception:
|
| 279 |
+
continue
|
| 280 |
+
if weights_path is None:
|
| 281 |
+
raise FileNotFoundError(
|
| 282 |
+
f"no model_{tier}[_int8].safetensors in repo {path_or_repo}"
|
| 283 |
+
)
|
| 284 |
+
for k, val in TIERS[tier].items():
|
| 285 |
+
cfg_dict.setdefault(k, val)
|
| 286 |
+
tensors = load_file(weights_path)
|
| 287 |
+
sd = _dequant_state_dict(tensors)
|
| 288 |
+
model = FelaTab(_to_config(cfg_dict))
|
| 289 |
+
model.load_state_dict(sd)
|
| 290 |
+
model.eval()
|
| 291 |
+
return model
|
| 292 |
+
|
| 293 |
+
|
| 294 |
+
from_pretrained = load_model
|
| 295 |
+
|
| 296 |
+
|
| 297 |
+
def _standardize_fit(Xtr: np.ndarray):
|
| 298 |
+
mean = Xtr.mean(axis=0)
|
| 299 |
+
scale = np.sqrt(((Xtr - mean) ** 2).mean(axis=0))
|
| 300 |
+
scale[scale == 0] = 1.0
|
| 301 |
+
return (mean.astype(np.float32), scale.astype(np.float32))
|
| 302 |
+
|
| 303 |
+
|
| 304 |
+
def _prep(model, Xtr, Xte):
|
| 305 |
+
cfg = model.cfg
|
| 306 |
+
Xtr = np.asarray(Xtr, dtype=np.float32)
|
| 307 |
+
Xte = np.asarray(Xte, dtype=np.float32)
|
| 308 |
+
mean, scale = _standardize_fit(Xtr)
|
| 309 |
+
Xtr2 = (Xtr - mean) / scale
|
| 310 |
+
Xte2 = (Xte - mean) / scale
|
| 311 |
+
F_ = cfg.max_features
|
| 312 |
+
if Xtr2.shape[1] > F_:
|
| 313 |
+
try:
|
| 314 |
+
from sklearn.decomposition import PCA
|
| 315 |
+
|
| 316 |
+
p = PCA(n_components=F_, random_state=0).fit(Xtr2)
|
| 317 |
+
Xtr2, Xte2 = (p.transform(Xtr2), p.transform(Xte2))
|
| 318 |
+
except Exception:
|
| 319 |
+
Xtr2, Xte2 = (Xtr2[:, :F_], Xte2[:, :F_])
|
| 320 |
+
|
| 321 |
+
def pad(A):
|
| 322 |
+
out = np.zeros((A.shape[0], F_), np.float32)
|
| 323 |
+
out[:, : min(A.shape[1], F_)] = A[:, :F_]
|
| 324 |
+
return out
|
| 325 |
+
|
| 326 |
+
return (np.nan_to_num(pad(Xtr2)), np.nan_to_num(pad(Xte2)))
|
| 327 |
+
|
| 328 |
+
|
| 329 |
+
@torch.no_grad()
|
| 330 |
+
def predict(
|
| 331 |
+
model, Xtr, ytr, Xte, task="classification", n_classes=None, support_cap=3000
|
| 332 |
+
):
|
| 333 |
+
is_cls = task.startswith("cls") or task == "classification"
|
| 334 |
+
Xtr = np.asarray(Xtr, dtype=np.float32)
|
| 335 |
+
ytr = np.asarray(ytr)
|
| 336 |
+
Xte = np.asarray(Xte, dtype=np.float32)
|
| 337 |
+
if len(Xtr) > support_cap:
|
| 338 |
+
idx = np.random.RandomState(0).permutation(len(Xtr))[:support_cap]
|
| 339 |
+
Xtr, ytr = (Xtr[idx], ytr[idx])
|
| 340 |
+
Xtr2, Xte2 = _prep(model, Xtr, Xte)
|
| 341 |
+
ns = len(Xtr2)
|
| 342 |
+
X = np.concatenate([Xtr2, Xte2], 0)[None]
|
| 343 |
+
if is_cls:
|
| 344 |
+
ncls = int(n_classes if n_classes is not None else ytr.max() + 1)
|
| 345 |
+
y = np.concatenate([ytr, np.zeros(len(Xte2))]).astype(np.int64)[None]
|
| 346 |
+
ttype = 0
|
| 347 |
+
else:
|
| 348 |
+
ymu, ysd = (float(ytr.mean()), float(ytr.std() + 1e-06))
|
| 349 |
+
y = np.concatenate([(ytr - ymu) / ysd, np.zeros(len(Xte2))]).astype(np.float32)[
|
| 350 |
+
None
|
| 351 |
+
]
|
| 352 |
+
ttype = 1
|
| 353 |
+
dev = next(model.parameters()).device
|
| 354 |
+
Xt = torch.from_numpy(X).to(dev)
|
| 355 |
+
yt = torch.from_numpy(y).to(dev)
|
| 356 |
+
nst = torch.tensor([ns]).to(dev)
|
| 357 |
+
out = model(Xt, yt, nst, torch.tensor(ttype, device=dev)).float()
|
| 358 |
+
q = out[0, ns:]
|
| 359 |
+
if is_cls:
|
| 360 |
+
return F.softmax(q[:, :ncls], dim=-1).cpu().numpy()
|
| 361 |
+
mean = q[:, 0].cpu().numpy() * ysd + ymu
|
| 362 |
+
std = np.sqrt(np.exp(np.clip(q[:, 1].cpu().numpy(), -8, 8))) * ysd
|
| 363 |
+
return (mean, std)
|
| 364 |
+
|
| 365 |
+
|
| 366 |
+
def predict_bagged(
|
| 367 |
+
model,
|
| 368 |
+
Xtr,
|
| 369 |
+
ytr,
|
| 370 |
+
Xte,
|
| 371 |
+
task="classification",
|
| 372 |
+
n_classes=None,
|
| 373 |
+
support_cap=3000,
|
| 374 |
+
n_bag=16,
|
| 375 |
+
base_seed=1000,
|
| 376 |
+
):
|
| 377 |
+
is_cls = task.startswith("cls") or task == "classification"
|
| 378 |
+
if not is_cls or n_bag <= 1:
|
| 379 |
+
return predict(model, Xtr, ytr, Xte, task, n_classes, support_cap)
|
| 380 |
+
Xtr = np.asarray(Xtr, dtype=np.float32)
|
| 381 |
+
ytr = np.asarray(ytr)
|
| 382 |
+
Xte = np.asarray(Xte, dtype=np.float32)
|
| 383 |
+
ncls = int(n_classes if n_classes is not None else ytr.max() + 1)
|
| 384 |
+
acc = []
|
| 385 |
+
for b in range(n_bag):
|
| 386 |
+
rng = np.random.RandomState(base_seed + b)
|
| 387 |
+
rp = rng.permutation(len(Xtr))
|
| 388 |
+
cperm = rng.permutation(Xtr.shape[1])
|
| 389 |
+
acc.append(
|
| 390 |
+
predict(
|
| 391 |
+
model,
|
| 392 |
+
Xtr[rp][:, cperm],
|
| 393 |
+
ytr[rp],
|
| 394 |
+
Xte[:, cperm],
|
| 395 |
+
"classification",
|
| 396 |
+
ncls,
|
| 397 |
+
support_cap,
|
| 398 |
+
)
|
| 399 |
+
)
|
| 400 |
+
return np.mean(acc, axis=0)
|
| 401 |
+
|
| 402 |
+
|
| 403 |
+
def count_params(m):
|
| 404 |
+
return sum((p.numel() for p in m.parameters()))
|
modeling_felatab.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
from transformers import PreTrainedModel
|
| 3 |
+
from transformers.modeling_outputs import SequenceClassifierOutput
|
| 4 |
+
|
| 5 |
+
from .configuration_felatab import FelaTabConfig as _HFConfig
|
| 6 |
+
from .modeling import FelaTab
|
| 7 |
+
from .modeling import FelaTabConfig as _CoreConfig
|
| 8 |
+
|
| 9 |
+
_FIELDS = set(_CoreConfig.__dataclass_fields__.keys())
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
class FelaTabModel(PreTrainedModel):
|
| 13 |
+
config_class = _HFConfig
|
| 14 |
+
base_model_prefix = "model"
|
| 15 |
+
|
| 16 |
+
def __init__(self, config):
|
| 17 |
+
super().__init__(config)
|
| 18 |
+
cfg = _CoreConfig(
|
| 19 |
+
**{k: getattr(config, k) for k in _FIELDS if hasattr(config, k)}
|
| 20 |
+
)
|
| 21 |
+
self.model = FelaTab(cfg)
|
| 22 |
+
self.post_init()
|
| 23 |
+
|
| 24 |
+
def forward(self, X=None, y=None, n_support=None, task_type_id=None, **kwargs):
|
| 25 |
+
if task_type_id is None:
|
| 26 |
+
task_type_id = torch.tensor(0, device=X.device)
|
| 27 |
+
logits = self.model(X, y, n_support, task_type_id)
|
| 28 |
+
return SequenceClassifierOutput(logits=logits)
|
prior.py
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
from dataclasses import dataclass
|
| 3 |
+
|
| 4 |
+
ACTS = ["relu", "tanh", "sin", "abs", "square", "identity", "sigmoid"]
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
def _act(name, x):
|
| 8 |
+
if name == "relu":
|
| 9 |
+
return np.maximum(x, 0.0)
|
| 10 |
+
if name == "tanh":
|
| 11 |
+
return np.tanh(x)
|
| 12 |
+
if name == "sin":
|
| 13 |
+
return np.sin(x)
|
| 14 |
+
if name == "abs":
|
| 15 |
+
return np.abs(x)
|
| 16 |
+
if name == "square":
|
| 17 |
+
return np.square(x) - 1.0
|
| 18 |
+
if name == "sigmoid":
|
| 19 |
+
return 1.0 / (1.0 + np.exp(-np.clip(x, -30, 30)))
|
| 20 |
+
return x
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
@dataclass
|
| 24 |
+
class PriorConfig:
|
| 25 |
+
max_features: int = 100
|
| 26 |
+
min_features: int = 2
|
| 27 |
+
max_classes: int = 10
|
| 28 |
+
min_rows: int = 128
|
| 29 |
+
max_rows: int = 2048
|
| 30 |
+
reg_frac: float = 0.35
|
| 31 |
+
cat_frac: float = 0.35
|
| 32 |
+
irrelevant_frac: float = 0.25
|
| 33 |
+
max_depth: int = 5
|
| 34 |
+
max_width: int = 32
|
| 35 |
+
noise_scale: float = 0.3
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
def sample_task(cfg: PriorConfig, rng: np.random.Generator):
|
| 39 |
+
F = int(rng.integers(cfg.min_features, cfg.max_features + 1))
|
| 40 |
+
N = int(rng.integers(cfg.min_rows, cfg.max_rows + 1))
|
| 41 |
+
is_reg = rng.random() < cfg.reg_frac
|
| 42 |
+
d_latent = int(rng.integers(2, 12))
|
| 43 |
+
h = rng.standard_normal((N, d_latent)).astype(np.float32)
|
| 44 |
+
if rng.random() < 0.3:
|
| 45 |
+
h = h * rng.gamma(2.0, 0.5, size=(1, d_latent)).astype(np.float32)
|
| 46 |
+
depth = int(rng.integers(2, cfg.max_depth + 1))
|
| 47 |
+
nodes = [h]
|
| 48 |
+
cur = h
|
| 49 |
+
for _ in range(depth):
|
| 50 |
+
w = int(rng.integers(4, cfg.max_width + 1))
|
| 51 |
+
W = rng.standard_normal((cur.shape[1], w)).astype(np.float32)
|
| 52 |
+
sparsity = rng.uniform(0.3, 0.9)
|
| 53 |
+
W *= rng.random(W.shape) > sparsity
|
| 54 |
+
W /= np.sqrt(np.maximum(1.0, (W != 0).sum(0, keepdims=True)))
|
| 55 |
+
b = rng.standard_normal((1, w)).astype(np.float32) * rng.uniform(0, 1.0)
|
| 56 |
+
pre = cur @ W + b
|
| 57 |
+
acts = rng.choice(ACTS, size=w)
|
| 58 |
+
post = np.empty_like(pre)
|
| 59 |
+
for j in range(w):
|
| 60 |
+
post[:, j] = _act(acts[j], pre[:, j])
|
| 61 |
+
if rng.random() < 0.3 and w >= 2:
|
| 62 |
+
i1, i2 = rng.integers(0, w, size=2)
|
| 63 |
+
post[:, i1] = post[:, i1] * post[:, i2]
|
| 64 |
+
post = np.clip(post, -30.0, 30.0)
|
| 65 |
+
nodes.append(post)
|
| 66 |
+
cur = post
|
| 67 |
+
allnodes = np.concatenate(nodes, axis=1)
|
| 68 |
+
total = allnodes.shape[1]
|
| 69 |
+
tgt_idx = int(rng.integers(max(0, total - cur.shape[1]), total))
|
| 70 |
+
target_raw = allnodes[:, tgt_idx].astype(np.float32)
|
| 71 |
+
k_mix = int(rng.integers(1, min(6, total)))
|
| 72 |
+
mix_idx = rng.choice(total, size=k_mix, replace=False)
|
| 73 |
+
mix_w = rng.standard_normal(k_mix).astype(np.float32)
|
| 74 |
+
target_raw = allnodes[:, mix_idx] @ mix_w
|
| 75 |
+
target_raw = target_raw + cfg.noise_scale * rng.standard_normal(N).astype(
|
| 76 |
+
np.float32
|
| 77 |
+
) * (target_raw.std() + 1e-06)
|
| 78 |
+
feat_pool = [i for i in range(total) if i not in set(mix_idx.tolist())]
|
| 79 |
+
if len(feat_pool) == 0:
|
| 80 |
+
feat_pool = list(range(total))
|
| 81 |
+
n_real = min(F, len(feat_pool))
|
| 82 |
+
chosen = rng.choice(feat_pool, size=n_real, replace=False)
|
| 83 |
+
X = allnodes[:, chosen].astype(np.float32)
|
| 84 |
+
if X.shape[1] < F:
|
| 85 |
+
n_noise = F - X.shape[1]
|
| 86 |
+
noise_cols = rng.standard_normal((N, n_noise)).astype(np.float32)
|
| 87 |
+
X = np.concatenate([X, noise_cols], axis=1)
|
| 88 |
+
n_irr = int(rng.uniform(0, cfg.irrelevant_frac) * F)
|
| 89 |
+
if n_irr > 0:
|
| 90 |
+
irr = rng.choice(F, size=min(n_irr, F), replace=False)
|
| 91 |
+
X[:, irr] = rng.standard_normal((N, len(irr))).astype(np.float32)
|
| 92 |
+
perm = rng.permutation(F)
|
| 93 |
+
X = X[:, perm]
|
| 94 |
+
for c in range(F):
|
| 95 |
+
if rng.random() < cfg.cat_frac:
|
| 96 |
+
n_lvl = int(rng.integers(2, 10))
|
| 97 |
+
qs = np.quantile(X[:, c], np.linspace(0, 1, n_lvl + 1)[1:-1])
|
| 98 |
+
X[:, c] = np.digitize(X[:, c], qs).astype(np.float32)
|
| 99 |
+
X = X + rng.standard_normal(X.shape).astype(np.float32) * cfg.noise_scale * 0.3
|
| 100 |
+
X = np.nan_to_num(X, nan=0.0, posinf=0.0, neginf=0.0)
|
| 101 |
+
mu = X.mean(0, keepdims=True)
|
| 102 |
+
sd = X.std(0, keepdims=True) + 1e-06
|
| 103 |
+
X = (X - mu) / sd
|
| 104 |
+
if is_reg:
|
| 105 |
+
y = np.nan_to_num(target_raw, nan=0.0, posinf=0.0, neginf=0.0)
|
| 106 |
+
y = (y - y.mean()) / (y.std() + 1e-06)
|
| 107 |
+
y = y.astype(np.float32)
|
| 108 |
+
n_classes = 0
|
| 109 |
+
task_type = "reg"
|
| 110 |
+
else:
|
| 111 |
+
K = int(rng.integers(2, cfg.max_classes + 1))
|
| 112 |
+
t = np.nan_to_num(target_raw, nan=0.0, posinf=0.0, neginf=0.0)
|
| 113 |
+
if rng.random() < 0.5:
|
| 114 |
+
qs = np.quantile(t, np.linspace(0, 1, K + 1)[1:-1])
|
| 115 |
+
y = np.digitize(t, qs).astype(np.int64)
|
| 116 |
+
else:
|
| 117 |
+
scores = allnodes @ rng.standard_normal((total, K)).astype(np.float32)
|
| 118 |
+
y = scores.argmax(1).astype(np.int64)
|
| 119 |
+
uniq = np.unique(y)
|
| 120 |
+
if len(uniq) < 2:
|
| 121 |
+
y = (t > np.median(t)).astype(np.int64)
|
| 122 |
+
uniq = np.unique(y)
|
| 123 |
+
remap = {u: i for i, u in enumerate(uniq)}
|
| 124 |
+
y = np.array([remap[v] for v in y], dtype=np.int64)
|
| 125 |
+
n_classes = int(len(uniq))
|
| 126 |
+
task_type = "cls"
|
| 127 |
+
feat_mask = np.ones(F, dtype=np.float32)
|
| 128 |
+
return {
|
| 129 |
+
"X": X,
|
| 130 |
+
"y": y,
|
| 131 |
+
"n_features": F,
|
| 132 |
+
"n_classes": n_classes,
|
| 133 |
+
"task_type": task_type,
|
| 134 |
+
"feat_mask": feat_mask,
|
| 135 |
+
}
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
def sample_batch(cfg, rng, n_tasks):
|
| 139 |
+
return [sample_task(cfg, rng) for _ in range(n_tasks)]
|
| 140 |
+
|
| 141 |
+
|
| 142 |
+
def _worker(args):
|
| 143 |
+
seed, n, cfg = args
|
| 144 |
+
rng = np.random.default_rng(seed)
|
| 145 |
+
return sample_batch(cfg, rng, n)
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
def gen_pool(cfg, n_tasks, seed=0, workers=None):
|
| 149 |
+
import multiprocessing as mp
|
| 150 |
+
|
| 151 |
+
if workers is None:
|
| 152 |
+
workers = min(mp.cpu_count(), 64)
|
| 153 |
+
per = max(1, n_tasks // workers)
|
| 154 |
+
jobs = [(seed + i, per, cfg) for i in range(workers)]
|
| 155 |
+
rem = n_tasks - per * workers
|
| 156 |
+
if rem > 0:
|
| 157 |
+
jobs.append((seed + workers, rem, cfg))
|
| 158 |
+
with mp.Pool(workers) as pool:
|
| 159 |
+
outs = pool.map(_worker, jobs)
|
| 160 |
+
tasks = [t for sub in outs for t in sub]
|
| 161 |
+
return tasks[:n_tasks]
|
| 162 |
+
|
| 163 |
+
|
| 164 |
+
if __name__ == "__main__":
|
| 165 |
+
cfg = PriorConfig()
|
| 166 |
+
rng = np.random.default_rng(0)
|
| 167 |
+
print("=== 8 sampled synthetic tasks ===")
|
| 168 |
+
kinds = {"cls": 0, "reg": 0}
|
| 169 |
+
for i in range(8):
|
| 170 |
+
t = sample_task(cfg, rng)
|
| 171 |
+
kinds[t["task_type"]] += 1
|
| 172 |
+
if t["task_type"] == "cls":
|
| 173 |
+
_, cnts = np.unique(t["y"], return_counts=True)
|
| 174 |
+
bal = f"class_counts={cnts.tolist()}"
|
| 175 |
+
else:
|
| 176 |
+
bal = f"y_range=[{t['y'].min():.2f},{t['y'].max():.2f}] std={t['y'].std():.2f}"
|
| 177 |
+
print(
|
| 178 |
+
f"[{i}] {t['task_type']:3s} N={t['X'].shape[0]:5d} F={t['n_features']:3d} K={t['n_classes']:2d} Xstd={t['X'].std():.2f} Xmean={t['X'].mean():+.3f} {bal}"
|
| 179 |
+
)
|
| 180 |
+
print("task-type mix:", kinds)
|
| 181 |
+
import time
|
| 182 |
+
|
| 183 |
+
t0 = time.time()
|
| 184 |
+
tasks = sample_batch(cfg, rng, 500)
|
| 185 |
+
dt = time.time() - t0
|
| 186 |
+
Fs = [t["n_features"] for t in tasks]
|
| 187 |
+
Ns = [t["X"].shape[0] for t in tasks]
|
| 188 |
+
Ks = [t["n_classes"] for t in tasks if t["task_type"] == "cls"]
|
| 189 |
+
regf = np.mean([t["task_type"] == "reg" for t in tasks])
|
| 190 |
+
print(f"\n500 tasks in {dt:.2f}s ({500 / dt:.0f} tasks/s single-core)")
|
| 191 |
+
print(f"F: min={min(Fs)} max={max(Fs)} mean={np.mean(Fs):.1f}")
|
| 192 |
+
print(f"N: min={min(Ns)} max={max(Ns)} mean={np.mean(Ns):.0f}")
|
| 193 |
+
print(f"K(cls): min={min(Ks)} max={max(Ks)} mean={np.mean(Ks):.1f}")
|
| 194 |
+
print(f"regression fraction: {regf:.2f}")
|
quickstart/README.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Quickstart
|
| 2 |
+
|
| 3 |
+
Point FelaTab at a real public table and get zero shot predictions on CPU. Uses the self
|
| 4 |
+
contained loader and in context predict path in `../modeling.py`.
|
| 5 |
+
|
| 6 |
+
## Steps
|
| 7 |
+
|
| 8 |
+
1. Install the pinned requirements (CPU PyTorch + scikit-learn for the example datasets):
|
| 9 |
+
|
| 10 |
+
```bash
|
| 11 |
+
pip install -r requirements.txt
|
| 12 |
+
```
|
| 13 |
+
|
| 14 |
+
2. Run. The model files ship in the parent directory, so the default `--weights` points there:
|
| 15 |
+
|
| 16 |
+
```bash
|
| 17 |
+
python run.py # small int8 tier, breast cancer classification
|
| 18 |
+
python run.py --tier big # the 411.9M flagship
|
| 19 |
+
python run.py --dataset wine --bag 8 # with inference time bagging
|
| 20 |
+
```
|
| 21 |
+
|
| 22 |
+
## Load from Python
|
| 23 |
+
|
| 24 |
+
```python
|
| 25 |
+
from modeling import load_model, predict, predict_bagged
|
| 26 |
+
|
| 27 |
+
# tier = "small" (dim512, ~51.6M) or "big" (dim1024, ~411.9M). The loader auto detects
|
| 28 |
+
# the int8 bundle and dequantizes it, so you always get a plain fp32 model.
|
| 29 |
+
model = load_model("/path/to/repo_dir", tier="small") # or a HF repo id, or a .safetensors path
|
| 30 |
+
|
| 31 |
+
# classification: Xtr/ytr are the support rows (your labelled examples), Xte the query rows
|
| 32 |
+
probs = predict(model, Xtr, ytr, Xte, task="classification", n_classes=3) # [n_query, 3]
|
| 33 |
+
|
| 34 |
+
# regression: returns (mean, std) error bars in the original label units
|
| 35 |
+
mean, std = predict(model, Xtr, ytr, Xte, task="regression")
|
| 36 |
+
|
| 37 |
+
# optional: inference time bagging lifts classification a little (no retraining)
|
| 38 |
+
probs = predict_bagged(model, Xtr, ytr, Xte, task="classification", n_classes=3, n_bag=16)
|
| 39 |
+
```
|
| 40 |
+
|
| 41 |
+
There is no per table training. The support rows and query rows are packed into one sequence and
|
| 42 |
+
run through the model in a single forward pass; the query predictions come out calibrated. See
|
| 43 |
+
the model card for the honest measured numbers, the regression caveat, and the intended use.
|
quickstart/requirements.txt
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
torch==2.8.0
|
| 2 |
+
numpy==2.1.3
|
| 3 |
+
safetensors==0.5.3
|
| 4 |
+
huggingface-hub==0.34.4
|
| 5 |
+
scikit-learn==1.5.2
|
quickstart/run.py
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import argparse
|
| 2 |
+
import os
|
| 3 |
+
import sys
|
| 4 |
+
import numpy as np
|
| 5 |
+
|
| 6 |
+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
|
| 7 |
+
from modeling import load_model, predict, predict_bagged
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
def main():
|
| 11 |
+
ap = argparse.ArgumentParser()
|
| 12 |
+
ap.add_argument(
|
| 13 |
+
"--weights",
|
| 14 |
+
default=os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
|
| 15 |
+
help="repo dir with model_<tier>[_int8].safetensors + config, or a .safetensors path",
|
| 16 |
+
)
|
| 17 |
+
ap.add_argument("--tier", default="small", choices=["small", "big"])
|
| 18 |
+
ap.add_argument(
|
| 19 |
+
"--dataset", default="breast_cancer", choices=["breast_cancer", "wine", "iris"]
|
| 20 |
+
)
|
| 21 |
+
ap.add_argument(
|
| 22 |
+
"--bag", type=int, default=1, help="inference-bagging passes (classification)"
|
| 23 |
+
)
|
| 24 |
+
args = ap.parse_args()
|
| 25 |
+
from sklearn.model_selection import train_test_split
|
| 26 |
+
from sklearn.datasets import load_breast_cancer, load_wine, load_iris
|
| 27 |
+
|
| 28 |
+
loader = {
|
| 29 |
+
"breast_cancer": load_breast_cancer,
|
| 30 |
+
"wine": load_wine,
|
| 31 |
+
"iris": load_iris,
|
| 32 |
+
}[args.dataset]
|
| 33 |
+
d = loader()
|
| 34 |
+
X, y = (d.data.astype(np.float32), d.target.astype(np.int64))
|
| 35 |
+
names = list(getattr(d, "target_names", [str(i) for i in range(int(y.max()) + 1)]))
|
| 36 |
+
Xtr, Xte, ytr, yte = train_test_split(
|
| 37 |
+
X, y, test_size=0.3, random_state=0, stratify=y
|
| 38 |
+
)
|
| 39 |
+
model = load_model(args.weights, tier=args.tier)
|
| 40 |
+
ncls = int(y.max() + 1)
|
| 41 |
+
print(
|
| 42 |
+
f"dataset={args.dataset} support rows={len(Xtr)} query rows={len(Xte)} features={X.shape[1]} classes={ncls} tier={args.tier}"
|
| 43 |
+
)
|
| 44 |
+
if args.bag > 1:
|
| 45 |
+
probs = predict_bagged(
|
| 46 |
+
model, Xtr, ytr, Xte, "classification", n_classes=ncls, n_bag=args.bag
|
| 47 |
+
)
|
| 48 |
+
else:
|
| 49 |
+
probs = predict(model, Xtr, ytr, Xte, "classification", n_classes=ncls)
|
| 50 |
+
acc = float((probs.argmax(1) == yte).mean())
|
| 51 |
+
print(f"zero-shot accuracy: {acc:.3f} (in-context, no training)")
|
| 52 |
+
i = 0
|
| 53 |
+
p = probs[i]
|
| 54 |
+
print(
|
| 55 |
+
f"example query row 0 -> predicted '{names[p.argmax()]}' ({p.max() * 100:.1f}% confidence); true '{names[yte[i]]}'"
|
| 56 |
+
)
|
| 57 |
+
print(
|
| 58 |
+
" full class probabilities: "
|
| 59 |
+
+ ", ".join((f"{names[c]}={p[c] * 100:.1f}%" for c in range(ncls)))
|
| 60 |
+
)
|
| 61 |
+
Xr = np.delete(X, 0, axis=1).astype(np.float32)
|
| 62 |
+
yr = X[:, 0].astype(np.float32)
|
| 63 |
+
Xr_tr, Xr_te, yr_tr, yr_te = train_test_split(Xr, yr, test_size=0.3, random_state=0)
|
| 64 |
+
mean, std = predict(model, Xr_tr, yr_tr, Xr_te, "regression")
|
| 65 |
+
print(
|
| 66 |
+
f"regression demo (predict feature 0): example -> mean {mean[0]:.3f} +/- {std[0]:.3f} (true {yr_te[0]:.3f}); this is the honest Gaussian error bar"
|
| 67 |
+
)
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
if __name__ == "__main__":
|
| 71 |
+
main()
|
requirements.txt
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
torch==2.8.0
|
| 2 |
+
numpy==2.1.3
|
| 3 |
+
safetensors==0.5.3
|
| 4 |
+
huggingface-hub==0.34.4
|
space/README.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: FelaTab playground
|
| 3 |
+
colorFrom: indigo
|
| 4 |
+
colorTo: green
|
| 5 |
+
sdk: gradio
|
| 6 |
+
sdk_version: 4.44.0
|
| 7 |
+
app_file: app.py
|
| 8 |
+
pinned: false
|
| 9 |
+
license: other
|
| 10 |
+
---
|
| 11 |
+
|
| 12 |
+
# FelaTab playground
|
| 13 |
+
|
| 14 |
+
Paste a small labelled table and a row to predict. FelaTab learns the pattern from your example
|
| 15 |
+
rows in a single forward pass, with no training or setup, and fills the answer with a
|
| 16 |
+
confidence range. Runs on CPU.
|
| 17 |
+
|
| 18 |
+
## How to use
|
| 19 |
+
|
| 20 |
+
Put your data as comma or space separated rows, one row per line, with a header line. The last
|
| 21 |
+
column is the label. Use `?` in the label column for the rows you want predicted.
|
| 22 |
+
|
| 23 |
+
- If the label column holds categories (e.g. Apple / Lemon / Grape), it predicts a class with
|
| 24 |
+
probabilities (classification).
|
| 25 |
+
- If the label column holds numbers, it predicts a value with an error bar (regression).
|
| 26 |
+
|
| 27 |
+
## Which model
|
| 28 |
+
|
| 29 |
+
The Space loads the small tier by default (dim512, about 51.6M parameters, int8, roughly 52 MB).
|
| 30 |
+
Set the environment variable `FELATAB_TIER=big` to load the flagship (about 411.9M parameters).
|
| 31 |
+
|
| 32 |
+
## Honest scope
|
| 33 |
+
|
| 34 |
+
This is a research preview. FelaTab matches or slightly trails a tuned gradient boosted tree on
|
| 35 |
+
zero shot classification and is behind trees on regression accuracy (it ships calibrated error
|
| 36 |
+
bars for regression rather than headline accuracy). See the model card for the measured numbers.
|
space/app.py
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import sys
|
| 3 |
+
import gradio as gr
|
| 4 |
+
import numpy as np
|
| 5 |
+
|
| 6 |
+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
|
| 7 |
+
from modeling import load_model, predict
|
| 8 |
+
|
| 9 |
+
WEIGHTS = os.environ.get(
|
| 10 |
+
"FELATAB_WEIGHTS", os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
| 11 |
+
)
|
| 12 |
+
TIER = os.environ.get("FELATAB_TIER", "small")
|
| 13 |
+
try:
|
| 14 |
+
MODEL = load_model(WEIGHTS, tier=TIER)
|
| 15 |
+
except Exception as e:
|
| 16 |
+
MODEL = None
|
| 17 |
+
_ERR = str(e)
|
| 18 |
+
EXAMPLE = "weight_g, sugar_pct, width_mm, label\n151, 7.2, 12, Apple\n149, 7.0, 13, Apple\n158, 7.4, 11, Apple\n102, 6.1, 3, Lemon\n98, 5.9, 2, Lemon\n110, 6.3, 4, Lemon\n6, 2.1, 16, Grape\n5, 1.9, 17, Grape\n7, 2.2, 15, Grape\n153, 7.1, 12, ?"
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def _parse(text):
|
| 22 |
+
rows = [r.strip() for r in text.strip().splitlines() if r.strip()]
|
| 23 |
+
header = [c.strip() for c in rows[0].replace(",", " ").split()]
|
| 24 |
+
data = [[c.strip() for c in r.replace(",", " ").split()] for r in rows[1:]]
|
| 25 |
+
return (header, data)
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
def run(text):
|
| 29 |
+
if MODEL is None:
|
| 30 |
+
return f"Weights not found ({_ERR}). Set FELATAB_WEIGHTS to the repo directory."
|
| 31 |
+
try:
|
| 32 |
+
header, data = _parse(text)
|
| 33 |
+
label_col = len(header) - 1
|
| 34 |
+
feats, labels, queries = ([], [], [])
|
| 35 |
+
for r in data:
|
| 36 |
+
xs = [float(v) for v in r[:label_col]]
|
| 37 |
+
lab = r[label_col]
|
| 38 |
+
if lab in ("?", "", "-"):
|
| 39 |
+
queries.append(xs)
|
| 40 |
+
else:
|
| 41 |
+
feats.append(xs)
|
| 42 |
+
labels.append(lab)
|
| 43 |
+
if not feats or not queries:
|
| 44 |
+
return (
|
| 45 |
+
"Provide labelled support rows and at least one query row (label '?')."
|
| 46 |
+
)
|
| 47 |
+
except Exception as e:
|
| 48 |
+
return f"Could not parse the table: {e}"
|
| 49 |
+
Xtr = np.array(feats, dtype=np.float32)
|
| 50 |
+
Xte = np.array(queries, dtype=np.float32)
|
| 51 |
+
classes = sorted(set(labels))
|
| 52 |
+
is_cls = not all((_is_num(l) for l in labels))
|
| 53 |
+
if is_cls:
|
| 54 |
+
cidx = {c: i for i, c in enumerate(classes)}
|
| 55 |
+
ytr = np.array([cidx[l] for l in labels], dtype=np.int64)
|
| 56 |
+
probs = predict(MODEL, Xtr, ytr, Xte, "classification", n_classes=len(classes))
|
| 57 |
+
out = []
|
| 58 |
+
for qi, p in enumerate(probs):
|
| 59 |
+
top = int(p.argmax())
|
| 60 |
+
dist = " ".join(
|
| 61 |
+
(f"{classes[c]}={p[c] * 100:.0f}%" for c in range(len(classes)))
|
| 62 |
+
)
|
| 63 |
+
out.append(
|
| 64 |
+
f"query {qi + 1}: {classes[top]} ({p[top] * 100:.0f}% confidence)\n {dist}"
|
| 65 |
+
)
|
| 66 |
+
return "\n".join(out)
|
| 67 |
+
else:
|
| 68 |
+
ytr = np.array([float(l) for l in labels], dtype=np.float32)
|
| 69 |
+
mean, std = predict(MODEL, Xtr, ytr, Xte, "regression")
|
| 70 |
+
return "\n".join(
|
| 71 |
+
(
|
| 72 |
+
f"query {i + 1}: {mean[i]:.2f} (likely within +/- {1.645 * std[i]:.2f})"
|
| 73 |
+
for i in range(len(mean))
|
| 74 |
+
)
|
| 75 |
+
)
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
def _is_num(s):
|
| 79 |
+
try:
|
| 80 |
+
float(s)
|
| 81 |
+
return True
|
| 82 |
+
except Exception:
|
| 83 |
+
return False
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
with gr.Blocks(title="FelaTab playground") as demo:
|
| 87 |
+
gr.Markdown(
|
| 88 |
+
"# FelaTab playground\nPaste a small labelled table and a row to predict. The model learns the pattern from your examples in a single pass, with no training or setup, and fills the answer with a confidence range. Put `?` in the label column for the rows you want predicted. If the label column is numbers, it predicts a value with an error bar (regression); if it is categories, it predicts a class with probabilities. Runs on CPU."
|
| 89 |
+
)
|
| 90 |
+
inp = gr.Textbox(
|
| 91 |
+
label="your table (comma or space separated, last column = label, '?' = predict)",
|
| 92 |
+
lines=12,
|
| 93 |
+
value=EXAMPLE,
|
| 94 |
+
)
|
| 95 |
+
out = gr.Textbox(label="prediction", lines=8)
|
| 96 |
+
with gr.Row():
|
| 97 |
+
gr.Button("Load example").click(lambda: EXAMPLE, outputs=inp)
|
| 98 |
+
gr.Button("Predict").click(run, inputs=inp, outputs=out)
|
| 99 |
+
if __name__ == "__main__":
|
| 100 |
+
demo.launch()
|
space/requirements.txt
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
torch==2.8.0
|
| 2 |
+
numpy==2.1.3
|
| 3 |
+
safetensors==0.5.3
|
| 4 |
+
huggingface-hub==0.34.4
|
| 5 |
+
scikit-learn==1.5.2
|
| 6 |
+
gradio==4.44.0
|
train.py
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import argparse
|
| 2 |
+
import math
|
| 3 |
+
import os
|
| 4 |
+
import time
|
| 5 |
+
import numpy as np
|
| 6 |
+
import torch
|
| 7 |
+
import torch.nn.functional as F
|
| 8 |
+
from modeling import FelaTab, FelaTabConfig, count_params
|
| 9 |
+
from prior import PriorConfig, gen_pool
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def collate(tasks, task_type, tmax, rng, maxF, s_frac=(0.5, 0.9)):
|
| 13 |
+
B = len(tasks)
|
| 14 |
+
used, sup = ([], [])
|
| 15 |
+
for t in tasks:
|
| 16 |
+
N = t["X"].shape[0]
|
| 17 |
+
n = min(N, tmax)
|
| 18 |
+
frac = rng.uniform(*s_frac)
|
| 19 |
+
s = int(np.clip(int(frac * n), 16, n - 8))
|
| 20 |
+
used.append(n)
|
| 21 |
+
sup.append(s)
|
| 22 |
+
T = max(used)
|
| 23 |
+
X = np.zeros((B, T, maxF), np.float32)
|
| 24 |
+
y = np.zeros((B, T), np.int64 if task_type == "cls" else np.float32)
|
| 25 |
+
lm = np.zeros((B, T), np.float32)
|
| 26 |
+
ncl = np.zeros(B, np.int64)
|
| 27 |
+
ns = np.zeros(B, np.int64)
|
| 28 |
+
for b, t in enumerate(tasks):
|
| 29 |
+
N = t["X"].shape[0]
|
| 30 |
+
n = used[b]
|
| 31 |
+
s = sup[b]
|
| 32 |
+
Ft = min(t["X"].shape[1], maxF)
|
| 33 |
+
perm = rng.permutation(N)[:n]
|
| 34 |
+
X[b, :n, :Ft] = t["X"][perm][:, :Ft]
|
| 35 |
+
y[b, :n] = t["y"][perm]
|
| 36 |
+
lm[b, s:n] = 1.0
|
| 37 |
+
ns[b] = s
|
| 38 |
+
ncl[b] = t["n_classes"] if task_type == "cls" else 0
|
| 39 |
+
return (
|
| 40 |
+
torch.from_numpy(X),
|
| 41 |
+
torch.from_numpy(y),
|
| 42 |
+
torch.from_numpy(ns),
|
| 43 |
+
torch.from_numpy(lm),
|
| 44 |
+
torch.from_numpy(ncl),
|
| 45 |
+
)
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
def cls_loss_acc(logits, y, lm, ncl):
|
| 49 |
+
B, T, C = logits.shape
|
| 50 |
+
cmask = torch.arange(C, device=logits.device).view(1, C) < ncl.view(B, 1)
|
| 51 |
+
logits = logits.masked_fill(~cmask.unsqueeze(1), -1000000000.0)
|
| 52 |
+
lf = logits.reshape(B * T, C)
|
| 53 |
+
yf = y.reshape(B * T).clamp(min=0)
|
| 54 |
+
mf = lm.reshape(B * T).bool()
|
| 55 |
+
if mf.sum() == 0:
|
| 56 |
+
return (logits.sum() * 0.0, 0.0)
|
| 57 |
+
loss = F.cross_entropy(lf[mf], yf[mf])
|
| 58 |
+
acc = (lf[mf].argmax(-1) == yf[mf]).float().mean().item()
|
| 59 |
+
return (loss, acc)
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
def reg_loss_r2(out, y, lm):
|
| 63 |
+
mean = out[..., 0]
|
| 64 |
+
logvar = out[..., 1].clamp(-8, 8)
|
| 65 |
+
mf = lm.bool()
|
| 66 |
+
if mf.sum() == 0:
|
| 67 |
+
return (out.sum() * 0.0, 0.0)
|
| 68 |
+
m, lv, t = (mean[mf], logvar[mf], y[mf])
|
| 69 |
+
nll = 0.5 * (lv + (t - m) ** 2 / torch.exp(lv) + math.log(2 * math.pi))
|
| 70 |
+
ss_res = ((t - m) ** 2).sum().item()
|
| 71 |
+
ss_tot = ((t - t.mean()) ** 2).sum().item() + 1e-08
|
| 72 |
+
return (nll.mean(), 1 - ss_res / ss_tot)
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
def main():
|
| 76 |
+
ap = argparse.ArgumentParser()
|
| 77 |
+
ap.add_argument("--steps", type=int, default=20000)
|
| 78 |
+
ap.add_argument("--bs", type=int, default=16)
|
| 79 |
+
ap.add_argument("--tmax", type=int, default=1024)
|
| 80 |
+
ap.add_argument("--lr", type=float, default=0.0003)
|
| 81 |
+
ap.add_argument("--dim", type=int, default=512)
|
| 82 |
+
ap.add_argument("--layers", type=int, default=14)
|
| 83 |
+
ap.add_argument("--heads", type=int, default=8)
|
| 84 |
+
ap.add_argument("--head_dim", type=int, default=64)
|
| 85 |
+
ap.add_argument("--pool", type=int, default=1000)
|
| 86 |
+
ap.add_argument("--refresh", type=int, default=400)
|
| 87 |
+
ap.add_argument("--ckpt", type=str, default="ckpt/felatab.pt")
|
| 88 |
+
ap.add_argument(
|
| 89 |
+
"--smoke", action="store_true", help="tiny fast loop to prove it trains"
|
| 90 |
+
)
|
| 91 |
+
args = ap.parse_args()
|
| 92 |
+
if args.smoke:
|
| 93 |
+
args.steps, args.dim, args.layers, args.heads = (200, 128, 4, 4)
|
| 94 |
+
args.pool, args.bs, args.tmax = (128, 8, 256)
|
| 95 |
+
dev = "cuda" if torch.cuda.is_available() else "cpu"
|
| 96 |
+
prior_cfg = PriorConfig(max_classes=10, max_rows=6000)
|
| 97 |
+
cfg = FelaTabConfig(
|
| 98 |
+
dim=args.dim,
|
| 99 |
+
n_layers=args.layers,
|
| 100 |
+
n_heads=args.heads,
|
| 101 |
+
head_dim=args.head_dim,
|
| 102 |
+
max_features=prior_cfg.max_features,
|
| 103 |
+
max_classes=prior_cfg.max_classes,
|
| 104 |
+
)
|
| 105 |
+
model = FelaTab(cfg).to(dev)
|
| 106 |
+
print(
|
| 107 |
+
f"params {count_params(model) / 1000000.0:.2f}M dim={cfg.dim} L={cfg.n_layers} H={cfg.n_heads} dev={dev}"
|
| 108 |
+
)
|
| 109 |
+
opt = torch.optim.AdamW(
|
| 110 |
+
model.parameters(), lr=args.lr, weight_decay=0.01, betas=(0.9, 0.95)
|
| 111 |
+
)
|
| 112 |
+
sched = torch.optim.lr_scheduler.OneCycleLR(
|
| 113 |
+
opt,
|
| 114 |
+
max_lr=args.lr,
|
| 115 |
+
total_steps=args.steps,
|
| 116 |
+
pct_start=0.03,
|
| 117 |
+
anneal_strategy="cos",
|
| 118 |
+
)
|
| 119 |
+
rng = np.random.default_rng(1234)
|
| 120 |
+
|
| 121 |
+
def refill(seed):
|
| 122 |
+
pool = gen_pool(prior_cfg, args.pool, seed=seed, workers=None)
|
| 123 |
+
return (
|
| 124 |
+
[t for t in pool if t["task_type"] == "cls"],
|
| 125 |
+
[t for t in pool if t["task_type"] == "reg"],
|
| 126 |
+
)
|
| 127 |
+
|
| 128 |
+
print("generating initial synthetic pool...")
|
| 129 |
+
t0 = time.time()
|
| 130 |
+
cls_pool, reg_pool = refill(int(rng.integers(1000000000.0)))
|
| 131 |
+
print(
|
| 132 |
+
f"pool ready {time.time() - t0:.1f}s (cls {len(cls_pool)} reg {len(reg_pool)})"
|
| 133 |
+
)
|
| 134 |
+
model.train()
|
| 135 |
+
run_loss = run_metric = 0.0
|
| 136 |
+
for step in range(1, args.steps + 1):
|
| 137 |
+
typ = "cls" if step % 2 == 0 else "reg"
|
| 138 |
+
src = cls_pool if typ == "cls" else reg_pool
|
| 139 |
+
if not src:
|
| 140 |
+
continue
|
| 141 |
+
T_target = int(rng.integers(128, args.tmax + 1))
|
| 142 |
+
idx = rng.integers(0, len(src), size=args.bs)
|
| 143 |
+
batch = [src[i] for i in idx]
|
| 144 |
+
X, y, ns, lm, ncl = collate(batch, typ, T_target, rng, cfg.max_features)
|
| 145 |
+
X, y, ns, lm, ncl = [z.to(dev) for z in (X, y, ns, lm, ncl)]
|
| 146 |
+
out = model(X, y, ns, torch.tensor(0 if typ == "cls" else 1, device=dev))
|
| 147 |
+
if typ == "cls":
|
| 148 |
+
loss, metric = cls_loss_acc(out.float(), y, lm, ncl)
|
| 149 |
+
else:
|
| 150 |
+
loss, metric = reg_loss_r2(out.float(), y, lm)
|
| 151 |
+
opt.zero_grad()
|
| 152 |
+
loss.backward()
|
| 153 |
+
torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)
|
| 154 |
+
opt.step()
|
| 155 |
+
sched.step()
|
| 156 |
+
run_loss += loss.item()
|
| 157 |
+
run_metric += metric
|
| 158 |
+
if step % 50 == 0:
|
| 159 |
+
print(
|
| 160 |
+
f"step {step:6d} {typ} loss {run_loss / 50:.4f} metric {run_metric / 50:.4f} lr {sched.get_last_lr()[0]:.2e}",
|
| 161 |
+
flush=True,
|
| 162 |
+
)
|
| 163 |
+
run_loss = run_metric = 0.0
|
| 164 |
+
if step % args.refresh == 0:
|
| 165 |
+
cls_pool, reg_pool = refill(int(rng.integers(1000000000.0)))
|
| 166 |
+
os.makedirs(os.path.dirname(args.ckpt) or ".", exist_ok=True)
|
| 167 |
+
torch.save(model.state_dict(), args.ckpt)
|
| 168 |
+
print(f"done. saved {args.ckpt}")
|
| 169 |
+
|
| 170 |
+
|
| 171 |
+
if __name__ == "__main__":
|
| 172 |
+
main()
|
verify.py
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import argparse
|
| 2 |
+
import os
|
| 3 |
+
import sys
|
| 4 |
+
import numpy as np
|
| 5 |
+
|
| 6 |
+
sys.path.insert(0, os.path.dirname(__file__))
|
| 7 |
+
from modeling import load_model, predict
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
def make_cls(seed=1234, ns=48, nq=4, nf=6, k=3):
|
| 11 |
+
rng = np.random.default_rng(seed)
|
| 12 |
+
W = rng.standard_normal((nf, k)).astype(np.float32)
|
| 13 |
+
X = rng.standard_normal((ns + nq, nf)).astype(np.float32) * 1.6 + 0.2
|
| 14 |
+
y = (X @ W).argmax(1).astype(np.int64)
|
| 15 |
+
return (X[:ns], y[:ns], X[ns:], k)
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
def make_reg(seed=5678, ns=48, nq=4, nf=6):
|
| 19 |
+
rng = np.random.default_rng(seed)
|
| 20 |
+
w = rng.standard_normal(nf).astype(np.float32)
|
| 21 |
+
X = rng.standard_normal((ns + nq, nf)).astype(np.float32) * 2.0 - 0.3
|
| 22 |
+
y = (X @ w + 0.1 * rng.standard_normal(ns + nq)).astype(np.float32)
|
| 23 |
+
return (X[:ns], y[:ns], X[ns:])
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
REF_CLS_PROBS = [
|
| 27 |
+
[0.67778, 0.29555, 0.02667],
|
| 28 |
+
[0.43088, 0.44604, 0.12308],
|
| 29 |
+
[0.8469, 0.11382, 0.03928],
|
| 30 |
+
[0.34364, 0.60266, 0.0537],
|
| 31 |
+
]
|
| 32 |
+
REF_REG_MEAN = [-3.22947, -1.90098, 0.24437, -3.92093]
|
| 33 |
+
TOL_PROB = 0.06
|
| 34 |
+
TOL_REG = 0.15
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
def main():
|
| 38 |
+
ap = argparse.ArgumentParser()
|
| 39 |
+
ap.add_argument("--weights", default=None, help="explicit .safetensors path")
|
| 40 |
+
ap.add_argument("--tier", default="small", choices=["small", "big"])
|
| 41 |
+
args = ap.parse_args()
|
| 42 |
+
src = args.weights or "."
|
| 43 |
+
model = load_model(src, tier=args.tier)
|
| 44 |
+
Xc_tr, yc_tr, Xc_te, k = make_cls()
|
| 45 |
+
Xr_tr, yr_tr, Xr_te = make_reg()
|
| 46 |
+
probs = predict(model, Xc_tr, yc_tr, Xc_te, "classification", n_classes=k)
|
| 47 |
+
mean, std = predict(model, Xr_tr, yr_tr, Xr_te, "regression")
|
| 48 |
+
ok = True
|
| 49 |
+
if probs.shape != (4, 3):
|
| 50 |
+
print(f"FAILURE: cls output shape {probs.shape} != (4, 3)")
|
| 51 |
+
sys.exit(1)
|
| 52 |
+
if mean.shape != (4,) or std.shape != (4,):
|
| 53 |
+
print(f"FAILURE: reg shapes mean {mean.shape} std {std.shape} != (4,)")
|
| 54 |
+
sys.exit(1)
|
| 55 |
+
print(f"Shapes OK: cls {probs.shape}, reg mean {mean.shape} std {std.shape}")
|
| 56 |
+
if not np.all(std > 0):
|
| 57 |
+
print(f"FAILURE: regression std not all positive: {std.tolist()}")
|
| 58 |
+
sys.exit(1)
|
| 59 |
+
if args.tier == "small":
|
| 60 |
+
d_cls = float(np.abs(probs - np.array(REF_CLS_PROBS)).max())
|
| 61 |
+
scale = float(np.std(REF_REG_MEAN)) + 1e-06
|
| 62 |
+
d_reg = float(np.abs(mean - np.array(REF_REG_MEAN)).max()) / scale
|
| 63 |
+
print(f"cls max abs prob diff = {d_cls:.4f} (tol {TOL_PROB})")
|
| 64 |
+
print(f"reg max rel mean diff = {d_reg:.4f} (tol {TOL_REG})")
|
| 65 |
+
if d_cls > TOL_PROB:
|
| 66 |
+
print("FAILURE: classification probabilities off reference")
|
| 67 |
+
ok = False
|
| 68 |
+
if d_reg > TOL_REG:
|
| 69 |
+
print("FAILURE: regression means off reference")
|
| 70 |
+
ok = False
|
| 71 |
+
else:
|
| 72 |
+
print(
|
| 73 |
+
"(reference stored for the small tier only; big tier ran a shape + sanity check)"
|
| 74 |
+
)
|
| 75 |
+
print("example cls probs[0]:", np.round(probs[0], 4).tolist())
|
| 76 |
+
print("example reg mean/std[0]:", round(float(mean[0]), 4), round(float(std[0]), 4))
|
| 77 |
+
print("VERIFY:", "PASS" if ok else "FAIL")
|
| 78 |
+
sys.exit(0 if ok else 1)
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
if __name__ == "__main__":
|
| 82 |
+
main()
|