<jupyter_start><jupyter_text>UniPd iCaRL<jupyter_code>%load_ext autoreload
%autoreload 2<jupyter_output><empty_output><jupyter_text>First of all let's append the parent and ```src``` directories so that we can easily import and use all the scripts created.<jupyter_code>import sys
sys.path.append('..')
sys.path.append('../src')<jupyter_output><empty_output><jupyter_text>We can now call the ```main()``` function from the ```main_incremental.py``` script. To pass the desired arguments to the function we use a list of arguments and values. In this incremental learning scenario, 2 classes are initially learned and the subsequent are learned one by one. We use 20 exemplars per class and 5 epochs.<jupyter_code>from src.main_incremental import main

argv = ['--approach', 'icarl', '--datasets', 'unipd', '--network', 'XaviNet', 
        '--num-exemplars-per-class', '20', '--batch-size', '32', '--nepochs', 
        '5', '--lr', '1e-3', '--nc-first-task', '2', '--num-tasks', '10', 
        '--exemplar-selection', 'herding', '--log', 'tensorboard']

acc_taw, acc_tag, forg_taw, forg_tag, logger_path, appr = main(argv)<jupyter_output>============================================================================================================
Arguments =
	approach: icarl
	batch_size: 32
	clipping: 10000
	datasets: ['unipd']
	eval_on_train: False
	exp_name: None
	f: 
	fix_bn: False
	gpu: 0
	gridsearch_tasks: -1
	keep_existing_head: False
	last_layer_analysis: False
	log: ['tensorboard']
	lr: 0.001
	lr_factor: 3
	lr_min: 0.0001
	lr_patience: 5
	momentum: 0.0
	multi_softmax: False
	nc_first_task: 2
	nepochs: 5
	network: XaviNet
	no_cudnn_deterministic: False
	num_tasks: 10
	num_workers: 4
	pin_memory: False
	pretrained: False
	results_path: /home/xcucurull/Documents/FACIL/results
	save_models: False
	seed: 0
	stop_at_task: 0
	use_valid_only: False
	warmup_lr_factor: 1.0
	warmup_nepochs: 0
	weight_decay: 0.0
============================================================================================================
Approach arguments =
	lamb: 1
=============================================================================[...]<jupyter_text>Now that the training has been done for the whole "task" we can use the resulting ```approach``` object to classify unseen data.  Test on custom data<jupyter_code># Load data
import os
import numpy as np

custom_data_path = os.path.join('..', 'data', 'xavi_data')

# TODO recreate new_data.npy
x = np.load(os.path.join(custom_data_path, 'new_data_x.npy'), allow_pickle=True)
y = np.load(os.path.join(custom_data_path, 'new_data_y.npy'), allow_pickle=True)
# Class distribution
%matplotlib inline
import matplotlib.pyplot as plt

classes, count = np.unique(y, return_counts=True)

plt.bar(classes, count)
plt.xticks(classes)
plt.show()
# Plot example
import cv2
import utils_landmarks

def plot_image_landmarks(image_path, landmarks, subject, gesture):
    image = cv2.imread(image_path)
    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    plt.figure(figsize=(14, 10))
    plt.subplot(121)
    plt.imshow(image)
    plt.axis('off')
    plt.title(f'Subject: {subject} - Gesture: {gesture}')    
    plt.subplot(122)
    plt.title('Mediapipe Landmarks')  
    image = utils_landmarks.draw_landmarks(image, landmarks)
    plt.imshow(image)
    plt.axis('off')
    plt.show()
    

gesture = 'G4'
landmarks = x[10]
image_path = os.path.join(custom_data_path, '3_010.png')
plot_image_landmarks(image_path, landmarks, 'Xavi', gesture)

gesture = 'G7'
landmarks = x[158]
image_path = os.path.join(custom_data_path, '6_002.png')
plot_image_landmarks(image_path, landmarks, 'Xavi', gesture)

gesture = 'G8'
landmarks = x[26]
image_path = os.path.join(custom_data_path, '7_000.png')
plot_image_landmarks(image_path, landmarks, 'Xavi', gesture)
# Calculate feature vector (Distances)
def calc_dist_feature(landmark_list):
    landmark_num = len(landmark_list)//2
    landmark_dist_features = []
    for i in range(landmark_num):
        for j in range(landmark_num):
            if j>i:
                landmark_dist_features.append(landmark_list[2*i] - landmark_list[2*j])      # x
                landmark_dist_features.append(landmark_list[2*i+1] - landmark_list[2*j+1])  # y

    data_tensor = np.array(landmark_dist_features, dtype=np.float32)
    
    return data_tensor

x_feature = [calc_dist_feature(l) for l in x]
# Create dataset and dataloader from arrays
# https://stackoverflow.com/a/44475689
import torch
from torch.utils.data import TensorDataset, DataLoader

tensor_y = torch.Tensor(y).to(torch.int64)
tensor_x = torch.Tensor(x_feature)    # transform to torch tensor

my_dataset = TensorDataset(tensor_x, tensor_y)    # create your datset
my_dataloader = DataLoader(my_dataset, batch_size=32)    # create your dataloader
help(appr.eval)
# Make predictions and calculate accuracy
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix

_, _, _, y_true, y_pred = appr.eval(9, my_dataloader, True)    # evaluate at last task (9)
print(classification_report(y_true, y_pred))
# Plot confusion matrix
import matplotlib.pyplot as plt
import seaborn as sns

labels = sorted(list(set(y_true)))
cmx_data = confusion_matrix(y_true, y_pred, normalize='true')
fig, ax = plt.subplots(figsize=(7, 6))
sns.heatmap(cmx_data.dot(100), annot=True, fmt='.0f' ,square=False, linewidths=.3, xticklabels=labels, yticklabels=labels)
plt.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.16957560169024435, 'fraction_numerical': 0.021495498805805622, 'mean_word_length': 5.257471264367816, 'pattern_counts': {'":': 0, '<': 16, '<?xml version=': 0, '>': 17, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '4', 'dir': 'jupyter-structured-clean-dedup', 'id': '168567', 'license': 'MIT', 'n_tokens_mistral': 1987, 'n_tokens_neox': 1880, 'n_words': 444, 'path': 'notebooks/unipd_icarl.ipynb', 'repo_name': 'xaviercucurull/FACIL', 'size': '5443'}