Mahmoud Amiri commited on
Commit
efe0622
·
1 Parent(s): 4a8a51a

update readme file

Browse files
Files changed (3) hide show
  1. README.md +224 -325
  2. config.yaml +2 -0
  3. requirements.txt +7 -14
README.md CHANGED
@@ -1,325 +1,224 @@
1
- ---
2
- language:
3
- - en
4
- library_name: keras
5
- pipeline_tag: text-classification
6
- license: cc-by-4.0
7
- tags:
8
- - chemistry
9
- - scientific-literature
10
- - multilabel
11
- - classification
12
- - embeddings
13
- - keras
14
- datasets:
15
- - Bocklitz-Lab/lit2vec-subfield-classifier-dataset
16
- model-index:
17
- - name: lit2vec-subfield-classifier-model
18
- results:
19
- - task:
20
- name: Multi-label Text Classification
21
- type: text-classification
22
- dataset:
23
- name: Lit2Vec Subfield Classifier Dataset
24
- type: Bocklitz-Lab/lit2vec-subfield-classifier-dataset
25
- split: test
26
- size: 7482
27
- metrics:
28
- - type: micro_f1
29
- value: 0.81
30
- - type: macro_f1
31
- value: 0.75
32
- - type: weighted_f1
33
- value: 0.80
34
- - type: pr_auc
35
- value: 0.8688
36
- - type: roc_auc
37
- value: 0.9725
38
- ---
39
-
40
- # Lit2Vec Subfield Classifier (MLP)
41
-
42
- > Multi-label classifier for chemistry subfields using dense text embeddings.
43
-
44
- **Repo:** [https://huggingface.co/Bocklitz-Lab/lit2vec-subfield-classifier-model](https://huggingface.co/Bocklitz-Lab/lit2vec-subfield-classifier-model)
45
- **Dataset:** [https://huggingface.co/datasets/Bocklitz-Lab/lit2vec-subfield-classifier-dataset](https://huggingface.co/datasets/Bocklitz-Lab/lit2vec-subfield-classifier-dataset)
46
-
47
- ---
48
-
49
- ## Model Summary
50
-
51
- This model is a **Keras MLP** for **multi-label** classification of chemistry-related scientific texts.
52
- It consumes a **dense embedding vector** and predicts one or more **subfields** (e.g., *Catalysis*, *Energy Chemistry*, *Materials Science*).
53
-
54
- * **Input:** dense embedding vector (`embedding` from the dataset)
55
- * **Output:** 18 sigmoid probabilities (one per subfield)
56
- * **Task:** multilabel text classification (thresholded at 0.5 by default)
57
-
58
- ---
59
-
60
- ## Intended Use & Limitations
61
-
62
- **Intended use**
63
-
64
- * Subfield tagging for chemistry abstracts/summaries
65
- * Metadata enrichment for literature databases
66
- * Retrieval, filtering, and analytics
67
-
68
- **Limitations**
69
-
70
- * Trained only on chemistry texts → may not generalize to other domains
71
- * Requires the **same embedding space** as the dataset encoder (raw text is **not** accepted directly)
72
- * Long-tail subfields (few examples) may have lower F1
73
-
74
- ---
75
-
76
- ## Labels
77
-
78
- | ID | Subfield |
79
- | -- | ---------------------------------- |
80
- | 0 | Catalysis |
81
- | 1 | Organic Chemistry |
82
- | 2 | Polymer Chemistry |
83
- | 3 | Inorganic Chemistry |
84
- | 4 | Materials Science |
85
- | 5 | Analytical Chemistry |
86
- | 6 | Physical Chemistry |
87
- | 7 | Biochemistry |
88
- | 8 | Environmental Chemistry |
89
- | 9 | Energy Chemistry |
90
- | 10 | Medicinal Chemistry |
91
- | 11 | Chemical Engineering |
92
- | 12 | Supramolecular Chemistry |
93
- | 13 | Radiochemistry & Nuclear Chemistry |
94
- | 14 | Forensic & Legal Chemistry |
95
- | 15 | Food Chemistry |
96
- | 16 | Chemical Education |
97
- | 17 | Others |
98
-
99
- The repo includes `label_mapping.json`.
100
-
101
- ---
102
-
103
- ## Training Details
104
-
105
- * **Framework:** TensorFlow/Keras
106
- * **Architecture:**
107
-
108
- * Input → Dense(256, ReLU) → (BatchNorm) → Dropout(0.3)
109
- * Dense(256, ReLU) → (BatchNorm) → Dropout(0.3)
110
- * Output: Dense(18, **sigmoid**)
111
- * **Loss:** **Weighted** Binary Cross-Entropy (per-class weights from train frequency)
112
- * **Optimizer:** Adam (ReduceLROnPlateau)
113
- * **Callbacks:** EarlyStopping (restore best), ReduceLROnPlateau, optional W\&B logging
114
- * **Validation:** 5-fold CV on train+val; final training on official splits
115
- * **Best epoch (val):** 11 (from W\&B)
116
-
117
- ---
118
-
119
- ## Evaluation
120
-
121
- **Validation (final run):**
122
-
123
- * PR-AUC: **0.8688**
124
- * ROC-AUC: **0.9725**
125
- * Binary Accuracy: **0.9597**
126
-
127
- **Test (held-out split, threshold = 0.5):**
128
-
129
- * **Micro F1:** **0.81**
130
- * **Macro F1:** **0.75**
131
- * **Weighted F1:** **0.80**
132
- * **Samples F1:** **0.80**
133
-
134
- **Per-label (F1, support):**
135
-
136
- | Subfield | F1 | Support |
137
- | ---------------------------------- | -------- | ------- |
138
- | Catalysis | 0.80 | 197 |
139
- | Organic Chemistry | 0.70 | 245 |
140
- | Polymer Chemistry | 0.72 | 120 |
141
- | Inorganic Chemistry | 0.71 | 203 |
142
- | Materials Science | 0.80 | 917 |
143
- | Analytical Chemistry | 0.71 | 633 |
144
- | Physical Chemistry | 0.63 | 240 |
145
- | Biochemistry | **0.92** | 2106 |
146
- | Environmental Chemistry | 0.79 | 508 |
147
- | Energy Chemistry | 0.79 | 166 |
148
- | Medicinal Chemistry | 0.82 | 1343 |
149
- | Chemical Engineering | **0.53** | 413 |
150
- | Supramolecular Chemistry | 0.68 | 34 |
151
- | Radiochemistry & Nuclear Chemistry | 0.65 | 20 |
152
- | Forensic & Legal Chemistry | 0.70 | 16 |
153
- | Food Chemistry | 0.83 | 282 |
154
- | Chemical Education | 0.85 | 20 |
155
- | Others | 0.83 | 19 |
156
-
157
- **Notes**
158
-
159
- * Strong performance on frequent classes like **Biochemistry**, **Medicinal Chemistry**, **Food Chemistry**.
160
- * Lower F1 on long-tail or heterogeneous labels like **Chemical Engineering** and **Physical Chemistry**.
161
-
162
- If included in the repo, the plot `f1_vs_freq.png` shows F1 vs. training label frequency.
163
-
164
- ---
165
-
166
- ## Usage
167
-
168
- > The model expects the **same embedding space** as the dataset’s `embedding`. If you want to apply it to new texts, you must compute embeddings with the **same encoder** used to create the dataset.
169
-
170
- ### Quick start (load from Hub, inference)
171
-
172
- ```python
173
- # pip install -r requirements.txt
174
- import json
175
- import numpy as np
176
- from typing import List, Tuple
177
- from huggingface_hub import hf_hub_download
178
- from tensorflow import keras
179
- from sentence_transformers import SentenceTransformer
180
-
181
- REPO_ID = "Bocklitz-Lab/lit2vec-subfield-classifier-model"
182
- EMBED_MODEL = "intfloat/e5-large-v2" # must match what you used to train!
183
- TEXT_PREFIX = {"abstract": "abstract: ", "summary": "summary: "} # keep consistent with your pipeline
184
- THRESHOLD = 0.5 # decision threshold for multilabel
185
-
186
- # ----- Load model + label mapping -----
187
- model_path = hf_hub_download(REPO_ID, filename="mlp_model.h5")
188
- label_map_path = hf_hub_download(REPO_ID, filename="label_mapping.json")
189
-
190
- with open(label_map_path, "r", encoding="utf-8") as f:
191
- mapping = json.load(f)
192
- index_to_label = {int(k): v for k, v in mapping["index_to_label"].items()}
193
-
194
- model = keras.models.load_model(model_path, compile=False) # inference only
195
- encoder = SentenceTransformer(EMBED_MODEL)
196
-
197
- def encode_text(text: str, text_type: str = "summary") -> np.ndarray:
198
- """
199
- Encode text into a normalized embedding compatible with the classifier.
200
- text_type: "summary" or "abstract" (affects prefix)
201
- """
202
- prefix = TEXT_PREFIX.get(text_type, "")
203
- emb = encoder.encode([prefix + text], normalize_embeddings=True) # shape: (1, D)
204
- return emb.astype("float32")
205
-
206
- def predict_labels_from_text(text: str, text_type: str = "summary", threshold: float = THRESHOLD
207
- ) -> Tuple[List[int], List[str], np.ndarray]:
208
- """
209
- Returns (predicted_ids, predicted_labels, probabilities)
210
- """
211
- x = encode_text(text, text_type=text_type) # (1, D)
212
- probs = model.predict(x, verbose=0)[0] # (18,)
213
- pred_ids = [i for i, p in enumerate(probs) if p > threshold]
214
- pred_labels = [index_to_label[i] for i in pred_ids]
215
- return pred_ids, pred_labels, probs
216
-
217
- # ----- Example -----
218
- if __name__ == "__main__":
219
- sample_text = (
220
- "The adsorption capacity of Helix aspera shell for Pb2+, Zn2+ and Ni2+ has been studied. This shell has the potential of adsorbing Pb2+, Zn2+ and Ni2+ from aqueous solution. The adsorption potentials of Helix aspera shell is largely influenced by the ionic character of the ions and occurred according to the order Pb2+ > Ni2+ > Zn2+. The adsorption of Pb(II), Zn(II) and Ni(II) ions from aqueous solutions by Helix aspera shell is thermodynamically feasible and is consistent with the models of Langmuir and Freundlich adsorption isotherms. From the results of the study, the shell of Helix aspera is recommended for use in the removal of Pb2+, Zn2+ and Ni2+ from aqueous solution."
221
- )
222
- ids, labels, probs = predict_labels_from_text(sample_text, text_type="abstract", threshold=0.5)
223
- print("Predicted IDs:", ids)
224
- print("Predicted Labels:", labels)
225
- print("Top scores:", sorted(((index_to_label[i], float(p)) for i, p in enumerate(probs)),
226
- key=lambda x: x[1], reverse=True)[:5])
227
-
228
- ```
229
-
230
- ### Batch inference
231
-
232
- ```python
233
- X = np.load("embeddings_batch.npy").astype("float32") # shape (N, D)
234
- probs = model.predict(X, verbose=0) # shape (N, 18)
235
- labels_per_row = [[index_to_label[i] for i, p in enumerate(row) if p > 0.5] for row in probs]
236
- ```
237
-
238
- > **Tip:** If you need to **fine-tune** the model, recompile it and reuse the weighted BCE:
239
- >
240
- > * At load time, pass `compile=False` and then `model.compile(loss="binary_crossentropy", ...)` for inference-only.
241
- > * For training with class weights, reintroduce the weighted loss you used in the training script.
242
-
243
- ---
244
-
245
- ## Files in this repository
246
-
247
- * `mlp_model.h5` – Keras model weights/graph
248
- * `label_mapping.json` – name ↔ id mapping
249
- * `training_history.json` – training curves (optional)
250
- * `f1_vs_freq.png` – F1 vs frequency plot (optional)
251
- * `README.md` – this model card
252
-
253
- ---
254
-
255
- ## Dataset
256
-
257
- **Lit2Vec Subfield Classifier Dataset**
258
-
259
- * \~39.9k CC-BY scientific texts with **embeddings** and **subfield labels**
260
- * Splits: \~80/10/10 (train/val/test)
261
- * [https://huggingface.co/datasets/Bocklitz-Lab/lit2vec-subfield-classifier-dataset](https://huggingface.co/datasets/Bocklitz-Lab/lit2vec-subfield-classifier-dataset)
262
-
263
- ---
264
-
265
- ## Model Index
266
-
267
- ```yaml
268
- model-index:
269
- - name: Lit2Vec Subfield Classifier (MLP)
270
- results:
271
- - task:
272
- type: text-classification
273
- name: Multi-label text classification
274
- dataset:
275
- name: Lit2Vec Subfield Classifier Dataset
276
- type: Bocklitz-Lab/lit2vec-subfield-classifier-dataset
277
- split: test
278
- metrics:
279
- - type: micro_f1
280
- value: 0.81
281
- - type: macro_f1
282
- value: 0.75
283
- - type: weighted_f1
284
- value: 0.80
285
- - type: pr_auc
286
- value: 0.8688
287
- - type: roc_auc
288
- value: 0.9725
289
- ```
290
-
291
- ---
292
-
293
- ## License
294
-
295
- * **Model:** CC BY 4.0
296
- * **Dataset:** CC BY 4.0
297
-
298
- ---
299
-
300
- ## Citations
301
-
302
- **Dataset**
303
-
304
- ```bibtex
305
- @dataset{lit2vec_classifier_2025,
306
- author = {Mahmoud Amiri, Thomas Bocklitz},
307
- title = {Lit2Vec Subfield Classifier Dataset},
308
- year = {2025},
309
- publisher = {Hugging Face},
310
- howpublished = {\url{https://huggingface.co/datasets/Bocklitz-Lab/lit2vec-subfield-classifier-dataset}},
311
- note = {Submitted to Nature Scientific Data}
312
- }
313
- ```
314
-
315
- **Model**
316
-
317
- ```bibtex
318
- @misc{lit2vec_mlp_classifier_2025,
319
- title = {Lit2Vec Subfield Classifier Model},
320
- author = {Mahmoud Amiri and Thomas Bocklitz},
321
- year = {2025},
322
- publisher = {Hugging Face},
323
- howpublished = {\url{https://huggingface.co/Bocklitz-Lab/lit2vec-subfield-classifier-model}}
324
- }
325
- ```
 
1
+ ---
2
+ language:
3
+ - en
4
+ library_name: keras
5
+ pipeline_tag: text-classification
6
+ license: apache-2.0
7
+ tags:
8
+ - chemistry
9
+ - scientific-literature
10
+ - multilabel
11
+ - classification
12
+ - embeddings
13
+ - keras
14
+ datasets:
15
+ - Bocklitz-Lab/lit2vec-subfield-classifier-dataset
16
+ model-index:
17
+ - name: lit2vec-subfield-classifier-model
18
+ results:
19
+ - task:
20
+ name: Multi-label Text Classification
21
+ type: text-classification
22
+ dataset:
23
+ name: Lit2Vec Subfield Classifier Dataset
24
+ type: Bocklitz-Lab/lit2vec-subfield-classifier-dataset
25
+ split: test
26
+ size: 3990
27
+ metrics:
28
+ - type: micro_f1
29
+ value: 0.8078
30
+ - type: macro_f1
31
+ value: 0.7476
32
+ - type: weighted_f1
33
+ value: 0.8003
34
+ - type: micro_roc_auc
35
+ value: 0.9844
36
+ - type: macro_roc_auc
37
+ value: 0.9778
38
+ - type: micro_pr_auc
39
+ value: 0.9014
40
+ - type: macro_pr_auc
41
+ value: 0.8425
42
+ ---
43
+
44
+ # Lit2Vec Subfield Classifier (MLP)
45
+
46
+ A multi-label classifier that assigns chemistry abstracts and summaries to one or more of 18 subfields. It is a small Keras MLP that works on top of `intfloat/e5-large-v2` embeddings and is used to produce the `predicted_subfield` field of the Lit2Vec workflow ([paper](https://arxiv.org/abs/2604.12498), [code](https://github.com/Bocklitz-Lab/Lit2Vec-code)). Training code: [lit2vec-subfield-classifier](https://github.com/Bocklitz-Lab/lit2vec-subfield-classifier). Dataset: [lit2vec-subfield-classifier-dataset](https://huggingface.co/datasets/Bocklitz-Lab/lit2vec-subfield-classifier-dataset). Demo: [Space](https://huggingface.co/spaces/Bocklitz-Lab/lit2vec-subfield-classifier-space).
47
+
48
+ - **Input:** a 1,024-dimensional, L2-normalised e5-large-v2 embedding of the text `abstract: <text>` or `summary: <text>`
49
+ - **Output:** 18 sigmoid scores, one per subfield; a label is assigned when its score is above 0.5
50
+ - **Not accepted:** raw text. You have to embed it first, as shown below.
51
+
52
+ ## Labels
53
+
54
+ | ID | Subfield |
55
+ |---:|---|
56
+ | 0 | Catalysis |
57
+ | 1 | Organic Chemistry |
58
+ | 2 | Polymer Chemistry |
59
+ | 3 | Inorganic Chemistry |
60
+ | 4 | Materials Science |
61
+ | 5 | Analytical Chemistry |
62
+ | 6 | Physical Chemistry |
63
+ | 7 | Biochemistry |
64
+ | 8 | Environmental Chemistry |
65
+ | 9 | Energy Chemistry |
66
+ | 10 | Medicinal Chemistry |
67
+ | 11 | Chemical Engineering |
68
+ | 12 | Supramolecular Chemistry |
69
+ | 13 | Radiochemistry & Nuclear Chemistry |
70
+ | 14 | Forensic & Legal Chemistry |
71
+ | 15 | Food Chemistry |
72
+ | 16 | Chemical Education |
73
+ | 17 | Others |
74
+
75
+ The mapping is also in `label_mapping.json`. The training labels were generated by GPT-4o from a controlled vocabulary. They were not curated by experts (see Limitations).
76
+
77
+ ## Quick start
78
+
79
+ ```python
80
+ # pip install -r requirements.txt
81
+ import json
82
+ import numpy as np
83
+ from huggingface_hub import hf_hub_download
84
+ from tensorflow import keras
85
+ from sentence_transformers import SentenceTransformer
86
+
87
+ REPO_ID = "Bocklitz-Lab/lit2vec-subfield-classifier-model"
88
+ EMBED_MODEL = "intfloat/e5-large-v2"
89
+ TEXT_PREFIX = {"abstract": "abstract: ", "summary": "summary: "} # the prefixes used for the training embeddings
90
+ THRESHOLD = 0.5
91
+
92
+ model = keras.models.load_model(hf_hub_download(REPO_ID, "mlp_model.h5"), compile=False)
93
+ with open(hf_hub_download(REPO_ID, "label_mapping.json"), encoding="utf-8") as f:
94
+ index_to_label = {int(k): v for k, v in json.load(f)["index_to_label"].items()}
95
+ encoder = SentenceTransformer(EMBED_MODEL)
96
+
97
+ def predict(text: str, text_type: str = "abstract", threshold: float = THRESHOLD):
98
+ x = encoder.encode([TEXT_PREFIX[text_type] + text], normalize_embeddings=True).astype("float32")
99
+ probs = model.predict(x, verbose=0)[0]
100
+ labels = [index_to_label[i] for i, p in enumerate(probs) if p > threshold]
101
+ return labels, probs
102
+
103
+ labels, probs = predict("The adsorption capacity of Helix aspera shell for Pb2+, Zn2+ and Ni2+ has been studied ...")
104
+ print(labels)
105
+ ```
106
+
107
+ The text prefix matters. The embeddings in the training dataset were computed with `abstract: ` for abstracts and `summary: ` for summaries. If you embed text without the prefix, or with e5's usual `passage: `, the vectors are close but not identical (cosine similarity of about 0.998), and scores can shift slightly.
108
+
109
+ For many texts, embed them in a batch and call `model.predict(X)` on the stacked array.
110
+
111
+ ## Training
112
+
113
+ | | |
114
+ |---|---|
115
+ | Framework | TensorFlow / Keras 2.15 |
116
+ | Architecture | Dense(256, ReLU) - BatchNorm - Dropout(0.3), twice, then Dense(18, sigmoid); 334,866 parameters |
117
+ | Loss | Binary cross-entropy weighted per class by (negatives / positives) of the training split |
118
+ | Optimiser | Adam, learning rate 1e-3, batch size 32, at most 50 epochs |
119
+ | Callbacks | EarlyStopping on validation loss (patience 5, best weights restored), ReduceLROnPlateau (factor 0.5, patience 3) |
120
+ | Run | stopped after 17 epochs; the weights of epoch 12 (lowest validation loss) are the ones in this repository |
121
+ | Model selection | 5-fold cross-validation on train and validation, then one final training on the official splits |
122
+ | Seed | 42 |
123
+
124
+ The full settings are in `config.yaml`, and `training_history.json` holds the curves of the final run.
125
+
126
+ ## Evaluation
127
+
128
+ Validation metrics at epoch 12: loss 1.064, binary accuracy 0.964, ROC-AUC 0.972, PR-AUC 0.854 (macro-averaged over the labels, as computed by Keras).
129
+
130
+ Test set (3,990 records, threshold 0.5):
131
+
132
+ | Metric | Value |
133
+ |---|---:|
134
+ | Micro F1 | 0.808 |
135
+ | Macro F1 | 0.748 |
136
+ | Weighted F1 | 0.800 |
137
+ | Samples F1 | 0.804 |
138
+ | Micro precision / recall | 0.854 / 0.766 |
139
+ | Exact-match accuracy | 0.508 |
140
+ | ROC-AUC (micro / macro) | 0.984 / 0.978 |
141
+ | PR-AUC (micro / macro) | 0.901 / 0.843 |
142
+
143
+ We recomputed these numbers from the weights in this repository and the test split of the dataset, and they match the evaluation outputs in the training repository.
144
+
145
+ ### The test split overlaps with the training split
146
+
147
+ Every paper in the dataset appears twice, once with its abstract and once with its GPT-4o summary, and both records carry the same labels. The dataset was split randomly by record, not by paper. As a result, 3,573 of the 3,990 test records (90%) have the other text of the same paper in the training or validation split. The scores above are therefore somewhat optimistic. On test records whose paper does not occur in the training split the model scores:
148
+
149
+ | Test records | n | Micro F1 | Macro F1 | Weighted F1 |
150
+ |---|---:|---:|---:|---:|
151
+ | All | 3,990 | 0.808 | 0.748 | 0.800 |
152
+ | Paper not in the training split | 838 | 0.804 | 0.707 | 0.794 |
153
+ | Paper not in training or validation | 417 | 0.790 | 0.680 | 0.775 |
154
+
155
+ The micro-averaged scores change little. Macro F1 drops more, partly because the rare classes have only 4 to 6 examples in the smaller subsets. For an estimate of how the model behaves on new papers, use the second row.
156
+
157
+ ### F1 per label (full test set)
158
+
159
+ | Subfield | F1 | Support |
160
+ |---|---:|---:|
161
+ | Catalysis | 0.80 | 197 |
162
+ | Organic Chemistry | 0.70 | 245 |
163
+ | Polymer Chemistry | 0.72 | 120 |
164
+ | Inorganic Chemistry | 0.71 | 203 |
165
+ | Materials Science | 0.80 | 917 |
166
+ | Analytical Chemistry | 0.71 | 633 |
167
+ | Physical Chemistry | 0.63 | 240 |
168
+ | Biochemistry | 0.92 | 2,106 |
169
+ | Environmental Chemistry | 0.79 | 508 |
170
+ | Energy Chemistry | 0.79 | 166 |
171
+ | Medicinal Chemistry | 0.82 | 1,343 |
172
+ | Chemical Engineering | 0.53 | 413 |
173
+ | Supramolecular Chemistry | 0.68 | 34 |
174
+ | Radiochemistry & Nuclear Chemistry | 0.65 | 20 |
175
+ | Forensic & Legal Chemistry | 0.70 | 16 |
176
+ | Food Chemistry | 0.83 | 282 |
177
+ | Chemical Education | 0.85 | 20 |
178
+ | Others | 0.83 | 19 |
179
+
180
+ Support is the number of test records that carry the label. The model is strongest on frequent classes such as Biochemistry, Medicinal Chemistry and Materials Science, and weakest on Chemical Engineering and Physical Chemistry.
181
+
182
+ ## Intended use
183
+
184
+ Tagging chemistry abstracts and summaries with broad subfields for browsing, filtering and retrieval, for example the subfield labels in the Lit2Vec corpus.
185
+
186
+ ## Limitations
187
+
188
+ - **Labels are model-generated.** The training labels come from GPT-4o. Two domain experts reviewed a random sample of 45 annotated abstracts and found them generally reasonable (see the paper). The classifier learns the labelling habits and the errors of GPT-4o, so treat the output as navigation metadata and not as ground truth.
189
+ - **Rare classes** (Supramolecular, Radiochemistry, Forensic, Chemical Education, Others) have very few examples, and their scores are noisy.
190
+ - **Overlapping splits.** See the section above.
191
+ - **Domain.** It was trained on chemistry abstracts and summaries. It may not work on other fields or on long full text.
192
+ - **Embedding space.** It only works with the e5-large-v2 embedding described above.
193
+
194
+ ## Files
195
+
196
+ - `mlp_model.h5`: the Keras model
197
+ - `label_mapping.json`: label name and ID mapping
198
+ - `training_history.json`: training and validation curves of the final run
199
+ - `config.yaml`: training settings
200
+ - `requirements.txt`: packages for the quick start
201
+
202
+ ## Citation
203
+
204
+ Please cite the Lit2Vec paper:
205
+
206
+ ```bibtex
207
+ @misc{amiri2026lit2vec,
208
+ title = {Lit2Vec: A Reproducible Workflow for Building a Legally Screened Chemistry Corpus from S2ORC for Downstream Retrieval and Text Mining},
209
+ author = {Amiri, Mahmoud and Jafari, Jamile Mohammad and Mostafapour, Sara and Bocklitz, Thomas},
210
+ year = {2026},
211
+ eprint = {2604.12498},
212
+ archivePrefix = {arXiv},
213
+ doi = {10.48550/arXiv.2604.12498},
214
+ url = {https://arxiv.org/abs/2604.12498}
215
+ }
216
+ ```
217
+
218
+ ## License
219
+
220
+ The model weights are released under Apache-2.0. The training dataset is released under CC BY 4.0. Its labels and summaries were generated with GPT-4o, so check OpenAI's terms of use if you use them to train other models.
221
+
222
+ ## Acknowledgements
223
+
224
+ The embeddings come from `intfloat/e5-large-v2`. The abstracts come from S2ORC (Allen Institute for AI and Semantic Scholar). The work was developed in the Bocklitz Lab at the Leibniz Institute of Photonic Technology (Leibniz IPHT) and Friedrich Schiller University Jena and was funded by the BMFTR within the programme Photonics Research Germany (13N15466, 13N15710, 13N15715). Questions: mahmoud.amiri@uni-jena.de.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
config.yaml CHANGED
@@ -1,3 +1,5 @@
 
 
1
  seed: 42
2
  mixed_precision: false
3
 
 
1
+ # Training settings of this model. The training code is in
2
+ # https://github.com/Bocklitz-Lab/lit2vec-subfield-classifier (src/train.py, configs/train.yaml).
3
  seed: 42
4
  mixed_precision: false
5
 
requirements.txt CHANGED
@@ -1,15 +1,8 @@
1
- numpy==1.26
2
- scikit-learn==1.2
3
- tensorflow==2.15.0
4
- matplotlib==3.7
5
- wandb==0.16
6
- datasets==2.19
7
- pyarrow==12
8
  sentence-transformers==2.7.0
9
- huggingface_hub>=0.23.0
10
- # Torch is required by sentence-transformers
11
- # CPU-only build (safer if you don’t need GPU)
12
- torch==2.3.1+cpu
13
- torchvision==0.18.1+cpu
14
- torchaudio==2.3.1+cpu
15
- --index-url https://download.pytorch.org/whl/cpu
 
1
+ # Packages for the quick start in README.md (inference only)
2
+ tensorflow-cpu==2.15.0
3
+ numpy==1.26.4
 
 
 
 
4
  sentence-transformers==2.7.0
5
+ huggingface_hub>=0.23.0,<1.0
6
+
7
+ # sentence-transformers installs PyTorch. For a smaller CPU-only build, install it first with:
8
+ # pip install torch --index-url https://download.pytorch.org/whl/cpu