| 23 | |
| 24 | |
| 25 | class SigmoidFeaturizer: |
| 26 | def __init__(self, gamma=1.0, n_components=100, method='random'): |
| 27 | self.M = n_components |
| 28 | self.gamma = gamma |
| 29 | assert(method in ('normal', 'random', 'kmeans', 'gmm')) |
| 30 | self.method = method |
| 31 | |
| 32 | def _subsample_data(self, X, Y, n=10000): |
| 33 | if Y is not None: |
| 34 | X, Y = shuffle(X, Y) |
| 35 | return X[:n], Y[:n] |
| 36 | else: |
| 37 | X = shuffle(X) |
| 38 | return X[:n] |
| 39 | |
| 40 | def fit(self, X, Y=None): |
| 41 | if self.method == 'random': |
| 42 | N = len(X) |
| 43 | idx = np.random.randint(N, size=self.M) |
| 44 | self.samples = X[idx] |
| 45 | elif self.method == 'normal': |
| 46 | # just sample from N(0,1) |
| 47 | D = X.shape[1] |
| 48 | self.samples = np.random.randn(self.M, D) / np.sqrt(D) |
| 49 | elif self.method == 'kmeans': |
| 50 | X, Y = self._subsample_data(X, Y) |
| 51 | |
| 52 | print("Fitting kmeans...") |
| 53 | t0 = datetime.now() |
| 54 | kmeans = KMeans(n_clusters=len(set(Y))) |
| 55 | kmeans.fit(X) |
| 56 | print("Finished fitting kmeans, duration:", datetime.now() - t0) |
| 57 | |
| 58 | # calculate the most ambiguous points |
| 59 | # we will do this by finding the distance between each point |
| 60 | # and all cluster centers |
| 61 | # and return which points have the smallest variance |
| 62 | dists = kmeans.transform(X) # returns an N x K matrix |
| 63 | variances = dists.var(axis=1) |
| 64 | idx = np.argsort(variances) # smallest to largest |
| 65 | idx = idx[:self.M] |
| 66 | self.samples = X[idx] |
| 67 | elif self.method == 'gmm': |
| 68 | X, Y = self._subsample_data(X, Y) |
| 69 | |
| 70 | print("Fitting GMM") |
| 71 | t0 = datetime.now() |
| 72 | gmm = GaussianMixture( |
| 73 | n_components=len(set(Y)), |
| 74 | covariance_type='spherical', |
| 75 | reg_covar=1e-6) |
| 76 | gmm.fit(X) |
| 77 | print("Finished fitting GMM, duration:", datetime.now() - t0) |
| 78 | |
| 79 | # calculate the most ambiguous points |
| 80 | probs = gmm.predict_proba(X) |
| 81 | ent = stats.entropy(probs.T) # N-length vector of entropies |
| 82 | idx = np.argsort(-ent) # negate since we want biggest first |