mlboydaisuke commited on
Commit
0c88b6c
Β·
verified Β·
1 Parent(s): 06d4b27

Upload README.md with huggingface_hub

Browse files
Files changed (1) hide show
  1. README.md +178 -0
README.md ADDED
@@ -0,0 +1,178 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ tags:
4
+ - executorch
5
+ - xnnpack
6
+ - pte
7
+ - on-device
8
+ - image-text-to-text
9
+ - image-to-text
10
+ - object-detection
11
+ base_model:
12
+ - microsoft/Florence-2-base
13
+ ---
14
+ # Florence-2-base β€” ExecuTorch (vision + text encoder + text decoder)
15
+
16
+ One set of weights that captions, detects, reads text and grounds phrases, with the
17
+ task chosen by the prompt you send. 0.23 B parameters. Three `.pte` files, split the
18
+ way Whisper is on this shelf and for the same reason: the vision tower and the text
19
+ encoder run once per image, the decoder runs once per generated token.
20
+
21
+ ```
22
+ vision : pixel_values (1,3,768,768) -> image_features (1,577,768)
23
+ encoder: (image_features, input_ids (1,32), mask (1,32)) -> hidden (1,609,768)
24
+ decoder: (hidden, mask (1,32), decoder_input_ids (1,128)) -> logits (1,128,51328)
25
+ ```
26
+
27
+ Every file takes and returns fp32 tensors, so a precision is a file swap, and the
28
+ three parts can be mixed β€” an fp16 vision tower pairs with an fp32 encoder.
29
+
30
+ | part | build | file | MB | corr vs fp32 eager | Mac ms* |
31
+ |---|---|---|---|---|---|
32
+ | vision | XNNPACK fp32 | `florence2_base_vision_xnnpack_fp32.pte` | 365.7 | 1.000000 | 360.0 |
33
+ | vision | XNNPACK int8 | `florence2_base_vision_xnnpack_int8.pte` | **112.5** | 0.998901 | 334.7 |
34
+ | vision | XNNPACK fp16 | `florence2_base_vision_xnnpack_fp16.pte` | 196.2 | 0.999946 | 1034.5 |
35
+ | vision | Core ML (iOS) | `florence2_base_vision_coreml_all.pte` | 185.1 | 0.998304 | 59.7 |
36
+ | encoder | XNNPACK fp32 | `florence2_base_encoder_xnnpack_fp32.pte` | 331.0 | 1.000000 | 51.0 |
37
+ | encoder | XNNPACK int8 | `florence2_base_encoder_xnnpack_int8.pte` | **203.8** | 0.999534 | 44.3 |
38
+ | encoder | Core ML (iOS) | `florence2_base_encoder_coreml_all.pte` | 165.1 | 0.999993 | 13.9 |
39
+ | decoder | XNNPACK fp32 | `florence2_base_decoder_xnnpack_fp32.pte` | 545.5 | 1.000000 | 35.7 |
40
+ | decoder | XNNPACK int8 | `florence2_base_decoder_xnnpack_int8.pte` | **257.9** | 0.999470 | 33.1 |
41
+ | decoder | Core ML (iOS) | `florence2_base_decoder_coreml_all.pte` | 193.0 | 0.999995 | 4.7 |
42
+
43
+ Three sets: **1242 MB** all-fp32, **574 MB** all-int8, **543 MB** Core ML. The int8
44
+ set is the one to reach for on Android β€” it is smaller than fp32 by more than half
45
+ and no slower, and it returns the same captions (below). The int8 recipe is dynamic
46
+ quantisation, which reaches the linear layers and leaves the 51328Γ—768 token
47
+ embedding table in fp32; that table is 158 MB of the decoder's file, which is why the
48
+ decoder halves rather than quarters.
49
+
50
+ \*Mac arm64, single process, median of 10 β€” a reference point for relative cost, not
51
+ a device number. Torch eager fp32 on the same machine: vision 466.0 ms, encoder
52
+ 30.8 ms, decoder 23.5 ms.
53
+
54
+ A caption of *n* tokens costs one vision pass, one encoder pass and *n* decoder
55
+ passes: about 0.95 s for a 15-token caption on the fp32 XNNPACK set, 0.88 s on the
56
+ int8 set, 0.14 s on Core ML, on this Mac. The decoder graph is a fixed 128-token
57
+ window, so every step costs the same whether it is the first token or the fiftieth.
58
+
59
+ ## Running it
60
+
61
+ **1. The image.** RGB, divide by 255, ImageNet normalise (mean .485/.456/.406, std
62
+ .229/.224/.225), bicubic resize to 768Γ—768. No crop. Run the vision `.pte`.
63
+
64
+ **2. The prompt.** Florence-2's task tokens are shorthand the processor expands into
65
+ a sentence before tokenising β€” the model never sees `<CAPTION>`:
66
+
67
+ | task | the sentence that is actually tokenised |
68
+ |---|---|
69
+ | `<CAPTION>` | What does the image describe? |
70
+ | `<DETAILED_CAPTION>` | Describe in detail what is shown in the image. |
71
+ | `<MORE_DETAILED_CAPTION>` | Describe with a paragraph what is shown in the image. |
72
+ | `<OD>` | Locate the objects with category name in the image. |
73
+ | `<DENSE_REGION_CAPTION>` | Locate the objects in the image, with their descriptions. |
74
+ | `<REGION_PROPOSAL>` | Locate the region proposals in the image. |
75
+ | `<OCR>` | What is the text in the image? |
76
+ | `<OCR_WITH_REGION>` | What is the text in the image, with regions? |
77
+ | `<CAPTION_TO_PHRASE_GROUNDING>` | Locate the phrases in the caption: {your caption} |
78
+ | `<OPEN_VOCABULARY_DETECTION>` | Locate {your phrase} in the image. |
79
+
80
+ Tokenise that sentence as `<s> sentence </s>` with the repo's tokenizer, right-pad to
81
+ 32 with the pad id (1), and build an `attention_mask` that is 1 on the real tokens and
82
+ 0 on the padding. Run the encoder `.pte` with `(image_features, input_ids, mask)`.
83
+
84
+ The 577 image tokens are handled inside the graphs. The prompt sequence the original
85
+ model sees is `<image>Γ—577 + <s> prompt </s>`, and because the image tokens are a
86
+ contiguous prefix, the encoder here concatenates the vision features in front of the
87
+ text embeddings instead of scattering them into placeholder positions. Same
88
+ arithmetic, no data-dependent mask, and nothing for the caller to line up.
89
+
90
+ **3. Greedy decoding.** Fill a `(1,128)` int64 window with the pad id, write the
91
+ decoder start token (2) at position 0, then for step `t = 0, 1, 2, ...`:
92
+
93
+ ```
94
+ logits = decoder(hidden, mask, window) # mask is the same one the encoder took
95
+ next = argmax(logits[0, t])
96
+ if next == 2: stop # </s>
97
+ window[0, t + 1] = next
98
+ ```
99
+
100
+ Detokenise the collected ids with the repo's tokenizer. There is no KV cache: the
101
+ decoder is a plain static graph over the window, which is what makes it a single
102
+ `.pte` with no state to carry between calls.
103
+
104
+ **4. Reading a detection answer.** Grounded tasks answer with `<loc_N>` tokens,
105
+ `N` in 0..999. Four in a row are a box, and each coordinate is `(N + 0.5) Γ— side /
106
+ 1000` in the original image's pixels β€” `side` being the image's width for x and its
107
+ height for y, not 768. That is the same arithmetic the processor's own parser does.
108
+
109
+ ## Verification
110
+
111
+ The three wrappers reproduce `Florence2ForConditionalGeneration` **exactly**:
112
+ composition `max_abs_diff` 0.000e+00 against the full model's logits on the same
113
+ image and prompt.
114
+
115
+ End to end through the three `.pte` files, greedy `<CAPTION>` on five photographs
116
+ against the same decoding in eager PyTorch: **5/5 captions identical**, character for
117
+ character. Correlation is measured per part in the table above; the caption test is
118
+ what says the split, the prompt layout and the decode agree.
119
+
120
+ ```
121
+ A black and white photo of a person playing a piano.
122
+ A wooden walkway leading to the ocean on a sunny day.
123
+ A group of dead trees in a forest under a cloudy sky.
124
+ A long empty road in the middle of a forest.
125
+ A couple of wooden benches sitting on top of a field of leaves.
126
+ ```
127
+
128
+ The **int8 set answers with the same five sentences**, character for character, with
129
+ all three parts quantised at once β€” which is how they would be used together.
130
+
131
+ ```bash
132
+ python convert/check_florence2.py fp32 # or int8
133
+ ```
134
+
135
+ ## Not shipped, and why
136
+
137
+ **fp16 for the encoder and the decoder does not export.** BART clamps its activations
138
+ when, and only when, they are half precision:
139
+
140
+ ```python
141
+ if hidden_states.dtype == torch.float16 and not torch.isfinite(hidden_states).all():
142
+ ```
143
+
144
+ In fp32 that line short-circuits and never reaches the graph. Halve the model and it
145
+ becomes a question about values `torch.export` cannot answer, and export stops with
146
+ `GuardOnDataDependentSymNode`. The clamp could be shimmed away, but then the shipped
147
+ graph would lack the overflow guard the original has, which is not a trade worth
148
+ making silently. Nothing is lost by it: int8 is both smaller and faster than fp16
149
+ here, and the Core ML builds compute in fp16 internally anyway, holding at
150
+ correlation 0.999993 and 0.999995.
151
+
152
+ **The fp16 vision tower ships and is probably not what you want.** It passes both
153
+ gates β€” 196.2 MB at correlation 0.999946 β€” but the int8 tower is 112.5 MB and three
154
+ times faster (334.7 ms against 1034.5 ms), because XNNPACK has no fp16 kernels here
155
+ and inserts casts instead. It is in the repo for anyone who needs more fidelity than
156
+ int8 without carrying the fp32 file.
157
+
158
+ ## Conversion notes
159
+
160
+ Converted from
161
+ [florence-community/Florence-2-base](https://huggingface.co/florence-community/Florence-2-base),
162
+ the transformers-format mirror of
163
+ [microsoft/Florence-2-base](https://huggingface.co/microsoft/Florence-2-base) β€” same
164
+ MIT weights. The original repo predates the in-tree implementation and its weight
165
+ names do not match it: loading it into `Florence2ForConditionalGeneration` prints a
166
+ load report where every key is unexpected and hands back a randomly initialised model
167
+ without raising.
168
+
169
+ The checkpoint declares `torch_dtype: float16` and transformers honours it, so
170
+ `from_pretrained` must be given `dtype=torch.float32` explicitly. Without it the
171
+ "fp32" build serialises fp16 weights β€” 196 MB for a 90 M parameter tower β€” and the
172
+ lowered vision graph returns NaN.
173
+
174
+ - **Source**: microsoft/Florence-2-base (via florence-community mirror)
175
+ - **License**: MIT
176
+
177
+ torch.export -> to_edge_transform_and_lower(partitioner) -> .pte
178
+ (conversion scripts: [executorch-models](https://github.com/john-rocky/executorch-models))