davebulaval commited on
Commit
dead74d
·
verified ·
1 Parent(s): 830f3b6

align the card with the repository: symmetry check, and examples that load the v2 checkpoint

Browse files
Files changed (1) hide show
  1. README.md +83 -6
README.md CHANGED
@@ -104,17 +104,44 @@ irrelevant sentence mainly composed of irrelevant words (also known as word soup
104
  Again, to account for computer floating-point inaccuracy, we round the ratings to the nearest integer and do not use
105
  a threshold value of 0%.
106
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  ## Use MeaningBERT
108
 
109
  You can use MeaningBERT as a [model](https://huggingface.co/davebulaval/MeaningBERT) that you can retrain or use for
110
  inference using the following with HuggingFace
111
 
112
  ```python
113
- # Load model directly
114
  from transformers import AutoTokenizer, AutoModelForSequenceClassification
115
 
116
- tokenizer = AutoTokenizer.from_pretrained("davebulaval/MeaningBERT")
117
- model = AutoModelForSequenceClassification.from_pretrained("davebulaval/MeaningBERT")
118
  ```
119
 
120
  or you can use MeaningBERT as a metric for evaluation (no retrain) using the following with HuggingFace
@@ -124,8 +151,8 @@ import torch
124
 
125
  from transformers import AutoTokenizer, AutoModelForSequenceClassification
126
 
127
- tokenizer = AutoTokenizer.from_pretrained("davebulaval/MeaningBERT")
128
- scorer = AutoModelForSequenceClassification.from_pretrained("davebulaval/MeaningBERT")
129
  scorer.eval()
130
 
131
  documents = ["He wanted to make them pay.", "This sandwich looks delicious.", "He wants to eat."]
@@ -139,9 +166,23 @@ with torch.no_grad():
139
  # We process the text
140
  scores = scorer(**tokenize_text)
141
 
142
- print(scores.logits.tolist())
 
 
143
  ```
144
 
 
 
 
 
 
 
 
 
 
 
 
 
145
  or using our HuggingFace Metric module
146
 
147
  ```python
@@ -151,11 +192,47 @@ documents = ["He wanted to make them pay.", "This sandwich looks delicious.", "H
151
  simplifications = ["He wanted to make them pay.", "This sandwich looks delicious.",
152
  "Whatever, whenever, this is a sentence."]
153
 
 
 
154
  meaning_bert = evaluate.load("davebulaval/meaningbert")
 
 
 
 
 
 
 
155
 
156
  print(meaning_bert.compute(references=documents, predictions=simplifications))
157
  ```
158
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
 
160
  ------------------
161
 
 
104
  Again, to account for computer floating-point inaccuracy, we round the ratings to the nearest integer and do not use
105
  a threshold value of 0%.
106
 
107
+ ### Symmetry
108
+
109
+ Our third test evaluates a property of the metric rather than of a sentence pair. `meaning(A, B)` and `meaning(B, A)`
110
+ ask the same question, how much of the meaning is shared, and the position of a sentence in the call carries no semantic
111
+ information. The two calls should therefore return the same number. Unlike the two tests above, this one needs no
112
+ generated data at all: it re-scores the evaluation pairs in the reverse order and measures the absolute difference,
113
+ which has an expected value of exactly 0.
114
+
115
+ A metric can pass the first two tests and fail this one. It is worth measuring because the failure is silent: two
116
+ studies using the same metric, one calling `meaning(source, simplification)` and the other `meaning(simplification,
117
+ source)`, would report different numbers with nothing signalling the discrepancy.
118
+
119
+ Measured on 1652 test pairs, mean absolute difference between the two orders:
120
+
121
+ | model | mean | median | pairs differing by more than 10 points |
122
+ |---|---|---|---|
123
+ | MeaningBERT v1, as published | 6.12 | 3.12 | **20.8 %** |
124
+ | v2 trained without mirrored pairs | 7.79 | 4.88 | 31.1 % |
125
+ | **v2 as released** | **1.48** | **0.74** | **0.6 %** |
126
+
127
+ The property is taught, not enforced: the training corpus contains the mirror of every non-identical pair, with the
128
+ label carried over unchanged. That brings the violation down by a factor of five, and it does not remove it. The scorer
129
+ deliberately runs a single direction, the one you pass, rather than averaging both: averaging would make the property
130
+ exact at twice the inference cost, and would hide in the wrapper a residual violation that belongs in the results. Pass
131
+ your pairs in a consistent order.
132
+
133
+
134
  ## Use MeaningBERT
135
 
136
  You can use MeaningBERT as a [model](https://huggingface.co/davebulaval/MeaningBERT) that you can retrain or use for
137
  inference using the following with HuggingFace
138
 
139
  ```python
140
+ # Load model directly. subfolder="large" is the v2 checkpoint; without it you get v1.
141
  from transformers import AutoTokenizer, AutoModelForSequenceClassification
142
 
143
+ tokenizer = AutoTokenizer.from_pretrained("davebulaval/MeaningBERT", subfolder="large")
144
+ model = AutoModelForSequenceClassification.from_pretrained("davebulaval/MeaningBERT", subfolder="large")
145
  ```
146
 
147
  or you can use MeaningBERT as a metric for evaluation (no retrain) using the following with HuggingFace
 
151
 
152
  from transformers import AutoTokenizer, AutoModelForSequenceClassification
153
 
154
+ tokenizer = AutoTokenizer.from_pretrained("davebulaval/MeaningBERT", subfolder="large")
155
+ scorer = AutoModelForSequenceClassification.from_pretrained("davebulaval/MeaningBERT", subfolder="large")
156
  scorer.eval()
157
 
158
  documents = ["He wanted to make them pay.", "This sandwich looks delicious.", "He wants to eat."]
 
166
  # We process the text
167
  scores = scorer(**tokenize_text)
168
 
169
+ # The output head is applied OUTSIDE the model, so the logits are NOT the score.
170
+ # config.meaningbert_output_head says which one: "clamped" for the v2 checkpoints.
171
+ print((scores.logits.squeeze(-1).clamp(0, 1) * 100).tolist())
172
  ```
173
 
174
+ > **The v1 snippet does not carry over.** v1 was trained with a linear head whose logit *is* the score, so its model card
175
+ > prints `scores.logits.tolist()` directly. The v2 checkpoints apply a bounded head outside the model: printing the raw
176
+ > logits returns unit-scale values such as `0.83`, silently, with no error. Read `config.meaningbert_output_head` and map
177
+ > accordingly, or use `meaningbert.scorer.MeaningBERTScorer`, which reads it for you and always returns 0-100.
178
+
179
+ ```python
180
+ # The same thing, without having to know which head the checkpoint uses
181
+ from meaningbert import MeaningBERTScorer
182
+
183
+ scorer = MeaningBERTScorer("davebulaval/MeaningBERT", subfolder="large")
184
+ print(scorer.score(documents, simplifications))
185
+ ```
186
  or using our HuggingFace Metric module
187
 
188
  ```python
 
192
  simplifications = ["He wanted to make them pay.", "This sandwich looks delicious.",
193
  "Whatever, whenever, this is a sentence."]
194
 
195
+ # Three checkpoints, named as the second argument of evaluate.load.
196
+ # "large" is the default: deberta-v3-large, the recommended one.
197
  meaning_bert = evaluate.load("davebulaval/meaningbert")
198
+ meaning_bert = evaluate.load("davebulaval/meaningbert", "large") # the same thing
199
+
200
+ # "base" is bert-base-uncased: 3.2x faster on GPU, 4.8x on CPU, a quarter of the memory.
201
+ meaning_bert_base = evaluate.load("davebulaval/meaningbert", "base")
202
+
203
+ # "v1" is the model published with the 2023 article, unchanged.
204
+ meaning_bert_v1 = evaluate.load("davebulaval/meaningbert", "v1")
205
 
206
  print(meaning_bert.compute(references=documents, predictions=simplifications))
207
  ```
208
 
209
+ ### Which checkpoint to load
210
+
211
+ The two v2 checkpoints are **subfolders of the same repository**,
212
+ [davebulaval/MeaningBERT](https://huggingface.co/davebulaval/MeaningBERT), whose root is still the v1 model. Nothing
213
+ already loading that repository changes behaviour.
214
+
215
+ ```python
216
+ from transformers import AutoModelForSequenceClassification
217
+
218
+ model = AutoModelForSequenceClassification.from_pretrained("davebulaval/MeaningBERT", subfolder="large")
219
+ ```
220
+
221
+ | name | encoder | Pearson *r* | identical pairs above 95 | 100 pairs, GPU / CPU | weights |
222
+ |---|---|---|---|---|---|
223
+ | **`large`** (default) | `deberta-v3-large` | **0.704 ± 0.009** | **97.1 % ± 1.4** | 1.16 s / 9.49 s | 1740 MB |
224
+ | `base`<sup>†</sup> | `bert-base-uncased` | 0.637 | 70.4 % | **0.36 s / 1.99 s** | **438 MB** |
225
+ | `v1` | `bert-base-uncased` | 0.323 | 0 % | 0.36 s / 1.99 s | 438 MB |
226
+
227
+ <sup>†</sup> `base` is **not published yet**: its figures come from a single seed, against ten for `large`, and loading it
228
+ raises rather than falling back on another checkpoint. A name that does not exist raises too, so a typo cannot silently
229
+ swap the model under you.
230
+
231
+ Load `base` when you score at volume or have no GPU, `large` when a wrong score costs you something. On a GPU the speed
232
+ argument is weak, see [A middle option worth knowing about](#a-middle-option-worth-knowing-about).
233
+
234
+ The numbers are detailed in [MeaningBERT v2: which checkpoint to use](#meaningbert-v2-which-checkpoint-to-use).
235
+
236
 
237
  ------------------
238