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)
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))
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
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
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))
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
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
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]))
# 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)
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
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)
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 = []
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)
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)
# 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()
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
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.
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)
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)