RamezCh commited on
Commit
127b6bf
·
verified ·
1 Parent(s): 5c17e82

Upload folder using huggingface_hub

Browse files
README.md CHANGED
@@ -1,262 +1,287 @@
1
- ---
2
- language: en
3
- license: apache-2.0
4
- library_name: transformers
5
-
6
- pipeline_tag: text-classification
7
- task_categories:
8
- - text-classification
9
-
10
- model_type: sproto
11
- base_model: microsoft/BiomedNLP-PubMedBERT-base-uncased-abstract-fulltext
12
-
13
- datasets:
14
- - mimic-iv
15
-
16
- metrics:
17
- - auroc
18
- - pr-auc
19
-
20
- tags:
21
- - text-classification
22
- - multi-label-classification
23
- - long-tail-learning
24
- - medical
25
- - clinical-nlp
26
- - interpretability
27
- - prototypical-networks
28
- - ehr
29
- ---
30
-
31
- # S-Proto: Sparse Prototypical Networks for Long-Tail Clinical Diagnosis Prediction
32
-
33
- **Published at ECML PKDD 2024 (CORE A)**
34
- *Boosting Long-Tail Data Classification with Sparse Prototypical Networks*
35
-
36
- Alexei Figueroa*, Jens-Michalis Papaioannou*, et al.
37
- DATEXIS, Berliner Hochschule für Technik, Feinstein Institutes, TU Munich, Leibniz University Hannover
38
- (* equal contribution)
39
-
40
- ![S-Proto](overview.png)
41
-
42
- This repository provides **S-Proto**, a sparse and interpretable prototypical network for extreme multi-label diagnosis prediction from clinical text. The model is designed to address the long-tail distribution of clinical diagnoses while preserving faithful, prototype-based explanations.
43
-
44
- ## Interactive Demo
45
-
46
- You can explore the model's predictions and interpretability features through our interactive web demo:
47
- **[https://s-proto.demo.datexis.com/](https://s-proto.demo.datexis.com/)**
48
-
49
- S-Proto was introduced in the paper:
50
-
51
- **[Boosting Long-Tail Data Classification with Sparse Prototypical Networks](https://ecmlpkdd-storage.s3.eu-central-1.amazonaws.com/preprints/2024/lncs14947/lncs14947435.pdf)**
52
- European Conference on Machine Learning and Principles and Practice of Knowledge Discovery in Databases (ECML PKDD 2024, CORE A)
53
- Alexei Figueroa*, Jens-Michalis Papaioannou*, et al.
54
- DATEXIS, Berliner Hochschule für Technik, Feinstein Institutes, TU Munich, Leibniz University Hannover
55
- (* equal contribution)
56
-
57
- ## Overview
58
-
59
- Clinical outcome prediction from Electronic Health Records is characterized by extreme label imbalance. A small number of diagnoses account for most patients, while the majority of diagnoses appear rarely. Standard transformer classifiers tend to perform well on frequent diagnoses but degrade sharply in the long tail.
60
-
61
- S-Proto addresses this problem by extending prototypical networks with:
62
-
63
- - Multiple prototypes per diagnosis
64
- - Sparse winner-takes-all activation
65
- - Prototype-level interpretability
66
- - Efficient training despite increased representational capacity
67
-
68
- The model achieves state-of-the-art performance on MIMIC-IV diagnosis prediction, with particularly strong gains in PR-AUC for rare diagnoses, and transfers successfully to unseen clinical datasets.
69
-
70
- ## Model Architecture
71
-
72
- S-Proto builds on **PubMedBERT** as the text encoder and introduces a sparse prototypical layer on top.
73
-
74
- For each diagnosis label, the model learns multiple sub-networks, each consisting of:
75
-
76
- - A label-specific attention vector
77
- - A prototype vector representing a prototypical patient
78
-
79
- Given an input clinical note:
80
-
81
- 1. The note is encoded using PubMedBERT
82
- 2. Token embeddings are projected into a latent space
83
- 3. Each diagnosis activates multiple candidate sub-networks
84
- 4. A winner-takes-all mechanism selects the single most relevant sub-network per diagnosis
85
- 5. Only the winning prototype contributes to the prediction and receives gradient updates
86
-
87
- This allows S-Proto to model heterogeneous disease phenotypes while remaining sparse and efficient.
88
-
89
- ## Intended Use
90
-
91
- This model is intended for:
92
-
93
- - Clinical diagnosis prediction from admission notes
94
- - Research on long-tail learning in healthcare NLP
95
- - Interpretable clinical decision support systems
96
- - Analysis of disease phenotypes via learned prototypes
97
-
98
- This model is **not intended for direct clinical deployment** without external validation, auditing, and regulatory approval.
99
-
100
- ## Inference Example
101
-
102
- ```python
103
- from transformers import AutoTokenizer, AutoModel
104
- import torch
105
-
106
- tokenizer = AutoTokenizer.from_pretrained("DATEXIS/sproto")
107
- model = AutoModel.from_pretrained("DATEXIS/sproto", trust_remote_code=True)
108
- model.eval()
109
-
110
- text_input = [
111
- "CHIEF COMPLAINT: Right Carotid Artery Stenosis. "
112
- "PRESENT ILLNESS: Ms. ___ is a ___ year old woman with hyperlipidemia, "
113
- "cirrhosis with esophageal varices, alcoholism, COPD, left eye blindness, "
114
- "and right carotid stenosis status post right carotid endarterectomy."
115
- ]
116
-
117
- inputs = tokenizer(
118
- text_input,
119
- padding=True,
120
- truncation=True,
121
- max_length=512,
122
- return_tensors="pt"
123
- )
124
-
125
- tokens = [tokenizer.convert_ids_to_tokens(ids) for ids in inputs["input_ids"]]
126
-
127
- with torch.no_grad():
128
- output = model(
129
- input_ids=inputs["input_ids"],
130
- attention_mask=inputs["attention_mask"],
131
- token_type_ids=inputs.get("token_type_ids"),
132
- tokens=tokens
133
- )
134
-
135
- logits = output["logits"]
136
- max_indices = output["max_indices"]
137
- metadata = output["metadata"]
138
-
139
- print("Inference successful")
140
- print("Logits shape:", logits.shape)
141
- print("Max indices:", max_indices)
142
- print("Metadata:", metadata)
143
- ```
144
-
145
- ## Outputs
146
-
147
- The model returns a dictionary with the following entries:
148
-
149
- - **logits**
150
- Prediction scores per diagnosis label.
151
-
152
- - **max_indices**
153
- Index of the winning prototype sub-network per diagnosis, corresponding to the selected prototype.
154
-
155
- - **metadata**
156
- Additional information useful for analysis and interpretability.
157
-
158
-
159
- ![Output Example](output_example.png)
160
-
161
- ## Explainability
162
-
163
- S-Proto provides built-in faithful explanations through its prototypical structure:
164
-
165
- - Attention vectors highlight clinically relevant tokens
166
- - Prototype distances reflect similarity to prototypical patients
167
- - Multiple prototypes per diagnosis capture disease subtypes and cohorts
168
- - Faithfulness metrics remain comparable to ProtoPatient despite higher capacity
169
-
170
- Qualitative evaluation with medical professionals confirms that learned prototypes often correspond to clinically meaningful phenotypes.
171
-
172
- ## Training
173
-
174
- First, clone the repository:
175
-
176
- ```bash
177
- git clone https://github.com/DATEXIS/sproto.git
178
- cd sproto
179
- ```
180
-
181
- Set up the environment using Poetry:
182
-
183
- ```bash
184
- poetry install
185
- ```
186
-
187
- Activate the virtual environment:
188
-
189
- ```bash
190
- poetry env activate
191
- ```
192
-
193
- Once the environment is active, you can start training by running the train command with the desired arguments.
194
-
195
- Example:
196
-
197
- ```bash
198
- train \
199
- --batch_size 3 \
200
- --pretrained_model microsoft/biomednlp-pubmedbert-base-uncased-abstract-fulltext \
201
- --pretrained_model_path path_to_pretrained_model.ckpt \
202
- --model_type MULTI_PROTO \
203
- --train_file training_data.csv \
204
- --val_file validation_data.csv \
205
- --test_file test_data.csv \
206
- --save_dir ../experiments/ \
207
- --gpus 1 \
208
- --check_val_every_n_epoch 2 \
209
- --num_warmup_steps 0 \
210
- --num_training_steps 50 \
211
- --max_length 512 \
212
- --lr_features 0.000005 \
213
- --lr_prototypes 0.001 \
214
- --lr_others 0.001 \
215
- --num_val_samples None \
216
- --use_attention True \
217
- --reduce_hidden_size 256 \
218
- --all_labels_path all_labels.pcl \
219
- --seed 42 \
220
- --label_column labels \
221
- --metric_opt auroc_macro \
222
- --train_files [] \
223
- --val_files [] \
224
- --only_test True \
225
- --model_name 5p \
226
- --store_metadata False \
227
- --num_prototypes_per_class 5
228
- ```
229
-
230
- ## Citation
231
-
232
- ```bibtex
233
- @inproceedings{figueroa2024sproto,
234
- title={Boosting Long-Tail Data Classification with Sparse Prototypical Networks},
235
- author={Figueroa, Alexei and Papaioannou, Jens-Michalis and Fallon, Conor and Bekiaridou, Alexandra and Bressem, Keno and Zanos, Stavros and Gers, Felix and Nejdl, Wolfgang and Löser, Alexander},
236
- booktitle={Proceedings of the European Conference on Machine Learning and Principles and Practice of Knowledge Discovery in Databases (ECML PKDD)},
237
- year={2024}
238
- }
239
- ```
240
-
241
- ## License
242
-
243
- This model and its associated code are released under the Apache License 2.0.
244
-
245
- The model was trained on the MIMIC-IV dataset, which is subject to restricted access. No training data is included or redistributed with this repository.
246
- The data were accessed under a data use agreement. No patient-identifiable information is shared.
247
-
248
- Use of this model must comply with all applicable data governance and ethical guidelines.
249
-
250
- ### Limitations
251
-
252
- - Extremely rare diagnoses remain challenging
253
- - Clinical dataset biases may be reflected in predictions
254
- - Winner-takes-all selection is fixed and not learned dynamically
255
- - Not validated for real-world clinical deployment
256
-
257
- ### Ethical Considerations
258
-
259
- - The model processes sensitive clinical text
260
- - Predictions should always be reviewed by qualified professionals
261
- - Outputs should not be used as sole evidence for clinical decisions
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
262
  - Care must be taken to avoid reinforcing existing healthcare biases
 
1
+ ---
2
+ language: en
3
+ license: apache-2.0
4
+ library_name: transformers
5
+
6
+ pipeline_tag: text-classification
7
+ task_categories:
8
+ - text-classification
9
+
10
+ model_type: sproto
11
+ base_model: microsoft/BiomedNLP-PubMedBERT-base-uncased-abstract-fulltext
12
+
13
+ datasets:
14
+ - mimic-iv
15
+
16
+ metrics:
17
+ - auroc
18
+ - pr-auc
19
+
20
+ tags:
21
+ - text-classification
22
+ - multi-label-classification
23
+ - long-tail-learning
24
+ - medical
25
+ - clinical-nlp
26
+ - interpretability
27
+ - prototypical-networks
28
+ - ehr
29
+ ---
30
+
31
+ # S-Proto: Sparse Prototypical Networks for Long-Tail Clinical Diagnosis Prediction
32
+
33
+ **Published at ECML PKDD 2024 (CORE A)**
34
+ *Boosting Long-Tail Data Classification with Sparse Prototypical Networks*
35
+
36
+ Alexei Figueroa*, Jens-Michalis Papaioannou*, et al.
37
+ DATEXIS, Berliner Hochschule für Technik, Feinstein Institutes, TU Munich, Leibniz University Hannover
38
+ (* equal contribution)
39
+
40
+ ![S-Proto](overview.png)
41
+
42
+ This repository provides **S-Proto**, a sparse and interpretable prototypical network for extreme multi-label diagnosis prediction from clinical text. The model is designed to address the long-tail distribution of clinical diagnoses while preserving faithful, prototype-based explanations.
43
+
44
+ ## Interactive Demo
45
+
46
+ You can explore the model's predictions and interpretability features through our interactive web demo:
47
+ **[https://s-proto.demo.datexis.com/](https://s-proto.demo.datexis.com/)**
48
+
49
+ S-Proto was introduced in the paper:
50
+
51
+ **[Boosting Long-Tail Data Classification with Sparse Prototypical Networks](https://ecmlpkdd-storage.s3.eu-central-1.amazonaws.com/preprints/2024/lncs14947/lncs14947435.pdf)**
52
+ European Conference on Machine Learning and Principles and Practice of Knowledge Discovery in Databases (ECML PKDD 2024, CORE A)
53
+ Alexei Figueroa*, Jens-Michalis Papaioannou*, et al.
54
+ DATEXIS, Berliner Hochschule für Technik, Feinstein Institutes, TU Munich, Leibniz University Hannover
55
+ (* equal contribution)
56
+
57
+ ## Overview
58
+
59
+ Clinical outcome prediction from Electronic Health Records is characterized by extreme label imbalance. A small number of diagnoses account for most patients, while the majority of diagnoses appear rarely. Standard transformer classifiers tend to perform well on frequent diagnoses but degrade sharply in the long tail.
60
+
61
+ S-Proto addresses this problem by extending prototypical networks with:
62
+
63
+ - Multiple prototypes per diagnosis
64
+ - Sparse winner-takes-all activation
65
+ - Prototype-level interpretability
66
+ - Efficient training despite increased representational capacity
67
+
68
+ The model achieves state-of-the-art performance on MIMIC-IV diagnosis prediction, with particularly strong gains in PR-AUC for rare diagnoses, and transfers successfully to unseen clinical datasets.
69
+
70
+ ## Model Architecture
71
+
72
+ S-Proto builds on **PubMedBERT** as the text encoder and introduces a sparse prototypical layer on top.
73
+
74
+ For each diagnosis label, the model learns multiple sub-networks, each consisting of:
75
+
76
+ - A label-specific attention vector
77
+ - A prototype vector representing a prototypical patient
78
+
79
+ Given an input clinical note:
80
+
81
+ 1. The note is encoded using PubMedBERT
82
+ 2. Token embeddings are projected into a latent space
83
+ 3. Each diagnosis activates multiple candidate sub-networks
84
+ 4. A winner-takes-all mechanism selects the single most relevant sub-network per diagnosis
85
+ 5. Only the winning prototype contributes to the prediction and receives gradient updates
86
+
87
+ This allows S-Proto to model heterogeneous disease phenotypes while remaining sparse and efficient.
88
+
89
+ ## Intended Use
90
+
91
+ This model is intended for:
92
+
93
+ - Clinical diagnosis prediction from admission notes
94
+ - Research on long-tail learning in healthcare NLP
95
+ - Interpretable clinical decision support systems
96
+ - Analysis of disease phenotypes via learned prototypes
97
+
98
+ This model is **not intended for direct clinical deployment** without external validation, auditing, and regulatory approval.
99
+
100
+ ## Requirements
101
+
102
+ The model depends on the base `sproto` package (which contains `MultiProtoModule`) and specific versions of its dependencies. Version mismatches — especially in `torchmetrics` and `pytorch-lightning` — will cause `AttributeError` or import failures.
103
+
104
+ ```bash
105
+ pip install torch>=1.12.1 \
106
+ transformers>=4.25.1 \
107
+ torchmetrics>=0.10.1 \
108
+ pytorch-lightning==1.9
109
+ ```
110
+
111
+ | Package | Required version | Reason |
112
+ |---------|-----------------|--------|
113
+ | `torch` | `>= 1.12.1` | Minimum version for `nn.PairwiseDistance` and `torch.einsum` patterns used in the prototype layer |
114
+ | `transformers` | `>= 4.25.1` | Minimum version with `trust_remote_code` + `auto_map` support for custom model loading |
115
+ | `torchmetrics` | `>= 0.10.1` | `MultilabelAveragePrecision` was added in 0.10; older versions raise `AttributeError` on load |
116
+ | `pytorch-lightning` | `== 1.9` | `MultiProtoModule` is a `pl.LightningModule`; the exact API (e.g. `validation_epoch_end`) changed in 2.x |
117
+ | `sproto` | bundled | The `sproto/` package is included in this HF repo and downloaded automatically with `trust_remote_code=True` — no separate install needed |
118
+
119
+ ## Inference Example
120
+
121
+ ```python
122
+ from transformers import AutoTokenizer, AutoModel
123
+ import torch
124
+
125
+ tokenizer = AutoTokenizer.from_pretrained("DATEXIS/sproto")
126
+ model = AutoModel.from_pretrained("DATEXIS/sproto", trust_remote_code=True)
127
+ model.eval()
128
+
129
+ text_input = [
130
+ "CHIEF COMPLAINT: Right Carotid Artery Stenosis. "
131
+ "PRESENT ILLNESS: Ms. ___ is a ___ year old woman with hyperlipidemia, "
132
+ "cirrhosis with esophageal varices, alcoholism, COPD, left eye blindness, "
133
+ "and right carotid stenosis status post right carotid endarterectomy."
134
+ ]
135
+
136
+ inputs = tokenizer(
137
+ text_input,
138
+ padding=True,
139
+ truncation=True,
140
+ max_length=512,
141
+ return_tensors="pt"
142
+ )
143
+
144
+ tokens = [tokenizer.convert_ids_to_tokens(ids) for ids in inputs["input_ids"]]
145
+
146
+ with torch.no_grad():
147
+ output = model(
148
+ input_ids=inputs["input_ids"],
149
+ attention_mask=inputs["attention_mask"],
150
+ token_type_ids=inputs.get("token_type_ids"),
151
+ tokens=tokens
152
+ )
153
+
154
+ logits = output["logits"]
155
+ max_indices = output["max_indices"]
156
+ metadata = output["metadata"]
157
+
158
+ print("Inference successful")
159
+ print("Logits shape:", logits.shape)
160
+ print("Max indices:", max_indices)
161
+ print("Metadata:", metadata)
162
+ ```
163
+
164
+ > **Note:** `tokens` (the list of token strings per sample) is **required** when `use_attention=True`
165
+ > (which is the default). The attention mechanism uses the actual token strings to mask clinical
166
+ > section headers (`[CLS]`, `[SEP]`, `"chief complaint :"`, etc.) before computing
167
+ > token-to-prototype attention. Omitting `tokens` will raise a `ValueError`.
168
+ > Obtain them with `tokenizer.convert_ids_to_tokens(input_ids[i])` as shown above.
169
+
170
+ ## Outputs
171
+
172
+ The model returns a dictionary with the following entries:
173
+
174
+ - **logits**
175
+ Prediction scores per diagnosis label.
176
+
177
+ - **max_indices**
178
+ Index of the winning prototype sub-network per diagnosis, corresponding to the selected prototype.
179
+
180
+ - **metadata**
181
+ Additional information useful for analysis and interpretability.
182
+
183
+
184
+ ![Output Example](output_example.png)
185
+
186
+ ## Explainability
187
+
188
+ S-Proto provides built-in faithful explanations through its prototypical structure:
189
+
190
+ - Attention vectors highlight clinically relevant tokens
191
+ - Prototype distances reflect similarity to prototypical patients
192
+ - Multiple prototypes per diagnosis capture disease subtypes and cohorts
193
+ - Faithfulness metrics remain comparable to ProtoPatient despite higher capacity
194
+
195
+ Qualitative evaluation with medical professionals confirms that learned prototypes often correspond to clinically meaningful phenotypes.
196
+
197
+ ## Training
198
+
199
+ First, clone the repository:
200
+
201
+ ```bash
202
+ git clone https://github.com/DATEXIS/sproto.git
203
+ cd sproto
204
+ ```
205
+
206
+ Set up the environment using Poetry:
207
+
208
+ ```bash
209
+ poetry install
210
+ ```
211
+
212
+ Activate the virtual environment:
213
+
214
+ ```bash
215
+ poetry env activate
216
+ ```
217
+
218
+ Once the environment is active, you can start training by running the train command with the desired arguments.
219
+
220
+ Example:
221
+
222
+ ```bash
223
+ train \
224
+ --batch_size 3 \
225
+ --pretrained_model microsoft/biomednlp-pubmedbert-base-uncased-abstract-fulltext \
226
+ --pretrained_model_path path_to_pretrained_model.ckpt \
227
+ --model_type MULTI_PROTO \
228
+ --train_file training_data.csv \
229
+ --val_file validation_data.csv \
230
+ --test_file test_data.csv \
231
+ --save_dir ../experiments/ \
232
+ --gpus 1 \
233
+ --check_val_every_n_epoch 2 \
234
+ --num_warmup_steps 0 \
235
+ --num_training_steps 50 \
236
+ --max_length 512 \
237
+ --lr_features 0.000005 \
238
+ --lr_prototypes 0.001 \
239
+ --lr_others 0.001 \
240
+ --num_val_samples None \
241
+ --use_attention True \
242
+ --reduce_hidden_size 256 \
243
+ --all_labels_path all_labels.pcl \
244
+ --seed 42 \
245
+ --label_column labels \
246
+ --metric_opt auroc_macro \
247
+ --train_files [] \
248
+ --val_files [] \
249
+ --only_test True \
250
+ --model_name 5p \
251
+ --store_metadata False \
252
+ --num_prototypes_per_class 5
253
+ ```
254
+
255
+ ## Citation
256
+
257
+ ```bibtex
258
+ @inproceedings{figueroa2024sproto,
259
+ title={Boosting Long-Tail Data Classification with Sparse Prototypical Networks},
260
+ author={Figueroa, Alexei and Papaioannou, Jens-Michalis and Fallon, Conor and Bekiaridou, Alexandra and Bressem, Keno and Zanos, Stavros and Gers, Felix and Nejdl, Wolfgang and Löser, Alexander},
261
+ booktitle={Proceedings of the European Conference on Machine Learning and Principles and Practice of Knowledge Discovery in Databases (ECML PKDD)},
262
+ year={2024}
263
+ }
264
+ ```
265
+
266
+ ## License
267
+
268
+ This model and its associated code are released under the Apache License 2.0.
269
+
270
+ The model was trained on the MIMIC-IV dataset, which is subject to restricted access. No training data is included or redistributed with this repository.
271
+ The data were accessed under a data use agreement. No patient-identifiable information is shared.
272
+
273
+ Use of this model must comply with all applicable data governance and ethical guidelines.
274
+
275
+ ### Limitations
276
+
277
+ - Extremely rare diagnoses remain challenging
278
+ - Clinical dataset biases may be reflected in predictions
279
+ - Winner-takes-all selection is fixed and not learned dynamically
280
+ - Not validated for real-world clinical deployment
281
+
282
+ ### Ethical Considerations
283
+
284
+ - The model processes sensitive clinical text
285
+ - Predictions should always be reviewed by qualified professionals
286
+ - Outputs should not be used as sole evidence for clinical decisions
287
  - Care must be taken to avoid reinforcing existing healthcare biases
__init__.py ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ from .configuration_sproto import SprotoConfig
2
+ from .modeling_sproto import SprotoModel, SprotoOutput
3
+ from transformers import AutoConfig, AutoModel
4
+
5
+ AutoConfig.register("sproto", SprotoConfig)
6
+ AutoModel.register(SprotoConfig, SprotoModel)
7
+
8
+ __all__ = ["SprotoConfig", "SprotoModel", "SprotoOutput"]
base_bert_config.json ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "BertForMaskedLM"
4
+ ],
5
+ "model_type": "bert",
6
+ "attention_probs_dropout_prob": 0.1,
7
+ "hidden_act": "gelu",
8
+ "hidden_dropout_prob": 0.1,
9
+ "hidden_size": 768,
10
+ "initializer_range": 0.02,
11
+ "intermediate_size": 3072,
12
+ "max_position_embeddings": 512,
13
+ "num_attention_heads": 12,
14
+ "num_hidden_layers": 12,
15
+ "type_vocab_size": 2,
16
+ "vocab_size": 30522
17
+ }
config.json CHANGED
@@ -1,33 +1,27 @@
1
- {
2
- "attention_vector_path": null,
3
- "auto_map": {
4
- "AutoConfig": "configuration_sproto.SprotoConfig",
5
- "AutoModel": "modeling_sproto.SprotoModel"
6
- },
7
- "batch_size": 21,
8
- "dot_product": false,
9
- "eval_buckets": null,
10
- "final_layer": false,
11
- "label_order_path": "/pvc/shared/continual/data/icd_10_all_labels_admission_mimiciv_dia.pcl",
12
- "loss": "BCE",
13
- "lr_features": 5e-06,
14
- "lr_others": 0.001,
15
- "lr_prototypes": 0.001,
16
- "model_type": "sproto",
17
- "normalize": null,
18
- "num_classes": 1643,
19
- "num_prototypes_per_class": 5,
20
- "num_training_steps": 5000,
21
- "num_warmup_steps": 5000,
22
- "pretrained_model": "microsoft/BiomedNLP-PubMedBERT-base-uncased-abstract-fulltext",
23
- "prototype_vector_path": null,
24
- "reduce_hidden_size": 256,
25
- "save_dir": "/pvc/shared/continual/experiments/mimiciv/icd10_clinical-continual-5p-test",
26
- "seed": 28,
27
- "transformers_version": "4.25.1",
28
- "use_attention": true,
29
- "use_cuda": true,
30
- "use_global_attention": false,
31
- "use_prototype_loss": false,
32
- "use_sigmoid": false
33
- }
 
1
+ {
2
+ "auto_map": {
3
+ "AutoConfig": "configuration_sproto.SprotoConfig",
4
+ "AutoModel": "modeling_sproto.SprotoModel"
5
+ },
6
+ "attention_probs_dropout_prob": 0.1,
7
+ "dot_product": false,
8
+ "final_layer": false,
9
+ "hidden_dropout_prob": 0.1,
10
+ "hidden_size": 768,
11
+ "label_order_path": null,
12
+ "loss": "BCE",
13
+ "max_position_embeddings": 512,
14
+ "model_type": "sproto",
15
+ "normalize": null,
16
+ "num_classes": 1643,
17
+ "num_prototypes_per_class": 5,
18
+ "pretrained_model": "microsoft/BiomedNLP-PubMedBERT-base-uncased-abstract-fulltext",
19
+ "reduce_hidden_size": 256,
20
+ "seed": 7,
21
+ "transformers_version": "4.25.1",
22
+ "use_attention": true,
23
+ "use_global_attention": false,
24
+ "use_prototype_loss": false,
25
+ "use_sigmoid": false,
26
+ "vocab_size": 28996
27
+ }
 
 
 
 
 
 
configuration_sproto.py CHANGED
@@ -1,61 +1,62 @@
1
- from transformers.configuration_utils import PretrainedConfig
2
-
3
- class SprotoConfig(PretrainedConfig):
4
- model_type = "sproto"
5
-
6
- def __init__(
7
- self,
8
- pretrained_model=None,
9
- num_classes=None,
10
- label_order_path=None,
11
- use_sigmoid=False,
12
- use_cuda=True,
13
- lr_prototypes=5e-2,
14
- lr_features=2e-6,
15
- lr_others=2e-2,
16
- num_training_steps=5000,
17
- num_warmup_steps=1000,
18
- loss="BCE",
19
- save_dir="output",
20
- use_attention=True,
21
- use_global_attention=False,
22
- dot_product=False,
23
- normalize=None,
24
- final_layer=False,
25
- reduce_hidden_size=None,
26
- use_prototype_loss=False,
27
- prototype_vector_path=None,
28
- attention_vector_path=None,
29
- eval_buckets=None,
30
- seed=7,
31
- num_prototypes_per_class=1,
32
- batch_size=10,
33
- **kwargs,
34
- ):
35
- super().__init__(**kwargs)
36
-
37
- self.pretrained_model = pretrained_model
38
- self.num_classes = num_classes
39
- self.label_order_path = label_order_path
40
- self.use_sigmoid = use_sigmoid
41
- self.use_cuda = use_cuda
42
- self.lr_prototypes = lr_prototypes
43
- self.lr_features = lr_features
44
- self.lr_others = lr_others
45
- self.num_training_steps = num_training_steps
46
- self.num_warmup_steps = num_warmup_steps
47
- self.loss = loss
48
- self.save_dir = save_dir
49
- self.use_attention = use_attention
50
- self.use_global_attention = use_global_attention
51
- self.dot_product = dot_product
52
- self.normalize = normalize
53
- self.final_layer = final_layer
54
- self.reduce_hidden_size = reduce_hidden_size
55
- self.use_prototype_loss = use_prototype_loss
56
- self.prototype_vector_path = prototype_vector_path
57
- self.attention_vector_path = attention_vector_path
58
- self.eval_buckets = eval_buckets
59
- self.seed = seed
60
- self.num_prototypes_per_class = num_prototypes_per_class
61
- self.batch_size = batch_size
 
 
1
+ from transformers import PretrainedConfig
2
+
3
+
4
+ class SprotoConfig(PretrainedConfig):
5
+ model_type = "sproto"
6
+
7
+ def __init__(
8
+ self,
9
+ pretrained_model="microsoft/BiomedNLP-PubMedBERT-base-uncased-abstract-fulltext",
10
+ num_classes=55,
11
+ label_order_path=None,
12
+ use_attention=True,
13
+ use_global_attention=False,
14
+ dot_product=False,
15
+ normalize=None,
16
+ final_layer=False,
17
+ reduce_hidden_size=None,
18
+ num_prototypes_per_class=1,
19
+ loss="BCE",
20
+ use_prototype_loss=False,
21
+ use_sigmoid=False,
22
+ seed=7,
23
+ vocab_size=28996,
24
+ hidden_size=768,
25
+ max_position_embeddings=512,
26
+ attention_probs_dropout_prob=0.1,
27
+ hidden_dropout_prob=0.1,
28
+ **kwargs,
29
+ ):
30
+ # Bug fix: the checkpoint serialises the num_prototypes_per_class buffer as a list
31
+ # (one float per class). MultiProtoModule expects a scalar int for the uniform case.
32
+ # Collapse the list → scalar, asserting all values are identical.
33
+ if isinstance(num_prototypes_per_class, (list, tuple)):
34
+ unique_vals = set(int(v) for v in num_prototypes_per_class)
35
+ assert len(unique_vals) == 1, (
36
+ "Non-uniform num_prototypes_per_class cannot be represented as a scalar "
37
+ "config value. Got: {}".format(unique_vals)
38
+ )
39
+ num_prototypes_per_class = unique_vals.pop()
40
+
41
+ self.pretrained_model = pretrained_model
42
+ self.num_classes = num_classes
43
+ self.label_order_path = label_order_path
44
+ self.use_attention = use_attention
45
+ self.use_global_attention = use_global_attention
46
+ self.dot_product = dot_product
47
+ self.normalize = normalize
48
+ self.final_layer = final_layer
49
+ self.reduce_hidden_size = reduce_hidden_size
50
+ self.num_prototypes_per_class = num_prototypes_per_class
51
+ self.loss = loss
52
+ self.use_prototype_loss = use_prototype_loss
53
+ self.use_sigmoid = use_sigmoid
54
+ self.seed = seed
55
+
56
+ self.vocab_size = vocab_size
57
+ self.hidden_size = hidden_size
58
+ self.max_position_embeddings = max_position_embeddings
59
+ self.attention_probs_dropout_prob = attention_probs_dropout_prob
60
+ self.hidden_dropout_prob = hidden_dropout_prob
61
+
62
+ super().__init__(**kwargs)
model.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:ef1e86215368bfcbb723cb3a28d2c343927f154decc09527cce2093326a07fd2
3
- size 455575332
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:62960c454029f57c3a2dbfde86e34ad0ae11a6860b3233de8cbb3577a22b7d86
3
+ size 455576732
modeling_sproto.py CHANGED
@@ -1,77 +1,127 @@
1
- from transformers import PreTrainedModel
2
- from sproto.model.multi_proto import MultiProtoModule
3
- from .configuration_sproto import SprotoConfig
4
-
5
- class SprotoModel(PreTrainedModel):
6
- config_class = SprotoConfig
7
- base_model_prefix = "sproto"
8
-
9
- def __init__(self, config: SprotoConfig):
10
- super().__init__(config)
11
-
12
- self.module = MultiProtoModule(
13
- pretrained_model=config.pretrained_model,
14
- num_classes=config.num_classes,
15
- label_order_path=config.label_order_path,
16
- use_sigmoid=config.use_sigmoid,
17
- use_cuda=config.use_cuda,
18
- lr_prototypes=config.lr_prototypes,
19
- lr_features=config.lr_features,
20
- lr_others=config.lr_others,
21
- num_training_steps=config.num_training_steps,
22
- num_warmup_steps=config.num_warmup_steps,
23
- loss=config.loss,
24
- save_dir=config.save_dir,
25
- use_attention=config.use_attention,
26
- use_global_attention=config.use_global_attention,
27
- dot_product=config.dot_product,
28
- normalize=config.normalize,
29
- final_layer=config.final_layer,
30
- reduce_hidden_size=config.reduce_hidden_size,
31
- use_prototype_loss=config.use_prototype_loss,
32
- prototype_vector_path=config.prototype_vector_path,
33
- attention_vector_path=config.attention_vector_path,
34
- eval_buckets=config.eval_buckets,
35
- seed=config.seed,
36
- num_prototypes_per_class=config.num_prototypes_per_class,
37
- batch_size=config.batch_size,
38
- )
39
-
40
- # Initialize weights and apply final processing
41
- self.post_init()
42
-
43
- def _init_weights(self, module):
44
- """Initialize the weights"""
45
- if isinstance(module, (MultiProtoModule)):
46
- # MultiProtoModule handles its own initialization or is loaded from checkpoint
47
- return
48
- # Add other initializations if standard layers are used directly in SprotoModel
49
- pass
50
-
51
- def forward(
52
- self,
53
- input_ids=None,
54
- attention_mask=None,
55
- token_type_ids=None,
56
- targets=None,
57
- tokens=None,
58
- sample_ids=None,
59
- **kwargs,
60
- ):
61
-
62
- batch = {
63
- "input_ids": input_ids,
64
- "attention_masks": attention_mask,
65
- "token_type_ids": token_type_ids,
66
- "targets": targets,
67
- "tokens": tokens,
68
- "sample_ids": sample_ids,
69
- }
70
-
71
- logits, max_indices, metadata = self.module(batch)
72
-
73
- return {
74
- "logits": logits,
75
- "max_indices": max_indices,
76
- "metadata": metadata,
77
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from dataclasses import dataclass
3
+ from transformers import PreTrainedModel
4
+ from transformers.modeling_outputs import ModelOutput
5
+
6
+ from sproto.model.multi_proto import MultiProtoModule
7
+
8
+ from .configuration_sproto import SprotoConfig
9
+
10
+
11
+ @dataclass
12
+ class SprotoOutput(ModelOutput):
13
+ logits: torch.Tensor = None
14
+ max_indices: torch.Tensor = None
15
+ metadata: dict = None
16
+
17
+ def __contains__(self, key):
18
+ return hasattr(self, key)
19
+
20
+ def __getitem__(self, key):
21
+ return getattr(self, key)
22
+
23
+
24
+ class SprotoModel(PreTrainedModel):
25
+ config_class = SprotoConfig
26
+ base_model_prefix = "sproto"
27
+
28
+ def __init__(self, config):
29
+ super().__init__(config)
30
+ self.config = config
31
+
32
+ # HF's from_pretrained (on newer PyTorch / Transformers) can set a meta-device
33
+ # context during weight loading. MultiProtoModule.__init__ internally calls
34
+ # AutoModel.from_pretrained() for the BERT backbone, which conflicts with that
35
+ # context. We escape it by forcing CPU initialization when on torch >= 2.0
36
+ # (torch.device context manager was added in 2.0); on older torch the conflict
37
+ # does not occur and we construct normally.
38
+ _torch_version = tuple(int(x) for x in torch.__version__.split(".")[:2] if x.isdigit())
39
+ if _torch_version >= (2, 0):
40
+ with torch.device("cpu"):
41
+ self.module = MultiProtoModule(
42
+ pretrained_model=config.pretrained_model,
43
+ num_classes=config.num_classes,
44
+ label_order_path=config.label_order_path,
45
+ use_attention=config.use_attention,
46
+ use_global_attention=config.use_global_attention,
47
+ dot_product=config.dot_product,
48
+ normalize=config.normalize,
49
+ final_layer=config.final_layer,
50
+ reduce_hidden_size=config.reduce_hidden_size,
51
+ num_prototypes_per_class=config.num_prototypes_per_class,
52
+ loss=config.loss,
53
+ use_prototype_loss=config.use_prototype_loss,
54
+ use_sigmoid=config.use_sigmoid,
55
+ seed=config.seed,
56
+ # use_cuda=False: HF handles device placement via .to(device);
57
+ # manual .cuda() calls in the base model are bypassed here.
58
+ use_cuda=False,
59
+ )
60
+ else:
61
+ self.module = MultiProtoModule(
62
+ pretrained_model=config.pretrained_model,
63
+ num_classes=config.num_classes,
64
+ label_order_path=config.label_order_path,
65
+ use_attention=config.use_attention,
66
+ use_global_attention=config.use_global_attention,
67
+ dot_product=config.dot_product,
68
+ normalize=config.normalize,
69
+ final_layer=config.final_layer,
70
+ reduce_hidden_size=config.reduce_hidden_size,
71
+ num_prototypes_per_class=config.num_prototypes_per_class,
72
+ loss=config.loss,
73
+ use_prototype_loss=config.use_prototype_loss,
74
+ use_sigmoid=config.use_sigmoid,
75
+ seed=config.seed,
76
+ use_cuda=False,
77
+ )
78
+
79
+ def forward(
80
+ self,
81
+ input_ids,
82
+ attention_mask,
83
+ token_type_ids=None,
84
+ targets=None,
85
+ tokens=None,
86
+ sample_ids=None,
87
+ ):
88
+ # tokens MUST be provided when use_attention=True.
89
+ # attention_mask_from_tokens() relies on real token strings to zero out clinical
90
+ # section headers ([CLS], [SEP], "chief complaint :", etc.) before computing
91
+ # token-prototype attention. A fake default would silently produce wrong logits.
92
+ if tokens is None and self.config.use_attention:
93
+ raise ValueError(
94
+ "tokens (list-of-lists of token strings per sample) must be provided "
95
+ "when use_attention=True. Obtain them via:\n"
96
+ " tokenizer.convert_ids_to_tokens(input_ids[i])\n"
97
+ "for each sample i in the batch, or pass the full batch at once with:\n"
98
+ " [tokenizer.convert_ids_to_tokens(ids) for ids in input_ids]"
99
+ )
100
+
101
+ batch = {
102
+ "input_ids": input_ids,
103
+ "attention_masks": attention_mask,
104
+ "token_type_ids": token_type_ids if token_type_ids is not None else torch.zeros_like(input_ids),
105
+ "targets": targets if targets is not None else torch.zeros(input_ids.shape[0], self.config.num_classes),
106
+ "tokens": tokens if tokens is not None else [["[PAD]"] * input_ids.shape[1]] * input_ids.shape[0],
107
+ "sample_ids": sample_ids if sample_ids is not None else [f"sample_{i}" for i in range(input_ids.shape[0])],
108
+ }
109
+
110
+ logits, max_indices, metadata = self.module(batch)
111
+
112
+ return SprotoOutput(
113
+ logits=logits,
114
+ max_indices=max_indices,
115
+ metadata=metadata,
116
+ )
117
+
118
+ def get_embeddings(self, input_ids, attention_mask, token_type_ids=None):
119
+ bert_output = self.module.bert(
120
+ input_ids=input_ids,
121
+ attention_mask=attention_mask,
122
+ token_type_ids=token_type_ids if token_type_ids is not None else torch.zeros_like(input_ids),
123
+ )
124
+ return bert_output.last_hidden_state
125
+
126
+ def _init_weights(self, module):
127
+ pass
pytorch_model.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9129bc3ced6a0e088a7ab7a8ab8ad508af4dd33fc5f29f64615d5116acb5f409
3
+ size 455619649
tokenizer_config.json CHANGED
@@ -1,16 +1,15 @@
1
- {
2
- "cls_token": "[CLS]",
3
- "do_basic_tokenize": true,
4
- "do_lower_case": true,
5
- "mask_token": "[MASK]",
6
- "model_max_length": 1000000000000000019884624838656,
7
- "name_or_path": "microsoft/BiomedNLP-PubMedBERT-base-uncased-abstract-fulltext",
8
- "never_split": null,
9
- "pad_token": "[PAD]",
10
- "sep_token": "[SEP]",
11
- "special_tokens_map_file": null,
12
- "strip_accents": null,
13
- "tokenize_chinese_chars": true,
14
- "tokenizer_class": "BertTokenizer",
15
- "unk_token": "[UNK]"
16
- }
 
1
+ {
2
+ "do_lower_case": true,
3
+ "tokenizer_class": "BertTokenizer",
4
+ "pad_token": "[PAD]",
5
+ "sep_token": "[SEP]",
6
+ "cls_token": "[CLS]",
7
+ "mask_token": "[MASK]",
8
+ "unk_token": "[UNK]",
9
+ "pad_token_id": 0,
10
+ "sep_token_id": 102,
11
+ "cls_token_id": 101,
12
+ "mask_token_id": 103,
13
+ "unk_token_id": 100,
14
+ "model_max_length": 512
15
+ }
 
vocab.txt ADDED
The diff for this file is too large to render. See raw diff