Пример #1
0
def same_class(
    query_dataset_name: str,
    queried_dataset_name: str,
    query_embeddings_name: str,
    queried_embeddings_name: str,
    k: int,
    distance: str,
    n_gpu: int,
    processes: int,
):
    """Cross-modal image recall of same class elements."""
    click.echo(
        "Calculating cross modal class recall@{} for the {} and {} embeddings".
        format(k, query_embeddings_name, queried_embeddings_name))
    query_dataset, queried_dataset = (
        get_dataset(query_dataset_name),
        get_dataset(queried_dataset_name),
    )
    query_embeddings = load_embeddings(query_embeddings_name)
    queried_embeddings = load_embeddings(queried_embeddings_name)
    average_class_recall_parallel(
        query_dataset,
        queried_dataset,
        query_embeddings,
        queried_embeddings,
        k,
        distance,
        n_gpu,
        processes,
    )
Пример #2
0
def retrieve_top_k(
    model,
    query_image_filename,
    query_dataset_name,
    queried_dataset_name,
    queried_embeddings_name,
    k=16,
    distance="cosine",
    n_gpu=0,
):
    """Query the embeddings for a dataset with the given image. The image is embedded with the given model. Pairwise
    distances to the query image are computed for each embedding in the dataset, so the embeddings created by `model`
    must have the same length as the ones in the embedding directory. The `k` most similar images are displayed.

    Args:
      model: name of the model to be used for embedding the DataSet.
      query_image_filename: the complete file path and name to the image to be used as query. The images in the
    dataset that are most similar to this image will be displayed.
      query_dataset_name: name of the registered dataset to which the query image belongs.
      queried_dataset_name: name of the registered dataset to be queried.
      queried_embeddings_name: the name of the pickle file where the embeddings will be saved.
      k: the number of most similar images that wil be displayed. (Default value = 16)
      distance: which distance function to be used for nearest neighbor computation. Either 'cosine' or 'pairwise' (Default value = "cosine")
      n_gpu: number of available GPUs. If zero, the CPU will be used. (Default value = 0)

    Returns:

    """
    device = get_device(n_gpu)
    # Load data
    query_dataset = get_dataset(query_dataset_name)
    queried_dataset = get_dataset(queried_dataset_name)
    # Load embeddings from pickle directory
    queried_embeddings = load_embeddings(queried_embeddings_name).to(device)
    # Get the query image and create the embedding for it
    image, image_class = query_dataset[query_image_filename]
    # Send elements to the specified device
    image, model = [var.to(device) for var in [image, model]]
    query_embedding = model(image.unsqueeze(
        0))  # unsqueeze to add the missing dimension expected by the model
    # Compute the distance to the query embedding for all images in the Dataset
    queried_embeddings, query_embedding = [
        var.to(device) for var in [queried_embeddings, query_embedding]
    ]
    top_distances, top_indices = get_top_k(query_embedding, queried_embeddings,
                                           k, distance)
    plot_image_retrieval(image, image_class, query_dataset, queried_dataset,
                         top_distances, top_indices)
Пример #3
0
def create_embeddings(model, dataset_name, embeddings_name, batch_size,
                      workers, n_gpu):
    """Creates embedding vectors for each element in the given DataSet, and saves a single Pytorch tensor of shape
    `len(dataset), embeddings_size` with all the embeddings in a file with the given name.

    Args:
      model: name of the model to be used for embedding the DataSet.
      dataset_name: name of the registered dataset which will be embedded.
      embeddings_name: the name of the pickle directory where the embeddings will be saved.
      batch_size: size of batches for the embedding process.
      workers: number of data loader workers.
      n_gpu: number of available GPUs. If zero, the CPU will be used.

    Returns:

    """
    device = get_device(n_gpu)
    model = model.eval().to(device)
    dataset = get_dataset(dataset_name)
    data_loader = DataLoader(dataset,
                             batch_size=batch_size,
                             shuffle=False,
                             num_workers=workers)
    embedding_list = [
        model(data[0].to(device)
              )  # model output sent to 'cpu' to prevent gpu memory overflow
        for data in tqdm(
            data_loader, total=len(data_loader), desc="Embedding data")
    ]
    torch.save(
        torch.cat(embedding_list).to("cpu"),
        open(get_path("embeddings", "{}.pt".format(embeddings_name)), "wb"))
Пример #4
0
def same_class(
    dataset_name: str,
    embeddings_name: str,
    test_split: float,
    k: int,
    distance: str,
    n_gpu: int,
) -> None:
    """Image recall of same class elements."""
    click.echo("Calculating class recall@{} for {} embeddings".format(
        k, embeddings_name))
    dataset = get_dataset(dataset_name)
    embeddings = load_embeddings(embeddings_name)
    (
        query_embeddings,
        queried_embeddings,
        query_indices,
        queried_indices,
    ) = random_simple_split(embeddings, test_split)
    query_dataset, queried_dataset = (
        Subset(dataset, query_indices),
        Subset(dataset, queried_indices),
    )
    average_class_recall(
        query_dataset,
        queried_dataset,
        query_embeddings,
        queried_embeddings,
        k,
        distance,
        n_gpu,
    )
Пример #5
0
 def initial_model(self):
     """ """
     dataset = get_dataset(self.dataset_name)
     image_dimension = dataset[0][0].shape[1]
     return HOGGCN(
         self.dataset.classes_dataframe,
         image_dimension,
         self.in_channels,
         self.cell_size,
         self.bins,
         self.signed_gradients,
         self.processes,
     )
Пример #6
0
def plot_embedding_tsne(dataset_name, embeddings_name, load_projection=False):
    """Plot a 2D projection of embeddings in the specified embedding directory using plotly.

    Args:
      dataset_name: name of the registered dataset which will be embedded.
      embeddings_name: the name of the directory where the batch pickles will be saved.
      load_projection: load projections from pickles. (Default value = False)

    Returns:

    """
    from vscvs.embeddings import load_embeddings  # import here to avoid circular import

    dataset = get_dataset(dataset_name)
    embeddings = load_embeddings(embeddings_name).to("cpu")
    projection_pickle_dir = get_path("embeddings", embeddings_name)
    if load_projection:
        click.echo("Loading existing 2D projection from pickle.")
        projection = pickle.load(
            open(os.path.join(projection_pickle_dir, "tsne.pickle"), "rb"))
        dataset_class_names = pickle.load(
            open(
                os.path.join(projection_pickle_dir, "tsne_class_names.pickle"),
                "rb"))
    else:
        click.echo("Creating 2D projection of the embeddings using TSNE")
        projection = TSNE(n_components=2).fit_transform(embeddings)
        dataset_class_names = [
            dataset.classes[tup[1]]
            for tup in tqdm(dataset, desc="Retrieving image class names")
        ]
        pickle.dump(
            projection,
            open(os.path.join(projection_pickle_dir, "tsne.pickle"), "wb"))
        pickle.dump(
            dataset_class_names,
            open(
                os.path.join(projection_pickle_dir, "tsne_class_names.pickle"),
                "wb"))
    trace = go.Scattergl(  # plot the resulting projection using plotly
        x=projection[:, 0],
        y=projection[:, 1],
        text=dataset_class_names,
        mode="markers",
        marker=dict(size=16,
                    color=np.random.randn(len(projection)),
                    colorscale="Viridis"),
    )
    data = [trace]
    plot(data)
Пример #7
0
def display_sample_batch(dataset_name, batch_size, workers):
    """Output a random batch form the specified dataset.

    Args:
      dataset_name: name of the registered dataset which will be embedded.
      batch_size: size of batches for the embedding process.
      workers: number of data loader workers.

    Returns:

    """
    dataset = get_dataset(dataset_name)  # load data
    data_loader = DataLoader(dataset,
                             batch_size=batch_size,
                             shuffle=True,
                             num_workers=workers)  # create the data_loader
    plot_image_batch(next(iter(data_loader)))  # plot the batch
Пример #8
0
def create_metadata_tsv(dataset_name):
    """Creates a metadata TSV file that can be used with any embeddings of the given dataset to be displayed in the
    Tensorboard embedding projector.

    Args:
      dataset_name: name of the registered DatasetFolder which will be embedded.

    Returns:

    """
    dataset = get_dataset(dataset_name)
    with open(get_path("embeddings", "{}.tsv".format(dataset_name)), "w") as f:
        writer = csv.DictWriter(f, ["class_idx", "class", "path"],
                                delimiter="\t")
        writer.writeheader()
        writer.writerows([{
            "class_idx": idx,
            "class": dataset.classes[idx],
            "path": path
        } for path, idx in tqdm(dataset.samples, desc="Creating tsv")])
Пример #9
0
def sprite_tensor(dataset_name, size=(64, 64)):
    """Create an image tensor that can be used to create a Tensorboard embedding projector sprite image for the dataset
    corresponding to `dataset_name`. This image tensor must have a shape of `(N, C, H, W)` where `N` is the length of
    the dataset, `C` is the number of color channels, and `H` and `W` are the height and width dimensions for the
    sprite components. Dataset elements must be reduced in size in order to fit in memory when using Tensorboard.

    Args:
      dataset_name: the name of the dataset from which the sprite tensor will be created.
      size: the dimension of the resulting sprite image components. If `size` is a sequence like `(h, w)`, the
    output size will be matched to this. If size is an int, the smaller edge of the image will be matched to this
    number. i.e, if `height > width`, then image will be rescaled to `(size * height / width, size)`. (Default value = (64)
      64): 

    Returns:
      the sprite image tensor, with the dimensions specified above.

    """
    from vscvs.datasets import get_dataset

    dataset = get_dataset(dataset_name, normalize=False, size=size)
    data_loader = DataLoader(dataset, batch_size=len(dataset), shuffle=False)
    return next(iter(data_loader))[0]
Пример #10
0
 def initial_model(self):
     """ """
     dataset = get_dataset(self.dataset_name)
     return GCNClassification(len(dataset.classes), 11)
Пример #11
0
def sketchy_suite(
    dataset_name: str,
    photo_embeddings_name: str,
    sketch_embeddings_name: str,
    test_split: float,
    top_k: List[int],
    distance: str,
    n_gpu: int,
) -> None:
    """Same mode recall for photos and sketches, as well as cross-modal recall using
    both modes as queries.
    """
    photo_dataset = get_dataset(f"{dataset_name}-photos")
    sketch_dataset = get_dataset(f"{dataset_name}-sketches")
    photo_embeddings = load_embeddings(photo_embeddings_name)
    sketch_embeddings = load_embeddings(sketch_embeddings_name)

    for k in top_k:
        click.echo(f"\nCalculating class recall@{k}\n\nphoto to photo:")

        (
            query_embeddings,
            queried_embeddings,
            query_indices,
            queried_indices,
        ) = random_simple_split(photo_embeddings, test_split)

        query_dataset, queried_dataset = (
            Subset(photo_dataset, query_indices),
            Subset(photo_dataset, queried_indices),
        )

        average_class_recall(  # photo to photo average class recall
            query_dataset,
            queried_dataset,
            query_embeddings,
            queried_embeddings,
            k,
            distance,
            n_gpu,
        )

        click.echo(f"\nsketch to sketch:")

        (
            query_embeddings,
            queried_embeddings,
            query_indices,
            queried_indices,
        ) = random_simple_split(sketch_embeddings, test_split)

        query_dataset, queried_dataset = (
            Subset(sketch_dataset, query_indices),
            Subset(sketch_dataset, queried_indices),
        )

        average_class_recall(  # sketch to sketch average class recall
            query_dataset,
            queried_dataset,
            query_embeddings,
            queried_embeddings,
            k,
            distance,
            n_gpu,
        )

        click.echo(f"\nphoto to sketch:")

        average_class_recall(  # photo to sketch average class recall
            photo_dataset,
            sketch_dataset,
            photo_embeddings,
            sketch_embeddings,
            k,
            distance,
            n_gpu,
        )

        click.echo(f"\nsketch to photo:")

        average_class_recall(  # sketch to photo average class recall
            sketch_dataset,
            photo_dataset,
            sketch_embeddings,
            photo_embeddings,
            k,
            distance,
            n_gpu,
        )
Пример #12
0
 def __init__(self,
              *args,
              batch_size=0,
              dataset_name=None,
              drop_last=False,
              epochs=1,
              n_gpu=0,
              parameter_dict=None,
              resume_date=None,
              resume_checkpoint=None,
              tags=None,
              train_validation_split=0.8,
              workers=6,
              **kwargs):
     """
     :param args: mixin arguments.
     :type: Tuple
     :param batch_size: batch size during training.
     :type: int
     :param dataset_name: the name of the Dataset to be used for training.
     :type: str
     :param drop_last: whether to drop the last batch if it is not the same size as `batch_size`.
     :type: bool
     :param epochs: the number of epochs used for training.
     :type: int
     :param n_gpu: number of GPUs available. Use 0 for CPU mode.
     :type: int
     :param parameter_dict: dictionary with important training parameters for logging.
     :type: Dict
     :param resume_date: date of the trainer state to be resumed. Dates must have this format: `%y-%m-%dT%H-%M`.
     :type: str
     :param resume_checkpoint: name of the model checkpoint to be loaded.
     :type: str
     :param tags: optional tags for model checkpoint and tensorboard logs organization.
     :type: List[int]
     :param train_validation_split: proportion of the training set that will be used for actual
     training. The remaining data will be used as the validation set.
     :type: float
     :param workers: number of workers for data_loader.
     :type: int
     :param kwargs: mixin keyword arguments.
     :type: Dict
     """
     date = datetime.now()
     self.batch_size = batch_size
     self.checkpoint_directory = get_checkpoint_path(self.trainer_id,
                                                     *tags,
                                                     date=date)
     self.dataset = get_dataset(dataset_name)
     self.dataset_name = dataset_name
     self.device = get_device(n_gpu)
     self.epochs = epochs
     self.log_directory = get_log_directory(self.trainer_id,
                                            *tags,
                                            date=date)
     self.model = self.initial_model
     self.parameter_dict = parameter_dict
     self.resume_date = datetime.strptime(
         resume_date,
         CHECKPOINT_NAME_FORMAT) if resume_date else resume_date
     self.resume_checkpoint = resume_checkpoint
     self.start_epoch = 1
     self.tags = tags
     self._load_checkpoint()
     self.epoch = self.start_epoch
     self.step = 0
     self.train_loader, self.validation_loader = self._create_data_loaders(
         train_validation_split, batch_size, workers, drop_last)
     self.trainer_engine = self._create_trainer_engine()
     self.evaluator_engine = self._create_evaluator_engine()
     self.timer = self._create_timer()
     self.progressbar = self._progressbar
     self.writer = SummaryWriter(self.log_directory)
     self._add_event_handlers()
     self._add_model_checkpoint_savers()
     super().__init__(*args, **kwargs)