Skip to content

Commit 1078d5e

Browse files
committed
minimize copying. switch to prenormalized/remove casting to avoid running out of memory. works on all datasets.
1 parent fd7f913 commit 1078d5e

File tree

4 files changed

+100
-36
lines changed

4 files changed

+100
-36
lines changed

vsms/fine_grained_embedding.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,16 @@ def restrict_fine_grained(vec_meta, vec, indxs):
1111
assert vec_meta.shape[0] == vec.shape[0]
1212
assert (indxs[1:] > indxs[:-1]).all(), 'must be sorted'
1313
mask = vec_meta.dbidx.isin(pr.BitMap(indxs))
14+
if mask.all():
15+
return vec_meta, vec
16+
1417
vec_meta = vec_meta[mask]
1518
vec = vec[mask]
16-
1719
lookup_table = np.zeros(vec_meta.dbidx.max()+1).astype('int') - 1
1820
lookup_table[indxs] = np.arange(indxs.shape[0], dtype='int')
1921
new_dbidx = lookup_table[vec_meta.dbidx]
2022
assert (new_dbidx >= 0).all()
2123
vec_meta = vec_meta.assign(dbidx=new_dbidx) # this line shows up in profiler
22-
2324
assert vec_meta.dbidx.unique().shape[0] == indxs.shape[0], 'missing fine-grained embedding for some of the indices requested'
2425
assert vec_meta.shape[0] == vec.shape[0]
2526
return vec_meta.reset_index(drop=True), vec

vsms/multigrain.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,9 @@ def get_pos_negs_all_v2(dbidxs, ds, vec_meta):
214214
max_ious = np.max(ious, axis=1)
215215

216216
pos_idxs = pr.BitMap(max_ious_id[max_ious > 0])
217+
# if label_boxes.shape[0] > 0: # some boxes are size 0 bc. of some bug in the data, so don't assert here.
218+
# assert len(pos_idxs) > 0
219+
217220
posvec_positions = acc_vecs.index[pos_idxs].values
218221
pos.append(posvec_positions)
219222
neg.append(negvec_positions)
@@ -225,6 +228,20 @@ def get_pos_negs_all_v2(dbidxs, ds, vec_meta):
225228
import math
226229
import annoy
227230
from annoy import AnnoyIndex
231+
import random
232+
import os
233+
234+
def build_index(vecs, file_name):
235+
t = AnnoyIndex(512, 'dot')
236+
for i in range(len(vecs)):
237+
t.add_item(i, vecs[i])
238+
t.build(n_trees=100) # tested 100 on bdd, works well, could do more.
239+
t.save(file_name)
240+
u = AnnoyIndex(512, 'dot')
241+
u.load(file_name) # verify can load.
242+
return u
243+
244+
228245
class AugmentedDB(object):
229246
"""implements a two stage lookup
230247
"""

vsms/vloop_dataset_loaders.py

Lines changed: 77 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,17 @@ def normalize(vecs):
5151
norms = np.linalg.norm(vecs, axis=1)[:,np.newaxis]
5252
return vecs/(norms + 1e-6)
5353

54+
def load_vecs(path):
55+
vecs = np.load(path)
56+
check_vecs(vecs)
57+
return vecs
58+
59+
def check_vecs(vecs):
60+
assert vecs.dtype == 'float32'
61+
samp = np.random.permutation(len(vecs))[:1000] # don't run it on everything.
62+
vecs = vecs[samp]
63+
norms = np.linalg.norm(vecs, axis=-1)
64+
assert np.isclose(norms, 1., atol=1e-5, rtol=1e-5).all(), (norms.min(), norms.max())
5465

5566
def get_qgt(box_data, min_box_size):
5667
box_data = box_data.assign(width=box_data.x2 - box_data.x1, height = box_data.y2 - box_data.y1)
@@ -62,14 +73,18 @@ def get_qgt(box_data, min_box_size):
6273
def make_evdataset(*, root, paths, embedded_dataset, query_ground_truth, box_data, embedding,
6374
fine_grained_embedding=None, fine_grained_meta=None, min_box_size=0.):
6475

65-
query_ground_truth = get_qgt(box_data, min_box_size) # boxes are still there
76+
#if query_ground_truth is None:
77+
#query_ground_truth = get_qgt(box_data, min_box_size) # boxes are still there
6678
# for use by algorithms but not used for accuracy metrics
67-
#query_ground_truth = query_ground_truth.clip(0.,1.)
79+
query_ground_truth = query_ground_truth.clip(0.,1.)
80+
# assert query_ground_truth.max() == 1.
81+
# assert query_ground_truth.min() == 0.
82+
6883
root = os.path.abspath(root)
69-
embedded_dataset = normalize(embedded_dataset.astype('float32'))
84+
check_vecs(embedded_dataset)
7085

7186
if fine_grained_embedding is not None:
72-
fine_grained_embedding = normalize(fine_grained_embedding.astype('float32'))
87+
check_vecs(fine_grained_embedding)
7388

7489
return EvDataset(root=root, paths=paths, embedded_dataset=embedded_dataset,
7590
query_ground_truth=query_ground_truth,
@@ -110,26 +125,38 @@ def get_class_ev(ev, category, boxes=False):
110125
return ev1, class_idxs
111126

112127
def extract_subset(ev : EvDataset, *, idxsample=None, categories=None, boxes=True) -> EvDataset:
113-
"""makes an evdataset consisting of that index sample only
128+
"""makes an evdataset consisting of those categories and those index samples only
114129
"""
115130
if categories is None:
116131
categories = ev.query_ground_truth.columns.values
117132

118133
if idxsample is None:
119134
idxsample = np.arange(len(ev), dtype='int')
135+
else:
136+
assert (np.sort(idxsample) == idxsample).all(), 'sort it because some saved data assumed it was sorted here'
120137

121-
assert (np.sort(idxsample) == idxsample).all(), 'sort it'
122-
123138
categories = set(categories)
124139
idxset = pr.BitMap(idxsample)
125140

141+
qgt = ev.query_ground_truth[categories]
142+
embedded_dataset = ev.embedded_dataset
143+
paths = ev.paths
144+
145+
if not (idxset == pr.BitMap(range(len(ev)))): # special case where everything is copied
146+
qgt = qgt.iloc[idxsample].reset_index(drop=True)
147+
embedded_dataset = embedded_dataset[idxsample]
148+
paths = ev.paths[idxsample]
149+
126150
if boxes:
127151
good_boxes = ev.box_data.dbidx.isin(idxset) & ev.box_data.category.isin(categories)
128-
sample_box_data = ev.box_data[good_boxes]
129-
lookup_table = np.zeros(len(ev), dtype=np.int) - 1
130-
lookup_table[idxsample] = np.arange(idxsample.shape[0], dtype=np.int)
131-
sample_box_data = sample_box_data.assign(dbidx = lookup_table[sample_box_data.dbidx])
132-
assert (sample_box_data.dbidx >= 0 ).all()
152+
if good_boxes.all(): # avoid copying when we want everything anyway (common case)
153+
sample_box_data = ev.box_data
154+
else:
155+
sample_box_data = ev.box_data[good_boxes]
156+
lookup_table = np.zeros(len(ev), dtype=np.int) - 1
157+
lookup_table[idxsample] = np.arange(idxsample.shape[0], dtype=np.int)
158+
sample_box_data = sample_box_data.assign(dbidx = lookup_table[sample_box_data.dbidx])
159+
assert (sample_box_data.dbidx >= 0 ).all()
133160
else:
134161
sample_box_data = None
135162

@@ -139,9 +166,9 @@ def extract_subset(ev : EvDataset, *, idxsample=None, categories=None, boxes=Tru
139166
meta = None
140167
vec = None
141168

142-
return EvDataset(root=ev.root, paths=ev.paths[idxsample],
143-
embedded_dataset=ev.embedded_dataset[idxsample],
144-
query_ground_truth=ev.query_ground_truth[categories].iloc[idxsample].reset_index(drop=True),
169+
return EvDataset(root=ev.root, paths=paths,
170+
embedded_dataset=embedded_dataset,
171+
query_ground_truth=qgt,
145172
box_data=sample_box_data,
146173
embedding=ev.embedding,
147174
fine_grained_embedding=vec,
@@ -153,12 +180,20 @@ def bdd_full(embedding : XEmbedding):
153180
box_data = pd.read_parquet('./data/bdd_boxes_all_qgt_classes_imsize.parquet')
154181
qgt = pd.read_parquet('./data/bdd_boxes_all_qgt_classes_qgt.parquet')
155182

156-
fgmeta = pd.read_parquet('./data/bdd_multiscale_meta_all.parquet')
157-
fge = np.load('./data/bdd_multiscale_vecs_all.npy', mmap_mode='r')
158-
if False:
159-
fgmeta = pd.read_parquet('./data/bdd_20k_finegrained_acc_meta.parquet')
160-
fge = np.load('./data/bdd_20k_finegrained_acc.npy')
161-
embedded_dataset = np.load('./data/bdd_all_valid_feats_CLIP.npy', mmap_mode='r')
183+
184+
#nm.to_parquet('./data/bdd_multiscale_meta_all2.parquet')
185+
#np.save('./data/bdd_multiscale_vecs_all2_normalized_float16.npy',nv.astype('float16'))
186+
fgmeta = pd.read_parquet('./data/bdd_multiscale_meta_all2.parquet')
187+
fge = load_vecs('./data/bdd_multiscale_vecs_all2_normalized_float32.npy')
188+
assert fgmeta.shape[0] == fge.shape[0]
189+
# fge = np.load('./data/bdd_multiscale_vecs_all2_normalized_float32.npy', mmap_mode='r')
190+
191+
# fgmeta = pd.read_parquet('./data/bdd_20k_finegrained_acc_meta.parquet')
192+
# fge = np.load('./data/bdd_20k_finegrained_acc.npy')
193+
194+
# embedded_dataset = np.load('./data/bdd_all_valid_feats_CLIP.npy', mmap_mode='r')
195+
embedded_dataset = load_vecs('./data/bdd_all_valid_feats_CLIP_normalized_float32.npy')
196+
# embedded_dataset = np.load('./data/bdd_all_valid_feats_CLIP_normalized_float32.npy', mmap_mode='r')
162197
ev1 = make_evdataset(root=image_root, paths=paths,
163198
embedded_dataset=embedded_dataset,
164199
query_ground_truth=qgt,
@@ -169,7 +204,7 @@ def bdd_full(embedding : XEmbedding):
169204
return ev1
170205

171206
def objectnet_cropped(embedding : XEmbedding, embedded_vecs : np.array = None ) -> EvDataset:
172-
image_vectors = np.load('./data/objnet_cropped_CLIP.npy')
207+
image_vectors = np.load('./data/objnet_cropped_CLIP.npy', mmap_mode='r')
173208
tmp = np.load('./data/objnet_vectors_cropped.npz', allow_pickle=True)
174209
paths = tmp['paths']
175210
root = './data/objectnet/cropped/'
@@ -250,15 +285,16 @@ def lvis_full(embedding : XEmbedding) -> EvDataset:
250285
# bd = pd.read_parquet('./data/lvis_boxes_wdbidx.parquet')
251286
# emb_vectors = embedding.from_image(img_vec=image_vectors.astype('float32'))
252287
# pd.read_parquet('./data/lvis_val_categories.parquet')
253-
emb_vectors = np.load('./data/coco_full_CLIP.npy')
288+
#emb_vectors = np.load('./data/coco_full_CLIP.npy', mmap_mode='r')
289+
emb_vectors = load_vecs('./data/coco_full_CLIP_normalized_float32.npy')
290+
#emb_vectors = np.load('./data/coco_full_CLIP_normalized_float32.npy',mmap_mode='r')
254291
root = './data/coco_root/' # using ./data/lvis/ seems to be slower for browser url loading.
255292
# coco_files = pd.read_parquet('./data/coco_full_CLIP_paths.parquet')
256293
# coco_files = coco_files.reset_index().rename(mapper={'index':'dbidx'}, axis=1)
257294
# paths = coco_files['paths'].values
258295

259-
gvec_meta = pd.read_parquet('./data/lvis_multigrained_all_meta.parquet')
260-
gvecs = np.load('./data/lvis_multigrained_all_vecs.npy')
261-
296+
gvec_meta = pd.read_parquet('./data/lvis_multiscale_meta_all.parquet')
297+
gvecs = load_vecs('./data/lvis_multiscale_vecs_all_normalized_float32.npy')#, mmap_mode='r')
262298
# gvec_meta = pd.read_parquet('./data/lvis_finegrained_acc_meta.parquet')
263299
# gvecs = np.load('./data/lvis_finegrained_acc.npy')
264300

@@ -272,7 +308,9 @@ def lvis_full(embedding : XEmbedding) -> EvDataset:
272308

273309

274310
def coco_full(embedding : XEmbedding) -> EvDataset:
275-
emb_vectors = np.load('./data/coco_full_CLIP.npy')
311+
312+
emb_vectors = load_vecs('./data/coco_full_CLIP_normalized_float32.npy')
313+
# emb_vectors = np.load('./data/coco_full_CLIP.npy', mmap_mode='r')
276314
root = './data/coco_root/'
277315
paths = np.load('./data/coco_paths.npy', allow_pickle=True)
278316
box_data = pd.read_parquet('./data/coco_boxes_imsize.parquet')
@@ -306,8 +344,13 @@ def coco_full(embedding : XEmbedding) -> EvDataset:
306344
# qgt = qgt.fillna(0)
307345
# qgt = qgt.rename(mapper=id2name, axis=1)
308346
# qgt = qgt.clip(0,1)
309-
gvec_meta = pd.read_parquet('./data/lvis_finegrained_acc_meta.parquet')
310-
gvecs = np.load('./data/lvis_finegrained_acc.npy')
347+
# nm.to_parquet('./data/lvis_multiscale_meta_all.parquet')
348+
# np.save('./data/lvis_multiscale_vecs_all_normalized_float16.npy',nv.astype('float16'))
349+
#
350+
gvec_meta = pd.read_parquet('./data/lvis_multiscale_meta_all.parquet')
351+
gvecs = load_vecs('./data/lvis_multiscale_vecs_all_normalized_float32.npy')
352+
# gvec_meta = pd.read_parquet('./data/lvis_finegrained_acc_meta.parquet')
353+
# gvecs = np.load('./data/lvis_finegrained_acc.npy',mmap_mode='r')
311354

312355
return make_evdataset(root=root, paths=paths, embedded_dataset=emb_vectors,
313356
query_ground_truth=qgt, box_data=box_data, embedding=embedding, fine_grained_embedding=gvecs,
@@ -327,7 +370,7 @@ def coco_split(coco_full : EvDataset, split : str) -> EvDataset:
327370
def dota1_full(embedding : XEmbedding) -> EvDataset:
328371
root = './data/dota_dataset/'
329372
relpaths= np.load('./data/dota1_paths.npy', allow_pickle=True)
330-
embedded_vecs = np.load('./data/dota_224_pool_clip.npy')
373+
embedded_vecs = load_vecs('./data/dota_224_pool_clip_normalized_float32.npy')#, mmap_mode='r')
331374
box_data = pd.read_parquet('./data/dota1_boxes_imsize.parquet')
332375
# box_data = pd.read_parquet('./data/dota1_boxes.parquet')
333376
# pngs = pd.Categorical(box_data.relpath, ordered=True).dtype.categories.map(lambda x : x.replace('labelTxt-v1.0', 'images/images').replace('.txt', '.png'))
@@ -340,8 +383,10 @@ def dota1_full(embedding : XEmbedding) -> EvDataset:
340383
assert qgt.shape[0] == relpaths.shape[0]
341384
# qgt = qgt.clip(0,1)#gt(0).astype('float')
342385
# embedded_dataset = embedding.from_image(img_vec=embedded_vecs)
343-
fge = np.load('./data/dota_finegrained_acc.npy')
344-
fgmeta = pd.read_parquet('./data/dota_finegrained_acc_meta.parquet')
386+
fgmeta = pd.read_parquet('./data/dota_multiscale_meta_all.parquet')
387+
fge = load_vecs('./data/dota_multiscale_vecs_all_normalized_float32.npy')
388+
# fge = np.load('./data/dota_finegrained_acc.npy',mmap_mode='r')
389+
# fgmeta = pd.read_parquet('./data/dota_finegrained_acc_meta.parquet')
345390

346391
return make_evdataset(root=root, paths=relpaths, embedded_dataset=embedded_vecs,
347392
query_ground_truth=qgt, box_data=box_data, embedding=embedding,fine_grained_embedding=fge,

vsms/vls_benchmark_tools.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -316,8 +316,9 @@ def run_loop6(*, ev :EvDataset, category, qstr, interactive, warm_start, n_batch
316316
Xt = np.concatenate([allpos, vecs[neg]])
317317
yt = np.concatenate([np.ones(len(allpos)), np.zeros(len(neg))])
318318

319-
if np.concatenate(acc_results).sum() > 0:
320-
assert len(pos) > 0
319+
# not really valid. some boxes are area 0. they should be ignored.but they affect qgt
320+
# if np.concatenate(acc_results).sum() > 0:
321+
# assert len(pos) > 0
321322
else:
322323
Xt = vecs[idxbatch]
323324
yt = gt[idxbatch]

0 commit comments

Comments
 (0)