Example #1
0
def learning_lw(net):
    net.cuda()
    net.eval()
    # set up the transform
    normalize = transforms.Normalize(mean=net.meta["mean"], std=net.meta["std"])
    transform = transforms.Compose([transforms.ToTensor(), normalize])

    test_whiten = "retrieval-SfM-30k"
    print(">> {}: Learning whitening...".format(test_whiten))

    # loading db
    db_root = os.path.join(get_data_root(), "train", test_whiten)
    ims_root = os.path.join(db_root, "ims")
    db_fn = os.path.join(db_root, "{}-whiten.pkl".format(test_whiten))
    with open(db_fn, "rb") as f:
        db = pickle.load(f)
    images = [cid2filename(db["cids"][i], ims_root) for i in range(len(db["cids"]))]

    # extract whitening vectors
    print(">> {}: Extracting...".format(args.test_whiten))
    wvecs = extract_vectors(net, images, 1024, transform)

    # learning whitening
    print(">> {}: Learning...".format(args.test_whiten))
    wvecs = wvecs.numpy()
    m, P = whitenlearn(wvecs, db["qidxs"], db["pidxs"])
    Lw = {"m": m, "P": P}
    return Lw
Example #2
0
    def __init__(self,
                 name,
                 imsize=None,
                 transform=None,
                 loader=default_loader,
                 random_size=False):

        # setting up paths
        mode = 'val'
        data_root = get_data_root()
        db_root = os.path.join(data_root, 'train', name)
        ims_root = os.path.join(db_root, 'ims')

        # loading db
        db_fn = os.path.join(db_root, '{}.pkl'.format(name))
        with open(db_fn, 'rb') as f:
            db = pickle.load(f)[mode]

        # initializing tuples dataset
        self.name = name
        self.imsize = imsize
        self.images = [
            cid2filename(db['cids'][i], ims_root)
            for i in range(len(db['cids']))
        ]
        self.clusters = db['cluster']
        self.qpool = db['qidxs']

        self.transform = transform
        self.loader = loader
        self.random_size = random_size
Example #3
0
    def __init__(self, params):
        # prepare config structure for the test dataset
        self.image_size = params.pop("image_size")
        self.dataset = params.pop("dataset")
        self.transforms = initialize_transforms(params.pop("transforms"), params.pop("mean_std"))

        if isinstance(self.dataset, dict):
            # Tsv dataset files
            assert self.dataset.keys() == {"name", "queries", "db", "imgdir"}
            imgdir = self.dataset['imgdir']
            with initialize_file_reader(self.dataset['db'], keys=["identifier"]) as reader:
                data = reader.get()
                self.images = [path_join(imgdir, x) for x in data["identifier"]]
                mapping = {x: i for i, x in enumerate(data["identifier"])}
            with initialize_file_reader(self.dataset['queries'], keys=["query", "bbx", "ok", "junk"]) as reader:
                data = reader.get()
                self.qimages = [path_join(imgdir, x) for x in data["query"]]
                self.bbxs = [tuple(x) if x else None for x in data["bbx"]]
                self.gnd = [{'ok': [mapping[x] for x in ok], 'junk': [mapping[x] for x in junk]} \
                                for ok, junk in zip(data["ok"], data["junk"])]
            self.dataset = self.dataset['name']
        else:
            # Official cirtorch files
            cfg = configdataset(self.dataset, os.path.join(get_data_root(), 'test'))
            self.images = [cfg['im_fname'](cfg,i) for i in range(cfg['n'])]
            self.qimages = [cfg['qim_fname'](cfg,i) for i in range(cfg['nq'])]
            self.bbxs = [tuple(cfg['gnd'][i]['bbx']) if cfg['gnd'][i]['bbx'] else None for i in range(cfg['nq'])]
            self.gnd = cfg['gnd']

        assert not params, params.keys()
Example #4
0
File: test.py Project: wzb1005/mdir
def _compute_whitening(whitening, net, image_size, transform, ms, msp):
    # compute whitening
    start = time.time()

    print('>> {}: Learning whitening...'.format(whitening))

    # loading db
    db_root = os.path.join(get_data_root(), 'train', whitening)
    ims_root = os.path.join(db_root, 'ims')
    db_fn = os.path.join(db_root, '{}-whiten.pkl'.format(whitening))
    with open(db_fn, 'rb') as f:
        db = pickle.load(f)
    images = [
        cid2filename(db['cids'][i], ims_root) for i in range(len(db['cids']))
    ]

    # extract whitening vectors
    print('>> {}: Extracting...'.format(whitening))
    wvecs = extract_vectors(net, images, image_size, transform, ms=ms, msp=msp)

    # learning whitening
    print('>> {}: Learning...'.format(whitening))
    wvecs = wvecs.numpy()
    m, P = whitenlearn(wvecs, db['qidxs'], db['pidxs'])
    Lw = {'m': m, 'P': P}

    elapsed = time.time() - start
    print('>> {}: elapsed time: {}'.format(whitening, htime(elapsed)))

    return Lw, elapsed
Example #5
0
def test(datasets, net):
    print(">> Evaluating network on test datasets...")
    image_size = 1024

    # moving network to gpu and eval mode
    net.cuda()
    net.eval()
    # set up the transform
    normalize = transforms.Normalize(mean=net.meta["mean"],
                                     std=net.meta["std"])
    transform = transforms.Compose([transforms.ToTensor(), normalize])

    # compute whitening
    # Lw = None
    Lw = net.meta["Lw"]["retrieval-SfM-120k"]["ss"]

    # evaluate on test datasets
    # datasets = args.test_datasets.split(",")
    for dataset in datasets:
        start = time.time()

        print(">> {}: Extracting...".format(dataset))

        # prepare config structure for the test dataset
        cfg = configdataset(dataset, os.path.join(get_data_root(), "test"))
        images = [cfg["im_fname"](cfg, i) for i in range(cfg["n"])]
        qimages = [cfg["qim_fname"](cfg, i) for i in range(cfg["nq"])]
        bbxs = [tuple(cfg["gnd"][i]["bbx"]) for i in range(cfg["nq"])]

        # extract database and query vectors
        print(">> {}: database images...".format(dataset))
        vecs = extract_vectors(net, images, image_size, transform)
        print(">> {}: query images...".format(dataset))
        qvecs = extract_vectors(net, qimages, image_size, transform, bbxs)

        print(">> {}: Evaluating...".format(dataset))

        # convert to numpy
        vecs = vecs.numpy()
        qvecs = qvecs.numpy()

        # search, rank, and print
        scores = np.dot(vecs.T, qvecs)
        ranks = np.argsort(-scores, axis=0)
        compute_map_and_print(dataset, ranks, cfg["gnd"])

        if Lw is not None:
            # whiten the vectors
            vecs_lw = whitenapply(vecs, Lw["m"], Lw["P"])
            qvecs_lw = whitenapply(qvecs, Lw["m"], Lw["P"])

            # search, rank, and print
            scores = np.dot(vecs_lw.T, qvecs_lw)
            ranks = np.argsort(-scores, axis=0)
            compute_map_and_print(dataset + " + whiten", ranks, cfg["gnd"])

        print(">> {}: elapsed time: {}".format(dataset,
                                               htime(time.time() - start)))
Example #6
0
    def __init__(
        self,
        imsize=None,
        nnum=5,
        qsize=2000,
        poolsize=20000,
        transform=None,
        loader=default_loader,
        norm=None,
        filename=None,
        random=True,
    ):

        # setting up paths
        data_root = get_data_root()
        name = "retrieval-SfM-120k"
        db_root = os.path.join(data_root, "train", name)
        ims_root = os.path.join(db_root, "ims")

        # loading db
        db_fn = os.path.join(db_root, "{}.pkl".format(name))
        with open(db_fn, "rb") as f:
            db = pickle.load(f)["val"]

        # initializing tuples dataset
        self.imsize = imsize
        self.images = [
            cid2filename(db["cids"][i], ims_root)
            for i in range(len(db["cids"]))
        ]
        self.clusters = db["cluster"]
        self.qpool = db["qidxs"]
        # self.ppool = db['pidxs']

        # size of training subset for an epoch
        self.nnum = nnum
        self.qsize = min(qsize, len(self.qpool))
        self.poolsize = min(poolsize, len(self.images))
        self.qidxs = None
        self.pidxs = None
        self.nidxs = None

        self.poolvecs = None

        self.transform = transform
        self.loader = loader
        self.pool_clusters_centers = None
        self.clustered_pool = []
        self.norm = norm
        self.kmeans_ = None
        if filename is None:
            self.filename = FNAME
        else:
            self.filename = filename

        self.loaded_imgs = []
        self.random = random
Example #7
0
    def __init__(self,
                 name,
                 mode,
                 imsize=None,
                 nnum=5,
                 qsize=2000,
                 poolsize=20000,
                 transform=None,
                 loader=loader_hashed):

        if not (mode == 'train' or mode == 'val'):
            raise RuntimeError(
                "MODE should be either train or val, passed as string")

        # setting up paths
        data_root = get_data_root()
        db_root = os.path.join(data_root, 'train', name)
        ims_root = os.path.join(db_root, 'ims')

        # loading db
        db_fn = os.path.join(db_root, '{}.pkl'.format(name))
        with open(db_fn, 'rb') as f:
            db = pickle.load(f)[mode]

        # setting fullpath for images
        self.images = [
            cid2filename(db['cids'][i], ims_root)
            for i in range(len(db['cids']))
        ]

        # initializing tuples dataset
        self.name = name
        self.mode = mode
        self.imsize = imsize
        self.clusters = db['cluster']
        self.qpool = db['qidxs']
        self.ppool = db['pidxs']

        ## If we want to keep only unique q-p pairs
        ## However, ordering of pairs will change, although that is not important
        # qpidxs = list(set([(self.qidxs[i], self.pidxs[i]) for i in range(len(self.qidxs))]))
        # self.qidxs = [qpidxs[i][0] for i in range(len(qpidxs))]
        # self.pidxs = [qpidxs[i][1] for i in range(len(qpidxs))]

        # size of training subset for an epoch
        self.nnum = nnum
        self.qsize = min(qsize, len(self.qpool))
        self.poolsize = min(poolsize, len(self.images))
        self.qidxs = None
        self.pidxs = None
        self.nidxs = None

        self.transform = transform
        self.loader = loader

        self.print_freq = 10
Example #8
0
def testUkbench(net, eConfig):

    #datasets = eConfig['test-datasets'].split(',')
    #results = []
    #
    #for dataset in datasets:
    #    results.append((dataset, np.random.rand(1)[0]))
    #
    #return results

    print('>> Evaluating network on test datasets...')

    # for testing we use image size of max 1024
    dataset = 'ukbench'
    image_size = 362

    # moving network to gpu and eval mode
    net.cuda()
    net.eval()

    # set up the transform
    normalize = transforms.Normalize(mean=net.meta['mean'],
                                     std=net.meta['std'])
    transform = transforms.Compose([transforms.ToTensor(), normalize])

    dbpath = os.path.join(get_data_root(), 'test', 'ukbench', 'full')
    images = [
        os.path.join(dbpath, 'ukbench{:05d}.jpg'.format(i))
        for i in range(10200)
    ]
    labels = np.arange(10200, dtype=np.int) // 4

    # extract database and query vectors
    print('>> {}: database images...'.format(dataset))
    X = extract_vectors(net, images, image_size, transform)

    print('>> {}: Evaluating...'.format(dataset))

    # rank the similarities
    X = X.numpy()
    scores = np.dot(X.T, X)
    ranks = np.argsort(-scores, axis=1)
    ranks = ranks[:, 0:4]

    # compute the average accuracy for the first 4 entries
    ranksLabel = labels[ranks]
    accs = np.sum(ranksLabel == np.repeat(labels[:, np.newaxis], 4, axis=1),
                  axis=1)
    avgAcc = np.mean(accs)
    print('avgAcc: {:.6f}'.format(avgAcc))

    return [('ukbench', avgAcc)]
Example #9
0
def gen_query_bbx_img():
    datasets = ['oxford5k', 'paris6k', 'roxford5k', 'rparis6k']
    for dataset in datasets:
        cfg = configdataset(dataset, os.path.join(get_data_root(), 'test'))
        qimages = [cfg['qim_fname'](cfg, i) for i in range(cfg['nq'])]
        bbxs = [tuple(cfg['gnd'][i]['bbx']) for i in range(cfg['nq'])]
        width = 5

        for i in range(len(qimages)):
            im = Image.open(qimages[i])
            draw = ImageDraw.Draw(im)
            (x0, y0, x1, y1) = bbxs[i]
            for j in range(width):
                draw.rectangle([x0-j, y0-j, x1+j, y1+j], outline='yellow')
            im.save('_bbx.jpg'.join(qimages[i].split('.jpg')))

        print("{} qurery_bbx generate ok".format(dataset))
def eval_datasets(model,
                  datasets=('oxford5k', 'paris6k', 'roxford5k', 'rparis6k'),
                  ms=False,
                  tta_gem_p=1.0,
                  logger=None):
    model = model.eval()

    data_root = get_data_root()
    scales = [1 / 2**(1 / 2), 1.0, 2**(1 / 2)] if ms else [1.0]
    results = dict()

    for dataset in datasets:

        # prepare config structure for the test dataset
        cfg = configdataset(dataset, os.path.join(data_root, 'test'))
        images = [cfg['im_fname'](cfg, i) for i in range(cfg['n'])]
        qimages = [cfg['qim_fname'](cfg, i) for i in range(cfg['nq'])]
        bbxs = [tuple(cfg['gnd'][i]['bbx']) for i in range(cfg['nq'])]
        tqdm_desc = cfg['dataset']

        db_feats = extract_vectors(model,
                                   images=images,
                                   bbxs=None,
                                   scales=scales,
                                   tta_gem_p=tta_gem_p,
                                   tqdm_desc=tqdm_desc)
        query_feats = extract_vectors(model,
                                      images=qimages,
                                      bbxs=bbxs,
                                      scales=scales,
                                      tta_gem_p=tta_gem_p,
                                      tqdm_desc=tqdm_desc)

        scores = np.dot(db_feats, query_feats.T)
        ranks = np.argsort(-scores, axis=0)
        results[dataset] = compute_map_and_print(dataset,
                                                 ranks,
                                                 cfg['gnd'],
                                                 kappas=[1, 5, 10],
                                                 logger=logger)

    return results
Example #11
0
def load_network(network_path):
    """Load network from a path."""
    print(">> Loading network:\n>>>> '{}'".format(network_path))
    if network_path in PRETRAINED:
        # pretrained networks (downloaded automatically)
        state = load_url(PRETRAINED[network_path], model_dir=os.path.join(get_data_root(), 'networks'))
    else:
        state = torch.load(network_path)
    net = init_network(model=state['meta']['architecture'], pooling=state['meta']['pooling'], whitening=state['meta']['whitening'],
                        mean=state['meta']['mean'], std=state['meta']['std'], pretrained=False)
    net.load_state_dict(state['state_dict'])

    # if whitening is precomputed
    if 'Lw' in state['meta']:
        net.meta['Lw'] = state['meta']['Lw']

    print(">>>> loaded network: ")
    print(net.meta_repr())

    return net
def main():
    args = parser.parse_args()

    # loading network from path
    if args.network_path is not None:

        print(">> Loading network:\n>>>> '{}'".format(args.network_path))
        if args.network_path in PRETRAINED:
            # pretrained networks (downloaded automatically)
            state = load_url(PRETRAINED[args.network_path],
                             model_dir=os.path.join(get_data_root(),
                                                    'networks'))
        else:
            # fine-tuned network from path
            state = torch.load(args.network_path)

        # parsing net params from meta
        # architecture, pooling, mean, std required
        # the rest has default values, in case that is doesnt exist
        net_params = {}
        net_params['architecture'] = state['meta']['architecture']
        net_params['pooling'] = state['meta']['pooling']
        net_params['local_whitening'] = state['meta'].get(
            'local_whitening', False)
        net_params['regional'] = state['meta'].get('regional', False)
        net_params['whitening'] = state['meta'].get('whitening', False)
        net_params['mean'] = state['meta']['mean']
        net_params['std'] = state['meta']['std']
        net_params['pretrained'] = False

        # load network
        net = init_network(net_params)
        net.load_state_dict(state['state_dict'])

        # if whitening is precomputed
        if 'Lw' in state['meta']:
            net.meta['Lw'] = state['meta']['Lw']

        print(">>>> loaded network: ")
        if "epoch" in state:
            print("Model after {} epochs".format(state["epoch"]))
        print(net.meta_repr())

    # loading offtheshelf network
    elif args.network_offtheshelf is not None:

        # parse off-the-shelf parameters
        offtheshelf = args.network_offtheshelf.split('-')
        net_params = {}
        net_params['architecture'] = offtheshelf[0]
        net_params['pooling'] = offtheshelf[1]
        net_params['local_whitening'] = 'lwhiten' in offtheshelf[2:]
        net_params['regional'] = 'reg' in offtheshelf[2:]
        net_params['whitening'] = 'whiten' in offtheshelf[2:]
        net_params['pretrained'] = True

        # load off-the-shelf network
        print(">> Loading off-the-shelf network:\n>>>> '{}'".format(
            args.network_offtheshelf))
        net = init_network(net_params)
        print(">>>> loaded network: ")
        print(net.meta_repr())

    # setting up the multi-scale parameters: test both single scale and multiscale
    ms_singlescale = [1]
    msp_singlescale = 1

    ms_multiscale = list(eval(args.multiscale))
    msp_multiscale = 1
    if len(ms_multiscale
           ) > 1 and net.meta['pooling'] == 'gem' and not net.meta[
               'regional'] and not net.meta['whitening']:
        msp_multiscale = net.pool.p.item()
    print(">> Set-up multiscale:")
    print(">>>> ms: {}".format(ms_multiscale))
    print(">>>> msp: {}".format(msp_multiscale))

    # moving network to gpu and eval mode
    net.cuda()
    net.eval()

    # set up the transform
    normalize = transforms.Normalize(mean=net.meta['mean'],
                                     std=net.meta['std'])
    transform = transforms.Compose([transforms.ToTensor(), normalize])

    # compute whitening
    if args.whitening is not None:
        start = time.time()
        if 'Lw' in net.meta and args.whitening in net.meta['Lw']:
            print('>> {}: Whitening is precomputed, loading it...'.format(
                args.whitening))
            Lw = net.meta['Lw'][args.whitening]
        else:
            # if we evaluate networks from path we should save/load whitening
            # not to compute it every time
            if args.network_path is not None:
                whiten_fn = args.network_path + '_{}_whiten'.format(
                    args.whitening)
                whiten_fn += '.pth'
            else:
                whiten_fn = None

            if whiten_fn is not None and os.path.isfile(whiten_fn):
                print('>> {}: Whitening is precomputed, loading it...'.format(
                    args.whitening))
                Lw = torch.load(whiten_fn)
            else:
                Lw = {}
                for whiten_type, ms, msp in zip(
                    ["ss", "ms"], [ms_singlescale, ms_multiscale],
                    [msp_singlescale, msp_multiscale]):
                    print('>> {0}: Learning whitening {1}...'.format(
                        args.whitening, whiten_type))

                    # loading db
                    db_root = os.path.join(get_data_root(), 'train',
                                           args.whitening)
                    ims_root = os.path.join(db_root, 'ims')
                    db_fn = os.path.join(
                        db_root, '{}-whiten.pkl'.format(args.whitening))
                    with open(db_fn, 'rb') as f:
                        db = pickle.load(f)
                    images = [
                        cid2filename(db['cids'][i], ims_root)
                        for i in range(len(db['cids']))
                    ]

                    # extract whitening vectors
                    print('>> {}: Extracting...'.format(args.whitening))
                    wvecs = extract_vectors(net,
                                            images,
                                            args.image_size,
                                            transform,
                                            ms=ms,
                                            msp=msp)

                    # learning whitening
                    print('>> {}: Learning...'.format(args.whitening))
                    wvecs = wvecs.numpy()
                    m, P = whitenlearn(wvecs, db['qidxs'], db['pidxs'])
                    Lw[whiten_type] = {'m': m, 'P': P}

                    print('>> {}: elapsed time: {}'.format(
                        args.whitening, htime(time.time() - start)))

                # saving whitening if whiten_fn exists
                if whiten_fn is not None:
                    print('>> {}: Saving to {}...'.format(
                        args.whitening, whiten_fn))
                    torch.save(Lw, whiten_fn)
    else:
        Lw = None

    # evaluate on test datasets
    datasets = args.datasets.split(',')
    for dataset in datasets:
        start = time.time()

        for whiten_type, ms, msp in zip(["ss", "ms"],
                                        [ms_singlescale, ms_multiscale],
                                        [msp_singlescale, msp_multiscale]):
            print('>> Extracting feature on {0}, whitening {1}'.format(
                dataset, whiten_type))

            # prepare config structure for the test dataset
            cfg = configdataset(dataset, os.path.join(get_data_root(), 'test'))
            images = [cfg['im_fname'](cfg, i) for i in range(cfg['n'])]
            qimages = [cfg['qim_fname'](cfg, i) for i in range(cfg['nq'])]
            bbxs = [tuple(cfg['gnd'][i]['bbx']) for i in range(cfg['nq'])]

            # extract database and query vectors
            print('>> {}: database images...'.format(dataset))
            vecs = extract_vectors(net,
                                   images,
                                   args.image_size,
                                   transform,
                                   ms=ms,
                                   msp=msp)
            print('>> {}: query images...'.format(dataset))
            qvecs = extract_vectors(net,
                                    qimages,
                                    args.image_size,
                                    transform,
                                    bbxs=bbxs,
                                    ms=ms,
                                    msp=msp)

            print('>> {}: Evaluating...'.format(dataset))

            # convert to numpy
            vecs = vecs.numpy()
            qvecs = qvecs.numpy()

            # search, rank, and print
            scores = np.dot(vecs.T, qvecs)
            ranks = np.argsort(-scores, axis=0)
            compute_map_and_print(dataset, ranks, cfg['gnd'])

            if Lw is not None:
                # whiten the vectors
                vecs_lw = whitenapply(vecs, Lw[whiten_type]['m'],
                                      Lw[whiten_type]['P'])
                qvecs_lw = whitenapply(qvecs, Lw[whiten_type]['m'],
                                       Lw[whiten_type]['P'])

                # search, rank, and print
                scores = np.dot(vecs_lw.T, qvecs_lw)
                ranks = np.argsort(-scores, axis=0)
                compute_map_and_print(
                    dataset + ' + whiten {}'.format(whiten_type), ranks,
                    cfg['gnd'])

            print('>> {}: elapsed time: {}'.format(dataset,
                                                   htime(time.time() - start)))
Example #13
0
def init_network(params):

    # parse params with default values
    architecture = params.get('architecture', 'resnet101')
    local_whitening = params.get('local_whitening', False)
    pooling = params.get('pooling', 'gem')
    regional = params.get('regional', False)
    whitening = params.get('whitening', False)
    mean = params.get('mean', [0.485, 0.456, 0.406])
    std = params.get('std', [0.229, 0.224, 0.225])
    pretrained = params.get('pretrained', True)

    # get output dimensionality size
    dim = OUTPUT_DIM[architecture]

    # loading network from torchvision
    if architecture not in FEATURES:
        if architecture == 'w_vgg16':
            net_in = vgg16(invariant='W', pretrained=pretrained)
        elif architecture == 'w_resnet101':
            net_in = resnet101(invariant='W', pretrained=pretrained)
        else:
            # initialize with network pretrained on imagenet in pytorch
            net_in = getattr(torchvision.models, architecture)(pretrained=pretrained)
    else:
        # initialize with random weights, later on we will fill features with custom pretrained network
        net_in = getattr(torchvision.models, architecture)(pretrained=False)

    # initialize features
    # take only convolutions for features,
    # always ends with ReLU to make last activations non-negative
    if architecture.startswith('alexnet'):
        features = list(net_in.features.children())[:-1]
    elif architecture.startswith('vgg'):
        features = list(net_in.features.children())[:-1]
    elif architecture == 'w_vgg16':
        features = [net_in.ciconv] + list(net_in.features.children())[:-1]
    elif architecture.startswith('resnet') or architecture == 'w_resnet101':
        features = list(net_in.children())[:-2]
    elif architecture.startswith('densenet'):
        features = list(net_in.features.children())
        features.append(nn.ReLU(inplace=True))
    elif architecture.startswith('squeezenet'):
        features = list(net_in.features.children())
    else:
        raise ValueError('Unsupported or unknown architecture: {}!'.format(architecture))

    # initialize local whitening
    if local_whitening:
        lwhiten = nn.Linear(dim, dim, bias=True)
        # TODO: lwhiten with possible dimensionality reduce

        if pretrained:
            lw = architecture
            if lw in L_WHITENING:
                print(">> {}: for '{}' custom computed local whitening '{}' is used"
                    .format(os.path.basename(__file__), lw, os.path.basename(L_WHITENING[lw])))
                whiten_dir = os.path.join(get_data_root(), 'whiten')
                lwhiten.load_state_dict(model_zoo.load_url(L_WHITENING[lw], model_dir=whiten_dir))
            else:
                print(">> {}: for '{}' there is no local whitening computed, random weights are used"
                    .format(os.path.basename(__file__), lw))

    else:
        lwhiten = None

    # initialize pooling
    if pooling == 'gemmp':
        pool = POOLING[pooling](mp=dim)
    else:
        pool = POOLING[pooling]()

    # initialize regional pooling
    if regional:
        rpool = pool
        rwhiten = nn.Linear(dim, dim, bias=True)
        # TODO: rwhiten with possible dimensionality reduce

        if pretrained:
            rw = '{}-{}-r'.format(architecture, pooling)
            if rw in R_WHITENING:
                print(">> {}: for '{}' custom computed regional whitening '{}' is used"
                    .format(os.path.basename(__file__), rw, os.path.basename(R_WHITENING[rw])))
                whiten_dir = os.path.join(get_data_root(), 'whiten')
                rwhiten.load_state_dict(model_zoo.load_url(R_WHITENING[rw], model_dir=whiten_dir))
            else:
                print(">> {}: for '{}' there is no regional whitening computed, random weights are used"
                    .format(os.path.basename(__file__), rw))

        pool = Rpool(rpool, rwhiten)

    # initialize whitening
    if whitening:
        whiten = nn.Linear(dim, dim, bias=True)
        # TODO: whiten with possible dimensionality reduce

        if pretrained:
            w = architecture
            if local_whitening:
                w += '-lw'
            w += '-' + pooling
            if regional:
                w += '-r'
            if w in WHITENING:
                print(">> {}: for '{}' custom computed whitening '{}' is used"
                    .format(os.path.basename(__file__), w, os.path.basename(WHITENING[w])))
                whiten_dir = os.path.join(get_data_root(), 'whiten')
                whiten.load_state_dict(model_zoo.load_url(WHITENING[w], model_dir=whiten_dir))
            else:
                print(">> {}: for '{}' there is no whitening computed, random weights are used"
                    .format(os.path.basename(__file__), w))
    else:
        whiten = None

    # create meta information to be stored in the network
    meta = {
        'architecture' : architecture,
        'local_whitening' : local_whitening,
        'pooling' : pooling,
        'regional' : regional,
        'whitening' : whitening,
        'mean' : mean,
        'std' : std,
        'outputdim' : dim,
    }

    # create a generic image retrieval network
    net = ImageRetrievalNet(features, lwhiten, pool, whiten, meta)

    # initialize features with custom pretrained network if needed
    if pretrained and architecture in FEATURES:
        print(">> {}: for '{}' custom pretrained features '{}' are used"
            .format(os.path.basename(__file__), architecture, os.path.basename(FEATURES[architecture])))
        model_dir = os.path.join(get_data_root(), 'networks')
        net.features.load_state_dict(model_zoo.load_url(FEATURES[architecture], model_dir=model_dir))

    return net
Example #14
0
def test(datasets, net, wandb_enabled=False, epoch=-1):
    
    global global_step

    print('>> Evaluating network on test datasets...')

    # for testing we use image size of max 1024
    image_size = 1024

    # moving network to gpu and eval mode
    net.cuda()
    net.eval()
    # set up the transform
    normalize = transforms.Normalize(
        mean=net.meta['mean'],
        std=net.meta['std']
    )
    transform = transforms.Compose([
        transforms.ToTensor(),
        normalize
    ])

    # compute whitening
    if args.test_whiten:
        start = time.time()

        print('>> {}: Learning whitening...'.format(args.test_whiten))

        # loading db
        db_root = os.path.join(get_data_root(), 'train', args.test_whiten)
        ims_root = os.path.join(db_root, 'ims')
        db_fn = os.path.join(db_root, '{}-whiten.pkl'.format(args.test_whiten))
        with open(db_fn, 'rb') as f:
            db = pickle.load(f)
        images = [cid2filename(db['cids'][i], ims_root) for i in range(len(db['cids']))]

        # extract whitening vectors
        print('>> {}: Extracting...'.format(args.test_whiten))
        wvecs = extract_vectors(net, images, image_size, transform)  # implemented with torch.no_grad
        
        # learning whitening 
        print('>> {}: Learning...'.format(args.test_whiten))
        wvecs = wvecs.numpy()
        m, P = whitenlearn(wvecs, db['qidxs'], db['pidxs'])
        Lw = {'m': m, 'P': P}

        print('>> {}: elapsed time: {}'.format(args.test_whiten, htime(time.time()-start)))
    else:
        Lw = None

    # evaluate on test datasets
    datasets = args.test_datasets.split(',')
    for dataset in datasets: 
        start = time.time()

        print('>> {}: Extracting...'.format(dataset))

        # prepare config structure for the test dataset
        cfg = configdataset(dataset, os.path.join(get_data_root(), 'test'))
        images = [cfg['im_fname'](cfg,i) for i in range(cfg['n'])]
        qimages = [cfg['qim_fname'](cfg,i) for i in range(cfg['nq'])]
        bbxs = [tuple(cfg['gnd'][i]['bbx']) for i in range(cfg['nq'])]
        
        # extract database and query vectors
        print('>> {}: database images...'.format(dataset))
        vecs = extract_vectors(net, images, image_size, transform)  # implemented with torch.no_grad
        print('>> {}: query images...'.format(dataset))
        qvecs = extract_vectors(net, qimages, image_size, transform, bbxs)  # implemented with torch.no_grad
        
        print('>> {}: Evaluating...'.format(dataset))

        # convert to numpy
        vecs = vecs.numpy()
        qvecs = qvecs.numpy()

        # search, rank, and print
        scores = np.dot(vecs.T, qvecs)
        ranks = np.argsort(-scores, axis=0)
        compute_map_and_print(dataset, ranks, cfg['gnd'], wandb_enabled=wandb_enabled, epoch=epoch, global_step=global_step)
    
        if Lw is not None:
            # whiten the vectors
            vecs_lw  = whitenapply(vecs, Lw['m'], Lw['P'])
            qvecs_lw = whitenapply(qvecs, Lw['m'], Lw['P'])

            # search, rank, and print
            scores = np.dot(vecs_lw.T, qvecs_lw)
            ranks = np.argsort(-scores, axis=0)
            compute_map_and_print(dataset + ' + whiten', ranks, cfg['gnd'], wandb_enabled=wandb_enabled, epoch=epoch, global_step=global_step)
        
        print('>> {}: elapsed time: {}'.format(dataset, htime(time.time()-start)))
Example #15
0
def main():
    global args, min_loss, global_step
    args = parser.parse_args()
    
    if args.wandb:
        # initialize wandb
        wandb.init(
            project='cnnimageretrieval-pytorch', name=args.directory,
            entity='ronaldseoh')
        
        # save args provided for this experiment to wandb
        wandb.config.update(args)

    # manually check if there are unknown test datasets
    for dataset in args.test_datasets.split(','):
        if dataset not in test_datasets_names:
            raise ValueError('Unsupported or unknown test dataset: {}!'.format(dataset))

    # check if test dataset are downloaded
    # and download if they are not
    download_train(get_data_root())
    download_test(get_data_root())

    # create export dir if it doesnt exist
    directory = "{}".format(args.training_dataset)
    directory += "_{}".format(args.arch)
    directory += "_{}".format(args.pool)
    if args.local_whitening:
        directory += "_lwhiten"
    if args.regional:
        directory += "_r"
    if args.whitening:
        directory += "_whiten"
    if not args.pretrained:
        directory += "_notpretrained"
    directory += "_{}_m{:.2f}".format(args.loss, args.loss_margin)
    directory += "_{}_lr{:.1e}_wd{:.1e}".format(args.optimizer, args.lr, args.weight_decay)
    directory += "_nnum{}_qsize{}_psize{}".format(args.neg_num, args.query_size, args.pool_size)
    directory += "_bsize{}_uevery{}_imsize{}".format(args.batch_size, args.update_every, args.image_size)

    args.directory = os.path.join(args.directory, directory)
    print(">> Creating directory if it does not exist:\n>> '{}'".format(args.directory))
    if not os.path.exists(args.directory):
        os.makedirs(args.directory)

    # set cuda visible device
    os.environ['CUDA_VISIBLE_DEVICES'] = args.gpu_id
    
    # set random seeds
    torch.manual_seed(args.seed)
    torch.cuda.manual_seed_all(args.seed)
    np.random.seed(args.seed)

    # initialize model
    if args.pretrained:
        print(">> Using pre-trained model '{}'".format(args.arch))
    else:
        print(">> Using model from scratch (random weights) '{}'".format(args.arch))
    model_params = {}
    model_params['architecture'] = args.arch
    model_params['pooling'] = args.pool
    model_params['local_whitening'] = args.local_whitening
    model_params['regional'] = args.regional
    model_params['whitening'] = args.whitening
    # model_params['mean'] = ...  # will use default
    # model_params['std'] = ...  # will use default
    model_params['pretrained'] = args.pretrained
    model = init_network(model_params)

    # move network to gpu
    model.cuda()

    # define loss function (criterion) and optimizer
    if args.loss == 'contrastive':
        criterion = ContrastiveLoss(margin=args.loss_margin).cuda()
    elif args.loss == 'triplet':
        criterion = TripletLoss(margin=args.loss_margin).cuda()
    else:
        raise(RuntimeError("Loss {} not available!".format(args.loss)))

    # parameters split into features, pool, whitening 
    # IMPORTANT: no weight decay for pooling parameter p in GeM or regional-GeM
    parameters = []
    # add feature parameters
    parameters.append({'params': model.features.parameters()})
    # add local whitening if exists
    if model.lwhiten is not None:
        parameters.append({'params': model.lwhiten.parameters()})
    # add pooling parameters (or regional whitening which is part of the pooling layer!)
    if not args.regional:
        # global, only pooling parameter p weight decay should be 0
        if args.pool == 'gem':
            parameters.append({'params': model.pool.parameters(), 'lr': args.lr*10, 'weight_decay': 0})
        elif args.pool == 'gemmp':
            parameters.append({'params': model.pool.parameters(), 'lr': args.lr*100, 'weight_decay': 0})
    else:
        # regional, pooling parameter p weight decay should be 0, 
        # and we want to add regional whitening if it is there
        if args.pool == 'gem':
            parameters.append({'params': model.pool.rpool.parameters(), 'lr': args.lr*10, 'weight_decay': 0})
        elif args.pool == 'gemmp':
            parameters.append({'params': model.pool.rpool.parameters(), 'lr': args.lr*100, 'weight_decay': 0})
        if model.pool.whiten is not None:
            parameters.append({'params': model.pool.whiten.parameters()})
    # add final whitening if exists
    if model.whiten is not None:
        parameters.append({'params': model.whiten.parameters()})

    # define optimizer
    if args.optimizer == 'sgd':
        optimizer = torch.optim.SGD(parameters, args.lr, momentum=args.momentum, weight_decay=args.weight_decay)
    elif args.optimizer == 'adam':
        optimizer = torch.optim.Adam(parameters, args.lr, weight_decay=args.weight_decay)

    # define learning rate decay schedule
    # TODO: maybe pass as argument in future implementation?
    exp_decay = math.exp(-0.01)
    scheduler = torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma=exp_decay)

    # optionally resume from a checkpoint
    start_epoch = 0
    if args.resume:
        args.resume = os.path.join(args.directory, args.resume)
        if os.path.isfile(args.resume):
            # load checkpoint weights and update model and optimizer
            print(">> Loading checkpoint:\n>> '{}'".format(args.resume))
            checkpoint = torch.load(args.resume)
            start_epoch = checkpoint['epoch']
            min_loss = checkpoint['min_loss']
            model.load_state_dict(checkpoint['state_dict'])
            optimizer.load_state_dict(checkpoint['optimizer'])
            print(">>>> loaded checkpoint:\n>>>> '{}' (epoch {})"
                  .format(args.resume, checkpoint['epoch']))
            # important not to forget scheduler updating
            scheduler = torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma=exp_decay, last_epoch=checkpoint['epoch']-1)
        else:
            print(">> No checkpoint found at '{}'".format(args.resume))

    # Data loading code
    normalize = transforms.Normalize(mean=model.meta['mean'], std=model.meta['std'])
    transform = transforms.Compose([
        transforms.ToTensor(),
        normalize,
    ])
    
    if args.query_size == -1:
        train_query_size = float('Inf')
    else:
        train_query_size = args.query_size
        
    if args.pool_size == -1:
        train_pool_size = float('Inf')
    else:
        train_pool_size = args.pool_size
    
    train_dataset = TuplesDataset(
        name=args.training_dataset,
        mode='train',
        imsize=args.image_size,
        nnum=args.neg_num,
        qsize=train_query_size,
        poolsize=train_pool_size,
        transform=transform,
        store_nidxs_others_up_to=args.store_nidxs_others_up_to,
        store_nidxs_others_order_by=args.store_nidxs_others_order_by,
        totally_random_nidxs=args.totally_random_nidxs,
        totally_random_nidxs_others=args.totally_random_nidxs_others,
        dense_refresh_batch_and_nearby=args.dense_refresh_batch_and_nearby,
        dense_refresh_batch_multi_hop=args.dense_refresh_batch_multi_hop,
        dense_refresh_batch_random=args.dense_refresh_batch_random,
    )

    train_loader = torch.utils.data.DataLoader(
        train_dataset, batch_size=args.batch_size, shuffle=True,
        num_workers=0, pin_memory=True, sampler=None,
        drop_last=True, collate_fn=collate_tuples
    )
    if args.val:
        val_dataset = TuplesDataset(
            name=args.training_dataset,
            mode='val',
            imsize=args.image_size,
            nnum=args.neg_num,
            qsize=float('Inf'),
            poolsize=float('Inf'),
            transform=transform
        )
        val_loader = torch.utils.data.DataLoader(
            val_dataset, batch_size=args.batch_size, shuffle=False,
            num_workers=args.workers, pin_memory=True,
            drop_last=True, collate_fn=collate_tuples
        )

    if args.wandb:
        # Start watching 'model' from wandb
        wandb.watch(model)

    # evaluate the network before starting
    # this might not be necessary?
    test(args.test_datasets, model, wandb_enabled=args.wandb, epoch=-1)
    
    indexes_to_refresh = []

    for epoch in range(start_epoch, args.epochs):

        # set manual seeds per epoch
        random.seed(args.seed + epoch)
        np.random.seed(args.seed + epoch)
        torch.manual_seed(args.seed + epoch)
        torch.cuda.manual_seed_all(args.seed + epoch)

        # train for one epoch on train set
        loss, indexes_to_refresh = train(train_loader, model, criterion, optimizer, epoch, indexes_to_refresh)
        
        if args.wandb:
            wandb.log({"loss_avg": loss, "epoch": epoch, "global_step": global_step}) ## This is average loss
        
        # adjust learning rate for each epoch
        scheduler.step()

        # # debug printing to check if everything ok
        # lr_feat = optimizer.param_groups[0]['lr']
        # lr_pool = optimizer.param_groups[1]['lr']
        # print('>> Features lr: {:.2e}; Pooling lr: {:.2e}'.format(lr_feat, lr_pool))

        # evaluate on validation set
        if args.val:
            with torch.no_grad():
                loss = validate(val_loader, model, criterion, epoch)
                
                if args.wandb:
                    wandb.log({"loss_validation": loss, "epoch": epoch, "global_step": global_step})

        # evaluate on test datasets every test_freq epochs
        if (epoch + 1) % args.test_freq == 0:
            with torch.no_grad():
                test(args.test_datasets, model, wandb_enabled=args.wandb, epoch=epoch)

        # remember best loss and save checkpoint
        is_best = loss < min_loss
        min_loss = min(loss, min_loss)
        
        if is_best:
            print("Epoch", str(epoch + 1), "lower loss:", min_loss)

        save_checkpoint({
            'epoch': epoch + 1,
            'meta': model.meta,
            'state_dict': model.state_dict(),
            'min_loss': min_loss,
            'optimizer' : optimizer.state_dict(),
        }, is_best, args.directory)
        
    # calculate avg_neg_distance and avg_pos_distance for one last time
    print("Training finished. Calculating the final avg_{neg,pos}_distance...")

    avg_neg_distance, _ = train_loader.dataset.create_epoch_tuples(
        model,
        batch_members=[],
        refresh_query_selection=False,
        refresh_query_vectors=False,
        refresh_negative_pool=False,
        refresh_negative_pool_vectors=False,
        refresh_nidxs=False,
        refresh_nidxs_vectors=False)
        
    if args.wandb:
        wandb.log({"avg_neg_distance": avg_neg_distance, 'epoch': epoch, "global_step": global_step})

    if args.calculate_positive_distance:
        avg_pos_distance = train_loader.dataset.calculate_average_positive_distance()
        
        if args.wandb:
            wandb.log({"avg_pos_distance": avg_pos_distance, 'epoch': epoch, "global_step": global_step})
Example #16
0
def main():
    args = parser.parse_args()

    # check if there are unknown datasets
    for dataset in args.datasets.split(','):
        if dataset not in datasets_names:
            raise ValueError(
                'Unsupported or unknown dataset: {}!'.format(dataset))

    # check if test dataset are downloaded
    # and download if they are not
    #download_train(get_data_root())
    download_test(get_data_root())

    # setting up the visible GPU
    os.environ['CUDA_VISIBLE_DEVICES'] = args.gpu_id

    # loading network from path
    if args.network_path is not None:

        print(">> Loading network:\n>>>> '{}'".format(args.network_path))
        if args.network_path in PRETRAINED:
            # pretrained networks (downloaded automatically)
            state = load_url(PRETRAINED[args.network_path],
                             model_dir=os.path.join(get_data_root(),
                                                    'networks'))
        else:
            # fine-tuned network from path
            state = torch.load(args.network_path)

        # parsing net params from meta
        # architecture, pooling, mean, std required
        # the rest has default values, in case that is doesnt exist
        net_params = {}
        net_params['architecture'] = state['meta']['architecture']
        net_params['pooling'] = state['meta']['pooling']
        net_params['local_whitening'] = state['meta'].get(
            'local_whitening', False)
        net_params['regional'] = state['meta'].get('regional', False)
        net_params['whitening'] = state['meta'].get('whitening', False)
        net_params['mean'] = state['meta']['mean']
        net_params['std'] = state['meta']['std']
        net_params['pretrained'] = False

        # load network
        net = init_network(net_params)
        net.load_state_dict(state['state_dict'])

        # if whitening is precomputed
        if 'Lw' in state['meta']:
            net.meta['Lw'] = state['meta']['Lw']

        print(">>>> loaded network: ")
        print(net.meta_repr())

    # loading offtheshelf network
    elif args.network_offtheshelf is not None:

        # parse off-the-shelf parameters
        offtheshelf = args.network_offtheshelf.split('-')
        net_params = {}
        net_params['architecture'] = offtheshelf[0]
        net_params['pooling'] = offtheshelf[1]
        net_params['local_whitening'] = 'lwhiten' in offtheshelf[2:]
        net_params['regional'] = 'reg' in offtheshelf[2:]
        net_params['whitening'] = 'whiten' in offtheshelf[2:]
        net_params['pretrained'] = True

        # load off-the-shelf network
        print(">> Loading off-the-shelf network:\n>>>> '{}'".format(
            args.network_offtheshelf))
        net = init_network(net_params)
        print(">>>> loaded network: ")
        print(net.meta_repr())

    # setting up the multi-scale parameters
    ms = list(eval(args.multiscale))
    if len(ms) > 1 and net.meta['pooling'] == 'gem' and not net.meta[
            'regional'] and not net.meta['whitening']:
        msp = net.pool.p.item()
        print(">> Set-up multiscale:")
        print(">>>> ms: {}".format(ms))
        print(">>>> msp: {}".format(msp))
    else:
        msp = 1

    # moving network to gpu and eval mode
    net.cuda()
    net.eval()

    # set up the transform
    normalize = transforms.Normalize(mean=net.meta['mean'],
                                     std=net.meta['std'])
    transform = transforms.Compose([transforms.ToTensor(), normalize])

    # compute whitening
    if args.whitening is not None:
        start = time.time()

        if 'Lw' in net.meta and args.whitening in net.meta['Lw']:

            print('>> {}: Whitening is precomputed, loading it...'.format(
                args.whitening))

            if len(ms) > 1:
                Lw = net.meta['Lw'][args.whitening]['ms']
            else:
                Lw = net.meta['Lw'][args.whitening]['ss']

        else:

            # if we evaluate networks from path we should save/load whitening
            # not to compute it every time
            if args.network_path is not None:
                whiten_fn = args.network_path + '_{}_whiten'.format(
                    args.whitening)
                if len(ms) > 1:
                    whiten_fn += '_ms'
                whiten_fn += '.pth'
            else:
                whiten_fn = None

            if whiten_fn is not None and os.path.isfile(whiten_fn):
                print('>> {}: Whitening is precomputed, loading it...'.format(
                    args.whitening))
                Lw = torch.load(whiten_fn)

            else:
                print('>> {}: Learning whitening...'.format(args.whitening))

                # loading db
                db_root = os.path.join(get_data_root(), 'train',
                                       args.whitening)
                ims_root = os.path.join(db_root, 'ims')
                db_fn = os.path.join(db_root,
                                     '{}-whiten.pkl'.format(args.whitening))
                with open(db_fn, 'rb') as f:
                    db = pickle.load(f)
                images = [
                    cid2filename(db['cids'][i], ims_root)
                    for i in range(len(db['cids']))
                ]

                # extract whitening vectors
                print('>> {}: Extracting...'.format(args.whitening))
                wvecs = extract_vectors(net,
                                        images,
                                        args.image_size,
                                        transform,
                                        ms=ms,
                                        msp=msp)

                # learning whitening
                print('>> {}: Learning...'.format(args.whitening))
                wvecs = wvecs.numpy()
                m, P = whitenlearn(wvecs, db['qidxs'], db['pidxs'])
                Lw = {'m': m, 'P': P}

                # saving whitening if whiten_fn exists
                if whiten_fn is not None:
                    print('>> {}: Saving to {}...'.format(
                        args.whitening, whiten_fn))
                    torch.save(Lw, whiten_fn)

        print('>> {}: elapsed time: {}'.format(args.whitening,
                                               htime(time.time() - start)))

    else:
        Lw = None

    # evaluate on test datasets
    datasets = args.datasets.split(',')
    for dataset in datasets:
        start = time.time()
        """
        print('>> {}: Extracting...'.format(dataset))

        # prepare config structure for the test dataset
        cfg = configdataset(dataset, os.path.join(get_data_root(), 'test'))
        images = [cfg['im_fname'](cfg,i) for i in range(cfg['n'])]
        qimages = [cfg['qim_fname'](cfg,i) for i in range(cfg['nq'])]
        try:
            bbxs = [tuple(cfg['gnd'][i]['bbx']) for i in range(cfg['nq'])]
        except:
            bbxs = None  # for holidaysmanrot and copydays

        # extract database and query vectors
        print('>> {}: database images...'.format(dataset))
        vecs = extract_vectors(net, images, args.image_size, transform, ms=ms, msp=msp)
        print('>> {}: query images...'.format(dataset))
        qvecs = extract_vectors(net, qimages, args.image_size, transform, bbxs=bbxs, ms=ms, msp=msp)
        
        print('>> {}: Evaluating...'.format(dataset))

        # convert to numpy
        vecs = vecs.numpy()
        qvecs = qvecs.numpy()

        print (vecs.shape)
        print (qvecs.shape)

        # search, rank, and print
        scores = np.dot(vecs.T, qvecs)
        print (scores.shape)

        # to save scores (single query)
        # oxford
        #f = 'oxf_single.npy'
        # paris
        #f = 'par_single.npy'
        # roxford
        #f = 'roxf_single.npy'
        # rparis
        f = 'rpar_single.npy'

        ranks = np.argsort(-scores, axis=0)
        compute_map_and_print(dataset, ranks, cfg['gnd'])
    
        if Lw is not None:
            # whiten the vectors
            vecs_lw  = whitenapply(vecs, Lw['m'], Lw['P'])
            qvecs_lw = whitenapply(qvecs, Lw['m'], Lw['P'])

            # search, rank, and print
            scores = np.dot(vecs_lw.T, qvecs_lw)
            # save
            np.save(f, scores)

            ranks = np.argsort(-scores, axis=0)
            compute_map_and_print(dataset + ' + whiten', ranks, cfg['gnd'])
        """

        ############################################################
        # Test
        # prepare config structure for the test dataset
        cfg = configdataset(dataset, os.path.join(get_data_root(), 'test'))
        images = [cfg['im_fname'](cfg, i) for i in range(cfg['n'])]
        qimages = [cfg['qim_fname'](cfg, i) for i in range(cfg['nq'])]

        print(qimages)

        # to load scores
        # oxford
        #f = 'oxf_single.npy'
        #f = 'oxf_mq_avg.npy'
        #f = 'oxf_mq_max.npy'
        #f = 'oxf_sc_imf.npy'

        # paris
        #f = 'par_single.npy'
        #f = 'par_mq_avg.npy'
        #f = 'par_mq_max.npy'
        f = 'par_sc_imf.npy'

        # roxford
        #f = 'roxf_single.npy'
        #f = 'roxf_mq_avg.npy'
        #f = 'roxf_mq_max.npy'
        #f = 'roxf_sc_imf.npy'

        # rparis
        #f = 'rpar_single.npy'
        #f = 'rpar_mq_avg.npy'
        #f = 'rpar_mq_max.npy'
        #f = 'rpar_sc_imf.npy'

        # load
        scores = np.load(f)
        ranks = np.argsort(-scores, axis=0)
        compute_map_and_print(dataset + ' + whiten', ranks, cfg['gnd'])

        print('>> {}: elapsed time: {}'.format(dataset,
                                               htime(time.time() - start)))
Example #17
0
def main():
    args = parser.parse_args()

    # check if there are unknown datasets
    for dataset in args.datasets.split(','):
        if dataset not in datasets_names:
            raise ValueError(
                'Unsupported or unknown dataset: {}!'.format(dataset))

    # check if test dataset are downloaded
    # and download if they are not
    download_train(get_data_root())
    download_test(get_data_root())

    # setting up the visible GPU
    os.environ['CUDA_VISIBLE_DEVICES'] = args.gpu_id

    # loading network
    # pretrained networks (downloaded automatically)
    print(">> Loading network:\n>>>> '{}'".format(args.network))
    state = load_url(PRETRAINED[args.network],
                     model_dir=os.path.join(get_data_root(), 'networks'))
    # parsing net params from meta
    # architecture, pooling, mean, std required
    # the rest has default values, in case that is doesnt exist
    net_params = {}
    net_params['architecture'] = state['meta']['architecture']
    net_params['pooling'] = state['meta']['pooling']
    net_params['local_whitening'] = state['meta'].get('local_whitening', False)
    net_params['regional'] = state['meta'].get('regional', False)
    net_params['whitening'] = state['meta'].get('whitening', False)
    net_params['mean'] = state['meta']['mean']
    net_params['std'] = state['meta']['std']
    net_params['pretrained'] = False
    # network initialization
    net = init_network(net_params)
    net.load_state_dict(state['state_dict'])

    print(">>>> loaded network: ")
    print(net.meta_repr())

    # setting up the multi-scale parameters
    ms = list(eval(args.multiscale))
    print(">>>> Evaluating scales: {}".format(ms))

    # moving network to gpu and eval mode
    net.cuda()
    net.eval()

    # set up the transform
    normalize = transforms.Normalize(mean=net.meta['mean'],
                                     std=net.meta['std'])
    transform = transforms.Compose([transforms.ToTensor(), normalize])

    # evaluate on test datasets
    datasets = args.datasets.split(',')
    for dataset in datasets:
        start = time.time()

        print('>> {}: Extracting...'.format(dataset))

        # prepare config structure for the test dataset
        cfg = configdataset(dataset, os.path.join(get_data_root(), 'test'))
        images = [cfg['im_fname'](cfg, i) for i in range(cfg['n'])]
        qimages = [cfg['qim_fname'](cfg, i) for i in range(cfg['nq'])]
        try:
            bbxs = [tuple(cfg['gnd'][i]['bbx']) for i in range(cfg['nq'])]
        except:
            bbxs = None  # for holidaysmanrot and copydays

        # extract database and query vectors
        print('>> {}: database images...'.format(dataset))
        vecs = extract_vectors(net, images, args.image_size, transform, ms=ms)
        print('>> {}: query images...'.format(dataset))
        qvecs = extract_vectors(net,
                                qimages,
                                args.image_size,
                                transform,
                                bbxs=bbxs,
                                ms=ms)

        print('>> {}: Evaluating...'.format(dataset))

        # convert to numpy
        vecs = vecs.numpy()
        qvecs = qvecs.numpy()

        # search, rank, and print
        scores = np.dot(vecs.T, qvecs)
        ranks = np.argsort(-scores, axis=0)

        top_k = 100
        ranks_fnames_qs = []
        for q_id in range(len(cfg["qimlist"])):
            ranks_q = list(ranks[:top_k, q_id])
            ranks_fname_per_q = []
            for img_id in ranks_q:
                ranks_fname_per_q.append(cfg["imlist"][img_id])
            ranks_fnames_qs.append(ranks_fname_per_q)

        compute_map_and_print(dataset, ranks, cfg['gnd'])
        compute_map_and_print_top_k(dataset, ranks_fnames_qs, cfg['gnd'],
                                    cfg["imlist"])

        sys.exit()
        with open(dataset + "_gl18_tl_resnet101_gem_w_m.pkl", "wb") as f:
            data = {"ranks": ranks, "db_images": images, "q_images": qimages}
            pickle.dump(data, f)

        print('>> {}: elapsed time: {}'.format(dataset,
                                               htime(time.time() - start)))
Example #18
0
def testHolidays(net, eConfig, dataset, Lw):

    print('>> Evaluating network on test dataset: {}'.format(dataset))

    # for testing we use image size of max 1024
    image_size = 1024

    ms = [1]
    msp = 1
    if (eConfig['multiscale']):
        ms = [1, 1. / math.sqrt(2), 1. / 2]
        if net.meta['pooling'] == 'gem' and net.whiten is None:
            msp = net.pool.p.data.tolist()[0]

    # moving network to gpu and eval mode
    net.cuda()
    net.eval()

    # set up the transform
    normalize = transforms.Normalize(mean=net.meta['mean'],
                                     std=net.meta['std'])
    transform = transforms.Compose([transforms.ToTensor(), normalize])

    # read the images and generate paths and queries-positive indexes
    dbpath = os.path.join(get_data_root(), 'test', 'holidays')
    ext = 'jpg' if dataset == 'holidays' else 'rjpg'
    images = sorted(os.listdir(os.path.join(dbpath, ext)))
    with open(os.path.join(dbpath, 'straight_gnd_holidays.pkl'), 'rb') as f:
        queries = pickle.load(f)
        positives = pickle.load(f)

    qidx = []
    pidx = []
    for i in range(len(queries)):

        qidx.append(images.index(queries[i]))

        aux = []
        for j in range(len(positives[i])):
            aux.append(images.index(positives[i][j]))
        pidx.append(aux)

    # extract database and query vectors
    print('>> {}: database images...'.format(dataset))
    X = extract_vectors(net, [os.path.join(dbpath, ext, n) for n in images],
                        image_size,
                        transform,
                        ms=ms,
                        msp=msp)

    print('>> {}: Evaluating...'.format(dataset))

    # rank the similarities
    X = X.numpy()

    if (Lw is not None):
        X = whitenapply(X, Lw['m'], Lw['P'])

    scores = np.dot(X.T, X)
    ranks = np.argsort(-scores, axis=1)
    ranks = ranks[qidx, 1::]

    APs = []
    for i, r in enumerate(ranks):
        trueRanks = np.isin(r, pidx[i])
        trueRanks = np.where(trueRanks == True)[0]
        APs.append(compute_ap(trueRanks, len(pidx[i])))

    mAP = np.mean(APs)
    print(">> {}: mAP {:.2f}".format(dataset, mAP * 100))

    # return the average mAP
    return (dataset + ('+ multiscale' if eConfig['multiscale'] else ''), mAP)
# %%
# check if there are unknown datasets
if dataset not in datasets_names:
    raise ValueError('Unsupported or unknown dataset: {}!'.format(dataset))

# setting up the visible GPU
os.environ['CUDA_VISIBLE_DEVICES'] = gpu_id

# loading network from path
if network_path is not None:
    print(">> Loading network:\n>>>> '{}'".format(network_path))
    if network_path in PRETRAINED:
        # pretrained networks (downloaded automatically)
        state = load_url(PRETRAINED[network_path],
                         model_dir=os.path.join(get_data_root(), 'networks'))
    else:
        # fine-tuned network from path
        state = torch.load(network_path)
    # parsing net params from meta
    # architecture, pooling, mean, std required
    # the rest has default values, in case that is doesnt exist
    net_params = {}
    net_params['architecture'] = state['meta']['architecture']
    net_params['pooling'] = state['meta']['pooling']
    net_params['local_whitening'] = state['meta'].get('local_whitening', False)
    net_params['regional'] = state['meta'].get('regional', False)
    net_params['whitening'] = state['meta'].get('whitening', False)
    net_params['mean'] = state['meta']['mean']
    net_params['std'] = state['meta']['std']
    net_params['pretrained'] = False
Example #20
0
    def __init__(self,
                 name,
                 mode,
                 imsize=None,
                 nnum=5,
                 qsize=2000,
                 poolsize=20000,
                 transform=None,
                 loader=default_loader):

        if not (mode == 'train' or mode == 'val'):
            raise (RuntimeError(
                "MODE should be either train or val, passed as string"))

        if name.startswith('retrieval-SfM'):
            # setting up paths
            data_root = get_data_root()
            db_root = os.path.join(data_root, 'train', name)
            ims_root = os.path.join(db_root, 'ims')

            # loading db
            db_fn = os.path.join(db_root, '{}.pkl'.format(name))
            with open(db_fn, 'rb') as f:
                db = pickle.load(f)[mode]

            # setting fullpath for images
            self.images = [
                cid2filename(db['cids'][i], ims_root)
                for i in range(len(db['cids']))
            ]

        elif name.startswith('gl'):
            ## TODO: NOT IMPLEMENTED YET PROPOERLY (WITH AUTOMATIC DOWNLOAD)

            # setting up paths
            db_root = '/mnt/fry2/users/datasets/landmarkscvprw18/recognition/'
            ims_root = os.path.join(db_root, 'images', 'train')

            # loading db
            db_fn = os.path.join(db_root, '{}.pkl'.format(name))
            with open(db_fn, 'rb') as f:
                db = pickle.load(f)[mode]

            # setting fullpath for images
            self.images = [
                os.path.join(ims_root, db['cids'][i] + '.jpg')
                for i in range(len(db['cids']))
            ]
        else:
            raise (RuntimeError("Unknown dataset name!"))

        # initializing tuples dataset
        self.name = name
        self.mode = mode
        self.imsize = imsize
        self.clusters = db['cluster']
        self.qpool = db['qidxs']
        self.ppool = db['pidxs']

        ## If we want to keep only unique q-p pairs
        ## However, ordering of pairs will change, although that is not important
        # qpidxs = list(set([(self.qidxs[i], self.pidxs[i]) for i in range(len(self.qidxs))]))
        # self.qidxs = [qpidxs[i][0] for i in range(len(qpidxs))]
        # self.pidxs = [qpidxs[i][1] for i in range(len(qpidxs))]

        # size of training subset for an epoch
        self.nnum = nnum
        self.qsize = min(qsize, len(self.qpool))
        self.poolsize = min(poolsize, len(self.images))
        self.qidxs = None
        self.pidxs = None
        self.nidxs = None

        self.transform = transform
        self.loader = loader

        self.print_freq = 10
Example #21
0
def init_network(params):

    # parse params with default values
    architecture = params.get('architecture', 'resnet101')
    local_whitening = params.get('local_whitening', False)
    pooling = params.get('pooling', 'gem')
    regional = params.get('regional', False)
    whitening = params.get('whitening', False)
    mean = params.get('mean', [0.485, 0.456, 0.406])
    std = params.get('std', [0.229, 0.224, 0.225])
    pretrained = params.get('pretrained', False)
    multi_layer_cat = params.get('multi_layer_cat', 1)

    # get output dimensionality size
    dim = OUTPUT_DIM[architecture]
    # # hxq modified, remove resnet50 con5_x for smaller receptive field
    # if architecture == 'resnet50':
    #     dim = 1024
    # else:
    #     dim = OUTPUT_DIM[architecture]

    # loading network from torchvision
    if pretrained:
        if architecture not in FEATURES:
            # initialize with network pretrained on imagenet in pytorch
            net_in = getattr(torchvision.models, architecture)(pretrained=True)
        else:
            # initialize with random weights, later on we will fill features with custom pretrained network
            net_in = getattr(torchvision.models,
                             architecture)(pretrained=False)
    else:
        # initialize with random weights
        net_in = getattr(torchvision.models, architecture)(pretrained=False)

    # initialize features
    # take only convolutions for features,
    # always ends with ReLU to make last activations non-negative
    if architecture.startswith('alexnet'):
        features = list(net_in.features.children())[:-1]
    elif architecture.startswith('vgg'):
        features = list(net_in.features.children())[:-1]
    elif architecture.startswith('resnet'):
        features = list(net_in.children())[:-2]
        # # hxq modified, remove resnet50 con5_x for smaller receptive field
        # if architecture == 'resnet50':
        #     features = list(net_in.children())[:-3]
        # else:
        #     features = list(net_in.children())[:-2]
    elif architecture.startswith('densenet'):
        features = list(net_in.features.children())
        features.append(nn.ReLU(inplace=True))
    elif architecture.startswith('squeezenet'):
        features = list(net_in.features.children())
    elif architecture.startswith('resnext101_32x8d'):
        features = list(net_in.children())[:-2]
    else:
        raise ValueError(
            'Unsupported or unknown architecture: {}!'.format(architecture))

    # initialize local whitening
    if local_whitening:
        lwhiten = nn.Linear(dim, dim, bias=True)
        # TODO: lwhiten with possible dimensionality reduce

        if pretrained:
            lw = architecture
            if lw in L_WHITENING:
                print(
                    ">> {}: for '{}' custom computed local whitening '{}' is used"
                    .format(os.path.basename(__file__), lw,
                            os.path.basename(L_WHITENING[lw])))
                whiten_dir = os.path.join(get_data_root(), 'whiten')
                lwhiten.load_state_dict(
                    model_zoo.load_url(L_WHITENING[lw], model_dir=whiten_dir))
            else:
                print(
                    ">> {}: for '{}' there is no local whitening computed, random weights are used"
                    .format(os.path.basename(__file__), lw))

    else:
        lwhiten = None

    # initialize pooling
    pool = POOLING[pooling]()
    # pool = POOLING[pooling](p=1.5)
    # print('>> GeM pool p: 1.5')

    # initialize regional pooling
    if regional:
        rpool = pool
        rwhiten = nn.Linear(dim, dim, bias=True)
        # TODO: rwhiten with possible dimensionality reduce

        if pretrained:
            rw = '{}-{}-r'.format(architecture, pooling)
            if rw in R_WHITENING:
                print(
                    ">> {}: for '{}' custom computed regional whitening '{}' is used"
                    .format(os.path.basename(__file__), rw,
                            os.path.basename(R_WHITENING[rw])))
                whiten_dir = os.path.join(get_data_root(), 'whiten')
                rwhiten.load_state_dict(
                    model_zoo.load_url(R_WHITENING[rw], model_dir=whiten_dir))
            else:
                print(
                    ">> {}: for '{}' there is no regional whitening computed, random weights are used"
                    .format(os.path.basename(__file__), rw))

        pool = Rpool(rpool, rwhiten)

    # initialize whitening
    output_dim = dim
    if whitening:
        if multi_layer_cat != 1:
            whiten = nn.Linear(dim + 1024, output_dim, bias=True)
            # whiten_fn = '/home/iap205/Datasets/retrieval-SfM/whiten/R101_M2_120k_IS1024_MS1_WL.pth'
            # # whiten_fn = '/home/iap205/Datasets/retrieval-SfM/whiten/R101_CA_M2_120k_IS1024_MS1_WL.pth'
            # # whiten_fn = '/home/iap205/Datasets/retrieval-SfM/whiten/RX101_M2_120k_IS1024_MS1_WL.pth'
            # # whiten_fn = '/home/iap205/Datasets/retrieval-SfM/whiten/R101_M4_120k_IS1024_MS1_WL.pth'
            # # whiten_fn = '/home/iap205/Datasets/retrieval-SfM/whiten/RX101_M4_120k_IS1024_MS1_WL.pth'
            # print('>> load computed whitening \'{}\''.format(whiten_fn.split('/')[-1]))
            # Lw = torch.load(whiten_fn)
            # P = Lw['P'][:dim, :]
            # m = Lw['m']
            # P = torch.from_numpy(P).float()
            # m = torch.from_numpy(m).float()
            # whiten.weight.data = P
            # whiten.bias.data = -torch.mm(P, m).squeeze()
        else:
            # whiten = nn.Linear(dim, dim, bias=True)

            output_dim = 512
            whiten = nn.Linear(dim, output_dim, bias=True)
            nn.init.xavier_normal_(whiten.weight)
            nn.init.constant_(whiten.bias, 0)

            # hxq added, for whitening test
            # print('>> load the parameters of supervised whitening for the FC layer initialization')
            # whiten_fn = '/media/iap205/Data/Export/cnnimageretrieval-google_landmark_retrieval/trained_network/' \
            #             'R101_O_GL_FC/google-landmarks-dataset-resize_resnet101_gem_whiten_contrastive_m0.85_' \
            #             'adam_lr5.0e-07_wd1.0e-04_nnum5_qsize2000_psize22000_bsize5_imsize362/' \
            #             'model_epoch114.pth.tar_google-landmarks-dataset_whiten_ms.pth'
            # whiten_fn = '/home/iap205/Datasets/google-landmarks-dataset-resize/whiten/imagenet-caffe-resnet101-' \
            #             'features-10a101d.pth_google-landmarks-dataset-test_256_whiten_MS1.pth'
            # whiten_fn = '/media/iap205/Data4T/Datasets/google-landmarks-dataset-v2/whiten/imagenet-caffe-' \
            #             'resnet101-features-10a101d.pth_google-landmarks-dataset-v2-test_256_whiten_MS1.pth'
            # whiten_fn = '/media/iap205/Data4T/Datasets/google-landmarks-dataset-v2/whiten/imagenet-caffe-' \
            #            'resnet101-features-10a101d.pth_google-landmarks-dataset-v2-test_1024_whiten_MS1.pth'
            # whiten_fn = '/media/iap205/Data/Export/cnnimageretrieval-pytorch/trained_network/retrieval-SfM-120k' \
            #             '_resnet101_gem_contrastive_m0.85_adam_lr5.0e-07_wd1.0e-04_nnum5_qsize2000_psize22000_bsize5' \
            #             '_imsize362/model_best.pth.tar_retrieval-SfM-120k_whiten_ms.pth'
            # whiten_fn = '/home/iap205/Datasets/retrieval-SfM/whiten/R101_120k_IS1024_MS1.pth'
            # whiten_fn = '/home/iap205/Datasets/retrieval-SfM/whiten/R101_120k_IS362_MS1.pth'
            # whiten_fn = '/home/iap205/Datasets/retrieval-SfM/whiten/R101_120k_IS1024_MS1_WL.pth'
            # # whiten_fn = '/home/iap205/Datasets/retrieval-SfM/whiten/R101_120k_IS1024_MS1_WL_WL.pth'
            # whiten_fn = '/home/iap205/Datasets/retrieval-SfM/whiten/R101_CA_120k_IS1024_MS1_WL.pth'
            # whiten_fn = '/home/iap205/Datasets/retrieval-SfM/whiten/R101_top9_120k_IS1024_MS1_WL.pth'
            # whiten_fn = '/home/iap205/Datasets/retrieval-SfM/whiten/R101_top0.25_120k_IS1024_MS1_WL.pth'
            # whiten_fn = '/home/iap205/Datasets/retrieval-SfM/whiten/R101_LA_120k_IS1024_MS1_WL.pth'
            # whiten_fn = '/home/iap205/Datasets/retrieval-SfM/whiten/R101_top0.25_p1.5_120k_IS1024_MS1_WL.pth'
            # print('>> load computed whitening \'{}\''.format(whiten_fn.split('/')[-1]))
            # Lw = torch.load(whiten_fn)
            # P = Lw['P']
            # m = Lw['m']
            # P = torch.from_numpy(P).float()
            # m = torch.from_numpy(m).float()
            # whiten.weight.data = P
            # whiten.bias.data = -torch.mm(P, m).squeeze()

            # multi PCA test
            # whiten = nn.Sequential(nn.Linear(dim, dim, bias=True),
            #                        nn.Linear(dim, dim, bias=True))
            # whiten_fn = ['/home/iap205/Datasets/retrieval-SfM/whiten/R101_120k_362_IS1024_MS1_WL.pth',
            #              '/home/iap205/Datasets/retrieval-SfM/whiten/R101_120k_362_IS1024_MS1_WL_WL.pth']
            # for i in range(len(whiten)):
            #     print('>> load computed whitening \'{}\''.format(whiten_fn[i].split('/')[-1]))
            #     Lw = torch.load(whiten_fn[i])
            #     P = Lw['P']
            #     m = Lw['m']
            #     P = torch.from_numpy(P).float()
            #     m = torch.from_numpy(m).float()
            #     whiten[i].weight.data = P
            #     whiten[i].bias.data = -torch.mm(P, m).squeeze()
        # TODO: whiten with possible dimensionality reduce

        if pretrained:
            w = architecture
            if local_whitening:
                w += '-lw'
            w += '-' + pooling
            if regional:
                w += '-r'
            if w in WHITENING:
                print(">> {}: for '{}' custom computed whitening '{}' is used".
                      format(os.path.basename(__file__), w,
                             os.path.basename(WHITENING[w])))
                whiten_dir = os.path.join(get_data_root(), 'whiten')
                whiten.load_state_dict(
                    model_zoo.load_url(WHITENING[w], model_dir=whiten_dir))
            else:
                print(
                    ">> {}: for '{}' there is no whitening computed, random weights are used"
                    .format(os.path.basename(__file__), w))
    else:
        whiten = None

    # create meta information to be stored in the network
    meta = {
        'architecture': architecture,
        'local_whitening': local_whitening,
        'pooling': pooling,
        'regional': regional,
        'whitening': whitening,
        'mean': mean,
        'std': std,
        'outputdim': output_dim,
        'multi_layer_cat': multi_layer_cat
    }

    # create a generic image retrieval network
    net = ImageRetrievalNet(features, lwhiten, pool, whiten, meta)

    # initialize features with custom pretrained network if needed
    if pretrained and architecture in FEATURES:
        print(
            ">> {}: for '{}' custom pretrained features '{}' are used".format(
                os.path.basename(__file__), architecture,
                os.path.basename(FEATURES[architecture])))
        model_dir = os.path.join(get_data_root(), 'networks')

        # hxq modified, remove resnet50 con5_x for smaller receptive field
        if architecture == 'resnet50-3':
            state_dict = model_zoo.load_url(FEATURES[architecture],
                                            model_dir=model_dir)
            for key in list(state_dict.keys()):
                if list(key)[0] == '7':
                    state_dict.pop(key)
            net.features.load_state_dict(state_dict)
        else:
            # hxq modified
            # state_dict = model_zoo.load_url(FEATURES[architecture], model_dir=model_dir)
            # state_dict_mGPU = {}
            # for key, val in state_dict.items():
            #     state_dict_mGPU['module.'+key] = val
            # net.features.load_state_dict(state_dict_mGPU)

            net.features.load_state_dict(
                model_zoo.load_url(FEATURES[architecture],
                                   model_dir=model_dir))

    return net
Example #22
0
def main():
    global args, min_loss
    args = parser.parse_args()

    # manually check if there are unknown test datasets
    for dataset in args.test_datasets.split(','):
        if dataset not in test_datasets_names:
            raise ValueError('Unsupported or unknown test dataset: {}!'.format(dataset))

    # check if test dataset are downloaded
    # and download if they are not
    download_train(get_data_root())
    download_test(get_data_root())

    # create export dir if it doesnt exist
    directory = "{}".format(args.training_dataset)
    directory += "_{}".format(args.arch)
    directory += "_{}".format(args.pool)
    if args.local_whitening:
        directory += "_lwhiten"
    if args.regional:
        directory += "_r"
    if args.whitening:
        directory += "_whiten"
    if not args.pretrained:
        directory += "_notpretrained"
    directory += "_{}_m{:.2f}".format(args.loss, args.loss_margin)
    directory += "_{}_lr{:.1e}_wd{:.1e}".format(args.optimizer, args.lr, args.weight_decay)
    directory += "_nnum{}_qsize{}_psize{}".format(args.neg_num, args.query_size, args.pool_size)
    directory += "_bsize{}_uevery{}_imsize{}".format(args.batch_size, args.update_every, args.image_size)

    args.directory = os.path.join(args.directory, directory)
    print(">> Creating directory if it does not exist:\n>> '{}'".format(args.directory))
    if not os.path.exists(args.directory):
        os.makedirs(args.directory)

    # set cuda visible device
    os.environ['CUDA_VISIBLE_DEVICES'] = args.gpu_id
    
    # set random seeds
    # TODO: maybe pass as argument in future implementation?
    torch.manual_seed(0)
    torch.cuda.manual_seed_all(0)
    np.random.seed(0)

    # initialize model
    if args.pretrained:
        print(">> Using pre-trained model '{}'".format(args.arch))
    else:
        print(">> Using model from scratch (random weights) '{}'".format(args.arch))
    model_params = {}
    model_params['architecture'] = args.arch
    model_params['pooling'] = args.pool
    model_params['local_whitening'] = args.local_whitening
    model_params['regional'] = args.regional
    model_params['whitening'] = args.whitening
    # model_params['mean'] = ...  # will use default
    # model_params['std'] = ...  # will use default
    model_params['pretrained'] = args.pretrained
    model = init_network(model_params)

    # move network to gpu
    model.cuda()

    if model_params['pooling'] == 'netvlad':
        normalize = torchvision.transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
        transform = torchvision.transforms.Compose([
            torchvision.transforms.Resize(size=(364, 364)),
            torchvision.transforms.ToTensor(),
            normalize,
        ])

        image_folder = folder.ImageFolder(root="/mnt/m2/dataset", transform=transform)

        train_loader = torch.utils.data.DataLoader(
            image_folder,
            batch_size=64,
            num_workers=8,
            shuffle=True
        )

        n_batches = 10

        descs_list = []
        i = 0
        with torch.no_grad():
            for x, _ in train_loader:
                model.eval()
                desc = model.compute_features(x.cuda())
                max_pooled_feat_3 = torch.nn.functional.max_pool2d(desc, kernel_size=3, stride=1)
                max_pooled_feat_2 = torch.nn.functional.max_pool2d(desc, kernel_size=2, stride=1)

                reshaped_pool_3 = make_locals(max_pooled_feat_3)
                reshaped_pool_2 = make_locals(max_pooled_feat_2)

                desc = torch.cat([reshaped_pool_2, reshaped_pool_3], dim=1)

                # N, dim, h, w = desc.shape
                # desc = desc.view(N, dim, h*w).permute(0, 2, 1).reshape(N, -1, 512)
                desc = desc.cpu().numpy().astype('float32')
                descs_list.append(desc)
                print(">> Extracted batch {}/{} - NetVLAD initialization -".format(i+1, n_batches))
                i+=1
                if i == n_batches:
                    break

        descs_list = np.array(descs_list).reshape(-1, 512)
        print(descs_list.shape)
        print(">> Sampling local features ")
        # locals = np.vstack((m[np.random.randint(len(m), size=150)] for m in descs_list)).astype('float32')
        locals = descs_list[np.random.randint(len(descs_list), size=len(descs_list)//3)]

        np.random.shuffle(locals)
        print(">> Locals extracted shape : {}".format(locals.shape))

        n_clust = 64

        locals = preprocessing.normalize(locals, axis=1)

        print(">> Fitting centroids with K-Means")
        kmeans = MiniBatchKMeans(n_clusters=n_clust).fit(locals)
        centroids = kmeans.cluster_centers_
        print(">> Centroids shape: ", centroids.shape)
        model.pool.init_params(centroids.T)
        print(">> NetVLAD initialized")

    # define loss function (criterion) and optimizer
    if args.loss == 'contrastive':
        criterion = ContrastiveLoss(margin=args.loss_margin).cuda()
    elif args.loss == 'triplet':
        criterion = TripletLoss(margin=args.loss_margin).cuda()
    else:
        raise(RuntimeError("Loss {} not available!".format(args.loss)))

    # parameters split into features, pool, whitening 
    # IMPORTANT: no weight decay for pooling parameter p in GeM or regional-GeM
    parameters = []
    # add feature parameters
    parameters.append({'params': model.features.parameters()})
    # add local whitening if exists
    if model.lwhiten is not None:
        parameters.append({'params': model.lwhiten.parameters()})
    # add pooling parameters (or regional whitening which is part of the pooling layer!)
    if not args.regional:
        # global, only pooling parameter p weight decay should be 0
        if args.pool == 'gem':
            parameters.append({'params': model.pool.parameters(), 'lr': args.lr*10, 'weight_decay': 0})
        elif args.pool == 'gemmp':
            parameters.append({'params': model.pool.parameters(), 'lr': args.lr*100, 'weight_decay': 0})
    else:
        # regional, pooling parameter p weight decay should be 0, 
        # and we want to add regional whitening if it is there
        if args.pool == 'gem':
            parameters.append({'params': model.pool.rpool.parameters(), 'lr': args.lr*10, 'weight_decay': 0})
        elif args.pool == 'gemmp':
            parameters.append({'params': model.pool.rpool.parameters(), 'lr': args.lr*100, 'weight_decay': 0})
        if model.pool.whiten is not None:
            parameters.append({'params': model.pool.whiten.parameters()})
    # add final whitening if exists
    if model.whiten is not None:
        parameters.append({'params': model.whiten.parameters()})

    # define optimizer
    if args.optimizer == 'sgd':
        optimizer = torch.optim.SGD(parameters, args.lr, momentum=args.momentum, weight_decay=args.weight_decay)
    elif args.optimizer == 'adam':
        optimizer = torch.optim.Adam(parameters, args.lr, weight_decay=args.weight_decay)

    # define learning rate decay schedule
    # TODO: maybe pass as argument in future implementation?
    exp_decay = math.exp(-0.01)
    scheduler = torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma=exp_decay)

    # optionally resume from a checkpoint
    start_epoch = 0
    if args.resume:
        args.resume = os.path.join(args.directory, args.resume)
        if os.path.isfile(args.resume):
            # load checkpoint weights and update model and optimizer
            print(">> Loading checkpoint:\n>> '{}'".format(args.resume))
            checkpoint = torch.load(args.resume)
            start_epoch = checkpoint['epoch']
            min_loss = checkpoint['min_loss']
            model.load_state_dict(checkpoint['state_dict'])
            optimizer.load_state_dict(checkpoint['optimizer'])
            print(">>>> loaded checkpoint:\n>>>> '{}' (epoch {})"
                  .format(args.resume, checkpoint['epoch']))
            # important not to forget scheduler updating
            scheduler = torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma=exp_decay, last_epoch=checkpoint['epoch']-1)
        else:
            print(">> No checkpoint found at '{}'".format(args.resume))

    # Data loading code
    normalize = transforms.Normalize(mean=model.meta['mean'], std=model.meta['std'])
    transform = transforms.Compose([
        transforms.ToTensor(),
        normalize,
    ])
    train_dataset = TuplesDataset(
        name=args.training_dataset,
        mode='train',
        imsize=args.image_size,
        nnum=args.neg_num,
        qsize=args.query_size,
        poolsize=args.pool_size,
        transform=transform
    )
    train_loader = torch.utils.data.DataLoader(
        train_dataset, batch_size=args.batch_size, shuffle=True,
        num_workers=args.workers, pin_memory=True, sampler=None,
        drop_last=True, collate_fn=collate_tuples
    )
    if args.val:
        val_dataset = TuplesDataset(
            name=args.training_dataset,
            mode='val',
            imsize=args.image_size,
            nnum=args.neg_num,
            qsize=float('Inf'),
            poolsize=float('Inf'),
            transform=transform
        )
        val_loader = torch.utils.data.DataLoader(
            val_dataset, batch_size=args.batch_size, shuffle=False,
            num_workers=args.workers, pin_memory=True,
            drop_last=True, collate_fn=collate_tuples
        )

    # evaluate the network before starting
    # this might not be necessary?
    test(args.test_datasets, model)

    for epoch in range(start_epoch, args.epochs):

        # set manual seeds per epoch
        np.random.seed(epoch)
        torch.manual_seed(epoch)
        torch.cuda.manual_seed_all(epoch)

        # adjust learning rate for each epoch
        scheduler.step()
        # # debug printing to check if everything ok
        # lr_feat = optimizer.param_groups[0]['lr']
        # lr_pool = optimizer.param_groups[1]['lr']
        # print('>> Features lr: {:.2e}; Pooling lr: {:.2e}'.format(lr_feat, lr_pool))

        # train for one epoch on train set
        loss = train(train_loader, model, criterion, optimizer, epoch)

        # evaluate on validation set
        if args.val:
            with torch.no_grad():
                loss = validate(val_loader, model, criterion, epoch)

        # evaluate on test datasets every test_freq epochs
        if (epoch + 1) % args.test_freq == 0:
            with torch.no_grad():
                test(args.test_datasets, model)

        # remember best loss and save checkpoint
        is_best = loss < min_loss
        min_loss = min(loss, min_loss)

        save_checkpoint({
            'epoch': epoch + 1,
            'meta': model.meta,
            'state_dict': model.state_dict(),
            'min_loss': min_loss,
            'optimizer' : optimizer.state_dict(),
        }, is_best, args.directory)
Example #23
0
    def __init__(
        self,
        imsize=None,
        nnum=5,
        qsize=2000,
        poolsize=20000,
        transform=None,
        loader=default_loader,
        filename=None,
        q_percent=1,
    ):

        # setting up paths
        data_root = get_data_root()
        name = "retrieval-SfM-120k"
        db_root = os.path.join(data_root, "train", name)
        ims_root = os.path.join(db_root, "ims")

        # loading db
        db_fn = os.path.join(db_root, "{}.pkl".format(name))
        with open(db_fn, "rb") as f:
            db = pickle.load(f)["val"]

        # initializing tuples dataset
        self.imsize = imsize
        self.images = [
            cid2filename(db["cids"][i], ims_root)
            for i in range(len(db["cids"]))
        ]
        self.clusters = db["cluster"]
        self.qpool = db["qidxs"]
        # self.ppool = db['pidxs']

        # size of training subset for an epoch
        self.nnum = nnum
        self.qsize = min(qsize, len(self.qpool))
        self.poolsize = min(poolsize, len(self.images))
        self.qidxs = self.qpool
        self.index = np.arange(len(self.qidxs))

        if q_percent < 1:
            number = int(len(self.qidxs) * q_percent)
            self.index = np.random.permutation(self.index)
            self.index = self.index[:number]

        self.pidxs = []
        self.nidxs = []

        self.poolvecs = None

        self.transform = transform
        self.loader = loader
        self.filename = filename
        self.phase = 1

        self.ranks = torch.load(f"{filename}/ranks_362")
        if os.path.isfile(f"{filename}/pool_vecs"):
            self.pool_vecs = pickle.load(open(f"{filename}/pool_vecs", "rb"))
        print(len(self.images))
        self.loaded_images = []
        if os.path.exists("./images"):
            self.loaded_images = pickle.load(open("./images", "rb"))
        else:
            for i in range(len(self.images)):
                try:
                    img = self.loader(self.images[i])
                    if self.imsize is not None:
                        img = imresize(img, self.imsize)
                    if self.transform is not None:
                        img_tensor = self.transform(img).unsqueeze(0)
                    img.close()
                    self.loaded_images.append(img_tensor)
                except:
                    self.loaded_images.append(None)
            pickle.dump(self.loaded_images, open("./images", "wb"))
Example #24
0
# whitening = 'google-landmarks-dataset-resize'

#%%
# check if there are unknown datasets
if dataset not in datasets_names:
    raise ValueError('Unsupported or unknown dataset: {}!'.format(dataset))

# setting up the visible GPU
os.environ['CUDA_VISIBLE_DEVICES'] = gpu_id

# loading network from path
print(">> Loading network:\n>>>> '{}'".format(network_path))
if network_path in PRETRAINED:
    # pretrained networks (downloaded automatically)
    state = load_url(PRETRAINED[network_path],
                     model_dir=os.path.join(get_data_root(), 'networks'))
else:
    # fine-tuned network from path
    state = torch.load(network_path)
# parsing net params from meta
# architecture, pooling, mean, std required
# the rest has default values, in case that is doesnt exist
net_params = {}
net_params['architecture'] = state['meta']['architecture']
net_params['pooling'] = state['meta']['pooling']
net_params['local_whitening'] = state['meta'].get('local_whitening', False)
net_params['regional'] = state['meta'].get('regional', False)
net_params['whitening'] = state['meta'].get('whitening', False)
net_params['mean'] = state['meta']['mean']
net_params['std'] = state['meta']['std']
net_params['pretrained'] = False
Example #25
0
def main():
    args = parser.parse_args()

    # check if test dataset are downloaded
    # and download if they are not
    #download_train(get_data_root())
    #download_test(get_data_root())

    # setting up the visible GPU
    os.environ['CUDA_VISIBLE_DEVICES'] = args.gpu_id

    # loading network from path
    if args.network_path is not None:
        print(">> Loading network:\n>>>> '{}'".format(args.network_path))
        if args.network_path in PRETRAINED:
            # pretrained networks (downloaded automatically)
            state = load_url(PRETRAINED[args.network_path],
                             model_dir=os.path.join(get_data_root(),
                                                    'networks'))
        else:
            state = torch.load(args.network_path)
        net = init_network(model=state['meta']['architecture'],
                           pooling=state['meta']['pooling'],
                           whitening=state['meta']['whitening'],
                           mean=state['meta']['mean'],
                           std=state['meta']['std'],
                           pretrained=False)
        net.load_state_dict(state['state_dict'])

        # if whitening is precomputed
        if 'Lw' in state['meta']:
            net.meta['Lw'] = state['meta']['Lw']

        print(">>>> loaded network: ")
        print(net.meta_repr())

    # loading offtheshelf network
    elif args.network_offtheshelf is not None:
        offtheshelf = args.network_offtheshelf.split('-')
        if len(offtheshelf) == 3:
            if offtheshelf[2] == 'whiten':
                offtheshelf_whiten = True
            else:
                raise (RuntimeError(
                    "Incorrect format of the off-the-shelf network. Examples: resnet101-gem | resnet101-gem-whiten"
                ))
        else:
            offtheshelf_whiten = False
        print(">> Loading off-the-shelf network:\n>>>> '{}'".format(
            args.network_offtheshelf))
        net = init_network(model=offtheshelf[0],
                           pooling=offtheshelf[1],
                           whitening=offtheshelf_whiten)
        print(">>>> loaded network: ")
        print(net.meta_repr())

    # setting up the multi-scale parameters
    ms = [1]
    msp = 1
    if args.multiscale:
        ms = [1, 1. / math.sqrt(2), 1. / 2]
        if net.meta['pooling'] == 'gem' and net.whiten is None:
            msp = net.pool.p.data.tolist()[0]

    # moving network to gpu and eval mode
    net.cuda()
    net.eval()
    # set up the transform
    normalize = transforms.Normalize(mean=net.meta['mean'],
                                     std=net.meta['std'])
    transform = transforms.Compose([transforms.ToTensor(), normalize])

    # compute whitening
    if args.whitening is not None:
        start = time.time()

        if 'Lw' in net.meta and args.whitening in net.meta['Lw']:

            print('>> {}: Whitening is precomputed, loading it...'.format(
                args.whitening))

            if args.multiscale:
                Lw = net.meta['Lw'][args.whitening]['ms']
            else:
                Lw = net.meta['Lw'][args.whitening]['ss']

        else:

            print('>> {}: Learning whitening...'.format(args.whitening))

            # loading db
            db_root = os.path.join(get_data_root(), 'train', args.whitening)
            ims_root = os.path.join(db_root, 'ims')
            db_fn = os.path.join(db_root,
                                 '{}-whiten.pkl'.format(args.whitening))
            with open(db_fn, 'rb') as f:
                db = pickle.load(f)
            images = [
                cid2filename(db['cids'][i], ims_root)
                for i in range(len(db['cids']))
            ]

            # extract whitening vectors
            print('>> {}: Extracting...'.format(args.whitening))
            wvecs = extract_vectors(net,
                                    images,
                                    args.image_size,
                                    transform,
                                    ms=ms,
                                    msp=msp)

            # learning whitening
            print('>> {}: Learning...'.format(args.whitening))
            wvecs = wvecs.numpy()
            m, P = whitenlearn(wvecs, db['qidxs'], db['pidxs'])
            Lw = {'m': m, 'P': P}

        print('>> {}: elapsed time: {}'.format(args.whitening,
                                               htime(time.time() - start)))
    else:
        Lw = None

    # evaluate on test datasets
    datasets = args.datasets.split(',')
    for dataset in datasets:
        start = time.time()

        print('>> {}: Extracting...'.format(dataset))

        # prepare config structure for the test dataset
        cfg = configdataset(dataset, os.path.join(get_data_root(), 'test'))
        images = [cfg['im_fname'](cfg, i) for i in range(cfg['n'])]
        qimages = [cfg['qim_fname'](cfg, i) for i in range(cfg['nq'])]
        bbxs = [tuple(cfg['gnd'][i]['bbx']) for i in range(cfg['nq'])]

        # extract database and query vectors
        print('>> {}: database images...'.format(dataset))
        vecs = extract_vectors(net,
                               images,
                               args.image_size,
                               transform,
                               ms=ms,
                               msp=msp)
        print('>> {}: query images...'.format(dataset))
        qvecs = extract_vectors(net,
                                qimages,
                                args.image_size,
                                transform,
                                bbxs=bbxs,
                                ms=ms,
                                msp=msp)

        print('>> {}: Evaluating...'.format(dataset))

        # convert to numpy
        vecs = vecs.numpy()
        qvecs = qvecs.numpy()

        # search, rank, and print
        scores = np.dot(vecs.T, qvecs)
        ranks = np.argsort(-scores, axis=0)
        compute_map_and_print(dataset, ranks, cfg['gnd'])

        if Lw is not None:
            # whiten the vectors
            vecs_lw = whitenapply(vecs, Lw['m'], Lw['P'])
            qvecs_lw = whitenapply(qvecs, Lw['m'], Lw['P'])

            # search, rank, and print
            scores = np.dot(vecs_lw.T, qvecs_lw)
            ranks = np.argsort(-scores, axis=0)
            compute_map_and_print(dataset + ' + whiten', ranks, cfg['gnd'])

        print('>> {}: elapsed time: {}'.format(dataset,
                                               htime(time.time() - start)))
Example #26
0
def gen_train_val_test_pkl(dataset):
    if dataset == 'google-landmarks-dataset-v2':
        data_table_path = os.path.join(get_data_root(), 'train.csv')
        img_check_path = os.path.join(get_data_root(), 'train')
        train_val_file_output_path = os.path.join(get_data_root())
        test_file_output_path = os.path.join(get_data_root(), 'test',
                                             dataset + '-test')
        val_set_size = 10000
        test_set_size = 10000
        q_index_ratio = 100000. / 700000.
        train_qp_pair_num = 12
    elif dataset == 'google-landmarks-dataset-resize':
        data_table_path = os.path.join(get_data_root(), 'train.csv')
        img_check_path = os.path.join(get_data_root(), 'resize_train_image')
        train_val_file_output_path = os.path.join(get_data_root())
        test_file_output_path = os.path.join(get_data_root(), 'test',
                                             dataset + '-test')
        val_set_size = 10000
        test_set_size = 10000
        q_index_ratio = 118000. / 1100000.
        train_qp_pair_num = 50
    elif dataset == 'google-landmarks-dataset':
        pass

    # step0: check image is exist
    print(">> load {} file...".format(data_table_path.split('/')[-1]))
    csvfile = open(data_table_path, 'r')
    csvreader = csv.reader(csvfile)
    id_url_class_list = [line[:3] for line in csvreader][1:]
    csvfile.close()
    if dataset == 'google-landmarks-dataset-v2':
        # https://github.com/cvdfoundation/google-landmark
        # images = [os.path.join(img_check_path, '/'.join(list(id_url_class_list[i][0])[:3]), id_url_class_list[i][0])
        #           + '.jpg' for i in range(len(id_url_class_list))]
        train_temp = [['1', id_url_class_list[i][0], id_url_class_list[i][2]]
                      for i in range(len(id_url_class_list))]
    elif dataset == 'google-landmarks-dataset-resize':
        print(">> check {} file...".format(data_table_path.split('/')[-1]))
        train_temp = []
        files = os.listdir(img_check_path)
        files = {
            files[i].split('.jpg')[0]: files[i].split('.jpg')[0]
            for i in range(len(files))
        }
        missfile = open(
            os.path.join(train_val_file_output_path, 'train_miss.csv'), 'w')
        miss_writer = csv.writer(missfile)
        miss_writer.writerow(['id', 'url'])
        miss_cnt = 0
        for line in id_url_class_list:
            if files.__contains__(line[0]):
                if line[2] != 'None':
                    train_temp.append(['1', line[0], line[2]])
                else:
                    train_temp.append(['1', line[0], '-1'])
                files.pop(line[0])
            else:
                if line[2] != 'None':
                    train_temp.append(['0', line[0], line[2]])
                else:
                    train_temp.append(['0', line[0], '-1'])
                miss_writer.writerow(line)
                miss_cnt += 1
        missfile.close()
        print('>>>> train image miss: {}, train_miss.csv save done...'.format(
            miss_cnt))
    elif dataset == 'google-landmarks-dataset':
        pass

    np.random.seed(0)  # added after the competition
    shuffle = np.random.permutation(len(train_temp))
    train_shuffle = []
    for i in shuffle:
        train_shuffle.append(train_temp[i])

    train_shuffle = pd.DataFrame(train_shuffle,
                                 columns=['mark', 'id', 'landmark_id'])
    train_shuffle['landmark_id'] = train_shuffle['landmark_id'].astype('int')
    # train = train.sort_values('landmark_id')
    train_shuffle = train_shuffle.to_numpy()

    # step1: extract test set
    print(">> extract test set...")
    landmark_id_shuffle = np.random.permutation(max(train_shuffle[:, 2]))
    test_landmark_num = round(test_set_size /
                              (len(train_shuffle) / max(train_shuffle[:, 2])))
    test_sel_landmark_id = landmark_id_shuffle[:test_landmark_num]
    landmark_id_shuffle = landmark_id_shuffle[test_landmark_num:]
    test = []
    for i in range(len(train_shuffle)):
        if train_shuffle[i][2] in test_sel_landmark_id:
            if train_shuffle[i][0] == '1':
                test.append(train_shuffle[i][1:])
                train_shuffle[i][0] = '0'

    test = pd.DataFrame(test, columns=['id', 'landmark_id'])
    test = test.sort_values('landmark_id')
    test = test.to_numpy()

    print(">> copy test image from train set...")
    imlist_all = list(test[:, 0])
    if dataset == 'google-landmarks-dataset-v2':
        img_path = [
            os.path.join(img_check_path, '/'.join(list(imlist_all[i])[:3]),
                         imlist_all[i] + '.jpg')
            for i in range(len(imlist_all))
        ]
    else:
        img_path = [
            os.path.join(img_check_path, imlist_all[i] + '.jpg')
            for i in range(len(imlist_all))
        ]
    for i in range(len(imlist_all)):
        shutil.copyfile(
            img_path[i],
            os.path.join(test_file_output_path, 'jpg', imlist_all[i] + '.jpg'))

    test_fold = []
    for i in range(test_landmark_num):
        test_fold.append([])
    landmark_cnt = 0
    test_fold[0].append([test[0][0], 0])
    for i in range(1, len(test)):
        if test[i][1] != test[i - 1][1]:
            landmark_cnt += 1
        test_fold[landmark_cnt].append([test[i][0], i])

    qimlist = []
    gnd = []
    imlist = []
    for i in range(test_landmark_num):
        q_num = max(round(q_index_ratio * len(test_fold[i])), 1)
        for j in range(q_num):
            qimlist.append(test_fold[i][j][0])
            gnd.append({'ok': []})
            for k in range(len(imlist),
                           len(imlist) + len(test_fold[i]) - q_num):
                gnd[-1]['ok'].append(k)
        for j in range(q_num, len(test_fold[i])):
            imlist.append(test_fold[i][j][0])

    test_pkl = {'imlist': imlist, 'qimlist': qimlist, 'gnd': gnd}
    pkl_output_path = os.path.join(test_file_output_path,
                                   'gnd_{}-test.pkl'.format(dataset))
    pickle_file = open(pkl_output_path, 'wb')
    pickle.dump(test_pkl, pickle_file)
    pickle_file.close()
    print(">> save gnd_{}-test.pkl done...".format(dataset))

    # step2: extract validation set
    print('>> extract validation set...')
    val_landmark_num = round(val_set_size /
                             (len(train_shuffle) / max(train_shuffle[:, 2])))
    val_sel_landmark_id = landmark_id_shuffle[:val_landmark_num]
    val = []
    for i in range(len(train_shuffle)):
        if train_shuffle[i][2] in val_sel_landmark_id:
            if train_shuffle[i][0] == '1':
                val.append(train_shuffle[i][1:])
                train_shuffle[i][0] = '0'
    val = pd.DataFrame(val, columns=['id', 'landmark_id'])
    val = val.sort_values('landmark_id')
    val = val.to_numpy()
    val_dict = {}
    val_dict['id'] = list(val[:, 0])
    val_dict['landmark_id'] = list(val[:, 1])

    pair_cnt = 0
    val_qidxs, val_pidxs = [], []
    val_qp_pair_num = round(
        train_qp_pair_num *
        (val_set_size / (len(train_shuffle) - val_set_size - test_set_size)))
    for i in range(len(val_dict['landmark_id']) - 1):
        if val_dict['landmark_id'][i] != -1:
            if val_dict['landmark_id'][i] == val_dict['landmark_id'][i + 1]:
                if pair_cnt < max(1, val_qp_pair_num):
                    val_qidxs.append(i)
                    val_pidxs.append(i + 1)
                    pair_cnt += 1
            else:
                pair_cnt = 0
    val_dict['qidxs'] = val_qidxs
    val_dict['pidxs'] = val_pidxs

    if dataset == 'google-landmarks-dataset-v2':
        print(">> copy val image from train set...")
        img_path = [
            os.path.join(img_check_path, '/'.join(list(val_dict['id'][i])[:3]),
                         val_dict['id'][i] + '.jpg')
            for i in range(len(val_dict['id']))
        ]
        for i in range(len(val_dict['id'])):
            shutil.copyfile(
                img_path[i],
                os.path.join(train_val_file_output_path, 'val',
                             val_dict['id'][i] + '.jpg'))

    # step3: extract train set
    print('>> extract train set...')

    train_dict = {}
    train = train_shuffle
    train = pd.DataFrame(train, columns=['mark', 'id', 'landmark_id'])
    train = train.sort_values('landmark_id')
    train = train.to_numpy()
    train_id, train_landmark_id = [], []
    for i in range(len(train)):
        if train[i, 0] == '1':
            train_id.append(train[i, 1])
            train_landmark_id.append(train[i, 2])
    train_dict['id'] = train_id
    train_dict['landmark_id'] = train_landmark_id

    pair_cnt = 0
    train_qidxs, train_pidxs = [], []
    for i in range(len(train_dict['landmark_id']) - 1):
        if train_dict['landmark_id'][i] != -1:
            if train_dict['landmark_id'][i] == train_dict['landmark_id'][i +
                                                                         1]:
                if pair_cnt < train_qp_pair_num:
                    train_qidxs.append(i)
                    train_pidxs.append(i + 1)
                    pair_cnt += 1
            else:
                pair_cnt = 0
    train_dict['qidxs'] = train_qidxs
    train_dict['pidxs'] = train_pidxs

    # warp all dict to one pickle file
    all_dict = {'train': train_dict, 'val': val_dict}
    pickle_file = open(
        os.path.join(train_val_file_output_path, '{}.pkl'.format(dataset)),
        'wb')
    pickle.dump(all_dict, pickle_file)
    pickle_file.close()
    print(">> save {}.pkl done...".format(dataset))
Example #27
0
def init_network(model='resnet101', pooling='gem', whitening=False, mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225], pretrained=True):

    # loading network from torchvision
    if pretrained:
        if model not in FEATURES:
            # initialize with network pretrained on imagenet in pytorch
            net_in = getattr(torchvision.models, model)(pretrained=True)
        else:
            # initialize with random weights, later on we will fill features with custom pretrained network
            net_in = getattr(torchvision.models, model)(pretrained=False)
    else:
        # initialize with random weights
        net_in = getattr(torchvision.models, model)(pretrained=False)

    # initialize features
    # take only convolutions for features,
    # always ends with ReLU to make last activations non-negative
    if model.startswith('alexnet'):
        features = list(net_in.features.children())[:-1]
    elif model.startswith('vgg'):
        features = list(net_in.features.children())[:-1]
    elif model.startswith('resnet'):
        features = list(net_in.children())[:-2]
    elif model.startswith('densenet'):
        features = list(net_in.features.children())
        features.append(nn.ReLU(inplace=True))
    elif model.startswith('squeezenet'):
        features = list(net_in.features.children())
    else:
        raise ValueError('Unsupported or unknown model: {}!'.format(model))
    
    # initialize pooling
    pool = POOLING[pooling]()

    # get output dimensionality size
    dim = OUTPUT_DIM[model]

    # initialize whitening
    if whitening:
        w = '{}-{}'.format(model, pooling)
        whiten = nn.Linear(dim, dim, bias=True)
        if w in WHITENING:
            print(">> {}: for '{}' custom computed whitening '{}' is used"
                .format(os.path.basename(__file__), w, os.path.basename(WHITENING[w])))
            whiten_dir = os.path.join(get_data_root(), 'whiten')
            whiten.load_state_dict(model_zoo.load_url(WHITENING[w], model_dir=whiten_dir))
        else:
            print(">> {}: for '{}' there is no whitening computed, random weights are used"
                .format(os.path.basename(__file__), w))
    else:
        whiten = None

    # create meta information to be stored in the network
    meta = {'architecture':model, 'pooling':pooling, 'whitening':whitening, 'outputdim':dim, 'mean':mean, 'std':std}

    # create a generic image retrieval network
    net = ImageRetrievalNet(features, pool, whiten, meta)

    # initialize features with custom pretrained network if needed
    if pretrained and model in FEATURES:
        print(">> {}: for '{}' custom pretrained features '{}' are used"
            .format(os.path.basename(__file__), model, os.path.basename(FEATURES[model])))
        model_dir = os.path.join(get_data_root(), 'networks')
        net.features.load_state_dict(model_zoo.load_url(FEATURES[model], model_dir=model_dir))

    return net
def main():
    args = parser.parse_args()

    # check if there are unknown datasets
    for dataset in args.datasets.split(','):
        if dataset not in datasets_names:
            raise ValueError(
                'Unsupported or unknown dataset: {}!'.format(dataset))

    # check if test dataset are downloaded
    # and download if they are not
    download_train(get_data_root())
    download_test(get_data_root())

    # setting up the visible GPU
    os.environ['CUDA_VISIBLE_DEVICES'] = args.gpu_id

    # loading network from path
    if args.network_path is not None:

        print(">> Loading network:\n>>>> '{}'".format(args.network_path))
        if args.network_path in PRETRAINED:
            # pretrained networks (downloaded automatically)
            state = load_url(PRETRAINED[args.network_path],
                             model_dir=os.path.join(get_data_root(),
                                                    'networks'))
        else:
            # fine-tuned network from path
            state = torch.load(args.network_path)

        # parsing net params from meta
        # architecture, pooling, mean, std required
        # the rest has default values, in case that is doesnt exist
        net_params = {}
        net_params['architecture'] = state['meta']['architecture']
        net_params['pooling'] = state['meta']['pooling']
        net_params['local_whitening'] = state['meta'].get(
            'local_whitening', False)
        net_params['regional'] = state['meta'].get('regional', False)
        net_params['whitening'] = state['meta'].get('whitening', False)
        net_params['mean'] = state['meta']['mean']
        net_params['std'] = state['meta']['std']
        net_params['pretrained'] = False

        # load network
        net = init_network(net_params)
        net.load_state_dict(state['state_dict'])

        # if whitening is precomputed
        if 'Lw' in state['meta']:
            net.meta['Lw'] = state['meta']['Lw']

        print(">>>> loaded network: ")
        print(net.meta_repr())

    # loading offtheshelf network
    elif args.network_offtheshelf is not None:

        # parse off-the-shelf parameters
        offtheshelf = args.network_offtheshelf.split('-')
        net_params = {}
        net_params['architecture'] = offtheshelf[0]
        net_params['pooling'] = offtheshelf[1]
        net_params['local_whitening'] = 'lwhiten' in offtheshelf[2:]
        net_params['regional'] = 'reg' in offtheshelf[2:]
        net_params['whitening'] = 'whiten' in offtheshelf[2:]
        net_params['pretrained'] = True

        # load off-the-shelf network
        print(">> Loading off-the-shelf network:\n>>>> '{}'".format(
            args.network_offtheshelf))
        net = init_network(net_params)
        print(">>>> loaded network: ")
        print(net.meta_repr())

    # setting up the multi-scale parameters
    ms = list(eval(args.multiscale))
    if len(ms) > 1 and net.meta['pooling'] == 'gem' and not net.meta[
            'regional'] and not net.meta['whitening']:
        msp = net.pool.p.item()
        print(">> Set-up multiscale:")
        print(">>>> ms: {}".format(ms))
        print(">>>> msp: {}".format(msp))
    else:
        msp = 1

    # moving network to gpu and eval mode
    net.cuda()
    net.eval()

    # set up the transform
    normalize = transforms.Normalize(mean=net.meta['mean'],
                                     std=net.meta['std'])
    transform = transforms.Compose([transforms.ToTensor(), normalize])

    # compute whitening
    if args.whitening is not None:
        start = time.time()

        if 'Lw' in net.meta and args.whitening in net.meta['Lw']:

            print('>> {}: Whitening is precomputed, loading it...'.format(
                args.whitening))

            if len(ms) > 1:
                Lw = net.meta['Lw'][args.whitening]['ms']
            else:
                Lw = net.meta['Lw'][args.whitening]['ss']

        else:

            # if we evaluate networks from path we should save/load whitening
            # not to compute it every time
            if args.network_path is not None:
                whiten_fn = args.network_path + '_{}_whiten'.format(
                    args.whitening)
                if len(ms) > 1:
                    whiten_fn += '_ms'
                whiten_fn += '.pth'
            else:
                whiten_fn = None

            if whiten_fn is not None and os.path.isfile(whiten_fn):
                print('>> {}: Whitening is precomputed, loading it...'.format(
                    args.whitening))
                Lw = torch.load(whiten_fn)

            else:
                print('>> {}: Learning whitening...'.format(args.whitening))

                # loading db
                db_root = os.path.join(get_data_root(), 'train',
                                       args.whitening)
                ims_root = os.path.join(db_root, 'ims')
                db_fn = os.path.join(db_root,
                                     '{}-whiten.pkl'.format(args.whitening))
                with open(db_fn, 'rb') as f:
                    db = pickle.load(f)
                images = [
                    cid2filename(db['cids'][i], ims_root)
                    for i in range(len(db['cids']))
                ]

                # extract whitening vectors
                print('>> {}: Extracting...'.format(args.whitening))
                wvecs = extract_vectors(net,
                                        images,
                                        args.image_size,
                                        transform,
                                        ms=ms,
                                        msp=msp)

                # learning whitening
                print('>> {}: Learning...'.format(args.whitening))
                wvecs = wvecs.numpy()
                m, P = whitenlearn(wvecs, db['qidxs'], db['pidxs'])
                Lw = {'m': m, 'P': P}

                # saving whitening if whiten_fn exists
                if whiten_fn is not None:
                    print('>> {}: Saving to {}...'.format(
                        args.whitening, whiten_fn))
                    torch.save(Lw, whiten_fn)

        print('>> {}: elapsed time: {}'.format(args.whitening,
                                               htime(time.time() - start)))

    else:
        Lw = None

    # evaluate on test datasets
    datasets = args.datasets.split(',')
    for dataset in datasets:
        start = time.time()

        print('>> {}: Extracting...'.format(dataset))

        # extract database and query vectors
        print('>> {}: database images...'.format(dataset))
        images = get_imlist("E:\\PycharmProjects\\image-retrieval\\holiday2\\")
        names = []
        for i, img_path in enumerate(images):
            img_name = os.path.split(img_path)[1]
            print(img_name)
            names.append(img_name)
        # prepare config structure for the test dataset
        # cfg = configdataset(dataset, os.path.join(get_data_root(), 'test'))
        # images = [cfg['im_fname'](cfg, i) for i in range(cfg['n'])]
        # try:
        #     bbxs = [tuple(cfg['gnd'][i]['bbx']) for i in range(cfg['nq'])]
        # except:
        #     bbxs = None  # for holidaysmanrot and copydays

        # names = []
        # for i, img_path in enumerate(images):
        #     img_name = os.path.split(img_path)[1]
        #     print(img_name)
        #     names.append(img_name)

        # extract database and query vectors
        print('>> {}: database images...'.format(dataset))
        vecs = extract_vectors(net,
                               images,
                               args.image_size,
                               transform,
                               ms=ms,
                               msp=msp)

        # convert to numpy
        vecs = vecs.numpy()
        vecs = vecs.T
        print("--------------------------------------------------")
        print("      writing feature extraction results ...")
        print("--------------------------------------------------")
        output = "gem_res_holiday_3.h5"
        h5f = h5py.File(output, 'w')
        h5f.create_dataset('dataset_1', data=vecs)
        h5f.create_dataset('dataset_2', data=np.string_(names))
        h5f.close()

        print('>> {}: elapsed time: {}'.format(dataset,
                                               htime(time.time() - start)))
Example #29
0
def testOxfordParisHolidays(net, eConfig):

    #datasets = eConfig['test-datasets'].split(',')
    #results = []
    #
    #for dataset in datasets:
    #    results.append((dataset, np.random.rand(1)[0]))
    #
    #return results

    print('>> Evaluating network on test datasets...')

    # for testing we use image size of max 1024
    image_size = 1024

    # setting up the multi-scale parameters
    ms = [1]
    msp = 1
    if (eConfig['multiscale']):
        ms = [1, 1. / math.sqrt(2), 1. / 2]
        if net.meta['pooling'] == 'gem' and net.whiten is None:
            msp = net.pool.p.data.tolist()[0]

    # moving network to gpu and eval mode
    net.cuda()
    net.eval()
    # set up the transform
    normalize = transforms.Normalize(mean=net.meta['mean'],
                                     std=net.meta['std'])
    transform = transforms.Compose([transforms.ToTensor(), normalize])

    # compute whitening
    if eConfig['whitening']:

        start = time.time()

        print('>> {}: Learning whitening...'.format(eConfig['test-whiten']))

        # loading db
        db_root = os.path.join(get_data_root(), 'train',
                               eConfig['test-whiten'])
        ims_root = os.path.join(db_root, 'ims')
        db_fn = os.path.join(db_root,
                             '{}-whiten.pkl'.format(eConfig['test-whiten']))
        with open(db_fn, 'rb') as f:
            db = pickle.load(f)
        images = [
            cid2filename(db['cids'][i], ims_root)
            for i in range(len(db['cids']))
        ]

        # extract whitening vectors
        print('>> {}: Extracting...'.format(eConfig['test-whiten']))
        wvecs = extract_vectors(net,
                                images,
                                image_size,
                                transform,
                                ms=ms,
                                msp=msp)

        # learning whitening
        print('>> {}: Learning...'.format(eConfig['test-whiten']))
        wvecs = wvecs.numpy()
        m, P = whitenlearn(wvecs, db['qidxs'], db['pidxs'])
        Lw = {'m': m, 'P': P}

        print('>> {}: elapsed time: {}'.format(eConfig['test-whiten'],
                                               htime(time.time() - start)))

    else:
        Lw = None

    # evaluate on test datasets
    datasets = eConfig['test-datasets'].split(',')
    results = []

    for dataset in datasets:
        start = time.time()

        if (dataset != 'holidays' and dataset != 'rholidays'):
            print('>> {}: Extracting...'.format(dataset))

            # prepare config structure for the test dataset
            cfg = configdataset(dataset, os.path.join(get_data_root(), 'test'))
            images = [cfg['im_fname'](cfg, i) for i in range(cfg['n'])]
            qimages = [cfg['qim_fname'](cfg, i) for i in range(cfg['nq'])]
            bbxs = [tuple(cfg['gnd'][i]['bbx']) for i in range(cfg['nq'])]

            if (dataset == 'oxford105k' or dataset == 'paris106k'):
                images.extend(cfg['distractors'])

            # extract database and query vectors
            print('>> {}: database images...'.format(dataset))
            vecs = extract_vectors(net,
                                   images,
                                   image_size,
                                   transform,
                                   ms=ms,
                                   msp=msp)
            print('>> {}: query images...'.format(dataset))
            qvecs = extract_vectors(net,
                                    qimages,
                                    image_size,
                                    transform,
                                    bbxs,
                                    ms=ms,
                                    msp=msp)
            print('>> {}: Evaluating...'.format(dataset))

            # convert to numpy
            vecs = vecs.numpy()
            qvecs = qvecs.numpy()

            # search, rank, and print
            scores = np.dot(vecs.T, qvecs)
            ranks = np.argsort(-scores, axis=0)
            results.append(
                compute_map_and_print(
                    dataset +
                    ('+ multiscale' if eConfig['multiscale'] else ''), ranks,
                    cfg['gnd']))

            if Lw is not None:
                # whiten the vectors
                vecs_lw = whitenapply(vecs, Lw['m'], Lw['P'])
                qvecs_lw = whitenapply(qvecs, Lw['m'], Lw['P'])

                # search, rank, and print
                scores = np.dot(vecs_lw.T, qvecs_lw)
                ranks = np.argsort(-scores, axis=0)
                results.append(
                    compute_map_and_print(dataset + ' + whiten', ranks,
                                          cfg['gnd']))

        else:
            results.append(testHolidays(net, eConfig, dataset, Lw))

        print('>> {}: elapsed time: {}'.format(dataset,
                                               htime(time.time() - start)))

    return results
Example #30
0
def main():
    args = parser.parse_args()

    # check if test dataset are downloaded
    # and download if they are not
    download_train(get_data_root())
    download_test(get_data_root())

    # setting up the visible GPU
    os.environ['CUDA_VISIBLE_DEVICES'] = args.gpu_id

    # loading network from path
    if args.network_path is not None:
        print(">> Loading network:\n>>>> '{}'".format(args.network_path))
        state = torch.load(args.network_path)
        net = init_network(model=state['meta']['architecture'],
                           pooling=state['meta']['pooling'],
                           whitening=state['meta']['whitening'],
                           mean=state['meta']['mean'],
                           std=state['meta']['std'],
                           pretrained=False)
        net.load_state_dict(state['state_dict'])
        print(">>>> loaded network: ")
        print(net.meta_repr())

    # loading offtheshelf network
    elif args.network_offtheshelf is not None:
        offtheshelf = args.network_offtheshelf.split('-')
        if len(offtheshelf) == 3:
            if offtheshelf[2] == 'whiten':
                offtheshelf_whiten = True
            else:
                raise (RuntimeError(
                    "Incorrect format of the off-the-shelf network. Examples: resnet101-gem | resnet101-gem-whiten"
                ))
        else:
            offtheshelf_whiten = False
        print(">> Loading off-the-shelf network:\n>>>> '{}'".format(
            args.network_offtheshelf))
        net = init_network(model=offtheshelf[0],
                           pooling=offtheshelf[1],
                           whitening=offtheshelf_whiten)
        print(">>>> loaded network: ")
        print(net.meta_repr())

    # setting up the multi-scale parameters
    ms = [1]
    msp = 1
    if args.multiscale:
        ms = [1, 1. / math.sqrt(2), 1. / 2]
        if net.meta['pooling'] == 'gem' and net.whiten is None:
            msp = net.pool.p.data.tolist()[0]

    # moving network to gpu and eval mode
    net.cuda()
    net.eval()
    # set up the transform
    normalize = transforms.Normalize(mean=net.meta['mean'],
                                     std=net.meta['std'])
    transform = transforms.Compose([transforms.ToTensor(), normalize])

    # compute whitening
    if args.whitening is not None:
        start = time.time()

        print('>> {}: Learning whitening...'.format(args.whitening))

        # loading db
        db_root = os.path.join(get_data_root(), 'train', args.whitening)
        ims_root = os.path.join(db_root, 'ims')
        db_fn = os.path.join(db_root, '{}-whiten.pkl'.format(args.whitening))
        with open(db_fn, 'rb') as f:
            db = pickle.load(f)
        images = [
            cid2filename(db['cids'][i], ims_root)
            for i in range(len(db['cids']))
        ]

        # extract whitening vectors
        print('>> {}: Extracting...'.format(args.whitening))
        wvecs = extract_vectors(net,
                                images,
                                args.image_size,
                                transform,
                                ms=ms,
                                msp=msp)

        # learning whitening
        print('>> {}: Learning...'.format(args.whitening))
        wvecs = wvecs.numpy()
        m, P = whitenlearn(wvecs, db['qidxs'], db['pidxs'])
        Lw = {'m': m, 'P': P}

        print('>> {}: elapsed time: {}'.format(args.whitening,
                                               htime(time.time() - start)))
    else:
        Lw = None

    datasets = args.datasets.split(',')
    for dataset in datasets:
        start = time.time()

        print('>> {}: Extracting...'.format(dataset))

        if dataset == 'reco':
            images, qimages = landmark_recognition_dataset()
            bbxs = [None for x in qimages]

        elif dataset == 'retr':
            images, _ = landmark_retrieval_dataset()
            qimages = []
            bbxs = [None for x in qimages]

        else:
            # prepare config structure for the test dataset
            cfg = configdataset(dataset, os.path.join(get_data_root(), 'test'))
            images = [cfg['im_fname'](cfg, i) for i in range(cfg['n'])]
            qimages = [cfg['qim_fname'](cfg, i) for i in range(cfg['nq'])]
            bbxs = [tuple(cfg['gnd'][i]['bbx']) for i in range(cfg['nq'])]

        with open('%s_fnames.pkl' % dataset, 'wb') as f:
            pickle.dump([images, qimages], f)

        # extract database and query vectors
        print('>> {}: database images...'.format(dataset))
        vecs = extract_vectors(net,
                               images,
                               args.image_size,
                               transform,
                               ms=ms,
                               msp=msp)
        vecs = vecs.numpy()
        print('>> saving')
        np.save('{}_vecs.npy'.format(dataset), vecs)

        if len(qimages) > 0:
            print('>> {}: query images...'.format(dataset))
            qvecs = extract_vectors(net,
                                    qimages,
                                    args.image_size,
                                    transform,
                                    bbxs=bbxs,
                                    ms=ms,
                                    msp=msp)
            qvecs = qvecs.numpy()
            np.save('{}_qvecs.npy'.format(dataset), qvecs)

        if Lw is not None:
            # whiten the vectors
            vecs_lw = whitenapply(vecs, Lw['m'], Lw['P'])
            qvecs_lw = whitenapply(qvecs, Lw['m'], Lw['P'])

            # TODO

        print('>> {}: elapsed time: {}'.format(dataset,
                                               htime(time.time() - start)))