Visualize the feature X in the 2-D space Params: - X: a feature matrix has dims (num_samples, hidden_dims) - Y: a label list has dims (num_samples) - label_list: a list has dims (num_classes) and it represents the name of each class
(X, Y, label_list, class_center_matrix=None, sample_ratio=1.0, select_labels=None)
| 321 | size=15) |
| 322 | |
| 323 | def plot_distribution(X, Y, label_list, class_center_matrix=None, sample_ratio=1.0, select_labels=None): |
| 324 | ''' |
| 325 | Visualize the feature X in the 2-D space |
| 326 | |
| 327 | Params: |
| 328 | - X: a feature matrix has dims (num_samples, hidden_dims) |
| 329 | - Y: a label list has dims (num_samples) |
| 330 | - label_list: a list has dims (num_classes) |
| 331 | and it represents the name of each class |
| 332 | - class_center_matrix: if not None, plot the class center of each class; |
| 333 | it has dims (num_classes, hidden_dims) |
| 334 | - sample_ratio: the ratio of the samples used for visualization |
| 335 | - select_labels: a list represents the selected labels for visualization |
| 336 | ''' |
| 337 | # clone and convert to tensor |
| 338 | if isinstance(X, list): |
| 339 | _X = torch.tensor(X) |
| 340 | else: |
| 341 | _X = X.clone().detach().cpu() |
| 342 | if isinstance(Y, list): |
| 343 | _Y = torch.tensor(Y) |
| 344 | else: |
| 345 | _Y = Y.clone().detach().cpu() |
| 346 | num_samples = _Y.shape[0] |
| 347 | print('Total %d samples for visualization'%num_samples) |
| 348 | |
| 349 | # random sampling |
| 350 | if sample_ratio<1.0: |
| 351 | assert sample_ratio>0.0, "Invalid sample ratio!!!" |
| 352 | |
| 353 | sample_lst = list(range(num_samples)) |
| 354 | random.shuffle(sample_lst) |
| 355 | sample_lst = sample_lst[:int(num_samples*sample_ratio)] |
| 356 | _X = _X[sample_lst] |
| 357 | _Y = _Y[sample_lst] |
| 358 | print('Select %d samples for visualization'%_Y.shape[0]) |
| 359 | |
| 360 | if select_labels!=None and len(select_labels)>0: |
| 361 | for i,l in enumerate(select_labels): |
| 362 | if i==0: |
| 363 | class_mask = np.equal(_Y,l) |
| 364 | else: |
| 365 | class_mask = np.logical_or(class_mask,np.equal(_Y,l)) |
| 366 | _Y = _Y[class_mask] |
| 367 | _X = _X[class_mask] |
| 368 | |
| 369 | # t-SNE for visualization |
| 370 | tsne = TSNE(n_components=2) |
| 371 | if not class_center_matrix is None: |
| 372 | assert len(label_list)==class_center_matrix.shape[0], "Number of classes is not consistent!!!" |
| 373 | num_class = class_center_matrix.shape[0] |
| 374 | concat_X = torch.cat((_X, class_center_matrix),dim=0) |
| 375 | concat_low_repre = torch.tensor(tsne.fit_transform(concat_X)) |
| 376 | |
| 377 | # scale to 0-1 |
| 378 | x_min, x_max = torch.min(concat_low_repre, 0)[0], torch.max(concat_low_repre, 0)[0] |
| 379 | concat_low_repre = (concat_low_repre - x_min) / (x_max - x_min) |
| 380 |
nothing calls this directly
no test coverage detected