예제 #1
0
def knn_NCA(X_train, Y_train, X_test, K=1) -> list:
    """
    Reduce the dimensionalty of the dataset using the NCA method
    This is slower than using PCA or not using anything at all,
    but yields better results for now

    If the dataset sample is too large this takes really long to run
    """
    # Scale all the output using a standard scaler
    scaler = StandardScaler()
    X_train = scaler.fit_transform(X_train)
    X_test = scaler.transform(X_test)
    # Reduce the dimensionalty of the data using NCA
    nca = NeighborhoodComponentsAnalysis(2).fit(X_train, Y_train)
    X_train_nca = nca.transform(X_train)
    X_test_nca = nca.transform(X_test)

    X_train_nca = pd.DataFrame(X_train_nca)
    X_test_nca = pd.DataFrame(X_test_nca)

    # Classify using a KNN classifier
    clf = KNeighborsClassifier(n_neighbors=K, leaf_size=2)
    clf.fit(X_train_nca, Y_train)
    # Return the predicted results
    return clf.predict(X_test_nca)
예제 #2
0
def knnGridSearch(X_train, Y_train, X_test, Y_test) -> list:
    """
    Used to run a grid search to find the best params for later usage
    Only runs if the param -grid is provided 
    """
    # Params used for the gird search
    grid_params = {
        'n_neighbors': [1, 3, 5],
    }
    # Scale all the output using a standard scaler
    scaler = StandardScaler()
    X_train = scaler.fit_transform(X_train)
    X_test = scaler.transform(X_test)
    # Reduce the dimensionalty of the data using NCA
    nca = NeighborhoodComponentsAnalysis(2).fit(X_train, Y_train)
    X_train_nca = nca.transform(X_train)
    X_test_nca = nca.transform(X_test)
    # Run the Grid search and print out the best params
    classifier = KNeighborsClassifier()
    gs = GridSearchCV(classifier, grid_params, verbose=1, cv=3, n_jobs=-1)
    gs.fit(X_train_nca, Y_train)
    print(gs.best_params_)
    # Score the best found params using a confusion matrix
    Y_pred = gs.predict(X_test_nca)
    print(confusion_matrix(Y_test, Y_pred))
예제 #3
0
파일: compare.py 프로젝트: vu-minh/hc-tsne
def run_nca(args):
    nca = NeighborhoodComponentsAnalysis(n_components=2,
                                         init=args.nca_init,
                                         max_iter=100,
                                         verbose=2,
                                         random_state=42)
    nca.fit(X_train, y_train)
    Z = nca.transform(X_train)
    Z_test = nca.transform(X_test)
    return Z, Z_test
예제 #4
0
def KPPVNCA(X_train, y_train, X_test, y_test, k):

    nca = NeighborhoodComponentsAnalysis()
    nca.fit(X_train, y_train)
    knn = KNeighborsClassifier(n_neighbors=k)

    knn.fit(nca.transform(X_train), y_train)

    score = knn.score(nca.transform(X_test), y_test)

    return score
예제 #5
0
def test_singleton_class():
    X = iris_data
    y = iris_target

    # one singleton class
    singleton_class = 1
    ind_singleton, = np.where(y == singleton_class)
    y[ind_singleton] = 2
    y[ind_singleton[0]] = singleton_class

    nca = NeighborhoodComponentsAnalysis(max_iter=30)
    nca.fit(X, y)

    # One non-singleton class
    ind_1, = np.where(y == 1)
    ind_2, = np.where(y == 2)
    y[ind_1] = 0
    y[ind_1[0]] = 1
    y[ind_2] = 0
    y[ind_2[0]] = 2

    nca = NeighborhoodComponentsAnalysis(max_iter=30)
    nca.fit(X, y)

    # Only singleton classes
    ind_0, = np.where(y == 0)
    ind_1, = np.where(y == 1)
    ind_2, = np.where(y == 2)
    X = X[[ind_0[0], ind_1[0], ind_2[0]]]
    y = y[[ind_0[0], ind_1[0], ind_2[0]]]

    nca = NeighborhoodComponentsAnalysis(init='identity', max_iter=30)
    nca.fit(X, y)
    assert_array_equal(X, nca.transform(X))
예제 #6
0
def nca_clustering(X_train, X_test, y_train, y_test, parameters):
    nca = NeighborhoodComponentsAnalysis()
    initial_classifier_knn = KNeighborsClassifier(
        n_jobs=-1, n_neighbors=parameters["k"], metric=parameters["distance"])

    cputime_start_train = time.process_time()
    nca.fit(X_train, y_train)
    classifier = initial_classifier_knn.fit(nca.transform(X_train), y_train)
    cputime_end_train = time.process_time()

    cputime_start_test = time.process_time()
    y_pred = classifier.predict(nca.transform(X_test))
    cputime_end_test = time.process_time()

    accuracy = classifier.score(nca.transform(X_test), y_test)

    return accuracy, cputime_end_train - cputime_start_train, cputime_end_test - cputime_start_test
예제 #7
0
def test_one_class():
    X = iris_data[iris_target == 0]
    y = iris_target[iris_target == 0]

    nca = NeighborhoodComponentsAnalysis(max_iter=30,
                                         n_components=X.shape[1],
                                         init='identity')
    nca.fit(X, y)
    assert_array_equal(X, nca.transform(X))
def nca_clustering(X_train, X_test, y_train, y_test, parameters,
                   evaluation_metrics):
    # modify parameters to call the clustering algorithm with modified ones, this mainly purposes the distance parameter
    modified_parameters = prepare_parameters(parameters)

    nca = NeighborhoodComponentsAnalysis()

    if modified_parameters["distance"] != "mahalanobis":
        initial_classifier_knn = KNeighborsClassifier(
            n_jobs=-1,
            n_neighbors=modified_parameters["k"],
            metric=modified_parameters["distance"],
            p=modified_parameters["minkowski_p"])
    else:
        try:
            initial_classifier_knn = KNeighborsClassifier(
                n_jobs=-1,
                n_neighbors=modified_parameters["k"],
                metric=modified_parameters["distance"],
                p=modified_parameters["minkowski_p"],
                algorithm="brute",
                metric_params={"VI": np.linalg.inv(np.cov(X_train))})
        except np.linalg.LinAlgError:
            print_warning(
                f"[Generator & Evaluator] <Warning> Error happened while running NCA, setting distance to euclidean & running again ..."
            )
            initial_classifier_knn = KNeighborsClassifier(
                n_jobs=-1,
                n_neighbors=modified_parameters["k"],
                metric="euclidean",
                p=modified_parameters["minkowski_p"])

    nca.fit(X_train, y_train)
    classifier = initial_classifier_knn.fit(nca.transform(X_train), y_train)

    y_pred = classifier.predict(nca.transform(X_test))

    evaluation_metrics["accuracy"] = classifier.score(nca.transform(X_test),
                                                      y_test)

    return evaluation_metrics
예제 #9
0
def test_simple_example():
    """Test on a simple example.

    Puts four points in the input space where the opposite labels points are
    next to each other. After transform the samples from the same class
    should be next to each other.

    """
    X = np.array([[0, 0], [0, 1], [2, 0], [2, 1]])
    y = np.array([1, 0, 1, 0])
    nca = NeighborhoodComponentsAnalysis(
        n_components=2, init="identity", random_state=42
    )
    nca.fit(X, y)
    X_t = nca.transform(X)
    assert_array_equal(pairwise_distances(X_t).argsort()[:, 1], np.array([2, 3, 0, 1]))
예제 #10
0
# 		        tol=1e-4,
# 		        max_iter=200)
# clf = LinearSVC(penalty='l2', random_state=0, tol=1e-4)
# clf = Pipeline([('nca', NeighborhoodComponentsAnalysis(random_state=42)), ('knn', KNeighborsClassifier(n_neighbors=3))])
nca = NeighborhoodComponentsAnalysis(random_state=42)
knn = KNeighborsClassifier(n_neighbors=3)

print('cart:' + path)

skf = StratifiedKFold(n_splits=10)
skf_accuracy1 = []
skf_accuracy2 = []

for train, test in skf.split(X, y):
    nca.fit(X[train], y[train])
    knn.fit(nca.transform(X[train]), y[train])
    skf_accuracy1.append(knn.score(nca.transform(X[train]), y[train]))
    if n_classes.size < 3:
        skf_accuracy2.append(
            roc_auc_score(y[test],
                          knn.predict(nca.transform(X[train])),
                          average='micro'))
    else:
        ytest_one_hot = label_binarize(y[test], n_classes)
        skf_accuracy2.append(
            roc_auc_score(ytest_one_hot,
                          knn.predict(nca.transform(X[train])),
                          average='micro'))
        # skf_accuracy2.append(roc_auc_score(ytest_one_hot, clf.decision_function(X[test]), average='micro'))
accuracy1 = np.mean(skf_accuracy1)
accuracy2 = np.mean(skf_accuracy2)
예제 #11
0
from sklearn.neighbors import NeighborhoodComponentsAnalysis
from sklearn.neighbors import KNeighborsClassifier
from sklearn.neighbors import NearestNeighbors


# demension reduction and classify
nca = NeighborhoodComponentsAnalysis(n_components = 2, random_state=42)
nca.fit(X_train, y_train)


knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(X_train, y_train)
print(knn.score(X_test, y_test))


knn.fit(nca.transform(X_train), y_train)
print(knn.score(nca.transform(X_test), y_test))


result = nca.transform(X_test)
  

a = result[:, 0]
b = result[:, 1]

sns.scatterplot(x=a, y=b, hue=y_test)
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0)



# similarity 
예제 #12
0
x_test, y_test = np.split(test1, indices_or_sections=(7680 * 2, ),
                          axis=1)  # x为数据,y为标签

x_train = x_train[:, ::2]
x_test = x_test[:, ::2]

nca = NeighborhoodComponentsAnalysis(random_state=42,
                                     n_components=100,
                                     init='pca')

std = MinMaxScaler()
x_train = std.fit_transform(x_train)
x_test = std.fit_transform(x_test)

nca.fit(x_train, y_train)
x_train1 = nca.transform(x_train)
x_test1 = nca.transform(x_test)

# imbalance
sm = SMOTE(random_state=0)
x_train1, y_train = sm.fit_resample(x_train1, y_train)

# # 3.训练KNN分类器
# C_list = [1]
# x = [['kernel', 'c', 'gamma', 'acc']]
# for C_index in range(len(C_list)):
#     classifier = KNeighborsClassifier(n_neighbors=C_list[C_index])
#     classifier.fit(x_train1, y_train.ravel())
#     score = balanced_accuracy_score(y_test, classifier.predict(x_test1))
#     aaa = [C_list[C_index], score]
#     print(aaa)
예제 #13
0
re = neigh.predict(XX_test)
print("Test Accuracy: ",metrics.accuracy_score(y_test, re))
print("--- %s seconds to predict ---" % (time.time() - start_time))

"""# **Neighbourhood Component Analysis (NCA)**"""

# Accuracy vs # of Dimensions with k=4 neighbours
print('Plotting Accuracy vs Dimensions for k=4 neighbours')
nca_list = []
for i in range(1,20,1):
  print('Dimensions =', i)
  nca = NeighborhoodComponentsAnalysis(n_components=i,random_state=42, warm_start=True)
  nca.fit(X_train, y_train)
  neigh = KNeighborsClassifier(n_neighbors=4, weights='distance', algorithm='kd_tree')
  neigh.fit(nca.transform(X_train), y_train)
  re = neigh.predict(nca.transform(X_test))
  nca_list.append(metrics.accuracy_score(y_test, re))

plt.ylabel('Accuracy')
plt.xlabel('# of Dimensions')
plt.title('NCA+K-NN')
plt.plot(list(range(1,20,1)),nca_list)
plt.show()
print("Maximum accurcay is " + str(nca_list[np.argmax(np.array(nca_list))]) + 
      " with " + str(np.argmax(np.array(nca_list))+1) + " components.")

print("Plotting Accuracy vs # of neighbours with Dimensions = 5")
nca = NeighborhoodComponentsAnalysis(n_components=5, random_state=42, warm_start=True)
nca.fit(X_train, y_train)
nca_neigh_list = []
예제 #14
0
    X_test.append(d[5])
    ar_test.append(d[2])
    val_test.append(d[3])

X_test = np.array(X_test)
ar_test = np.array(ar_test)
val_test = np.array(val_test)

#features selectrion
nca_ar = NeighborhoodComponentsAnalysis(random_state=0)
nca_val = NeighborhoodComponentsAnalysis(random_state=0)
nca_ar.fit(X_train, ar_train)
nca_val.fit(X_train, val_train)

X_train_ar = nca_ar.transform(X_train)
X_train_val = nca_val.transform(X_train)
X_test_ar = nca_ar.transform(X_test)
X_test_val = nca_val.transform(X_test)

# X_train_ar = X_train
# X_train_val = X_train
# X_test_ar = X_test
# X_test_val = X_test

parameters = {"n_estimators": [50, 75, 100], "learning_rate": [0.1, 0.5, 1.]}
reg_ar = AdaBoostRegressor(ExtraTreeRegressor(max_depth=5, random_state=0),
                           random_state=0)
reg_val = AdaBoostRegressor(ExtraTreeRegressor(max_depth=5, random_state=0),
                            random_state=0)
예제 #15
0
relate_point(X, i, ax)
ax.set_title("Original points")
ax.axes.get_xaxis().set_visible(False)
ax.axes.get_yaxis().set_visible(False)
ax.axis('equal')

# Learn an embedding with NeighborhoodComponentsAnalysis
nca = NeighborhoodComponentsAnalysis(max_iter=30, random_state=random_state)
nca = nca.fit(X, y)

# Plot the points after transformation with NeighborhoodComponentsAnalysis
plt.figure()
ax2 = plt.gca()

# Get the embedding and find the new nearest neighbors
X_embedded = nca.transform(X)

relate_point(X_embedded, i, ax2)

for i in range(len(X)):
    ax2.text(X_embedded[i, 0],
             X_embedded[i, 1],
             str(i),
             va='center',
             ha='center')
    ax2.scatter(X_embedded[i, 0],
                X_embedded[i, 1],
                s=300,
                c=cm.Set1(y[i]),
                alpha=0.4)
예제 #16
0
# check data
df.info()
df.isnull().values.sum()

# neighbors
from sklearn.neighbors import NeighborhoodComponentsAnalysis
from sklearn.neighbors import NearestNeighbors

# mtx
X = df.iloc[:, 1:21].values
y = df['Target'].values

# demension reduction and classify
nca = NeighborhoodComponentsAnalysis(random_state=1234)
nca.fit(X, y)
X = nca.transform(X)

from sklearn.preprocessing import MinMaxScaler
mms = MinMaxScaler()
X = mms.fit_transform(X)

# fit neighbors
# metrics minkowski p 2, 'cosine'
n_size = 50
nbrs = NearestNeighbors(n_neighbors=n_size, metric='minkowski', p=2).fit(X)

# Let's find the k-neighbors of each point in object X. To do that we call the kneighbors() function on object X.
distances, indices = nbrs.kneighbors(X)

# Let's print out the indices of neighbors for each record in object X.
indices
relate_point(X, i, ax)
ax.set_title("Original points")
ax.axes.get_xaxis().set_visible(False)
ax.axes.get_yaxis().set_visible(False)
ax.axis('equal')

# Learn an embedding with NeighborhoodComponentsAnalysis
nca = NeighborhoodComponentsAnalysis(max_iter=30, random_state=random_state)
nca = nca.fit(X, y)

# Plot the points after transformation with NeighborhoodComponentsAnalysis
plt.figure()
ax2 = plt.gca()

# Get the embedding and find the new nearest neighbors
X_embedded = nca.transform(X)

relate_point(X_embedded, i, ax2)

for i in range(len(X)):
    ax2.text(X_embedded[i, 0], X_embedded[i, 1], str(i),
             va='center', ha='center')
    ax2.scatter(X_embedded[i, 0], X_embedded[i, 1], s=300, c=cm.Set1(y[i]),
                alpha=0.4)

# Make axes equal so that boundaries are displayed correctly as circles
ax2.set_title("NCA embedding")
ax2.axes.get_xaxis().set_visible(False)
ax2.axes.get_yaxis().set_visible(False)
ax2.axis('equal')
plt.show()
예제 #18
0
plt.figure()
plt.pcolormesh(xx, yy, Z, cmap=cmap_light)

# Plot also the training points
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=cmap_bold, edgecolor='k', s=20)
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())
plt.title("%i-Class classification (k = %i, weights = '%s')" %
          (len(np.unique(y)), grid_pca.best_estimator_.n_neighbors,
           grid_pca.best_estimator_.weights))

#%% NCA

nca = NeighborhoodComponentsAnalysis(n_components=2, random_state=42)
nca.fit(x_scaled, y)
X_reduced_nca = nca.transform(x_scaled)
nca_data = pd.DataFrame(X_reduced_nca, columns=["p1", "p2"])
nca_data["target"] = y
sns.scatterplot(x="p1", y="p2", hue="target", data=nca_data)
plt.title("NCA: p1 vs p2")

X_train_nca, X_test_nca, Y_train_nca, Y_test_nca = train_test_split(
    X_reduced_nca, y, test_size=test_size, random_state=42)

grid_nca = KNN_Best_Params(X_train_nca, X_test_nca, Y_train_nca, Y_test_nca)

# visualize
cmap_light = ListedColormap(['orange', 'cornflowerblue'])
cmap_bold = ListedColormap(['darkorange', 'darkblue'])

h = .2  # step size in the mesh
예제 #19
0
df = pd.DataFrame(data=X, columns=['V' + str(i) for i in range(1, 20 + 1)])
df.insert(0, 'ID', np.array(range(2000)))
df['Target'] = y

# check data
df.info()
df.isnull().values.sum()

# neighbors
from sklearn.neighbors import NeighborhoodComponentsAnalysis
from sklearn.neighbors import NearestNeighbors

# demension reduction and classify
nca = NeighborhoodComponentsAnalysis(n_components=2, random_state=42)
nca.fit(X, y)
trans_nca = nca.transform(X)

# mtx
X = df.iloc[:, 1:21].values
y = df['Target'].values

from sklearn.preprocessing import MinMaxScaler
mms = MinMaxScaler()
X = mms.fit_transform(X)

# fit neighbors
# metrics minkowski p 2, 'cosine'
n_size = 50
nbrs = NearestNeighbors(n_neighbors=n_size, metric='minkowski', p=2).fit(X)

# Let's find the k-neighbors of each point in object X. To do that we call the kneighbors() function on object X.
예제 #20
0
class iCarl:
    def __init__(self,
                 n_classes,
                 memory=2000,
                 classifier="NCM",
                 loss="iCaRL",
                 task_size=10,
                 K=7,
                 C=1,
                 neurons=256,
                 nca_dim=64,
                 examplar=True,
                 random_exemplar=False,
                 resnet_with_norm=False):
        super(iCarl, self).__init__()
        """ Salvo l'istanza del modello attuale """
        self.model = Network(classifier, resnet32withNorm(),
                             neurons) if resnet_with_norm else Network(
                                 classifier, resnet32(), neurons)
        """ Salvo il vecchio modello """
        self.old_model = None
        """ Numero di classi imparate ad un certo step """
        self.n_classes = n_classes
        """ Memoria assegnata (K) per salvare gli exemplar. """
        self.memory = memory
        """ Numero di classi che processo alla volta """
        self.task_size = task_size
        """ Classificatore che uso. [NCM, KNN, SVM, MLP] """
        self.classifier = classifier
        """ True/False se fare uso o no di exemplar. """
        self.exemplar_usage = examplar
        """ Salvo i parametri dei classificatori. """
        self.K = K
        self.neurons = neurons
        self.resnet_with_norm = resnet_with_norm
        self.C = C
        self.NCA_dim = nca_dim
        """ lista delle medie per classe. """
        self.class_mean_set = []
        """ Scelgo gli exemplar casualmente o usando il criterio di icarl. """
        self.random_exemplar = random_exemplar
        """ Set degli exemplar, salvo solo gli indici """
        self.exemplar_sets = []
        """ Trasformazione per il training set"""
        self.train_transforms = transforms.Compose([
            transforms.RandomCrop((32, 32), padding=4),
            transforms.RandomHorizontalFlip(p=0.5),
            transforms.ToTensor(),
            transforms.Normalize(CIFAR100_MEAN, CIFAR100_STD)
        ])
        """ Trasformazioni per il test set """
        self.test_transforms = transforms.Compose([
            transforms.ToTensor(),
            transforms.Normalize(CIFAR100_MEAN, CIFAR100_STD)
        ])
        """ Trasformazioni per il classify """
        self.classify_transforms = transforms.Compose([
            transforms.RandomHorizontalFlip(p=1.),
            transforms.ToTensor(),
            transforms.Normalize(CIFAR100_MEAN, CIFAR100_STD)
        ])
        """ Dataset di train e test """
        self.train_dataset = iCIFAR100(ROOT_FOLDER,
                                       train=True,
                                       transform=self.train_transforms,
                                       t1=self.test_transforms,
                                       t2=self.classify_transforms,
                                       download=True)
        self.test_dataset = iCIFAR100(ROOT_FOLDER,
                                      train=False,
                                      transform=self.test_transforms,
                                      download=True)
        """ Dataloader """
        self.train_loader = None
        self.test_loader = None
        """ Loss functions """
        self.loss_type = loss
        self.BCE = nn.BCEWithLogitsLoss()
        self.KLDIV = nn.KLDivLoss(reduction="batchmean")
        self.MSE = nn.MSELoss()
        self.L1 = nn.L1Loss()
        self.NLLoss = nn.NLLLoss()
        self.CE = nn.CrossEntropyLoss()
        """ Scelgo l'ordine delle 100 classi. """
        np.random.seed(1993)  # Fix the random seed
        self.classes = np.arange(100)
        np.random.shuffle(self.classes)

    def beforeTrain(self):
        """
        Procedure da eseguire prima del train come ad esempio incrementare il layer FC.
        :return: Void
        """
        self._update_dataloaders()
        self.model.to(DEVICE)

    def train(self):
        # Definisco l'optimizer e lo scheduler
        optimizer = optim.SGD(self.model.parameters(),
                              lr=2.,
                              momentum=0.9,
                              weight_decay=1e-5)
        scheduler = optim.lr_scheduler.MultiStepLR(optimizer,
                                                   milestones=[48, 62],
                                                   gamma=0.2)

        for epoch in range(num_epochs):
            running_loss = 0.0
            self.model.train()
            for images, labels in self.train_loader:
                images, labels = images.to(DEVICE), labels.to(DEVICE)
                optimizer.zero_grad()

                if self.loss_type == "iCaRL":
                    loss_value = self._compute_loss(images, labels)
                elif self.loss_type == "KLDiv, KLDiv":
                    loss_value = self._kldiv_kldiv_loss(images, labels)
                elif self.loss_type == "KLDiv, BCEWL":
                    loss_value = self._kldiv_bce_loss(images, labels)
                elif self.loss_type == "MSE, MSE":
                    loss_value = self._mse_mse_loss(images, labels)
                elif self.loss_type == "MSE, BCEWL":
                    loss_value = self._mse_bce_loss(images, labels)
                elif self.loss_type == "CE, BCEWL":
                    loss_value = self._ce_bce_loss(images, labels)
                elif self.loss_type == "MSE, MSE":
                    loss_value = self._mse_mse_loss(images, labels)
                elif self.loss_type == "CE_W, BCEWL":
                    loss_value = self._ce_weights_bce_loss(images, labels)

                loss_value.backward()
                optimizer.step()
                running_loss += loss_value.item() * images.size(0)

            epoch_loss = running_loss / len(self.train_loader.dataset)
            accuracy = self._test()
            self.model.train()
            print('epoch:%d/%d,loss:%f,accuracy (FC layer):%.3f,LR=%s' %
                  (epoch + 1, num_epochs, epoch_loss, accuracy,
                   scheduler.get_last_lr()))
            scheduler.step()
        self.model.eval()

    def afterTrain(self):
        """
        Eseguo le operazioni sugli exemplar ed eseguo il test finale.
        :return:
        """
        self.model.eval()
        m = self.memory // self.n_classes
        if self.exemplar_usage:
            self._compute_exemplar_class_mean()
            self._reduce_exemplar_sets(m)
            for i in self.classes[self.n_classes -
                                  self.task_size:self.n_classes]:
                print('construct class %s examplar:' % i, end='')
                images, indexes, _ = self.train_dataset.get_images_by_class(i)
                self._construct_exemplar_set(images, indexes, m)

        # self.model.train()
        accuracy = self._test(True)

        self.model.eval()
        self.old_model = Network(
            self.classifier, resnet32withNorm(),
            self.neurons) if self.resnet_with_norm else Network(
                self.classifier, resnet32(), self.neurons)
        self.old_model.load_state_dict(self.model.state_dict())
        self.old_model = self.old_model.to(DEVICE)
        self.old_model.eval()

        self.n_classes += self.task_size
        print(self.classifier + " accuracy:" + str(accuracy))

    def _test(self, final_step=False):

        self.model.eval()  # Set Network to evaluation mode

        running_corrects = 0
        if final_step and self.classifier == "KNN":
            self._update_KNN()
        elif final_step and self.classifier == "SVN":
            self._update_SVN()
        elif final_step and self.classifier == "KNN+NCA":
            self._update_KNN_NCA()
        for images, labels in self.test_loader:
            images = images.to(DEVICE)
            labels = labels.to(DEVICE)
            with torch.no_grad():
                if self.classifier == "NCM" and final_step:
                    preds = self.classify(images).to(DEVICE)
                elif self.classifier == "KNN" and final_step:
                    preds = self.knn_classify(images).to(DEVICE)
                elif self.classifier == "KNN+NCA" and final_step:
                    preds = self.knn_nca_classify(images).to(DEVICE)
                elif self.classifier == "SVM" and final_step:
                    preds = self.SVN_classify(images).to(DEVICE)
                else:
                    # Forward Pass
                    outputs = self.model(images)

                    # Get predictions
                    _, preds = torch.max(outputs.data, 1)

            # Update Corrects
            running_corrects += torch.sum(preds == labels.data).data.item()

        # Calculate Accuracy
        return 100 * running_corrects / float(len(self.test_loader.dataset))

    def _compute_exemplar_class_mean(self):
        """
        Compute the mean of all the exemplars.
        :return: None
        """
        self.class_mean_set = []
        self.model.eval()
        if self.n_classes > self.task_size:
            for label, P_y in enumerate(self.exemplar_sets):
                images_1, images_2 = self.train_dataset.get_images_by_indexes(
                    P_y)
                class_mean_1, _ = self.compute_class_mean(images_1)
                class_mean_2, _ = self.compute_class_mean(images_2)
                class_mean = (class_mean_1 + class_mean_2) / 2
                class_mean = class_mean.data / class_mean.norm()
                self.class_mean_set.append(class_mean)
        for i in self.classes[self.n_classes - self.task_size:self.n_classes]:
            images_1, _, images_2 = self.train_dataset.get_images_by_class(i)
            class_mean_1, _ = self.compute_class_mean(images_1)
            class_mean_2, _ = self.compute_class_mean(images_2)
            class_mean = (class_mean_1 + class_mean_2) / 2
            class_mean = class_mean.data / class_mean.norm()
            self.class_mean_set.append(class_mean)

    def _construct_exemplar_set(self, images, ind, m):
        """
        Costruisco il set degli exemplar basato sugli indici.
        :param images: tutte le immagini di quella classe
        :param m: numero di immagini da salvare
        :return:
        """
        self.model.eval()
        if self.random_exemplar:
            Py = list()
            np.random.seed()
            indexes = np.arange(len(images))
            np.random.shuffle(indexes)
            for i in range(m):
                Py.append(ind[indexes[i]])
        else:
            images = torch.stack(images).to(DEVICE)
            with torch.no_grad():
                phi_X = torch.nn.functional.normalize(
                    self.model.features_extractor(images)).cpu()

            mu_y = phi_X.mean(dim=0)  # vettore di 64 colonne
            mu_y.data = mu_y.data / mu_y.data.norm()

            Py = []
            # Accumulates sum of exemplars
            sum_taken_exemplars = torch.zeros(1, 64)

            indexes = list()
            for k in range(1, int(m + 1)):
                asd = nn.functional.normalize(
                    (1 / k) * (phi_X + sum_taken_exemplars))
                mean_distances = (mu_y - asd).norm(dim=1)
                used = -1
                a, indici = torch.sort(mean_distances)
                for item in a:
                    mins = (mean_distances == item).nonzero()
                    for j in mins:
                        if j not in indexes:
                            indexes.append(j)
                            Py.append(ind[j])
                            used = j
                            sum_taken_exemplars += phi_X[j]
                            break
                    if used != -1:
                        break

        print(len(Py))
        self.exemplar_sets.append(Py)

    def compute_class_mean(self, images):
        """
        Passo tutte le immagini di una determinata classe e faccio la media.
        :param special_transform:
        :param images: tutte le immagini della classe x
        :return: media della classe e features extractor.
        """
        self.model.eval()
        images = torch.stack(images).to(
            DEVICE
        )  # 500x3x32x32  #stack vs cat. Il primo le attacca in una nuova dim. 3x4 diventa 1x3x4.
        # cat invece le fa diventare 6x4
        with torch.no_grad():
            phi_X = torch.nn.functional.normalize(
                self.model.features_extractor(images))

        # phi_X.shape = 500x64
        mean = phi_X.mean(dim=0)
        mean.data = mean.data / mean.data.norm()
        return mean, phi_X

    def _reduce_exemplar_sets(self, images_per_class):
        for index in range(len(self.exemplar_sets)):
            self.exemplar_sets[index] = self.exemplar_sets[
                index][:images_per_class]
            print('Reduce size of class %d to %s examplar' %
                  (self.classes[index], str(len(self.exemplar_sets[index]))))

    def _update_dataloaders(self):
        """
        Aggiorno i dataloader con le nuove immagini/labels delle nuove classi.
        :rtype: object
        """
        train_indexes = []
        if self.exemplar_usage:
            for i in self.exemplar_sets:
                train_indexes.extend(i)
        train_indexes.extend(
            self.train_dataset.get_indexes_by_classes(
                self.classes[self.n_classes - self.task_size:self.n_classes]))

        self.train_loader = DataLoader(dataset=Subset(self.train_dataset,
                                                      train_indexes),
                                       shuffle=True,
                                       num_workers=4,
                                       batch_size=128)
        print(len(self.train_loader.dataset))
        test_indexes = self.test_dataset.get_indexes_by_classes(
            self.classes[:self.n_classes])
        self.test_loader = DataLoader(dataset=Subset(self.test_dataset,
                                                     test_indexes),
                                      shuffle=False,
                                      num_workers=4,
                                      batch_size=128)
        print(len(self.test_loader.dataset))

    def _compute_loss(self, images, target):
        """
        Calcolo la loss usando la BCEWithLogits singola (senza usarne 2 separate)
        :param images: 128 immagini da processare
        :param target: 128 true labels
        :return: la loss
        """
        self.model.train()
        output = self.model(images)
        target = self.to_onehot(target, 100)
        output, target = output.to(DEVICE), target.to(DEVICE)
        if self.old_model is None or self.classifier.lower() == 'finetuning':
            return self.BCE(output, target)
        else:
            with torch.no_grad():
                old_target = torch.sigmoid(self.old_model(images))

            n_c = self.classes[:self.n_classes - self.task_size]
            target[:, n_c] = old_target[:, n_c]
            return self.BCE(output, target)

    def _kldiv_kldiv_loss(self, images, target):
        self.model.train()
        output = self.model(images)
        target = self.to_onehot(target, 100)
        log_max = nn.LogSoftmax(dim=1)
        output, target = output.to(DEVICE), target.to(DEVICE)
        loss = self.KLDIV(log_max(output), target)
        if self.old_model is not None:
            with torch.no_grad():
                old_target = nn.functional.softmax(self.old_model(images),
                                                   dim=1)

            n_c = self.classes[:self.n_classes - self.task_size]
            loss += self.KLDIV(log_max(output[:, n_c]), old_target[:, n_c])
        return loss

    def _kldiv_bce_loss(self, images, target):
        self.model.train()
        output = self.model(images)
        target = self.to_onehot(target, 100)
        log_max = nn.LogSoftmax(dim=1)
        output, target = output.to(DEVICE), target.to(DEVICE)
        loss = self.KLDIV(log_max(output), target)
        if self.old_model is not None:
            with torch.no_grad():
                old_target = torch.sigmoid(self.old_model(images))

            n_c = self.classes[:self.n_classes - self.task_size]
            loss += self.BCE(output[:, n_c], old_target[:, n_c])

        return loss

    def _ce_bce_loss(self, images, target):
        self.model.train()
        output = self.model(images)
        output, target = output.to(DEVICE), target.to(DEVICE)
        loss = self.CE(output, target)
        if self.old_model is not None:
            with torch.no_grad():
                old_target = torch.sigmoid(self.old_model(images))

            n_c = self.classes[:self.n_classes - self.task_size]
            loss += self.BCE(output[:, n_c], old_target[:, n_c])

        return loss

    def _mse_bce_loss(self, images, target):
        self.model.train()
        output = self.model(images)
        target = self.to_onehot(target, 100)
        output, target = output.to(DEVICE), target.to(DEVICE)
        loss = self.MSE(nn.functional.softmax(output, dim=1), target)
        if self.old_model is not None:
            with torch.no_grad():
                old_target = torch.sigmoid(self.old_model(images))

            n_c = self.classes[:self.n_classes - self.task_size]
            loss += self.BCE(output[:, n_c], old_target[:, n_c])

        return loss

    # ce pesaate +bce
    def _mse_mse_loss(self, images, target):
        self.model.train()
        output = self.model(images)
        target = self.to_onehot(target, 100)
        output, target = output.to(DEVICE), target.to(DEVICE)
        loss = self.MSE(nn.functional.softmax(output, dim=1), target)
        if self.old_model is not None:
            with torch.no_grad():
                old_target = nn.functional.softmax(self.old_model(images),
                                                   dim=1)

            n_c = self.classes[:self.n_classes - self.task_size]
            loss += self.MSE(nn.functional.softmax(output[:, n_c], dim=1),
                             old_target[:, n_c])

        return loss

    def _get_weights(self):
        weights = torch.zeros(100)
        old_weights = 500 / (self.memory // self.n_classes)
        for i in self.classes[:self.n_classes - self.task_size]:
            weights[i] = old_weights
        for i in self.classes[self.n_classes - self.task_size:]:
            weights[i] = 1
        return weights

    def _ce_weights_bce_loss(self, images, target):
        self.model.train()
        output = self.model(images)

        if self.n_classes != self.task_size:
            self.CE = nn.CrossEntropyLoss(
                weight=self._get_weights().to(DEVICE))
        output, target = output.to(DEVICE), target.to(DEVICE)
        loss = self.CE(output, target)
        if self.old_model is not None:
            with torch.no_grad():
                old_target = torch.sigmoid(self.old_model(images))

            n_c = self.classes[:self.n_classes - self.task_size]
            loss += self.BCE(output[:, n_c], old_target[:, n_c])
        return loss

    def _l1_bce_loss(self, images, target):
        self.model.train()
        output = self.model(images)
        target = self.to_onehot(target, 100)
        output, target = output.to(DEVICE), target.to(DEVICE)
        loss = self.L1(nn.functional.softmax(output, dim=1), target)
        if self.old_model is not None:
            with torch.no_grad():
                old_target = torch.sigmoid(self.old_model(images))

            n_c = self.classes[:self.n_classes - self.task_size]
            loss += self.BCE(output[:, n_c], old_target[:, n_c])

        return loss

    @staticmethod
    def to_onehot(targets, n_classes):
        return torch.eye(n_classes)[targets]

    def classify(self, images):
        # batch_sizex3x32x32
        result = []
        self.model.eval()
        with torch.no_grad():
            phi_X = nn.functional.normalize(
                self.model.features_extractor(images))

        ex_means = torch.stack(self.class_mean_set)
        # 10x64 (di ogni classe mi salvo la media di ogni features)
        for x in phi_X:
            # x: 64. media delle features di quella immagine
            distances_from_class = (ex_means - x).norm(dim=1)  # giusto
            y = distances_from_class.argmin()
            result.append(self.classes[y])
        return torch.tensor(result)

    def _update_KNN(self):
        self.knn = KNeighborsClassifier(n_neighbors=self.K)
        self.model.eval()

        labels = list()
        images = None
        for label in range(0, len(self.exemplar_sets)):
            image, _ = self.train_dataset.get_images_by_indexes(
                self.exemplar_sets[label])
            image = torch.stack(image).to(DEVICE)
            with torch.no_grad():
                image = torch.nn.functional.normalize(
                    self.model.features_extractor(image)).cpu()
            if label == 0:
                images = image
            else:
                images = torch.cat((images, image), 0)
            labels.extend([self.classes[label]] * len(image))

        self.knn.fit(images, labels)

    def _update_KNN_NCA(self):
        self.knn = KNeighborsClassifier(n_neighbors=self.K)
        self.nca = NeighborhoodComponentsAnalysis(n_components=self.NCA_dim)
        self.model.eval()

        labels = list()
        images = None
        for label in range(0, len(self.exemplar_sets)):
            image, _ = self.train_dataset.get_images_by_indexes(
                self.exemplar_sets[label])
            image = torch.stack(image).to(DEVICE)
            with torch.no_grad():
                image = torch.nn.functional.normalize(
                    self.model.features_extractor(image)).cpu()
            if label == 0:
                images = image
            else:
                images = torch.cat((images, image), 0)
            labels.extend([self.classes[label]] * len(image))
        # plt.figure()
        self.nca.fit(images, labels)
        self.knn.fit(self.nca.transform(images), labels)
        # X_embedded = self.nca.transform(images)
        # plt.scatter(X_embedded[:, 0], X_embedded[:, 1], c=labels, s=30, cmap='Set1')
        # plt.show()

    def knn_classify(self, test_images):
        self.model.eval()
        with torch.no_grad():
            phi_X = torch.nn.functional.normalize(
                self.model.features_extractor(test_images)).cpu()  # nx64
        y_pred = self.knn.predict(phi_X)
        return torch.tensor(y_pred)

    def knn_nca_classify(self, test_images):
        self.model.eval()
        with torch.no_grad():
            phi_X = torch.nn.functional.normalize(
                self.model.features_extractor(test_images)).cpu()  # nx64
        y_pred = self.knn.predict(self.nca.transform(phi_X))
        return torch.tensor(y_pred)

    def _update_SVN(self):
        self.svn = SVC(C=self.C)
        self.model.eval()

        labels = list()
        images = None
        for label in range(0, len(self.exemplar_sets)):
            image, _ = self.train_dataset.get_images_by_indexes(
                self.exemplar_sets[label])
            image = torch.stack(image).to(DEVICE)
            with torch.no_grad():
                image = torch.nn.functional.normalize(
                    self.model.features_extractor(image)).cpu()
            if label == 0:
                images = image
            else:
                images = torch.cat((images, image), 0)
            labels.extend([self.classes[label]] * len(image))
        self.svn.fit(images, labels)

    def SVN_classify(self, test_images):
        self.model.eval()
        with torch.no_grad():
            phi_X = torch.nn.functional.normalize(
                self.model.features_extractor(test_images)).cpu()  # nx64

        y_pred = self.svn.predict(phi_X)
        return torch.tensor(y_pred)
예제 #21
0
def nca(x_train, y_train, x_test, n_c):
    nca = NeighborhoodComponentsAnalysis(n_c)
    nca.fit(x_train, y_train)
    return nca.transform(x_test)