Safetensors
Dutch
llama
medical
cardiology
UMCU commited on
Commit
3f81ded
·
verified ·
1 Parent(s): dc4f65f

Update README.md

Browse files
Files changed (1) hide show
  1. README.md +149 -5
README.md CHANGED
@@ -12,14 +12,145 @@ tags:
12
  ---
13
 
14
  Llama-3.2-1B-Instruct, with domain adapted pretraining (DAPT), also called Continuous Pre-training (CPT) on a Dutch medical corpus, slightly biased towards cardiology.
 
15
 
16
- Training for one full epoch, with a 256 batch size, maximally 768 sequence length and a linear-cosine schedule (details follow..).
17
 
18
- This model will be further pre-trained on 5 million cardiology records from the UMCU.
19
 
20
- The perplexity was around 5 on the validation set.
 
21
 
22
- Note: this is not instruction tuned, and does not generate an EOS token. Update coming.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
 
24
  If you use this model please cite with
25
 
@@ -33,4 +164,17 @@ If you use this model please cite with
33
  primaryClass={cs.CL},
34
  url={https://arxiv.org/abs/2604.25374},
35
  }
36
- ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  ---
13
 
14
  Llama-3.2-1B-Instruct, with domain adapted pretraining (DAPT), also called Continuous Pre-training (CPT) on a Dutch medical corpus, slightly biased towards cardiology.
15
+ Training, with a 256 batch size, maximally 1024 sequence length during training and a linear-cosine schedul, with 100 cycles per 250M steps, with LRmax=1e-4 and 100K warmup steps, AdamW for optimization.
16
 
17
+ Currently at 5 perplexity, could still use more training.
18
 
19
+ Planned: on-premise continuous pre-training on Dutch clinical texts.
20
 
21
+ To use directly for the generation of embeddings:
22
+ ```python
23
 
24
+ import torch
25
+ import torch.nn.functional as F
26
+ from transformers import AutoTokenizer, AutoModel
27
+
28
+
29
+ MODEL_ID = "UMCU/MedLlama.nl"
30
+
31
+ tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
32
+
33
+ model = AutoModel.from_pretrained(
34
+ MODEL_ID,
35
+ torch_dtype=torch.bfloat16,
36
+ )
37
+
38
+ device = (
39
+ "cuda" if torch.cuda.is_available()
40
+ else "mps" if torch.backends.mps.is_available()
41
+ else "cpu"
42
+ )
43
+
44
+ model = model.to(device)
45
+ model.eval()
46
+
47
+ if tokenizer.pad_token_id is None:
48
+ tokenizer.pad_token = tokenizer.eos_token
49
+
50
+
51
+ def echo_embedding(
52
+ text: str,
53
+ max_length: int = 1024,
54
+ ):
55
+ # Tokenize the pieces separately so that we know exactly
56
+ # which tokens belong to the second occurrence.
57
+
58
+ prefix1 = tokenizer(
59
+ "Rewrite the following paragraph:\n",
60
+ add_special_tokens=False,
61
+ )["input_ids"]
62
+
63
+ prefix2 = tokenizer(
64
+ "\nThe rewritten paragraph:\n",
65
+ add_special_tokens=False,
66
+ )["input_ids"]
67
+
68
+ text_ids = tokenizer(
69
+ text,
70
+ add_special_tokens=False,
71
+ )["input_ids"]
72
+
73
+ bos = (
74
+ [tokenizer.bos_token_id]
75
+ if tokenizer.bos_token_id is not None
76
+ else []
77
+ )
78
+
79
+ eos = (
80
+ [tokenizer.eos_token_id]
81
+ if tokenizer.eos_token_id is not None
82
+ else []
83
+ )
84
+
85
+ # Text occurs twice, so calculate the maximum amount
86
+ # that fits into the context window.
87
+ overhead = len(bos) + len(prefix1) + len(prefix2) + len(eos)
88
+
89
+ max_text_tokens = (max_length - overhead) // 2
90
+ text_ids = text_ids[:max_text_tokens]
91
+
92
+ # ------------------------------------------------
93
+ # BOS prefix1 TEXT prefix2 TEXT EOS
94
+ # ^^^^^^^^^
95
+ # pool only here
96
+ # ------------------------------------------------
97
+
98
+ input_ids = (
99
+ bos
100
+ + prefix1
101
+ + text_ids
102
+ + prefix2
103
+ + text_ids
104
+ + eos
105
+ )
106
+
107
+ second_start = (
108
+ len(bos)
109
+ + len(prefix1)
110
+ + len(text_ids)
111
+ + len(prefix2)
112
+ )
113
+
114
+ second_end = second_start + len(text_ids)
115
+
116
+ input_ids = torch.tensor(
117
+ [input_ids],
118
+ dtype=torch.long,
119
+ device=device,
120
+ )
121
+
122
+ attention_mask = torch.ones_like(input_ids)
123
+
124
+ with torch.inference_mode():
125
+ outputs = model(
126
+ input_ids=input_ids,
127
+ attention_mask=attention_mask,
128
+ )
129
+
130
+ # [batch, sequence, hidden_size]
131
+ hidden = outputs.last_hidden_state
132
+
133
+ # Hidden states corresponding ONLY to second occurrence
134
+ echo_tokens = hidden[:, second_start:second_end, :]
135
+
136
+ # Mean-token pooling
137
+ embedding = echo_tokens.mean(dim=1)
138
+
139
+ # Usually desirable for cosine similarity / retrieval
140
+ embedding = F.normalize(embedding, p=2, dim=-1)
141
+
142
+ return embedding
143
+ ```
144
+
145
+
146
+ To use for text-generation we note that currently the EOS/EOT is untrained due to a config error, i.e. it will repeat itself ad infinitum.
147
+
148
+ ```py
149
+ import torch
150
+ from transformers import AutoTokenizer, AutoModelForCausalLM
151
+ tokenizer = AutoTokenizer.from_pretrained("UMCU/MedLlama.nl")
152
+ model = AutoModelForCausalLM.from_pretrained("UMCU/MedLlama.nl", torch_dtype=torch.float16)
153
+ ```
154
 
155
  If you use this model please cite with
156
 
 
164
  primaryClass={cs.CL},
165
  url={https://arxiv.org/abs/2604.25374},
166
  }
167
+ ```
168
+
169
+ If you use the model to generate embeddings with the above code snippet, please cite
170
+ ```bibtex
171
+ @misc{springer2025repetitionimproveslanguagemodel,
172
+ title={Repetition Improves Language Model Embeddings},
173
+ author={Jacob Mitchell Springer and Suhas Kotha and Daniel Fried and Graham Neubig and Aditi Raghunathan},
174
+ year={2025},
175
+ eprint={2402.15449},
176
+ archivePrefix={arXiv},
177
+ primaryClass={cs.CL},
178
+ url={https://arxiv.org/abs/2402.15449},
179
+ }
180
+ ```