Exemplo n.º 1
0
    def test_complex_mean(self, concept: Concept):
        """Test obtaining the mean concept embedding, meaning the optimal
        mean hyperplane."""

        concept_args = dict(concept=concept, model_stump=None)
        for desc, (embs, (m_w, m_b)) in self.INTUITIVE_MEAN_EXAMPLES.items():
            m_w: np.ndarray = np.array(m_w)
            embeddings = [
                ConceptEmbedding(normal_vec=w,
                                 support_factor=b,
                                 **concept_args) for w, b in embs
            ]
            # Actual routine
            m_emb: ConceptEmbedding = ConceptEmbedding.mean_by_angle(
                embeddings)
            context_info = (("context:\n  mean embedding: ({}, {})"
                             "\n  in embeddings ({}) as (normal vec, support, "
                             "scaling):\n   {}").format(
                                 m_emb.normal_vec, m_emb.support_factor, desc,
                                 [(e.normal_vec, e.support_factor,
                                   e.scaling_factor) for e in embeddings]))

            # Format checks
            assert m_emb.normal_vec.shape == embeddings[0].normal_vec.shape
            assert np.array(m_emb.support_factor).shape == np.array(
                embeddings[0].support_factor).shape

            # Value checks
            assert np.allclose(m_emb.normal_vec, m_w), \
                ("Wrong mean normal weight: expected {}, but was {}; {}"
                 .format(m_w, m_emb.normal_vec, context_info))
            assert np.allclose(m_emb.support_factor, m_b), \
                ("Wrong mean normal bias: expected {}, but was {}; {}"
                 .format(m_b, m_emb.support_factor, context_info))
Exemplo n.º 2
0
 def test_distance_mean_condition(self, concept: Concept):
     """Test that the mean embedding by distance really fulfills the
     distance condition.
     This is that at any point in space the distance of the mean embedding is
     the mean of the distances of the other embeddings."""
     # test points for testing the distance condition in several dimensions
     concept_args = dict(concept=concept, model_stump=None)
     for desc, (embs, _) in self.DISTANCE_MEAN_EXAMPLES.items():
         embeddings = [
             ConceptEmbedding(normal_vec=w,
                              support_factor=b,
                              **concept_args) for w, b in embs
         ]
         # Actual routine
         m_emb: ConceptEmbedding = \
             ConceptEmbedding.mean_by_distance(embeddings)
         dims: int = m_emb.normal_vec.size
         test_points = self.TEST_POINTS_nD[dims]
         for point in test_points:
             dist_mean: float = m_emb.distance(point)
             dists: List[float] = [e.distance(point) for e in embeddings]
             mean_dist: float = float(np.mean(dists))
             assert np.allclose(dist_mean, mean_dist), \
                 (("In point {},  distance of mean ({}) is not mean of "
                   "distances {} ({}) for\n  in embeddings: {}:\n   {}"
                   "\n  mean embedding: {}")
                  .format(point, dist_mean, dists, mean_dist,
                          desc, [(e.normal_vec, e.support_factor)
                                 for e in embeddings],
                          (m_emb.normal_vec, m_emb.support_factor)))
Exemplo n.º 3
0
    def test_complex_mean_condition(self, concept: Concept):
        """Test obtaining the mean concept embedding, meaning the optimal mean
        hyperplane.
        The condition for the more complex mean here is that at any point the
        mean distances to the hyperplanes along the normal vector equal the
        (unscaled!) distance to the mean hyperplane."""
        concept_args = dict(concept=concept, model_stump=None)
        for desc, (embs, _) in self.INTUITIVE_MEAN_EXAMPLES.items():
            embs: List[ConceptEmbedding] = \
                [ConceptEmbedding(normal_vec=w, support_factor=b,
                                  **concept_args) for w, b in embs]
            # Actual routine
            m_emb: ConceptEmbedding = ConceptEmbedding.mean_by_angle(embs) \
                .normalize().to_pos_scaling()
            context_info = ((
                "embeddings in context as (normal vec, support, scaling):"
                "\n  mean embedding: ({}, {}, {})"
                "\n  in embeddings ({}):\n   {}").format(
                    m_emb.normal_vec, m_emb.support_factor,
                    m_emb.scaling_factor, desc,
                    [(e.normal_vec, e.support_factor, e.scaling_factor)
                     for e in embs]))

            for point in self.TEST_POINTS_nD[m_emb.normal_vec.size]:
                # The normalized vectors with no scaling for distance
                # calculation
                # pylint: disable=no-member
                normed_embs: List[ConceptEmbedding] = \
                    [e.normalize().to_pos_scaling().forget_scaling()
                     for e in embs]
                # pylint: enable=no-member
                # The for each hyperplane the cosine of its angle to the mean
                # hyperplane
                cos_angles = [
                    cos_angle(e.normal_vec, m_emb.normal_vec)
                    for e in normed_embs
                ]
                # Distance from each hyperplane to the point along the
                # hyperplane's normal vec
                plane_to_pt_dists: List[float] = [
                    e.distance(point) for e in normed_embs
                ]
                # Distances from the point to each hyperplane along the mean
                # normal vec
                dists: List[float] = [
                    d / cos_a
                    for d, cos_a in zip(plane_to_pt_dists, cos_angles)
                ]
                # Condition: The distances along the mean normal vec should
                # sum up to the mean dist
                dist_to_mean = m_emb.forget_scaling().distance(point)
                assert np.allclose(dist_to_mean, np.mean(dists)), \
                    (("In point {}, distance to mean hyperplane is not the "
                      "mean distance to the other hyperplanes along the mean "
                      "hyperplane normal vector!"
                      "\ndists to hyperplanes along mean normal vec: {}, "
                      "mean: {};\nunscaled dist to mean hyperplane: {}; {}")
                     .format(point, dists, np.mean(dists), dist_to_mean,
                             context_info))
Exemplo n.º 4
0
    def test_scale(self):
        """Test fundamental properties of applying the scaling factor."""
        # normal_vec, support_factor, scaling_factor
        orig = ([3, 4], 1, 1)
        normal_vec, support_factor, scaling_factor = orig
        # noinspection PyTypeChecker
        emb = ConceptEmbedding(normal_vec=normal_vec,
                               support_factor=support_factor,
                               scaling_factor=scaling_factor)

        # Scaling yields new instance and old one is not changed:
        assert emb is not emb.scale(), "Scaling did not yield new instance"
        assert np.allclose(emb.normal_vec, np.array(normal_vec))
        assert np.allclose(emb.support_factor, np.array(support_factor))
        assert np.allclose(emb.scaling_factor, np.array(scaling_factor))

        # Scaling embedding of scaling factor 1 does nothing
        scaled_unchanged_emb = emb.scale()
        assert np.allclose(emb.normal_vec, scaled_unchanged_emb.normal_vec)
        assert np.allclose(emb.support_factor,
                           scaled_unchanged_emb.support_factor)
        assert np.allclose(emb.scaling_factor,
                           scaled_unchanged_emb.scaling_factor)

        # Normalization and then scaling should yield the same embedding:
        backscaled_emb = emb.normalize().scale()
        for key, (expected, obtained) in \
                {"normal_vec": (emb.normal_vec, backscaled_emb.normal_vec),
                 "support_factor": (emb.support_factor,
                                    backscaled_emb.support_factor),
                 "scaling_factor": (emb.scaling_factor,
                                    backscaled_emb.scaling_factor)
                 }.items():
            assert np.allclose(obtained, expected), \
                ("Wrong normalized {}: expected {}, but was {}"
                 .format(key, expected, obtained))

        # Simple scaling example: scale by 2
        emb.scaling_factor = 2
        new = ([6, 8], 0.5, 1)
        normal_vec, support_factor, scaling_factor = new
        scaled_emb = emb.scale()
        assert np.allclose(normal_vec, scaled_emb.normal_vec)
        assert np.allclose(support_factor, scaled_emb.support_factor)
        assert np.allclose(scaling_factor, scaled_emb.scaling_factor)

        # Another scaling example: scale by -2
        emb.scaling_factor = -2
        new = ([-6, -8], -0.5, 1)
        normal_vec, support_factor, scaling_factor = new
        scaled_emb = emb.scale()
        assert np.allclose(normal_vec, scaled_emb.normal_vec)
        assert np.allclose(support_factor, scaled_emb.support_factor)
        assert np.allclose(scaling_factor, scaled_emb.scaling_factor)
Exemplo n.º 5
0
    def test_distance_mean_exceptions(self, concept: SegmentationConcept2D):
        """Test obtaining the mean concept embedding, meaning the optimal mean
        hyperplane. Are appropriate errors raised?"""
        with pytest.raises(ValueError):
            # Two parallels equally distributed around zero but with opposite
            # pos/neg sides
            concept_args = dict(concept=concept, model_stump=None)
            embeddings = [
                ConceptEmbedding(normal_vec=w,
                                 support_factor=b,
                                 **concept_args)
                for w, b in [([0, 1], 2), ([0, -1], 2)]
            ]
            ConceptEmbedding.mean_by_distance(embeddings)

        with pytest.raises(ValueError):
            ConceptEmbedding.mean_by_distance([])
Exemplo n.º 6
0
    def test_mean_results(self, concept: Concept):
        """Test obtaining the mean concept embedding by sample values."""
        concept_args = dict(concept=concept, model_stump=None)
        for desc, (embs, (m_w, m_b)) in self.INTUITIVE_MEAN_EXAMPLES.items():
            m_w: np.ndarray = np.array(m_w)
            embeddings = [
                ConceptEmbedding(normal_vec=w,
                                 support_factor=b,
                                 **concept_args) for w, b in embs
            ]
            # Actual routine
            m_emb: ConceptEmbedding = ConceptEmbedding.mean(embeddings)
            context_info = (("context:\n  mean embedding: ({}, {}, 1.)"
                             "\n  in embeddings ({}) as (normal vec, support, "
                             "scaling):\n   {}").format(
                                 m_emb.normal_vec, m_emb.support_factor, desc,
                                 [(e.normal_vec, e.support_factor,
                                   e.scaling_factor) for e in embeddings]))

            # Format checks
            assert m_emb.normal_vec.shape == embeddings[0].normal_vec.shape
            assert np.array(m_emb.support_factor).shape == np.array(
                embeddings[0].support_factor).shape

            # Value checks
            # Scaling
            expected_scaling: float = float(
                np.mean([
                    e.scaling_factor
                    for e in [e.normalize() for e in embeddings]
                ]))
            assert float(m_emb.scaling_factor) == expected_scaling, \
                ("Mean scaling wrong: expected {}., but was {}; {}"
                 .format(expected_scaling, m_emb.scaling_factor, context_info))
            # Normal vector
            assert np.allclose(m_emb.normal_vec, m_w), \
                ("Wrong mean normal vector: expected {}, but was {}; {}"
                 .format(m_w, m_emb.normal_vec, context_info))
            # Support
            assert np.allclose(m_emb.support_factor, m_b), \
                ("Wrong mean support factor: expected {}, but was {}; {}"
                 .format(m_b, m_emb.support_factor, context_info))
Exemplo n.º 7
0
    def test_distance_mean_results(self, concept: Concept):
        """Test obtaining the mean concept embedding by sample values."""

        concept_args = dict(concept=concept, model_stump=None)
        for desc, (embs, (m_w, m_b)) in self.DISTANCE_MEAN_EXAMPLES.items():
            m_w: np.ndarray = np.array(m_w)
            embeddings = [
                ConceptEmbedding(normal_vec=w,
                                 support_factor=b,
                                 **concept_args) for w, b in embs
            ]
            # Actual routine
            m_emb: ConceptEmbedding = \
                ConceptEmbedding.mean_by_distance(embeddings)
            context_info = (("context:\n  mean embedding: ({}, {}, 1.)"
                             "\n  in embeddings ({}) as (normal vec, support, "
                             "scaling):\n   {}").format(
                                 m_emb.normal_vec, m_emb.support_factor, desc,
                                 [(e.normal_vec, e.support_factor,
                                   e.scaling_factor) for e in embeddings]))

            # Format checks
            assert m_emb.normal_vec.shape == embeddings[0].normal_vec.shape
            assert np.array(m_emb.support_factor).shape == np.array(
                embeddings[0].support_factor).shape

            # Value checks
            # the embedding should be scaled
            assert float(m_emb.scaling_factor) == 1., \
                ("Mean embedding not scaled: expected 1., but was {}; {}"
                 .format(m_emb.scaling_factor, context_info))
            assert np.allclose(m_emb.normal_vec, m_w), \
                ("Wrong mean normal vector: expected {}, but was {}; {}"
                 .format(m_w, m_emb.normal_vec, context_info))
            # For all given ground truths of support factors, check them:
            if m_b is not None:
                assert np.allclose(m_emb.support_factor, m_b), \
                    ("Wrong mean support factor: expected {}, but was {}; {}"
                     .format(m_b, m_emb.support_factor, context_info))
Exemplo n.º 8
0
    def test_upper_sphere_neg_bias(self):
        """Test embedding normalization with negative bias."""
        weight = np.array([-3, 4])  # |weight| = 5
        bias = -1
        normed_weight = np.array([3 / 5, -4 / 5])
        normed_bias = 5
        # noinspection PyTypeChecker
        emb = ConceptEmbedding(normal_vec=weight, support_factor=bias)
        normed_emb = emb.unique_upper_sphere()

        # Format checks
        assert normed_emb.normal_vec.shape == emb.normal_vec.shape
        assert np.array(normed_emb.support_factor).shape == np.array(
            emb.support_factor).shape

        # Value checks
        assert np.allclose(normed_emb.normal_vec, normed_weight), \
            ("Wrong normalized weight: expected {}, but was {}"
             .format(normed_weight, normed_emb.normal_vec))
        assert np.allclose(normed_emb.support_factor, normed_bias), \
            ("Wrong normalized bias: expected {}, but was {}"
             .format(normed_bias, normed_emb.support_factor))
Exemplo n.º 9
0
def to_emb(emb_vals: Sequence[float],
           concept: Concept = None) -> ConceptEmbedding:
    """Given a tuple of (normal_vec, support_factor, scaling_factor) yield
    embedding.
    ``model_stump`` is set to None."""
    assert 2 <= len(emb_vals) <= 3
    concept_args = dict(concept=concept,
                        model_stump=None,
                        normal_vec=emb_vals[0],
                        support_factor=emb_vals[1])
    if len(emb_vals) == 3:
        concept_args["scaling_factor"] = emb_vals[2]
    return ConceptEmbedding(**concept_args)
Exemplo n.º 10
0
    def test_normalize(self):
        """Test fundamental properties of normalization."""
        normal_vec = np.array([3, 4])  # |normal_vec| = 5
        support_factor = 1
        scaling_factor = 1.
        normed_normal_vec = np.array([3 / 5, 4 / 5])
        normed_support_factor = 5
        normed_scaling_factor = 5
        # noinspection PyTypeChecker
        emb = ConceptEmbedding(normal_vec=normal_vec,
                               support_factor=support_factor)
        assert emb.scaling_factor == scaling_factor, \
            "Scaling factor wrongly initialized."
        normed_emb = emb.normalize()

        # Normalization yields new instance
        assert normed_emb is not emb, "Normalization did not yield new instance"

        # Format checks
        assert normed_emb.normal_vec.shape == emb.normal_vec.shape
        assert np.array(normed_emb.support_factor).shape == np.array(
            emb.support_factor).shape
        assert np.array(normed_emb.scaling_factor).shape == np.array(
            emb.scaling_factor).shape

        # Value checks
        for key, (expected, obtained) in \
                {"normal_vec": (normed_normal_vec, normed_emb.normal_vec),
                 "support_factor": (normed_support_factor,
                                    normed_emb.support_factor),
                 "scaling_factor": (normed_scaling_factor,
                                    normed_emb.scaling_factor)
                 }.items():
            assert np.allclose(obtained, expected), \
                ("Wrong normalized {}: expected {}, but was {}"
                 .format(key, expected, obtained))
Exemplo n.º 11
0
        if not os.path.isdir(os.path.join(args.exp_root, concept)):
            raise NotADirectoryError(
                "Concept {} in exp_root {} is not a directory".format(
                    concept, args.exp_root))
    # endregion

    print("Starting sample generation with settings:")
    key_len = max([len(k) for k in vars(args)])
    print("\n".join([("{:" + str(key_len) + "}\t{}").format(k, v)
                     for k, v in vars(args).items()]),
          flush=True)

    main_model: torch.nn.Module = model_loaders.MODELS_INFO[args.model].loader(
        torch.load(pkl_file, map_location=args.device))
    best_embeddings: Dict[str, ConceptEmbedding] = {
        concept:
        ConceptEmbedding.load(os.path.join(args.exp_root, concept, 'best.npz'))
        for concept in args.concepts
    }
    best_c_models: Dict[str, ConceptModel] = {
        concept: ConceptModel.from_embedding(emb, main_model=main_model)
        for concept, emb in best_embeddings.items()
    }

    generate(named_c_models=best_c_models,
             sample_root=args.samples_root,
             dest_root=args.dest_root,
             recursive=args.recursive,
             overwrite=args.force,
             device=args.device)
Exemplo n.º 12
0
 def to_emb(normal_vec, support_factor, scaling_factor):
     """Shorthand to concept embedding creation"""
     return ConceptEmbedding(normal_vec=normal_vec,
                             support_factor=support_factor,
                             scaling_factor=scaling_factor,
                             **args)
Exemplo n.º 13
0
 def test_complex_mean_exceptions(self):
     """Test obtaining the mean concept embedding, meaning the optimal
     mean hyperplane. Are appropriate errors raised?"""
     with pytest.raises(ValueError):
         ConceptEmbedding.mean_by_angle([])