Samuel Stevens commited on
Commit
d4005aa
1 Parent(s): 9cbc5ff

more image examples; no open-ended prediction

Browse files
app.py CHANGED
@@ -33,13 +33,19 @@ preprocess_img = transforms.Compose(
33
 
34
  ranks = ("Kingdom", "Phylum", "Class", "Order", "Family", "Genus", "Species")
35
 
36
- open_domain_examples = [
37
- ["examples/Ursus-arctos.jpeg", "Species"],
38
- ["examples/Phoca-vitulina.png", "Species"],
39
- ["examples/Felis-catus.jpeg", "Genus"],
40
- ["examples/Sarcoscypha-coccinea.jpeg", "Order"],
41
- ]
42
  zero_shot_examples = [
 
 
 
 
 
 
43
  [
44
  "examples/Carnegiea-gigantea.png",
45
  "Carnegiea gigantea\nSchlumbergera opuntioides\nMammillaria albicoma",
@@ -52,6 +58,18 @@ zero_shot_examples = [
52
  "examples/Actinostola-abyssorum.png",
53
  "Animalia Cnidaria Hexacorallia Actiniaria Actinostolidae Actinostola abyssorum\nAnimalia Cnidaria Hexacorallia Actiniaria Actinostolidae Actinostola bulbosa\nAnimalia Cnidaria Hexacorallia Actiniaria Actinostolidae Actinostola callosa\nAnimalia Cnidaria Hexacorallia Actiniaria Actinostolidae Actinostola capensis\nAnimalia Cnidaria Hexacorallia Actiniaria Actinostolidae Actinostola carlgreni",
54
  ],
 
 
 
 
 
 
 
 
 
 
 
 
55
  ]
56
 
57
 
@@ -153,89 +171,94 @@ if __name__ == "__main__":
153
  status_msg = f"{done}/{total} ({done / total * 100:.1f}%) indexed"
154
 
155
  with gr.Blocks() as app:
156
- img_input = gr.Image()
157
-
158
- with gr.Tab("Open-Ended"):
159
- with gr.Row():
160
- with gr.Column():
161
- rank_dropdown = gr.Dropdown(
162
- label="Taxonomic Rank",
163
- info="Which taxonomic rank to predict. Fine-grained ranks (genus, species) are more challenging.",
164
- choices=ranks,
165
- value="Species",
166
- type="index",
167
- )
168
- open_domain_btn = gr.Button("Submit", variant="primary")
169
- gr.Examples(
170
- examples=open_domain_examples,
171
- inputs=[img_input, rank_dropdown],
172
- )
173
-
174
- with gr.Column():
175
- open_domain_outputs = [
176
- gr.Label(num_top_classes=5, label=rank, show_label=True)
177
- for rank in reversed(ranks)
178
- ]
179
- open_domain_flag_btn = gr.Button("Flag Mistake", variant="primary")
180
-
181
- open_domain_callback = gr.HuggingFaceDatasetSaver(
182
- hf_token, "imageomics/bioclip-demo-open-domain-mistakes", private=True
183
- )
184
- open_domain_callback.setup(
185
- [img_input, *open_domain_outputs], flagging_dir="logs/flagged"
186
- )
187
- open_domain_flag_btn.click(
188
- lambda *args: open_domain_callback.flag(args),
189
- [img_input, *open_domain_outputs],
190
- None,
191
- preprocess=False,
192
- )
193
-
194
- with gr.Tab("Zero-Shot"):
195
- with gr.Row():
196
- with gr.Column():
197
- classes_txt = gr.Textbox(
198
- placeholder="Canis familiaris (dog)\nFelis catus (cat)\n...",
199
- lines=3,
200
- label="Classes",
201
- show_label=True,
202
- info="Use taxonomic names where possible; include common names if possible.",
203
- )
204
- zero_shot_btn = gr.Button("Submit", variant="primary")
205
- gr.Examples(
206
- examples=zero_shot_examples,
207
- inputs=[img_input, classes_txt],
208
- )
209
-
210
- with gr.Column():
211
- zero_shot_output = gr.Label(
212
- num_top_classes=5, label="Prediction", show_label=True
213
- )
214
- zero_shot_flag_btn = gr.Button("Flag Mistake", variant="primary")
215
-
216
- zero_shot_callback = gr.HuggingFaceDatasetSaver(
217
- hf_token, "imageomics/bioclip-demo-zero-shot-mistakes", private=True
218
- )
219
- zero_shot_callback.setup(
220
- [img_input, zero_shot_output], flagging_dir="logs/flagged"
221
- )
222
- zero_shot_flag_btn.click(
223
- lambda *args: zero_shot_callback.flag(args),
224
- [img_input, zero_shot_output],
225
- None,
226
- preprocess=False,
227
  )
228
 
229
- rank_dropdown.change(
230
- fn=change_output, inputs=rank_dropdown, outputs=open_domain_outputs
231
  )
232
-
233
- open_domain_btn.click(
234
- fn=open_domain_classification,
235
- inputs=[img_input, rank_dropdown],
236
- outputs=open_domain_outputs,
 
 
 
237
  )
238
 
 
 
 
 
 
 
 
 
 
 
239
  zero_shot_btn.click(
240
  fn=zero_shot_classification,
241
  inputs=[img_input, classes_txt],
 
33
 
34
  ranks = ("Kingdom", "Phylum", "Class", "Order", "Family", "Genus", "Species")
35
 
36
+ # open_domain_examples = [
37
+ # ["examples/Ursus-arctos.jpeg", "Species"],
38
+ # ["examples/Phoca-vitulina.png", "Species"],
39
+ # ["examples/Felis-catus.jpeg", "Genus"],
40
+ # ["examples/Sarcoscypha-coccinea.jpeg", "Order"],
41
+ # ]
42
  zero_shot_examples = [
43
+ [
44
+ "examples/Ursus-arctos.jpeg",
45
+ "brown bear\nblack bear\npolar bear\nkoala bear\ngrizzly bear",
46
+ ],
47
+ ["examples/milk-snake.png", "coral snake\nmilk snake"],
48
+ ["examples/coral-snake.jpeg", "coral snake\nmilk snake"],
49
  [
50
  "examples/Carnegiea-gigantea.png",
51
  "Carnegiea gigantea\nSchlumbergera opuntioides\nMammillaria albicoma",
 
58
  "examples/Actinostola-abyssorum.png",
59
  "Animalia Cnidaria Hexacorallia Actiniaria Actinostolidae Actinostola abyssorum\nAnimalia Cnidaria Hexacorallia Actiniaria Actinostolidae Actinostola bulbosa\nAnimalia Cnidaria Hexacorallia Actiniaria Actinostolidae Actinostola callosa\nAnimalia Cnidaria Hexacorallia Actiniaria Actinostolidae Actinostola capensis\nAnimalia Cnidaria Hexacorallia Actiniaria Actinostolidae Actinostola carlgreni",
60
  ],
61
+ [
62
+ "examples/Sarcoscypha-coccinea.jpeg",
63
+ "scarlet elf cup (coccinea)\nscharlachroter kelchbecherling (austriaca)\ncrimson cup (dudleyi)\nstalked scarlet cup (occidentalis)",
64
+ ],
65
+ [
66
+ "examples/Onoclea-hintonii.jpg",
67
+ "Onoclea attenuata\nOnoclea boryana\nOnoclea hintonii\nOnoclea intermedia\nOnoclea sensibilis",
68
+ ],
69
+ [
70
+ "examples/Onoclea-sensibilis.jpg",
71
+ "Onoclea attenuata\nOnoclea boryana\nOnoclea hintonii\nOnoclea intermedia\nOnoclea sensibilis",
72
+ ],
73
  ]
74
 
75
 
 
171
  status_msg = f"{done}/{total} ({done / total * 100:.1f}%) indexed"
172
 
173
  with gr.Blocks() as app:
174
+ img_input = gr.Image(height=512)
175
+
176
+ # with gr.Tab("Open-Ended"):
177
+ # with gr.Row():
178
+ # with gr.Column():
179
+ # rank_dropdown = gr.Dropdown(
180
+ # label="Taxonomic Rank",
181
+ # info="Which taxonomic rank to predict. Fine-grained ranks (genus, species) are more challenging.",
182
+ # choices=ranks,
183
+ # value="Species",
184
+ # type="index",
185
+ # )
186
+ # open_domain_btn = gr.Button("Submit", variant="primary")
187
+ # gr.Examples(
188
+ # examples=open_domain_examples,
189
+ # inputs=[img_input, rank_dropdown],
190
+ # )
191
+
192
+ # with gr.Column():
193
+ # open_domain_outputs = [
194
+ # gr.Label(num_top_classes=5, label=rank, show_label=True)
195
+ # for rank in reversed(ranks)
196
+ # ]
197
+ # open_domain_flag_btn = gr.Button("Flag Mistake", variant="primary")
198
+
199
+ # open_domain_callback = gr.HuggingFaceDatasetSaver(
200
+ # hf_token, "imageomics/bioclip-demo-open-domain-mistakes", private=True
201
+ # )
202
+ # open_domain_callback.setup(
203
+ # [img_input, *open_domain_outputs], flagging_dir="logs/flagged"
204
+ # )
205
+ # open_domain_flag_btn.click(
206
+ # lambda *args: open_domain_callback.flag(args),
207
+ # [img_input, *open_domain_outputs],
208
+ # None,
209
+ # preprocess=False,
210
+ # )
211
+
212
+ # with gr.Tab("Zero-Shot"):
213
+ with gr.Row():
214
+ with gr.Column():
215
+ classes_txt = gr.Textbox(
216
+ placeholder="Canis familiaris (dog)\nFelis catus (cat)\n...",
217
+ lines=3,
218
+ label="Classes",
219
+ show_label=True,
220
+ info="Use taxonomic names where possible; include common names if possible.",
221
+ )
222
+ zero_shot_btn = gr.Button("Submit", variant="primary")
223
+
224
+ with gr.Column():
225
+ zero_shot_output = gr.Label(
226
+ num_top_classes=5, label="Prediction", show_label=True
227
+ )
228
+ zero_shot_flag_btn = gr.Button("Flag Mistake", variant="primary")
229
+
230
+ with gr.Row():
231
+ gr.Examples(
232
+ examples=zero_shot_examples,
233
+ inputs=[img_input, classes_txt],
234
+ cache_examples=True,
235
+ fn=zero_shot_classification,
236
+ outputs=[zero_shot_output],
 
 
 
 
 
 
 
 
237
  )
238
 
239
+ zero_shot_callback = gr.HuggingFaceDatasetSaver(
240
+ hf_token, "imageomics/bioclip-demo-zero-shot-mistakes", private=True
241
  )
242
+ zero_shot_callback.setup(
243
+ [img_input, zero_shot_output], flagging_dir="logs/flagged"
244
+ )
245
+ zero_shot_flag_btn.click(
246
+ lambda *args: zero_shot_callback.flag(args),
247
+ [img_input, zero_shot_output],
248
+ None,
249
+ preprocess=False,
250
  )
251
 
252
+ # rank_dropdown.change(
253
+ # fn=change_output, inputs=rank_dropdown, outputs=open_domain_outputs
254
+ # )
255
+
256
+ # open_domain_btn.click(
257
+ # fn=open_domain_classification,
258
+ # inputs=[img_input, rank_dropdown],
259
+ # outputs=open_domain_outputs,
260
+ # )
261
+
262
  zero_shot_btn.click(
263
  fn=zero_shot_classification,
264
  inputs=[img_input, classes_txt],
examples/Onoclea-hintonii.jpg ADDED
examples/Onoclea-sensibilis.jpg ADDED
examples/coral-snake.jpeg ADDED

Git LFS Details

  • SHA256: 871066d1d902bbc5ab9fffa38b2a2d5117bf1b5eacc932188b782cdb6a6eed01
  • Pointer size: 130 Bytes
  • Size of remote file: 51.8 kB
examples/milk-snake.png ADDED

Git LFS Details

  • SHA256: 4c5820dfcdaa056903767cc7a3dade6e9e9d24c686fab9d457889879e80fa3ab
  • Pointer size: 131 Bytes
  • Size of remote file: 411 kB
make_txt_embedding.py CHANGED
@@ -74,24 +74,31 @@ def convert_txt_features_to_avgs(name_lookup):
74
  all_features = torch.from_numpy(np.load(args.out_path)).to(device)
75
  logger.info("Loaded text features from disk to %s.", device)
76
 
77
- all_names = [set() for rank in ranks]
78
  for name, index in tqdm(name_lookup.values()):
79
  i = len(name) - 1
80
- all_names[i].add((name, index))
81
 
82
  zeroed = 0
83
  for i, rank in reversed(list(enumerate(ranks))):
84
  if rank == "Species":
85
  continue
86
- for name, index in tqdm(all_names[i], desc=rank):
87
- species = tuple(zip(*((d, i) for d, i in name_lookup.descendants(prefix=name) if len(d) >= 6)))
 
 
 
 
 
 
 
 
88
  if not species:
89
  logger.warning("No species for %s.", " ".join(name))
90
  all_features[:, index] = 0.0
91
  zeroed += 1
92
  continue
93
 
94
-
95
  values, indices = species
96
  mean = all_features[:, indices].mean(dim=1)
97
  all_features[:, index] = F.normalize(mean, dim=0)
@@ -99,7 +106,10 @@ def convert_txt_features_to_avgs(name_lookup):
99
  out_path, ext = os.path.splitext(args.out_path)
100
  np.save(f"{out_path}_avgs{ext}", all_features.cpu().numpy())
101
  if zeroed:
102
- logger.warning("Zeroed out %d nodes because they didn't have any genus or species-level labels.", zeroed)
 
 
 
103
 
104
 
105
  def get_name_lookup(catalog_path, cache_path):
 
74
  all_features = torch.from_numpy(np.load(args.out_path)).to(device)
75
  logger.info("Loaded text features from disk to %s.", device)
76
 
77
+ names_by_rank = [set() for rank in ranks]
78
  for name, index in tqdm(name_lookup.values()):
79
  i = len(name) - 1
80
+ names_by_rank[i].add((name, index))
81
 
82
  zeroed = 0
83
  for i, rank in reversed(list(enumerate(ranks))):
84
  if rank == "Species":
85
  continue
86
+ for name, index in tqdm(names_by_rank[i], desc=rank):
87
+ species = tuple(
88
+ zip(
89
+ *(
90
+ (d, i)
91
+ for d, i in name_lookup.descendants(prefix=name)
92
+ if len(d) >= 6
93
+ )
94
+ )
95
+ )
96
  if not species:
97
  logger.warning("No species for %s.", " ".join(name))
98
  all_features[:, index] = 0.0
99
  zeroed += 1
100
  continue
101
 
 
102
  values, indices = species
103
  mean = all_features[:, indices].mean(dim=1)
104
  all_features[:, index] = F.normalize(mean, dim=0)
 
106
  out_path, ext = os.path.splitext(args.out_path)
107
  np.save(f"{out_path}_avgs{ext}", all_features.cpu().numpy())
108
  if zeroed:
109
+ logger.warning(
110
+ "Zeroed out %d nodes because they didn't have any genus or species-level labels.",
111
+ zeroed,
112
+ )
113
 
114
 
115
  def get_name_lookup(catalog_path, cache_path):