File size: 2,308 Bytes
c881b77
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
"""Claim 1 verification: GICDM out-of-sample generated-point scaling (Eq. 1, Algorithm 1).

Test scenario (Figure 1 of paper): real samples drawn from a 60/40 mixture of two
hyperspheres with radii (r1, r2); generated samples from a mixture with swapped
radii and proportions. The two sets are disjoint, so all fidelity/coverage metrics
should score 0 in the ideal case. Standard metrics fail in high dimension due to
hubness; GICDM-corrected metrics should remain ~0.
"""
import numpy as np
import sys, os
sys.path.insert(0, os.path.dirname(__file__))
from gicdm_core import (pairwise_sq_dists, icdm_scaling, gicdm,
                        clipped_density, clipped_coverage, hubness_stats)


def sample_mixture_spheres(d, n, r1, r2, p1):
    n1 = int(round(p1 * n))
    n2 = n - n1
    def sphere(r, m):
        v = np.random.normal(size=(m, d))
        v /= np.linalg.norm(v, axis=1, keepdims=True)
        return v * r
    return np.vstack([sphere(r1, n1), sphere(r2, n2)])


def run(d, n, seed=0):
    np.random.seed(seed)
    Xr = sample_mixture_spheres(d, n, 3.0, 5.0, 0.6)
    # swapped radii & proportions
    Xg = sample_mixture_spheres(d, n, 5.0, 3.0, 0.4)
    K1, K2 = 5, 50  # K2 = 10*K1

    # raw metric
    cd_raw = clipped_density(Xr, Xg, k=5)
    cc_raw = clipped_coverage(Xr, Xg, k=5)

    # GICDM-corrected
    D_final, keep, Drr_gicdm = gicdm(Xr, Xg, K1, K2)
    dissim = (D_final, Drr_gicdm)  # (generated-to-real, real-to-real) GICDM dissimilarities
    cd_gicdm = clipped_density(Xr, Xg, k=5, dissim=dissim, keep=keep)
    cc_gicdm = clipped_coverage(Xr, Xg, k=5, dissim=dissim, keep=keep)

    # Hubness in raw real-real space
    h5_raw, A5_raw = hubness_stats(pairwise_sq_dists(Xr), k=5)

    return dict(d=d, n=n, cd_raw=cd_raw, cc_raw=cc_raw,
                cd_gicdm=cd_gicdm, cc_gicdm=cc_gicdm,
                kept=float(keep.mean()), h5_raw=h5_raw, A5_raw=A5_raw)


if __name__ == "__main__":
    import json
    out = []
    for d in [10, 50, 100, 500, 1000]:
        r = run(d, 1000, seed=42)
        out.append(r)
        print(f"d={d:5d}  CD raw={r['cd_raw']:.3f} GICDM={r['cd_gicdm']:.3f} | "
              f"CC raw={r['cc_raw']:.3f} GICDM={r['cc_gicdm']:.3f} | kept={r['kept']:.2f} h5={r['h5_raw']:.2f}")
    json.dump(out, open("results/claim1_hypersphere.json", "w"))