| import os |
|
|
| from sklearn.metrics import accuracy_score |
| import pandas as pd |
| import numpy as np |
|
|
| from models import Xgboost |
| from configs import XgbConfig |
| from utils import get_experiment_name, load_label_map |
| from augment import ( |
| plus7rotation, |
| minus7rotation, |
| gaussSample, |
| cutout, |
| upsample, |
| downsample, |
| ) |
| from tqdm.auto import tqdm |
|
|
|
|
| def flatten(arr, max_seq_len=200): |
| arr = np.array(arr) |
| arr = np.pad(arr, ((0, max_seq_len - arr.shape[0]), (0, 0)), "constant") |
| arr = arr.flatten() |
| return arr |
|
|
|
|
| def combine_xy(x, y): |
| x, y = np.array(x), np.array(y) |
| _, length = x.shape |
| x = x.reshape((-1, length, 1)) |
| y = y.reshape((-1, length, 1)) |
| return np.concatenate((x, y), -1).astype(np.float32) |
|
|
|
|
| def split_xy(data): |
| value_x, value_y = [], [] |
| for row in data: |
| row = np.asarray(row) |
| if row.shape == (): |
| continue |
| value_x.append(row[:, 0]) |
| value_y.append(row[:, 1]) |
| value_x, value_y = np.asarray(value_x), np.asarray(value_y) |
| return value_x, value_y |
|
|
|
|
| def augment_sample(df, augs): |
| df = df.copy() |
| pose = combine_xy(df.pose_x, df.pose_y) |
| h1 = combine_xy(df.hand1_x, df.hand1_y) |
| h2 = combine_xy(df.hand2_x, df.hand2_y) |
| input_df = pd.DataFrame.from_dict( |
| { |
| "uid": df.uid, |
| "pose": pose.tolist(), |
| "hand1": h1.tolist(), |
| "hand2": h2.tolist(), |
| "label": df.label, |
| } |
| ) |
| augmented_samples = [] |
| for augmentation in augs: |
| df_augmented = augmentation(input_df) |
| pose_x, pose_y = split_xy(df_augmented.pose) |
| hand1_x, hand1_y = split_xy(df_augmented.hand1) |
| hand2_x, hand2_y = split_xy(df_augmented.hand2) |
| save_df = pd.Series( |
| { |
| "uid": df.uid + "_" + augmentation.__name__, |
| "label": df.label, |
| "pose_x": pose_x.tolist(), |
| "pose_y": pose_y.tolist(), |
| "hand1_x": hand1_x.tolist(), |
| "hand1_y": hand1_y.tolist(), |
| "hand2_x": hand2_x.tolist(), |
| "hand2_y": hand2_y.tolist(), |
| "n_frames": df.n_frames, |
| } |
| ) |
| augmented_samples.append(save_df) |
|
|
| return pd.concat(augmented_samples, axis=0) |
|
|
|
|
| def preprocess(df, use_augs, label_map, mode): |
| feature_cols = ["pose_x", "pose_y", "hand1_x", "hand1_y", "hand2_x", "hand2_y"] |
| x, y = [], [] |
| i = 0 |
| no_of_videos = df.shape[0] |
| pbar = tqdm(total=no_of_videos, desc=f"Processing {mode} file....") |
| while i < no_of_videos: |
| if use_augs and mode == "train": |
| augs = [ |
| plus7rotation, |
| minus7rotation, |
| gaussSample, |
| cutout, |
| upsample, |
| downsample, |
| ] |
| augmented_rows = augment_sample(df.iloc[i], augs) |
| df = pd.concat([df, augmented_rows], axis=0) |
| row = df.loc[i, feature_cols] |
| flatten_features = np.hstack(list(map(flatten, row.values))) |
| x.append(flatten_features) |
| y.append(label_map[df.loc[i, "label"]]) |
| i += 1 |
| pbar.update(1) |
| x = np.stack(x) |
| y = np.array(y) |
| return x, y |
|
|
|
|
| def load_dataframe(files): |
| series = [] |
| for file_path in files: |
| series.append(pd.read_json(file_path, typ="series")) |
| return pd.concat(series, axis=0) |
|
|
|
|
| def fit(args): |
| train_files = sorted( |
| glob.glob( |
| os.path.join(args.data_dir, f"{args.dataset}_train_keypoints", "*.json") |
| ) |
| ) |
| val_files = sorted( |
| glob.glob( |
| os.path.join(args.data_dir, f"{args.dataset}_val_keypoints", "*.json") |
| ) |
| ) |
|
|
| train_df = load_dataframe(train_files) |
| val_df = load_dataframe(val_files) |
|
|
| label_map = load_label_map(args.dataset) |
| x_train, y_train = preprocess(train_df, args.use_augs, label_map, "train") |
| x_val, y_val = preprocess(val_df, args.use_augs, label_map, "val") |
|
|
| config = XgbConfig() |
| model = Xgboost(config=config) |
| model.fit(x_train, y_train, x_val, y_val) |
|
|
| exp_name = get_experiment_name(args) |
| save_path = os.path.join(args.save_dir, exp_name, ".pickle.dat") |
| model.save(save_path) |
|
|
|
|
| def evaluate(args): |
| test_files = sorted( |
| glob.glob( |
| os.path.join(args.data_dir, f"{args.dataset}_test_keypoints", "*.json") |
| ) |
| ) |
|
|
| test_df = load_dataframe(test_files) |
|
|
| label_map = load_label_map(args.dataset) |
| x_test, y_test = preprocess(test_df, args.use_augs, label_map, "test") |
|
|
| exp_name = get_experiment_name(args) |
| config = XgbConfig() |
| model = Xgboost(config=config) |
| load_path = os.path.join(args.save_dir, exp_name, ".pickle.dat") |
| model.load(load_path) |
| print("### Model loaded ###") |
|
|
| test_preds = model(x_test) |
| print("Test accuracy:", accuracy_score(y_test, test_preds)) |
|
|