Jarbas commited on
Commit
1873344
·
verified ·
1 Parent(s): 7643252

Upload README.md with huggingface_hub

Browse files
Files changed (1) hide show
  1. README.md +43 -151
README.md CHANGED
@@ -6,7 +6,6 @@
6
  - question-classification
7
  - text-classification
8
  - onnx
9
- - model2vec
10
  - english
11
  - eat
12
  - calibrated
@@ -16,178 +15,71 @@
16
 
17
  # eat-classifiers
18
 
19
- English question-type classifiers trained on the
20
- [EAT (Expected Answer Type) dataset](https://huggingface.co/datasets/TigreGotico/EAT) — 30,017 questions
21
- labelled with 53 fine-grained answer types across 7 main categories.
22
 
23
- Two model families are included:
24
 
25
- | Family | Location | Inference deps | Best macro F1 (53-class) |
26
- |--------|----------|----------------|--------------------------|
27
- | **ONNX** (LinearSVC, calibrated) | `models/eat/` | `onnxruntime` only | **0.934** (two-stage svm_cal) |
28
- | **Model2Vec** (potion-base + LinearSVC) | `models/eat_m2v/` | `model2vec`, `scikit-learn` | **0.921** (32M+tfidf) |
29
-
30
- ---
31
 
32
  ## Label taxonomy
33
 
34
- 7 main categories and 53 fine-grained sub-types:
35
 
36
  | Main | Sub-types |
37
  |------|-----------|
38
- | `ABBR` | `abb`, `exp` |
39
- | `BOOL` | `yesno` |
40
- | `DESC` | `def`, `desc`, `manner`, `reason` |
41
- | `ENTY` | `animal`, `body`, `color`, `cremat`, `currency`, `dismed`, `event`, `food`, `instru`, `lang`, `letter`, `other`, `plant`, `product`, `religion`, `sport`, `substance`, `symbol`, `techmeth`, `termeq`, `veh`, `word` |
42
- | `HUM` | `desc`, `gr`, `ind`, `title` |
43
- | `LOC` | `city`, `country`, `landmass`, `mount`, `other`, `state`, `water` |
44
- | `NUM` | `code`, `count`, `date`, `dist`, `money`, `ord`, `other`, `perc`, `period`, `speed`, `temp`, `volsize`, `weight` |
45
-
46
- ---
47
-
48
- ## ONNX models
49
-
50
- Calibrated models (`_cal`) use Platt sigmoid calibration
51
- (`CalibratedClassifierCV(LinearSVC, cv=5, method="sigmoid")`) so that
52
- `output[1]` is a true probability vector — values in [0, 1] summing to 1.
53
- Uncalibrated models output raw decision-function scores.
54
-
55
- | File | Classes | Type | Output[1] | Accuracy | Macro F1 |
56
- |------|---------|------|-----------|----------|----------|
57
- | `eat53_logreg_EN_0.9.0.onnx` | 53 | logreg | decision scores | 0.877 | 0.878 |
58
- | `eat53_sgd_EN_0.9.0.onnx` | 53 | sgd | decision scores | 0.846 | 0.841 |
59
- | `eat53_svm_EN_0.9.0.onnx` | 53 | svm | decision scores | 0.917 | 0.915 |
60
- | `eat53_svm_cal_EN_0.9.0.onnx` | 53 | svm_cal | calibrated proba | 0.915 | 0.914 |
61
- | `eat7_logreg_EN_0.9.0.onnx` | 7 | logreg | decision scores | 0.924 | 0.837 |
62
- | `eat7_sgd_EN_0.9.0.onnx` | 7 | sgd | decision scores | 0.846 | 0.698 |
63
- | `eat7_svm_EN_0.9.0.onnx` | 7 | svm | decision scores | 0.956 | 0.921 |
64
- | `eat7_svm_cal_EN_0.9.0.onnx` | 7 | svm_cal | calibrated proba | 0.956 | 0.929 |
65
- | _(two-stage svm)_ | 53 | svm | decision scores | 0.934 | 0.933 |
66
- | _(two-stage svm_cal)_ | 53 | svm_cal | calibrated proba | 0.934 | 0.934 |
67
-
68
- ### Two-stage inference
69
-
70
- Run `eat7_svm_cal` first to predict the main category, then run
71
- `eat53_svm_cal`, zero out all labels outside that category, and
72
- renormalise the surviving probabilities. This is the highest-accuracy
73
- configuration (macro F1 = 0.934 on the held-out test set).
74
 
75
  ```python
76
- import onnxruntime as rt
77
- import numpy as np, json
78
 
79
- sess7 = rt.InferenceSession("models/eat/eat7_svm_cal_EN_0.9.0.onnx")
80
- sess53 = rt.InferenceSession("models/eat/eat53_svm_cal_EN_0.9.0.onnx")
81
  classes7 = json.loads(sess7.get_modelmeta().custom_metadata_map["classes"])
82
  classes53 = json.loads(sess53.get_modelmeta().custom_metadata_map["classes"])
83
  main_of_53 = [c.split(":")[0] for c in classes53]
84
 
85
- def classify(text: str) -> tuple[str, float]:
86
  inp = np.array([text], dtype=object)
87
- main_idx = int(sess7.run(None, {"input": inp})[0][0])
88
- main = classes7[main_idx]
89
- _, probs53 = sess53.run(None, {"input": inp})
90
- row = probs53[0].copy()
91
  for j, m in enumerate(main_of_53):
92
  if m != main:
93
  row[j] = 0.0
94
  row /= row.sum()
95
- best = int(np.argmax(row))
96
- return classes53[best], float(row[best])
97
 
98
- label, confidence = classify("Who invented the telephone?")
99
- print(label, confidence) # HUM:ind 0.96
100
  ```
101
 
102
- ### Single-model ONNX inference
103
-
104
- ```python
105
- import onnxruntime as rt
106
- import numpy as np, json
107
-
108
- sess = rt.InferenceSession("models/eat/eat53_svm_cal_EN_0.9.0.onnx")
109
- classes = json.loads(sess.get_modelmeta().custom_metadata_map["classes"])
110
-
111
- inp = np.array(["Who invented the telephone?"], dtype=object)
112
- label_idx, probs = sess.run(None, {"input": inp})
113
- label = classes[int(label_idx[0])]
114
- confidence = float(probs[0].max())
115
- print(label, confidence) # HUM:ind 0.94
116
- ```
117
-
118
- ---
119
-
120
- ## Model2Vec models
121
-
122
- Static [model2vec](https://github.com/MinishLab/model2vec) embeddings
123
- (potion-base 2M / 8M / 32M) with a LinearSVC classifier on top.
124
- The `+tfidf` variants concatenate TF-IDF word (1,2)-gram features with
125
- the embeddings before fitting — this consistently adds 5–30 pp macro F1
126
- over embeddings alone.
127
-
128
- | Directory | Classes | Backbone | TF-IDF fusion | Accuracy | Macro F1 |
129
- |-----------|---------|----------|---------------|----------|----------|
130
- | `m2v-potion-base-2M+tfidf-en-53c` | 53 | potion-base-2M | ✓ | 0.916 | 0.914 |
131
- | `m2v-potion-base-2M+tfidf-en-7c` | 7 | potion-base-2M | ✓ | 0.953 | 0.908 |
132
- | `m2v-potion-base-2M-en-53c` | 53 | potion-base-2M | — | 0.631 | 0.607 |
133
- | `m2v-potion-base-2M-en-7c` | 7 | potion-base-2M | — | 0.700 | 0.562 |
134
- | `m2v-potion-base-32M+tfidf-en-53c` | 53 | potion-base-32M | ✓ | 0.922 | 0.920 |
135
- | `m2v-potion-base-32M+tfidf-en-7c` | 7 | potion-base-32M | ✓ | 0.956 | 0.922 |
136
- | `m2v-potion-base-32M-en-53c` | 53 | potion-base-32M | — | 0.857 | 0.854 |
137
- | `m2v-potion-base-32M-en-7c` | 7 | potion-base-32M | — | 0.895 | 0.843 |
138
- | `m2v-potion-base-8M+tfidf-en-53c` | 53 | potion-base-8M | ✓ | 0.918 | 0.917 |
139
- | `m2v-potion-base-8M+tfidf-en-7c` | 7 | potion-base-8M | ✓ | 0.952 | 0.913 |
140
- | `m2v-potion-base-8M-en-53c` | 53 | potion-base-8M | — | 0.818 | 0.811 |
141
- | `m2v-potion-base-8M-en-7c` | 7 | potion-base-8M | — | 0.843 | 0.763 |
142
-
143
- ### Usage (Model2Vec)
144
-
145
- ```python
146
- from huggingface_hub import snapshot_download
147
- from train.classifiers import Model2VecClassifier
148
-
149
- local = snapshot_download("TigreGotico/eat-classifiers")
150
- clf = Model2VecClassifier.load(f"{local}/models/eat_m2v/m2v-potion-base-8M+tfidf-en-53c")
151
- print(clf.predict(["Who invented the telephone?"]))
152
- # ["HUM:ind"]
153
- ```
154
-
155
- ---
156
-
157
- ## Integration with little_questions
158
-
159
- When installed as part of [little_questions](https://github.com/TigreGotico/little_questions), the
160
- calibrated ONNX model (`eat53_svm_cal`) is loaded automatically and
161
- exposed through the `Sentence` API:
162
-
163
- ```python
164
- from little_questions import Sentence
165
-
166
- s = Sentence("Who invented the telephone?")
167
- print(s.classification) # "HUM:ind"
168
- print(s.main_label) # "HUM"
169
- print(s.secondary_label) # "ind"
170
- print(s.confidence) # 0.94
171
- print(s.pretty_label) # "individual (Human)"
172
- # Full probability distribution over all 53 labels:
173
- print(s.classification_scores)
174
- ```
175
-
176
- ---
177
-
178
- ## Datasets
179
-
180
- Both datasets were built specifically for this project:
181
-
182
- | Dataset | Task | Size | Labels |
183
- |---------|------|------|--------|
184
- | [TigreGotico/EAT](https://huggingface.co/datasets/TigreGotico/EAT) | Question answer-type | 30K EN | 53 fine-grained / 7 main |
185
- | [TigreGotico/sentence-types-multilingual](https://huggingface.co/datasets/TigreGotico/sentence-types-multilingual) | Sentence type | 80K multilingual | 5 types |
186
-
187
- ---
188
-
189
  ## Benchmarks
190
 
191
- Full results tables and confusion matrices: [BENCHMARKS.md](BENCHMARKS.md)
192
-
193
- ![Model comparison](benchmarks/eat/benchmark_eat_model_comparison.png)
 
6
  - question-classification
7
  - text-classification
8
  - onnx
 
9
  - english
10
  - eat
11
  - calibrated
 
15
 
16
  # eat-classifiers
17
 
18
+ English question answer-type (EAT) classifiers trained on the
19
+ [TigreGotico/EAT](https://huggingface.co/datasets/TigreGotico/EAT) dataset
20
+ (30,017 questions, 53 fine-grained labels across 7 TREC categories).
21
 
22
+ Two-stage inference (eat7 gates eat53) achieves **93.4% macro F1** on the test set.
23
 
24
+ Used by [little_questions](https://github.com/OpenJarbas/little_questions).
 
 
 
 
 
25
 
26
  ## Label taxonomy
27
 
28
+ 7 main categories, 53 sub-types:
29
 
30
  | Main | Sub-types |
31
  |------|-----------|
32
+ | `ABBR` | abb, exp |
33
+ | `BOOL` | yesno |
34
+ | `DESC` | def, desc, manner, reason |
35
+ | `ENTY` | animal, body, color, cremat, currency, dismed, event, food, instru, lang, letter, other, plant, product, religion, sport, substance, symbol, techmeth, termeq, veh, word |
36
+ | `HUM` | desc, gr, ind, title |
37
+ | `LOC` | city, country, landmass, mount, other, state, water |
38
+ | `NUM` | code, count, date, dist, money, ord, other, perc, period, speed, temp, volsize, weight |
39
+
40
+ ## Models
41
+
42
+ | File | Input variant | Output[1] |
43
+ |------|---------------|-----------|
44
+ | `eat53_logreg_EN_0.9.0.onnx` | punctuated (written) | decision score |
45
+ | `eat53_sgd_EN_0.9.0.onnx` | punctuated (written) | decision score |
46
+ | `eat53_svm_EN_0.9.0.onnx` | punctuated (written) | decision score |
47
+ | `eat53_svm_cal_EN_0.9.0.onnx` | punctuated (written) | calibrated probability |
48
+ | `eat53_svm_cal_unpunct_EN_0.9.0.onnx` | unpunctuated (ASR/voice) | calibrated probability |
49
+ | `eat7_logreg_EN_0.9.0.onnx` | punctuated (written) | decision score |
50
+ | `eat7_sgd_EN_0.9.0.onnx` | punctuated (written) | decision score |
51
+ | `eat7_svm_EN_0.9.0.onnx` | punctuated (written) | decision score |
52
+ | `eat7_svm_cal_EN_0.9.0.onnx` | punctuated (written) | calibrated probability |
53
+ | `eat7_svm_cal_unpunct_EN_0.9.0.onnx` | unpunctuated (ASR/voice) | calibrated probability |
54
+
55
+ Both punctuated and unpunctuated variants are provided.
56
+ Use the unpunctuated (`_unpunct`) model for ASR / voice assistant input.
57
+
58
+ ## Two-stage inference
 
 
 
 
 
 
 
 
 
59
 
60
  ```python
61
+ import onnxruntime as rt, numpy as np, json
 
62
 
63
+ sess7 = rt.InferenceSession("eat7_svm_cal_EN_0.9.0.onnx")
64
+ sess53 = rt.InferenceSession("eat53_svm_cal_EN_0.9.0.onnx")
65
  classes7 = json.loads(sess7.get_modelmeta().custom_metadata_map["classes"])
66
  classes53 = json.loads(sess53.get_modelmeta().custom_metadata_map["classes"])
67
  main_of_53 = [c.split(":")[0] for c in classes53]
68
 
69
+ def classify(text):
70
  inp = np.array([text], dtype=object)
71
+ main = classes7[int(sess7.run(None, {"input": inp})[0][0])]
72
+ _, probs = sess53.run(None, {"input": inp})
73
+ row = probs[0].copy()
 
74
  for j, m in enumerate(main_of_53):
75
  if m != main:
76
  row[j] = 0.0
77
  row /= row.sum()
78
+ return classes53[int(np.argmax(row))], float(row.max())
 
79
 
80
+ print(classify("Who invented the telephone?")) # ('HUM:ind', 0.96)
 
81
  ```
82
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  ## Benchmarks
84
 
85
+ Full results: [BENCHMARKS.md](BENCHMARKS.md)