├── README.md ├── checkpoints └── README.md ├── ucf101 ├── ckpt │ └── README.md └── anno │ └── used_idxs.pkl ├── model.py ├── kinetics400 ├── config │ ├── tpn_resnet50_f32s2_kinetics400.yaml │ ├── i3d_nl5_resnet50_v1_kinetics400.yaml │ ├── tpn_resnet101_f32s2_kinetics400.yaml │ ├── i3d_nl5_resnet101_v1_kinetics400.yaml │ ├── slowfast_8x8_resnet50_kinetics400.yaml │ └── slowfast_8x8_resnet101_kinetics400.yaml └── anno │ └── val400.csv ├── dataset_kinetics.py ├── eval_kinetics.py ├── eval_ucf.py ├── generators.py ├── dataset_ucf.py ├── train.py └── transforms_ucf101.py /README.md: -------------------------------------------------------------------------------- 1 | # GCMA -------------------------------------------------------------------------------- /checkpoints/README.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ucf101/ckpt/README.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ucf101/anno/used_idxs.pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kay-ck/GCMA/HEAD/ucf101/anno/used_idxs.pkl -------------------------------------------------------------------------------- /model.py: -------------------------------------------------------------------------------- 1 | import os 2 | from gluoncv.torch.model_zoo import get_model 3 | 4 | 5 | CONFIG_ROOT_KINETICS = "kinetics400/config" 6 | CKPT_ROOT_UCF = "ucf101/ckpt" 7 | CONFIG_PATH = { 8 | "nl5_50": os.path.join(CONFIG_ROOT_KINETICS, "i3d_nl5_resnet50_v1_kinetics400.yaml"), 9 | "slowfast_50": os.path.join(CONFIG_ROOT_KINETICS, "slowfast_8x8_resnet50_kinetics400.yaml"), 10 | "tpn_50": os.path.join(CONFIG_ROOT_KINETICS, "tpn_resnet50_f32s2_kinetics400.yaml"), 11 | "nl5_101": os.path.join(CONFIG_ROOT_KINETICS, "i3d_nl5_resnet101_v1_kinetics400.yaml"), 12 | "slowfast_101": os.path.join(CONFIG_ROOT_KINETICS, "slowfast_8x8_resnet101_kinetics400.yaml"), 13 | "tpn_101": os.path.join(CONFIG_ROOT_KINETICS, "tpn_resnet101_f32s2_kinetics400.yaml"), 14 | } 15 | CKPT_PATH = { 16 | "nl5_50": os.path.join(CKPT_ROOT_UCF, "i3d_resnet50.pth"), 17 | "slowfast_50": os.path.join(CKPT_ROOT_UCF, "slowfast_resnet50.pth"), 18 | "tpn_50": os.path.join(CKPT_ROOT_UCF, "tpn_resnet50.pth"), 19 | "nl5_101": os.path.join(CKPT_ROOT_UCF, "i3d_resnet101.pth"), 20 | "slowfast_101": os.path.join(CKPT_ROOT_UCF, "slowfast_resnet101.pth"), 21 | "tpn_101": os.path.join(CKPT_ROOT_UCF, "tpn_resnet101.pth") 22 | } 23 | 24 | 25 | def custom_model(cfg): 26 | cfg.CONFIG.MODEL.PRETRAINED = True 27 | model = get_model(cfg) 28 | return model -------------------------------------------------------------------------------- /kinetics400/config/tpn_resnet50_f32s2_kinetics400.yaml: -------------------------------------------------------------------------------- 1 | # tpn_resnet50_f32s2_kinetics400 2 | 3 | DDP_CONFIG: 4 | WORLD_SIZE: 1 5 | WORLD_RANK: 0 6 | GPU_WORLD_SIZE: 8 7 | GPU_WORLD_RANK: 0 8 | DIST_URL: 'tcp://172.31.72.195:23456' 9 | WOLRD_URLS: ['172.31.72.195'] 10 | AUTO_RANK_MATCH: True 11 | DIST_BACKEND: 'nccl' 12 | GPU: 0 13 | DISTRIBUTED: True 14 | 15 | CONFIG: 16 | TRAIN: 17 | EPOCH_NUM: 150 18 | BATCH_SIZE: 8 19 | LR: 0.01 20 | MOMENTUM: 0.9 21 | W_DECAY: 1e-5 22 | LR_POLICY: 'Step' 23 | USE_WARMUP: False 24 | LR_MILESTONE: [75, 125] 25 | STEP: 0.1 26 | 27 | VAL: 28 | FREQ: 2 29 | BATCH_SIZE: 8 30 | 31 | DATA: 32 | TRAIN_ANNO_PATH: '/home/ubuntu/data/kinetics400/k400_train.txt' 33 | VAL_ANNO_PATH: '/home/ubuntu/data/kinetics400/k400_val.txt' 34 | TRAIN_DATA_PATH: '/home/ubuntu/data/kinetics400/train_256/' 35 | VAL_DATA_PATH: '/home/ubuntu/data/kinetics400/val_256/' 36 | NUM_CLASSES: 400 37 | CLIP_LEN: 32 38 | FRAME_RATE: 2 39 | NUM_SEGMENT: 1 40 | NUM_CROP: 1 41 | TEST_NUM_SEGMENT: 10 42 | TEST_NUM_CROP: 3 43 | MULTIGRID: False 44 | KEEP_ASPECT_RATIO: False 45 | 46 | MODEL: 47 | NAME: 'tpn_resnet50_f32s2_kinetics400' 48 | PRETRAINED: False 49 | 50 | LOG: 51 | BASE_PATH: './logs/tpn_resnet50_f32s2_kinetics400' 52 | LOG_DIR: 'tb_log' 53 | SAVE_DIR: 'checkpoints' 54 | EVAL_DIR: './logs/tpn_resnet50_f32s2_kinetics400/eval' 55 | SAVE_FREQ: 2 56 | -------------------------------------------------------------------------------- /kinetics400/config/i3d_nl5_resnet50_v1_kinetics400.yaml: -------------------------------------------------------------------------------- 1 | # i3d_nl5_resnet50_v1_kinetics400 2 | 3 | DDP_CONFIG: 4 | WORLD_SIZE: 1 5 | WORLD_RANK: 0 6 | GPU_WORLD_SIZE: 8 7 | GPU_WORLD_RANK: 0 8 | DIST_URL: 'tcp://172.31.69.134:23456' 9 | WOLRD_URLS: ['172.31.69.134'] 10 | AUTO_RANK_MATCH: True 11 | DIST_BACKEND: 'nccl' 12 | GPU: 0 13 | DISTRIBUTED: True 14 | 15 | CONFIG: 16 | TRAIN: 17 | EPOCH_NUM: 100 18 | BATCH_SIZE: 8 19 | LR: 0.01 20 | MOMENTUM: 0.9 21 | W_DECAY: 1e-5 22 | LR_POLICY: 'Step' 23 | USE_WARMUP: False 24 | LR_MILESTONE: [40, 80] 25 | STEP: 0.1 26 | 27 | VAL: 28 | FREQ: 5 29 | BATCH_SIZE: 8 30 | 31 | DATA: 32 | TRAIN_ANNO_PATH: '/home/ubuntu/data/kinetics400/k400_train.txt' 33 | VAL_ANNO_PATH: '/home/ubuntu/data/kinetics400/k400_val.txt' 34 | TRAIN_DATA_PATH: '/home/ubuntu/data/kinetics400/train_256/' 35 | VAL_DATA_PATH: '/home/ubuntu/data/kinetics400/val_256/' 36 | NUM_CLASSES: 400 37 | CLIP_LEN: 32 38 | FRAME_RATE: 2 39 | NUM_SEGMENT: 1 40 | NUM_CROP: 1 41 | TEST_NUM_SEGMENT: 10 42 | TEST_NUM_CROP: 3 43 | MULTIGRID: False 44 | KEEP_ASPECT_RATIO: False 45 | 46 | MODEL: 47 | NAME: 'i3d_nl5_resnet50_v1_kinetics400' 48 | PRETRAINED: False 49 | 50 | LOG: 51 | BASE_PATH: './logs/i3d_nl5_resnet50_v1_kinetics400/' 52 | LOG_DIR: 'tb_log' 53 | SAVE_DIR: 'checkpoints' 54 | EVAL_DIR: './logs/i3d_nl5_resnet50_v1_kinetics400/eval' 55 | SAVE_FREQ: 5 56 | -------------------------------------------------------------------------------- /kinetics400/config/tpn_resnet101_f32s2_kinetics400.yaml: -------------------------------------------------------------------------------- 1 | # tpn_resnet101_f32s2_kinetics400 2 | 3 | DDP_CONFIG: 4 | WORLD_SIZE: 1 5 | WORLD_RANK: 0 6 | GPU_WORLD_SIZE: 8 7 | GPU_WORLD_RANK: 0 8 | DIST_URL: 'tcp://172.31.72.252:23456' 9 | WOLRD_URLS: ['172.31.72.252'] 10 | AUTO_RANK_MATCH: True 11 | DIST_BACKEND: 'nccl' 12 | GPU: 0 13 | DISTRIBUTED: True 14 | 15 | CONFIG: 16 | TRAIN: 17 | EPOCH_NUM: 150 18 | BATCH_SIZE: 8 19 | LR: 0.01 20 | MOMENTUM: 0.9 21 | W_DECAY: 1e-5 22 | LR_POLICY: 'Step' 23 | USE_WARMUP: False 24 | LR_MILESTONE: [75, 125] 25 | STEP: 0.1 26 | 27 | VAL: 28 | FREQ: 2 29 | BATCH_SIZE: 8 30 | 31 | DATA: 32 | TRAIN_ANNO_PATH: '/home/ubuntu/data/kinetics400/k400_train.txt' 33 | VAL_ANNO_PATH: '/home/ubuntu/data/kinetics400/k400_val.txt' 34 | TRAIN_DATA_PATH: '/home/ubuntu/data/kinetics400/train_256/' 35 | VAL_DATA_PATH: '/home/ubuntu/data/kinetics400/val_256/' 36 | NUM_CLASSES: 400 37 | CLIP_LEN: 32 38 | FRAME_RATE: 2 39 | NUM_SEGMENT: 1 40 | NUM_CROP: 1 41 | TEST_NUM_SEGMENT: 10 42 | TEST_NUM_CROP: 3 43 | MULTIGRID: False 44 | KEEP_ASPECT_RATIO: False 45 | 46 | MODEL: 47 | NAME: 'tpn_resnet101_f32s2_kinetics400' 48 | PRETRAINED: False 49 | 50 | LOG: 51 | BASE_PATH: './logs/tpn_resnet101_f32s2_kinetics400' 52 | LOG_DIR: 'tb_log' 53 | SAVE_DIR: 'checkpoints' 54 | EVAL_DIR: './logs/tpn_resnet101_f32s2_kinetics400/eval' 55 | SAVE_FREQ: 2 56 | -------------------------------------------------------------------------------- /kinetics400/config/i3d_nl5_resnet101_v1_kinetics400.yaml: -------------------------------------------------------------------------------- 1 | # i3d_nl5_resnet101_v1_kinetics400 2 | 3 | DDP_CONFIG: 4 | WORLD_SIZE: 1 5 | WORLD_RANK: 0 6 | GPU_WORLD_SIZE: 8 7 | GPU_WORLD_RANK: 0 8 | DIST_URL: 'tcp://172.31.72.195:23456' 9 | WOLRD_URLS: ['172.31.72.195'] 10 | AUTO_RANK_MATCH: True 11 | DIST_BACKEND: 'nccl' 12 | GPU: 0 13 | DISTRIBUTED: True 14 | 15 | CONFIG: 16 | TRAIN: 17 | EPOCH_NUM: 100 18 | BATCH_SIZE: 8 19 | LR: 0.01 20 | MOMENTUM: 0.9 21 | W_DECAY: 1e-5 22 | LR_POLICY: 'Step' 23 | USE_WARMUP: False 24 | LR_MILESTONE: [40, 80] 25 | STEP: 0.1 26 | 27 | VAL: 28 | FREQ: 2 29 | BATCH_SIZE: 8 30 | 31 | DATA: 32 | TRAIN_ANNO_PATH: '/home/ubuntu/data/kinetics400/k400_train.txt' 33 | VAL_ANNO_PATH: '/home/ubuntu/data/kinetics400/k400_val.txt' 34 | TRAIN_DATA_PATH: '/home/ubuntu/data/kinetics400/train_256/' 35 | VAL_DATA_PATH: '/home/ubuntu/data/kinetics400/val_256/' 36 | NUM_CLASSES: 400 37 | CLIP_LEN: 32 38 | FRAME_RATE: 2 39 | NUM_SEGMENT: 1 40 | NUM_CROP: 1 41 | TEST_NUM_SEGMENT: 10 42 | TEST_NUM_CROP: 3 43 | MULTIGRID: False 44 | KEEP_ASPECT_RATIO: False 45 | 46 | MODEL: 47 | NAME: 'i3d_nl5_resnet101_v1_kinetics400' 48 | PRETRAINED: False 49 | 50 | LOG: 51 | BASE_PATH: './logs/i3d_nl5_resnet101_v1_kinetics400' 52 | LOG_DIR: 'tb_log' 53 | SAVE_DIR: 'checkpoints' 54 | EVAL_DIR: './logs/i3d_nl5_resnet101_v1_kinetics400/eval' 55 | SAVE_FREQ: 2 56 | -------------------------------------------------------------------------------- /kinetics400/config/slowfast_8x8_resnet50_kinetics400.yaml: -------------------------------------------------------------------------------- 1 | # slowfast_8x8_resnet50_kinetics400 2 | 3 | DDP_CONFIG: 4 | WORLD_SIZE: 1 5 | WORLD_RANK: 0 6 | GPU_WORLD_SIZE: 8 7 | GPU_WORLD_RANK: 0 8 | DIST_URL: 'tcp://172.31.72.195:23456' 9 | WOLRD_URLS: ['172.31.72.195'] 10 | AUTO_RANK_MATCH: True 11 | DIST_BACKEND: 'nccl' 12 | GPU: 0 13 | DISTRIBUTED: True 14 | 15 | CONFIG: 16 | TRAIN: 17 | EPOCH_NUM: 196 18 | BATCH_SIZE: 8 19 | LR: 0.01 20 | MOMENTUM: 0.9 21 | W_DECAY: 1e-5 22 | USE_WARMUP: True 23 | WARMUP_EPOCHS: 34 24 | LR_POLICY: 'Cosine' 25 | WARMUP_END_LR: 0.1 26 | RESUME_EPOCH: -1 27 | 28 | VAL: 29 | FREQ: 2 30 | BATCH_SIZE: 8 31 | 32 | DATA: 33 | TRAIN_ANNO_PATH: '/home/ubuntu/data/kinetics400/k400_train.txt' 34 | VAL_ANNO_PATH: '/home/ubuntu/data/kinetics400/k400_val.txt' 35 | TRAIN_DATA_PATH: '/home/ubuntu/data/kinetics400/train_256/' 36 | VAL_DATA_PATH: '/home/ubuntu/data/kinetics400/val_256/' 37 | NUM_CLASSES: 400 38 | CLIP_LEN: 32 39 | FRAME_RATE: 2 40 | NUM_SEGMENT: 1 41 | NUM_CROP: 1 42 | TEST_NUM_SEGMENT: 10 43 | TEST_NUM_CROP: 3 44 | MULTIGRID: False 45 | KEEP_ASPECT_RATIO: False 46 | 47 | MODEL: 48 | NAME: 'slowfast_8x8_resnet50_kinetics400' 49 | PRETRAINED: False 50 | 51 | LOG: 52 | BASE_PATH: './logs/slowfast_8x8_resnet50_kinetics400' 53 | LOG_DIR: 'tb_log' 54 | SAVE_DIR: 'checkpoints' 55 | EVAL_DIR: './logs/slowfast_8x8_resnet50_kinetics400/eval' 56 | SAVE_FREQ: 2 57 | -------------------------------------------------------------------------------- /kinetics400/config/slowfast_8x8_resnet101_kinetics400.yaml: -------------------------------------------------------------------------------- 1 | # slowfast_8x8_resnet101_kinetics400 2 | 3 | DDP_CONFIG: 4 | WORLD_SIZE: 1 5 | WORLD_RANK: 0 6 | GPU_WORLD_SIZE: 8 7 | GPU_WORLD_RANK: 0 8 | DIST_URL: 'tcp://172.31.72.195:23456' 9 | WOLRD_URLS: ['172.31.72.195'] 10 | AUTO_RANK_MATCH: True 11 | DIST_BACKEND: 'nccl' 12 | GPU: 0 13 | DISTRIBUTED: True 14 | 15 | CONFIG: 16 | TRAIN: 17 | EPOCH_NUM: 196 18 | BATCH_SIZE: 8 19 | LR: 0.01 20 | MOMENTUM: 0.9 21 | W_DECAY: 1e-5 22 | USE_WARMUP: True 23 | WARMUP_EPOCHS: 34 24 | LR_POLICY: 'Cosine' 25 | WARMUP_END_LR: 0.1 26 | RESUME_EPOCH: -1 27 | 28 | VAL: 29 | FREQ: 2 30 | BATCH_SIZE: 8 31 | 32 | DATA: 33 | TRAIN_ANNO_PATH: '/home/ubuntu/data/kinetics400/k400_train.txt' 34 | VAL_ANNO_PATH: '/home/ubuntu/data/kinetics400/k400_val.txt' 35 | TRAIN_DATA_PATH: '/home/ubuntu/data/kinetics400/train_256/' 36 | VAL_DATA_PATH: '/home/ubuntu/data/kinetics400/val_256/' 37 | NUM_CLASSES: 400 38 | CLIP_LEN: 32 39 | FRAME_RATE: 2 40 | NUM_SEGMENT: 1 41 | NUM_CROP: 1 42 | TEST_NUM_SEGMENT: 10 43 | TEST_NUM_CROP: 3 44 | MULTIGRID: False 45 | KEEP_ASPECT_RATIO: False 46 | 47 | MODEL: 48 | NAME: 'slowfast_8x8_resnet101_kinetics400' 49 | PRETRAINED: False 50 | 51 | LOG: 52 | BASE_PATH: './logs/slowfast_8x8_resnet101_kinetics400' 53 | LOG_DIR: 'tb_log' 54 | SAVE_DIR: 'checkpoints' 55 | EVAL_DIR: './logs/slowfast_8x8_resnet101_kinetics400/eval' 56 | SAVE_FREQ: 2 57 | -------------------------------------------------------------------------------- /dataset_kinetics.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from gluoncv.torch.data import VideoClsDataset 3 | 4 | from transforms_ucf101 import * 5 | 6 | 7 | def custom_dataset(args, cfg): 8 | cfg.CONFIG.VAL.BATCH_SIZE = args.batch_size 9 | cfg.CONFIG.DATA.VAL_ANNO_PATH = "kinetics400/anno/val.csv" 10 | # cfg.CONFIG.DATA.VAL_ANNO_PATH = "kinetics400/anno/val400.csv" 11 | cfg.CONFIG.DATA.VAL_DATA_PATH = "kinetics400/videos/val/" 12 | val_loader = build_dataloader_val(cfg) 13 | return val_loader, len(val_loader) 14 | 15 | 16 | def build_dataloader_val(cfg): 17 | """Build dataloader for testing""" 18 | val_dataset = VideoClsDataset(anno_path=cfg.CONFIG.DATA.VAL_ANNO_PATH, 19 | data_path=cfg.CONFIG.DATA.VAL_DATA_PATH, 20 | mode="validation", 21 | clip_len=cfg.CONFIG.DATA.CLIP_LEN, 22 | frame_sample_rate=cfg.CONFIG.DATA.FRAME_RATE, 23 | num_segment=cfg.CONFIG.DATA.NUM_SEGMENT, 24 | num_crop=cfg.CONFIG.DATA.NUM_CROP, 25 | keep_aspect_ratio=cfg.CONFIG.DATA.KEEP_ASPECT_RATIO, 26 | crop_size=cfg.CONFIG.DATA.CROP_SIZE, 27 | short_side_size=cfg.CONFIG.DATA.SHORT_SIDE_SIZE, 28 | new_height=cfg.CONFIG.DATA.NEW_HEIGHT, 29 | new_width=cfg.CONFIG.DATA.NEW_WIDTH) 30 | 31 | if cfg.DDP_CONFIG.DISTRIBUTED: 32 | val_sampler = torch.utils.data.distributed.DistributedSampler(val_dataset) 33 | else: 34 | val_sampler = None 35 | val_loader = torch.utils.data.DataLoader( 36 | val_dataset, batch_size=cfg.CONFIG.VAL.BATCH_SIZE, shuffle=(val_sampler is None), 37 | num_workers=4, sampler=val_sampler, pin_memory=True) 38 | 39 | return val_loader -------------------------------------------------------------------------------- /eval_kinetics.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import random 3 | import torch 4 | import numpy as np 5 | import torchvision.utils as vutils 6 | from gluoncv.torch.engine.config import get_cfg_defaults 7 | from torch.nn.parallel import DistributedDataParallel 8 | 9 | from dataset_kinetics import custom_dataset 10 | from model import custom_model, CONFIG_PATH 11 | from generators import custom_gan 12 | 13 | 14 | def setup_seed(seed): 15 | np.random.seed(seed) 16 | random.seed(seed) 17 | torch.manual_seed(seed) 18 | torch.cuda.manual_seed_all(seed) 19 | torch.backends.cudnn.benchmark = False 20 | torch.backends.cudnn.deterministic = True 21 | 22 | 23 | def get_args_parser(): 24 | parser = argparse.ArgumentParser(description="Cross Modal Transferability", add_help=False) 25 | parser.add_argument("--batch_size", type=int, default=13, help="Batch Size") 26 | parser.add_argument("--eps", type=int, default=10, help="Perturbation Budget") 27 | parser.add_argument("--model_type", type=str, default= "res152", help ="Model against GAN is trained: res152, dense201, squeeze1_1, shufflev2_x1.0") 28 | parser.add_argument("--model_t",type=str, default= "nl5_50", help ="Model under attack: nl5_50/101, slowfast_50/101, tpn_50/101" ) 29 | parser.add_argument("--local_rank", default=0, type=int, help="node rank for distributed training") 30 | return parser 31 | 32 | 33 | def main(args): 34 | cfg = get_cfg_defaults() 35 | cfg.merge_from_file(CONFIG_PATH[args.model_t]) 36 | 37 | # Normalize (0-1) 38 | eps = args.eps / 255 39 | 40 | setup_seed(0) 41 | 42 | # GPU 43 | torch.cuda.set_device(args.local_rank) 44 | torch.distributed.init_process_group(backend="nccl", init_method="env://") 45 | device = torch.device("cuda", args.local_rank) 46 | 47 | netG = custom_gan(args).to(device) 48 | netG.load_state_dict(torch.load("checkpoints/netG_{}_gcma.pth".format(args.model_type), map_location="cpu")) 49 | netG = DistributedDataParallel(netG, device_ids=[args.local_rank], output_device=args.local_rank) 50 | netG.eval() 51 | 52 | model_t = custom_model(cfg).to(device) 53 | model_t = DistributedDataParallel(model_t, device_ids=[args.local_rank], output_device=args.local_rank) 54 | model_t.eval() 55 | 56 | mean = [0.485, 0.456, 0.406] 57 | std = [0.229, 0.224, 0.225] 58 | def normalize(t): 59 | t[:, 0, :, :, :] = (t[:, 0, :, :, :] - mean[0]) / std[0] 60 | t[:, 1, :, :, :] = (t[:, 1, :, :, :] - mean[1]) / std[1] 61 | t[:, 2, :, :, :] = (t[:, 2, :, :, :] - mean[2]) / std[2] 62 | return t 63 | 64 | inv_mean = [-0.485 / 0.229, -0.456 / 0.224, -0.406 / 0.225] 65 | inv_std = [1 / 0.229, 1 / 0.224, 1 / 0.225] 66 | def inv_normalize(t): 67 | t[:, 0, :, :, :] = (t[:, 0, :, :, :] - inv_mean[0]) / inv_std[0] 68 | t[:, 1, :, :, :] = (t[:, 1, :, :, :] - inv_mean[1]) / inv_std[1] 69 | t[:, 2, :, :, :] = (t[:, 2, :, :, :] - inv_mean[2]) / inv_std[2] 70 | return t 71 | 72 | val_loader, val_size = custom_dataset(args, cfg) 73 | print("Testing data size:", val_size) 74 | 75 | # Evaluation 76 | correct = torch.zeros(1).to(device) 77 | incorrect = torch.zeros(1).to(device) 78 | total = torch.zeros(1).to(device) 79 | for i, (vid, label, _) in enumerate(val_loader): 80 | with torch.no_grad(): 81 | vid, label = inv_normalize(vid).to(device), label.to(device) 82 | B, C, T, H, W = vid.size() 83 | 84 | vid_out = model_t(normalize(vid.clone().detach())).argmax(dim=-1) 85 | correct += torch.sum(vid_out == label).item() 86 | total += B 87 | 88 | # Untargeted Adversary 89 | pert = netG(vid.permute(0, 2, 1, 3, 4).contiguous().view(-1, C, H, W)) * 2 - 1 90 | pert = pert.view(B, T, C, H, W).permute(0, 2, 1, 3, 4) 91 | 92 | # Projection 93 | adv = pert * eps + vid 94 | adv = torch.clamp(adv, 0.0, 1.0) 95 | 96 | adv_out = model_t(normalize(adv.clone().detach())).argmax(dim=-1) 97 | incorrect += torch.sum((adv_out != label) & (vid_out == label)).item() 98 | 99 | if args.local_rank == 0: 100 | for t in range(T): 101 | vutils.save_image(vutils.make_grid(adv[0, :, t, :, :], normalize=True, scale_each=True), "./adv/adv_{}.png".format(t)) 102 | vutils.save_image(vutils.make_grid(vid[0, :, t, :, :], normalize=True, scale_each=True), "./ori/ori_{}.png".format(t)) 103 | print("At Batch:{}\t l_inf:{}".format(i, (vid - adv).max() * 255)) 104 | 105 | torch.distributed.all_reduce(correct) 106 | torch.distributed.all_reduce(incorrect) 107 | torch.distributed.all_reduce(total) 108 | print("Clean:{0:}\t Adversarial:{1:}\t Total:{2:}\t ACC:{3:}\t ASR:{4:}".format(correct, incorrect, total, correct/total, incorrect / correct)) 109 | if __name__ == "__main__": 110 | parser = get_args_parser() 111 | args = parser.parse_args() 112 | print(args) 113 | main(args) 114 | -------------------------------------------------------------------------------- /eval_ucf.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import random 3 | import torch 4 | import numpy as np 5 | import torchvision.utils as vutils 6 | from gluoncv.torch.engine.config import get_cfg_defaults 7 | from torch.nn.parallel import DistributedDataParallel 8 | 9 | from dataset_ucf import custom_dataset 10 | from model import custom_model, CONFIG_PATH, CKPT_PATH 11 | from generators import custom_gan 12 | 13 | 14 | def setup_seed(seed): 15 | np.random.seed(seed) 16 | random.seed(seed) 17 | torch.manual_seed(seed) 18 | torch.cuda.manual_seed_all(seed) 19 | torch.backends.cudnn.benchmark = False 20 | torch.backends.cudnn.deterministic = True 21 | 22 | 23 | def get_args_parser(): 24 | parser = argparse.ArgumentParser(description="Cross Modal Transferability", add_help=False) 25 | parser.add_argument("--batch_size", type=int, default=13, help="Batch Size") 26 | parser.add_argument("--eps", type=int, default=10, help="Perturbation Budget") 27 | parser.add_argument("--model_type", type=str, default= "res152", help ="Model against GAN is trained: res152, dense201, squeeze1_1, shufflev2_x1.0") 28 | parser.add_argument("--model_t",type=str, default= "nl5_50", help ="Model under attack: nl5_50/101, slowfast_50/101, tpn_50/101" ) 29 | parser.add_argument("--local_rank", default=0, type=int, help="node rank for distributed training") 30 | return parser 31 | 32 | 33 | def main(args): 34 | cfg = get_cfg_defaults() 35 | cfg.merge_from_file(CONFIG_PATH[args.model_t]) 36 | 37 | # Normalize (0-1) 38 | eps = args.eps / 255 39 | 40 | setup_seed(0) 41 | 42 | # GPU 43 | torch.cuda.set_device(args.local_rank) 44 | torch.distributed.init_process_group(backend="nccl", init_method="env://") 45 | device = torch.device("cuda", args.local_rank) 46 | 47 | netG = custom_gan(args).to(device) 48 | netG.load_state_dict(torch.load("checkpoints/netG_{}_gcma.pth".format(args.model_type), map_location="cpu")) 49 | netG = DistributedDataParallel(netG, device_ids=[args.local_rank], output_device=args.local_rank) 50 | netG.eval() 51 | 52 | model_t = custom_model(cfg).to(device) 53 | model_t.load_state_dict(torch.load(CKPT_PATH[args.model_t])["state_dict"]) 54 | model_t = DistributedDataParallel(model_t, device_ids=[args.local_rank], output_device=args.local_rank) 55 | model_t.eval() 56 | 57 | mean = [0.485, 0.456, 0.406] 58 | std = [0.229, 0.224, 0.225] 59 | def normalize(t): 60 | t[:, 0, :, :, :] = (t[:, 0, :, :, :] - mean[0]) / std[0] 61 | t[:, 1, :, :, :] = (t[:, 1, :, :, :] - mean[1]) / std[1] 62 | t[:, 2, :, :, :] = (t[:, 2, :, :, :] - mean[2]) / std[2] 63 | return t 64 | 65 | inv_mean = [-0.485 / 0.229, -0.456 / 0.224, -0.406 / 0.225] 66 | inv_std = [1 / 0.229, 1 / 0.224, 1 / 0.225] 67 | def inv_normalize(t): 68 | t[:, 0, :, :, :] = (t[:, 0, :, :, :] - inv_mean[0]) / inv_std[0] 69 | t[:, 1, :, :, :] = (t[:, 1, :, :, :] - inv_mean[1]) / inv_std[1] 70 | t[:, 2, :, :, :] = (t[:, 2, :, :, :] - inv_mean[2]) / inv_std[2] 71 | return t 72 | 73 | val_loader, val_size = custom_dataset(args, cfg) 74 | print("Testing data size:", val_size) 75 | 76 | # Evaluation 77 | correct = torch.zeros(1).to(device) 78 | incorrect = torch.zeros(1).to(device) 79 | total = torch.zeros(1).to(device) 80 | for i, (vid, label) in enumerate(val_loader): 81 | with torch.no_grad(): 82 | vid, label = inv_normalize(vid).to(device), label.to(device) 83 | B, C, T, H, W = vid.size() 84 | 85 | vid_out = model_t(normalize(vid.clone().detach())).argmax(dim=-1) 86 | correct += torch.sum(vid_out == label).item() 87 | total += B 88 | 89 | # Untargeted Adversary 90 | pert = netG(vid.permute(0, 2, 1, 3, 4).contiguous().view(-1, C, H, W)) * 2 - 1 91 | pert = pert.view(B, T, C, H, W).permute(0, 2, 1, 3, 4) 92 | 93 | # Projection 94 | adv = pert * eps + vid 95 | adv = torch.clamp(adv, 0.0, 1.0) 96 | 97 | adv_out = model_t(normalize(adv.clone().detach())).argmax(dim=-1) 98 | incorrect += torch.sum((adv_out != label) & (vid_out == label)).item() 99 | 100 | if args.local_rank == 0: 101 | for t in range(T): 102 | vutils.save_image(vutils.make_grid(adv[0, :, t, :, :], normalize=True, scale_each=True), "./adv/adv_{}.png".format(t)) 103 | vutils.save_image(vutils.make_grid(vid[0, :, t, :, :], normalize=True, scale_each=True), "./ori/ori_{}.png".format(t)) 104 | print("At Batch:{}\t l_inf:{}".format(i, (vid - adv).max() * 255)) 105 | 106 | torch.distributed.all_reduce(correct) 107 | torch.distributed.all_reduce(incorrect) 108 | torch.distributed.all_reduce(total) 109 | print("Clean:{0:}\t Adversarial:{1:}\t Total:{2:}\t ACC:{3:}\t ASR:{4:}".format(correct, incorrect, total, correct/total, incorrect / correct)) 110 | if __name__ == "__main__": 111 | parser = get_args_parser() 112 | args = parser.parse_args() 113 | print(args) 114 | main(args) 115 | -------------------------------------------------------------------------------- /generators.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | 4 | 5 | ########################### 6 | # Generator: Resnet 7 | ########################### 8 | 9 | # To control feature map in generator 10 | ngf = 64 11 | 12 | def custom_gan(args): 13 | if args.model_type == 'incv3': 14 | netG = GeneratorResnet(inception=True) 15 | else: 16 | netG = GeneratorResnet() 17 | return netG 18 | 19 | 20 | class GeneratorResnet(nn.Module): 21 | def __init__(self, inception=False, data_dim='high'): 22 | ''' 23 | :param inception: if True crop layer will be added to go from 3x300x300 t0 3x299x299. 24 | :param data_dim: for high dimentional dataset (imagenet) 6 resblocks will be add otherwise only 2. 25 | ''' 26 | super(GeneratorResnet, self).__init__() 27 | self.inception = inception 28 | self.data_dim = data_dim 29 | # Input_size = 3, n, n 30 | self.block1 = nn.Sequential( 31 | nn.ReflectionPad2d(3), 32 | nn.Conv2d(3, ngf, kernel_size=7, padding=0, bias=False), 33 | nn.BatchNorm2d(ngf), 34 | nn.ReLU(True) 35 | ) 36 | 37 | # Input size = 3, n, n 38 | self.block2 = nn.Sequential( 39 | nn.Conv2d(ngf, ngf * 2, kernel_size=3, stride=2, padding=1, bias=False), 40 | nn.BatchNorm2d(ngf * 2), 41 | nn.ReLU(True) 42 | ) 43 | 44 | # Input size = 3, n/2, n/2 45 | self.block3 = nn.Sequential( 46 | nn.Conv2d(ngf * 2, ngf * 4, kernel_size=3, stride=2, padding=1, bias=False), 47 | nn.BatchNorm2d(ngf * 4), 48 | nn.ReLU(True) 49 | ) 50 | 51 | # Input size = 3, n/4, n/4 52 | # Residual Blocks: 6 53 | self.resblock1 = ResidualBlock(ngf * 4) 54 | self.resblock2 = ResidualBlock(ngf * 4) 55 | if self.data_dim == 'high': 56 | self.resblock3 = ResidualBlock(ngf * 4) 57 | self.resblock4 = ResidualBlock(ngf * 4) 58 | self.resblock5 = ResidualBlock(ngf * 4) 59 | self.resblock6 = ResidualBlock(ngf * 4) 60 | # self.resblock7 = ResidualBlock(ngf*4) 61 | # self.resblock8 = ResidualBlock(ngf*4) 62 | # self.resblock9 = ResidualBlock(ngf*4) 63 | 64 | # Input size = 3, n/4, n/4 65 | self.upsampl1 = nn.Sequential( 66 | nn.ConvTranspose2d(ngf * 4, ngf * 2, kernel_size=3, stride=2, padding=1, output_padding=1, bias=False), 67 | nn.BatchNorm2d(ngf * 2), 68 | nn.ReLU(True) 69 | ) 70 | 71 | # Input size = 3, n/2, n/2 72 | self.upsampl2 = nn.Sequential( 73 | nn.ConvTranspose2d(ngf * 2, ngf, kernel_size=3, stride=2, padding=1, output_padding=1, bias=False), 74 | nn.BatchNorm2d(ngf), 75 | nn.ReLU(True) 76 | ) 77 | 78 | # Input size = 3, n, n 79 | self.blockf = nn.Sequential( 80 | nn.ReflectionPad2d(3), 81 | nn.Conv2d(ngf, 3, kernel_size=7, padding=0) 82 | ) 83 | 84 | self.crop = nn.ConstantPad2d((0, -1, -1, 0), 0) 85 | 86 | def forward(self, input): 87 | x = self.block1(input) 88 | x = self.block2(x) 89 | x = self.block3(x) 90 | x = self.resblock1(x) 91 | x = self.resblock2(x) 92 | if self.data_dim == 'high': 93 | x = self.resblock3(x) 94 | x = self.resblock4(x) 95 | x = self.resblock5(x) 96 | x = self.resblock6(x) 97 | # x = self.resblock7(x) 98 | # x = self.resblock8(x) 99 | # x = self.resblock9(x) 100 | x = self.upsampl1(x) 101 | x = self.upsampl2(x) 102 | x = self.blockf(x) 103 | if self.inception: 104 | x = self.crop(x) 105 | return (torch.tanh(x) + 1) / 2 # Output range [0 1] 106 | 107 | 108 | class ResidualBlock(nn.Module): 109 | def __init__(self, num_filters): 110 | super(ResidualBlock, self).__init__() 111 | self.block = nn.Sequential( 112 | nn.ReflectionPad2d(1), 113 | nn.Conv2d(in_channels=num_filters, out_channels=num_filters, kernel_size=3, stride=1, padding=0, 114 | bias=False), 115 | nn.BatchNorm2d(num_filters), 116 | nn.ReLU(True), 117 | 118 | nn.Dropout(0.5), 119 | 120 | nn.ReflectionPad2d(1), 121 | nn.Conv2d(in_channels=num_filters, out_channels=num_filters, kernel_size=3, stride=1, padding=0, 122 | bias=False), 123 | nn.BatchNorm2d(num_filters) 124 | ) 125 | 126 | def forward(self, x): 127 | residual = self.block(x) 128 | return x + residual 129 | 130 | 131 | 132 | if __name__ == '__main__': 133 | netG = GeneratorResnet(data_dim='low') 134 | test_sample = torch.rand(1, 3, 32, 32) 135 | print('Generator output:', netG(test_sample).size()) 136 | print('Generator parameters:', sum(p.numel() for p in netG.parameters() if p.requires_grad)) -------------------------------------------------------------------------------- /dataset_ucf.py: -------------------------------------------------------------------------------- 1 | import functools 2 | import os 3 | import torch 4 | import torch.utils.data as data 5 | 6 | from transforms_ucf101 import * 7 | 8 | 9 | def custom_dataset(args, cfg): 10 | cfg.CONFIG.VAL.BATCH_SIZE = args.batch_size 11 | val_loader = build_dataloader_val_ucf(cfg) 12 | return val_loader, len(val_loader) 13 | 14 | 15 | def build_dataloader_val_ucf(cfg): 16 | val_spa_trans, val_temp_trans = val_transform() 17 | val_dataset = attack_ucf101(spatial_transform=val_spa_trans, temporal_transform=val_temp_trans) 18 | 19 | if cfg.DDP_CONFIG.DISTRIBUTED: 20 | val_sampler = torch.utils.data.distributed.DistributedSampler(val_dataset) 21 | else: 22 | val_sampler = None 23 | val_loader = torch.utils.data.DataLoader( 24 | val_dataset, batch_size=cfg.CONFIG.VAL.BATCH_SIZE, shuffle=(val_sampler is None), 25 | num_workers=4, sampler=val_sampler, pin_memory=True) 26 | 27 | return val_loader 28 | 29 | 30 | def val_transform(): 31 | input_size = 224 32 | scale_ratios = "1.0, 0.8" 33 | scale_ratios = [float(i) for i in scale_ratios.split(',')] 34 | default_mean = [0.485, 0.456, 0.406] 35 | default_std = [0.229, 0.224, 0.225] 36 | norm_method = Normalize(default_mean, default_std) 37 | spatial_transform = spatial_Compose([Scale(int(input_size / 1.0)), CornerCrop(input_size, 'c'), ToTensor(), norm_method]) 38 | temporal_transform = LoopPadding(32) 39 | return spatial_transform, temporal_transform 40 | 41 | 42 | def get_default_video_loader(): 43 | image_loader = get_default_image_loader() 44 | return functools.partial(video_loader, image_loader=image_loader) 45 | 46 | 47 | class attack_ucf101(data.Dataset): 48 | 49 | def __init__(self, spatial_transform=None, temporal_transform=None, get_loader=get_default_video_loader): 50 | setting="ucf101/anno/test01_setting.txt" 51 | self.clips = self._make_dataset(setting) 52 | self.spatial_transform = spatial_transform 53 | self.temporal_transform = temporal_transform 54 | self.loader = get_loader() 55 | # with open("ucf101/anno/used_idxs.pkl", "rb") as ipt: 56 | # used_idxs = pkl.load(ipt) 57 | # self.new_clips = [] 58 | # for i in used_idxs: 59 | # self.new_clips.append(self.clips[i]) 60 | # self.clips = self.new_clips 61 | print ("length", len(self.clips)) 62 | 63 | def __getitem__(self, index): 64 | directory, duration, target = self.clips[index] 65 | frame_indices = list(range(1, duration + 1)) 66 | 67 | if self.temporal_transform is not None: 68 | frame_indices = self.temporal_transform(frame_indices) 69 | 70 | clip = self.loader(directory, frame_indices) 71 | 72 | if self.spatial_transform is not None: 73 | self.spatial_transform.randomize_parameters() 74 | clip = [self.spatial_transform(img) for img in clip] 75 | 76 | clip = torch.stack(clip, 0).permute(1, 0, 2, 3) 77 | 78 | return clip, target 79 | 80 | def _make_dataset(self, setting): 81 | if not os.path.exists(setting): 82 | raise(RuntimeError("Setting file %s doesn't exist. Check opt.train-list and opt.val-list. " % (setting))) 83 | clips = [] 84 | with open(setting) as split_f: 85 | data = split_f.readlines() 86 | for line in data: 87 | line_info = line.split() 88 | # line format: video_path, video_duration, video_label 89 | if len(line_info) < 3: 90 | raise(RuntimeError("Video input format is not correct, missing one or more element. %s" % line)) 91 | clip_path = os.path.join("ucf101/dataset", line_info[0]) 92 | duration = int(line_info[1]) 93 | target = int(line_info[2]) 94 | item = (clip_path, duration, target) 95 | clips.append(item) 96 | return clips 97 | 98 | def __len__(self): 99 | return len(self.clips) 100 | 101 | 102 | def video_loader(video_dir_path, frame_indices, image_loader): 103 | video = [] 104 | for i in frame_indices: 105 | image_path = os.path.join(video_dir_path, "image_{:05d}.jpg".format(i)) 106 | if os.path.exists(image_path): 107 | video.append(image_loader(image_path)) 108 | else: 109 | return video 110 | return video 111 | 112 | 113 | def get_default_image_loader(): 114 | from torchvision import get_image_backend 115 | if get_image_backend() == "accimage": 116 | return accimage_loader 117 | else: 118 | return pil_loader 119 | 120 | 121 | def accimage_loader(path): 122 | try: 123 | import accimage 124 | return accimage.Image(path) 125 | except IOError: 126 | # Potentially a decoding problem, fall back to PIL.Image 127 | return pil_loader(path) 128 | 129 | 130 | def pil_loader(path): 131 | # open path as file to avoid ResourceWarning (https://github.com/python-pillow/Pillow/issues/835) 132 | with open(path, "rb") as f: 133 | with Image.open(f) as img: 134 | return img.convert("RGB") -------------------------------------------------------------------------------- /train.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import cv2 3 | import random 4 | import torch 5 | import numpy as np 6 | import torch.nn as nn 7 | import torch.nn.functional as F 8 | import torch.optim as optim 9 | import torchvision.datasets as datasets 10 | import torchvision.models as models 11 | import torchvision.transforms as transforms 12 | from torch.nn.parallel import DistributedDataParallel 13 | from torch.utils.data import DataLoader 14 | from torch.utils.data.distributed import DistributedSampler 15 | 16 | from generators import custom_gan 17 | 18 | 19 | sigma = {"res152": 10, "dense201": 8, "squeeze1_1": 12, "shufflev2_x1.0": 8} 20 | 21 | 22 | internal_feature_in = [] 23 | internal_feature_out = [] 24 | def forward_hook(module, input, output): 25 | if len(internal_feature_in) == 0: 26 | internal_feature_in.append(input) 27 | internal_feature_out.append(output) 28 | else: 29 | internal_feature_in[0] = input 30 | internal_feature_out[0] = output 31 | return None 32 | 33 | 34 | def get_args_parser(): 35 | parser = argparse.ArgumentParser(description="Cross Modal Transferability", add_help=False) 36 | parser.add_argument("--train_dir", default="imagenet_2012/train", help="imagenet") 37 | parser.add_argument("--batch_size", type=int, default=16, help="Number of trainig samples/batch") 38 | parser.add_argument("--epochs", type=int, default=1, help="Number of training epochs") 39 | parser.add_argument("--lr", type=float, default=0.0002, help="Initial learning rate for adam") 40 | parser.add_argument("--eps", type=int, default=10, help="Perturbation Budget") 41 | parser.add_argument("--model_type", type=str, default="res152", help="Model against GAN is trained: res152, dense201, squeeze1_1, shufflev2_x1.0") 42 | parser.add_argument("--local_rank", default=0, type=int, help="node rank for distributed training") 43 | return parser 44 | 45 | 46 | def setup_seed(seed): 47 | np.random.seed(seed) 48 | random.seed(seed) 49 | torch.manual_seed(seed) 50 | torch.cuda.manual_seed_all(seed) 51 | torch.backends.cudnn.benchmark = False 52 | torch.backends.cudnn.deterministic = True 53 | 54 | 55 | def warp(x, flo, padding_mode="border"): 56 | B, _, H, W = x.size() 57 | 58 | # Mesh grid 59 | xx = torch.arange(0, W).view(1, -1).repeat(H, 1) 60 | yy = torch.arange(0, H).view(-1, 1).repeat(1, W) 61 | xx = xx.view(1, 1, H, W).repeat(B, 1, 1, 1) 62 | yy = yy.view(1, 1, H, W).repeat(B, 1, 1, 1) 63 | grid = torch.cat((xx, yy), 1).float() 64 | vgrid = grid + flo 65 | 66 | # Scale grid to [-1, 1] 67 | vgrid[:, 0, :, :] = 2.0 * vgrid[:, 0, :, :] / max(W - 1, 1) - 1.0 68 | vgrid[:, 1, :, :] = 2.0 * vgrid[:, 1, :, :] / max(H - 1, 1) - 1.0 69 | vgrid = vgrid.permute(0, 2, 3, 1).cuda() 70 | output = F.grid_sample(x, vgrid, padding_mode=padding_mode, mode="nearest") 71 | return output 72 | 73 | 74 | def random_optical_flow(t, model_type): 75 | B, _, H, W = t.size() 76 | flows = [] 77 | for b in range(B): 78 | flow = np.random.normal(0, sigma[model_type], size = [H // 100, W // 100, 2]) 79 | flow = cv2.resize(flow, (H, W)) 80 | flow[:, :, 0] += random.randint(-10, 10) 81 | flow[:, :, 1] += random.randint(-10, 10) 82 | flow = cv2.blur(flow, (100, 100)) 83 | flows.append(torch.from_numpy(flow.transpose((2, 0, 1))).float()) 84 | return torch.stack(flows, 0) 85 | 86 | 87 | def main(args): 88 | # Normalize (0-1) 89 | eps = args.eps / 255 90 | warmup_eps = 4 / 255 91 | 92 | setup_seed(0) 93 | 94 | # GPU 95 | torch.cuda.set_device(args.local_rank) 96 | torch.distributed.init_process_group(backend="nccl", init_method="env://") 97 | device = torch.device("cuda", args.local_rank) 98 | 99 | #################### 100 | # Model and Generator 101 | #################### 102 | if args.model_type == "res152": 103 | model = models.resnet152(pretrained=True).to(device) 104 | model.layer3.register_forward_hook(hook=forward_hook) 105 | elif args.model_type == "dense201": 106 | model = models.densenet201(pretrained=True).to(device) 107 | for name, module in model.features.named_modules(): 108 | if name == "transition3": 109 | module.register_forward_hook(hook=forward_hook) 110 | elif args.model_type == "squeeze1_1": 111 | model = models.squeezenet1_1(pretrained=True).to(device) 112 | model.features[10].register_forward_hook(hook=forward_hook) 113 | elif args.model_type == "shufflev2_x1.0": 114 | model = models.shufflenet_v2_x1_0(pretrained=True).to(device) 115 | model.stage3.register_forward_hook(hook=forward_hook) 116 | model = DistributedDataParallel(model, device_ids=[args.local_rank], output_device=args.local_rank) 117 | model.eval() 118 | for param in model.parameters(): 119 | param.requires_grad = False 120 | 121 | netG = custom_gan(args) 122 | netG = nn.SyncBatchNorm.convert_sync_batchnorm(netG).to(device) 123 | netG = DistributedDataParallel(netG, device_ids=[args.local_rank], output_device=args.local_rank) 124 | 125 | # Optimizer 126 | optimG = optim.Adam(netG.parameters(), lr=args.lr, betas=(0.5, 0.999)) 127 | 128 | # Input dimensions 129 | scale_size = 256 130 | img_size = 224 131 | 132 | # Data 133 | data_transform = transforms.Compose([ 134 | transforms.Resize(scale_size), 135 | transforms.CenterCrop(img_size), 136 | transforms.ToTensor(), 137 | ]) 138 | 139 | mean = [0.485, 0.456, 0.406] 140 | std = [0.229, 0.224, 0.225] 141 | def normalize(t): 142 | t[:, 0, :, :] = (t[:, 0, :, :] - mean[0]) / std[0] 143 | t[:, 1, :, :] = (t[:, 1, :, :] - mean[1]) / std[1] 144 | t[:, 2, :, :] = (t[:, 2, :, :] - mean[2]) / std[2] 145 | return t 146 | 147 | train_dir = args.train_dir 148 | train_set = datasets.ImageFolder(train_dir, data_transform) 149 | train_sampler = DistributedSampler(train_set) 150 | train_loader = DataLoader(train_set, batch_size=args.batch_size, shuffle=False, num_workers=4, sampler=train_sampler, pin_memory=True) 151 | train_size = len(train_set) 152 | print("Training data size:", train_size) 153 | 154 | # Loss 155 | cos_sim = nn.CosineSimilarity() 156 | 157 | # Training 158 | print("Model: {} \t Distribution: {} \t Saving instances: {}".format(args.model_type, args.train_dir, args.epochs)) 159 | netG.train() 160 | for epoch in range(args.epochs): 161 | train_loader.sampler.set_epoch(epoch) 162 | running_loss = 0 163 | for step, (img, label) in enumerate(train_loader): 164 | img, label = img.to(device), label.to(device) 165 | B, C, H, W = img.size() 166 | 167 | flow = random_optical_flow(img, args.model_type) 168 | next_img = warp(img, flow) 169 | imgs = torch.cat((img, next_img), 0) 170 | 171 | perts = netG(imgs) * 2 - 1 172 | 173 | # Projection 174 | if step < 250: 175 | advs = perts * warmup_eps + imgs 176 | else: 177 | advs = perts * eps + imgs 178 | advs = torch.clamp(advs, 0.0, 1.0) 179 | 180 | optimG.zero_grad() 181 | 182 | # Gradient accent (Untargeted Attack) 183 | adv, next_adv = torch.split(advs, B, 0) 184 | adv_next = warp(adv, flow) 185 | cat_in = torch.cat([next_img, next_adv, adv_next], 0) 186 | cat_out = model(normalize(cat_in.clone())) 187 | next_img_fea = internal_feature_out[0][0 : B, :, :, :] 188 | next_adv_fea = internal_feature_out[0][B : 2 * B, :, :, :] 189 | adv_next_fea = internal_feature_out[0][2 * B : 3 * B, :, :, :] 190 | print(cos_sim(next_img_fea.view(B, -1), next_adv_fea.view(B, -1)).mean(), cos_sim(next_adv_fea.view(B, -1), adv_next_fea.view(B, -1)).mean()) 191 | 192 | loss = cos_sim(next_img_fea.view(B, -1), adv_next_fea.view(B, -1)).mean() - cos_sim(next_adv_fea.view(B, -1), adv_next_fea.view(B, -1)).mean() 193 | 194 | loss.backward() 195 | optimG.step() 196 | 197 | if step != 0 and step % 10 == 0: 198 | print("Epoch: {0} \t Batch: {1} \t loss: {2:.5f}".format(epoch, step, running_loss / 10)) 199 | running_loss = 0 200 | running_loss += loss.item() 201 | if args.local_rank == 0: 202 | torch.save(netG.module.state_dict(), "netG_{}_gcma.pth".format(args.model_type)) 203 | if __name__ == "__main__": 204 | parser = get_args_parser() 205 | args = parser.parse_args() 206 | print(args) 207 | main(args) -------------------------------------------------------------------------------- /transforms_ucf101.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | import numbers 4 | import collections 5 | import numpy as np 6 | import torch 7 | from PIL import Image 8 | try: 9 | import accimage 10 | except ImportError: 11 | accimage = None 12 | 13 | # the code from 3D-ResNets-PyTorch-master/temporal_transforms.py, spatial_transforms.py and target_transforms.py 14 | 15 | #******************************************** 16 | # temporal_transforms 17 | #******************************************** 18 | # LoopPadding: frame_indices < size, loop 19 | # TemporalBeginCrop: frame_indices[:size] < size, loop, [1:] 20 | # TemporalCenterCrop: frame_indice[center-size/2:center+size/2] < size, loop, [1:] 21 | # TemporalRandomCrop: frame_indice[random_begin,:random_begin+size] < size, loop, [1:] 22 | class LoopPadding(object): 23 | """ 24 | Variable size means that the length of temporal images we wanted. 25 | The length of variable out should be equal with variable size. 26 | If not, LoopPadding the temporal images. 27 | """ 28 | def __init__(self, size): 29 | self.size = size 30 | 31 | def __call__(self, frame_indices): 32 | out = frame_indices[1:self.size+1] 33 | 34 | for index in out: 35 | if len(out) >= self.size: 36 | break 37 | out.append(index) 38 | 39 | return out 40 | 41 | 42 | class TemporalBeginCrop(object): 43 | """ 44 | Temporally crop the given frame indices at a beginning. 45 | If the number of frames is less than the size, 46 | loop the indices as many times as necessary to satisfy the size. 47 | Args: 48 | size (int): Desired output size of the crop. 49 | """ 50 | 51 | def __init__(self, size): 52 | self.size = size 53 | 54 | def __call__(self, frame_indices): 55 | out = frame_indices[1:self.size+1] 56 | 57 | for index in out: 58 | if len(out) >= self.size: 59 | break 60 | out.append(index) 61 | return out 62 | 63 | 64 | class TemporalCenterCrop(object): 65 | """ 66 | Temporally crop the given frame indices at a center. 67 | If the number of frames is less than the size, 68 | loop the indices as many times as necessary to satisfy the size. 69 | Args: 70 | size (int): Desired output size of the crop. 71 | """ 72 | 73 | def __init__(self, size): 74 | self.size = size 75 | 76 | def __call__(self, frame_indices): 77 | """ 78 | Args: 79 | frame_indices (list): frame indices to be cropped. 80 | Returns: 81 | list: Cropped frame indices. 82 | """ 83 | 84 | center_index = len(frame_indices) // 2 85 | begin_index = max(1, center_index - (self.size // 2)) 86 | end_index = min(begin_index + self.size, len(frame_indices)) 87 | 88 | out = frame_indices[begin_index:end_index] 89 | 90 | for index in out: 91 | if len(out) >= self.size: 92 | break 93 | out.append(index) 94 | 95 | return out 96 | 97 | 98 | class TemporalRandomCrop(object): 99 | """ 100 | Temporally crop the given frame indices at a random location. 101 | If the number of frames is less than the size, 102 | loop the indices as many times as necessary to satisfy the size. 103 | Args: 104 | size (int): Desired output size of the crop. 105 | """ 106 | 107 | def __init__(self, size): 108 | self.size = size 109 | 110 | def __call__(self, frame_indices): 111 | """ 112 | Args: 113 | frame_indices (list): frame indices to be cropped. 114 | Returns: 115 | list: Cropped frame indices. 116 | """ 117 | 118 | rand_end = max(1, len(frame_indices) - self.size - 1) 119 | random.seed(1024) 120 | begin_index = random.randint(0, rand_end) 121 | end_index = min(begin_index + self.size, len(frame_indices)) 122 | 123 | out = frame_indices[begin_index:end_index] 124 | 125 | for index in out: 126 | if len(out) >= self.size: 127 | break 128 | out.append(index) 129 | 130 | return out 131 | 132 | #******************************************** 133 | # spatial_transforms 134 | #******************************************** 135 | # spatial_Compose: combine multiple spatial transforms function. 136 | # ToTensor: np.array, Image.image to tensor, H*W*C(0-255) to C*H*W (0.0-1.0), pixel/norm_value, for tensor. 137 | # Normalize: (pixel-mean)/std, for tensor. 138 | # Scale: Keeping aspect ratio unchanged, scaled the smaller side, for Image. 139 | # CenterCrop: for Image. 140 | # RandomHorizontalFlip: Horizontally flip a image by a probability 0.5. 141 | # MultiScaleCornerCrop: Multiple Scales from 4 corners and 1 center. 142 | # MultiScaleRandomCrop: Multiple Scales from random position. 143 | 144 | class spatial_Compose(object): 145 | """Composes several transforms together. 146 | Args: 147 | transforms (list of ``Transform`` objects): list of transforms to compose. 148 | Example: 149 | >>> transforms.Compose([ 150 | >>> transforms.CenterCrop(10), 151 | >>> transforms.ToTensor(), 152 | >>> ]) 153 | """ 154 | 155 | def __init__(self, transforms): 156 | self.transforms = transforms 157 | 158 | def __call__(self, img): 159 | for t in self.transforms: 160 | img = t(img) 161 | return img 162 | 163 | def randomize_parameters(self): 164 | for t in self.transforms: 165 | t.randomize_parameters() 166 | 167 | 168 | class ToTensor(object): 169 | """ 170 | Convert a ``PIL.Image`` or ``numpy.ndarray`` to tensor. 171 | Converts a PIL.Image or numpy.ndarray (H x W x C) in the range 172 | [0, 255] to a torch.FloatTensor of shape (C x H x W) in the range [0.0, 1.0]. 173 | """ 174 | 175 | def __init__(self, norm_value=255): 176 | self.norm_value = norm_value 177 | 178 | def __call__(self, pic): 179 | """ 180 | Args: 181 | pic (PIL.Image or numpy.ndarray): Image to be converted to tensor. 182 | Returns: 183 | Tensor: Converted image. 184 | """ 185 | if isinstance(pic, np.ndarray): 186 | # handle numpy array 187 | img = torch.from_numpy(pic.transpose((2, 0, 1))) 188 | # backward compatibility 189 | return img.float().div(self.norm_value) 190 | 191 | if accimage is not None and isinstance(pic, accimage.Image): 192 | nppic = np.zeros( 193 | [pic.channels, pic.height, pic.width], dtype=np.float32) 194 | pic.copyto(nppic) 195 | return torch.from_numpy(nppic) 196 | 197 | # handle PIL Image 198 | if pic.mode == 'I': 199 | img = torch.from_numpy(np.array(pic, np.int32, copy=False)) 200 | elif pic.mode == "I;16": 201 | img = torch.from_numpy(np.array(pic, np.int16, copy=False)) 202 | else: 203 | img = torch.ByteTensor(torch.ByteStorage.from_buffer(pic.tobytes())) 204 | # PIL image mode: 1, L, P, I, F, RGB, YCbCr, RGBA, CMYK 205 | if pic.mode == "YCbCr": 206 | nchannel = 3 207 | elif pic.mode == "I;16": 208 | nchannel = 1 209 | else: 210 | nchannel = len(pic.mode) 211 | img = img.view(pic.size[1], pic.size[0], nchannel) 212 | # put it from HWC to CHW format 213 | # yikes, this transpose takes 80% of the loading time/CPU 214 | img = img.transpose(0, 1).transpose(0, 2).contiguous() 215 | if isinstance(img, torch.ByteTensor): 216 | return img.float().div(self.norm_value) 217 | else: 218 | return img 219 | 220 | def randomize_parameters(self): 221 | pass 222 | 223 | 224 | class Normalize(object): 225 | """ 226 | Normalize an tensor image with mean and standard deviation. 227 | Given mean: (R, G, B) and std: (R, G, B), 228 | will normalize each channel of the torch.*Tensor, i.e. 229 | channel = (channel - mean) / std 230 | Args: 231 | mean (sequence): Sequence of means for R, G, B channels respecitvely. 232 | std (sequence): Sequence of standard deviations for R, G, B channels 233 | respecitvely. 234 | """ 235 | 236 | def __init__(self, mean, std): 237 | self.mean = mean 238 | self.std = std 239 | 240 | def __call__(self, tensor): 241 | """ 242 | Args: 243 | tensor (Tensor): Tensor image of size (C, H, W) to be normalized. 244 | Returns: 245 | Tensor: Normalized image. 246 | """ 247 | # TODO: make efficient 248 | for t, m, s in zip(tensor, self.mean, self.std): 249 | t.sub_(m).div_(s) 250 | return tensor 251 | 252 | def randomize_parameters(self): 253 | pass 254 | 255 | 256 | class Scale(object): 257 | """Rescale the input PIL.Image to the given size. 258 | Args: 259 | size (sequence or int): Desired output size. If size is a sequence like 260 | (w, h), output size will be matched to this. If size is an int, 261 | smaller edge of the image will be matched to this number. 262 | i.e, if height > width, then image will be rescaled to 263 | (size * height / width, size) 264 | interpolation (int, optional): Desired interpolation. Default is 265 | ``PIL.Image.BILINEAR`` 266 | """ 267 | 268 | def __init__(self, size, interpolation=Image.BILINEAR): 269 | assert isinstance(size, 270 | int) or (isinstance(size, collections.Iterable) and 271 | len(size) == 2) 272 | self.size = size 273 | self.interpolation = interpolation 274 | 275 | def __call__(self, img): 276 | """ 277 | Args: 278 | img (PIL.Image): Image to be scaled. 279 | Returns: 280 | PIL.Image: Rescaled image. 281 | """ 282 | if isinstance(self.size, int): 283 | w, h = img.size 284 | if (w <= h and w == self.size) or (h <= w and h == self.size): 285 | return img 286 | if w < h: 287 | ow = self.size 288 | oh = int(self.size * h / w) 289 | return img.resize((ow, oh), self.interpolation) 290 | else: 291 | oh = self.size 292 | ow = int(self.size * w / h) 293 | return img.resize((ow, oh), self.interpolation) 294 | else: 295 | return img.resize(self.size, self.interpolation) 296 | 297 | def randomize_parameters(self): 298 | pass 299 | 300 | 301 | class CenterCrop(object): 302 | """Crops the given PIL.Image at the center. 303 | Args: 304 | size (sequence or int): Desired output size of the crop. If size is an 305 | int instead of sequence like (h, w), a square crop (size, size) is 306 | made. 307 | """ 308 | 309 | def __init__(self, size): 310 | if isinstance(size, numbers.Number): 311 | self.size = (int(size), int(size)) 312 | else: 313 | self.size = size 314 | 315 | def __call__(self, img): 316 | """ 317 | Args: 318 | img (PIL.Image): Image to be cropped. 319 | Returns: 320 | PIL.Image: Cropped image. 321 | """ 322 | w, h = img.size 323 | th, tw = self.size 324 | x1 = int(round((w - tw) / 2.)) 325 | y1 = int(round((h - th) / 2.)) 326 | return img.crop((x1, y1, x1 + tw, y1 + th)) 327 | 328 | def randomize_parameters(self): 329 | pass 330 | 331 | 332 | class CornerCrop(object): 333 | 334 | def __init__(self, size, crop_position=None): 335 | self.size = size 336 | if crop_position is None: 337 | self.randomize = True 338 | else: 339 | self.randomize = False 340 | self.crop_position = crop_position 341 | self.crop_positions = ['c', "tl", "tr", "bl", "br"] 342 | 343 | def __call__(self, img): 344 | image_width = img.size[0] 345 | image_height = img.size[1] 346 | 347 | if self.crop_position == 'c': 348 | th, tw = (self.size, self.size) 349 | x1 = int(round((image_width - tw) / 2.)) 350 | y1 = int(round((image_height - th) / 2.)) 351 | x2 = x1 + tw 352 | y2 = y1 + th 353 | elif self.crop_position == "tl": 354 | x1 = 0 355 | y1 = 0 356 | x2 = self.size 357 | y2 = self.size 358 | elif self.crop_position == "tr": 359 | x1 = image_width - self.size 360 | y1 = 0 361 | x2 = image_width 362 | y2 = self.size 363 | elif self.crop_position == "bl": 364 | x1 = 0 365 | y1 = image_height - self.size 366 | x2 = self.size 367 | y2 = image_height 368 | elif self.crop_position == "br": 369 | x1 = image_width - self.size 370 | y1 = image_height - self.size 371 | x2 = image_width 372 | y2 = image_height 373 | 374 | img = img.crop((x1, y1, x2, y2)) 375 | 376 | return img 377 | 378 | def randomize_parameters(self): 379 | if self.randomize: 380 | random.seed(1024) 381 | self.crop_position = self.crop_positions[random.randint( 382 | 0, 383 | len(self.crop_positions) - 1)] 384 | 385 | 386 | class RandomHorizontalFlip(object): 387 | """Horizontally flip the given PIL.Image randomly with a probability of 0.5.""" 388 | 389 | def __call__(self, img): 390 | """ 391 | Args: 392 | img (PIL.Image): Image to be flipped. 393 | Returns: 394 | PIL.Image: Randomly flipped image. 395 | """ 396 | if self.p < 0.5: 397 | return img.transpose(Image.FLIP_LEFT_RIGHT) 398 | return img 399 | 400 | def randomize_parameters(self): 401 | random.seed(1024) 402 | self.p = random.random() 403 | 404 | 405 | class MultiScaleCornerCrop(object): 406 | """Crop the given PIL.Image to randomly selected size. 407 | A crop of size is selected from scales of the original size. 408 | A position of cropping is randomly selected from 4 corners and 1 center. 409 | This crop is finally resized to given size. 410 | Args: 411 | scales: cropping scales of the original size 412 | size: size of the smaller edge 413 | interpolation: Default: PIL.Image.BILINEAR 414 | """ 415 | 416 | def __init__(self, 417 | scales, 418 | size, 419 | interpolation=Image.BILINEAR, 420 | crop_positions=['c', "tl", "tr", "bl", "br"]): 421 | self.scales = scales 422 | self.size = size 423 | self.interpolation = interpolation 424 | 425 | self.crop_positions = crop_positions 426 | 427 | def __call__(self, img): 428 | min_length = min(img.size[0], img.size[1]) 429 | crop_size = int(min_length * self.scale) 430 | 431 | image_width = img.size[0] 432 | image_height = img.size[1] 433 | 434 | if self.crop_position == 'c': 435 | center_x = image_width // 2 436 | center_y = image_height // 2 437 | box_half = crop_size // 2 438 | x1 = center_x - box_half 439 | y1 = center_y - box_half 440 | x2 = center_x + box_half 441 | y2 = center_y + box_half 442 | elif self.crop_position == "tl": 443 | x1 = 0 444 | y1 = 0 445 | x2 = crop_size 446 | y2 = crop_size 447 | elif self.crop_position == "tr": 448 | x1 = image_width - crop_size 449 | y1 = 0 450 | x2 = image_width 451 | y2 = crop_size 452 | elif self.crop_position == "bl": 453 | x1 = 0 454 | y1 = image_height - crop_size 455 | x2 = crop_size 456 | y2 = image_height 457 | elif self.crop_position == "br": 458 | x1 = image_width - crop_size 459 | y1 = image_height - crop_size 460 | x2 = image_width 461 | y2 = image_height 462 | 463 | img = img.crop((x1, y1, x2, y2)) 464 | 465 | return img.resize((self.size, self.size), self.interpolation) 466 | 467 | def randomize_parameters(self): 468 | random.seed(1024) 469 | self.scale = self.scales[random.randint(0, len(self.scales) - 1)] 470 | random.seed(1024) 471 | self.crop_position = self.crop_positions[random.randint( 472 | 0, 473 | len(self.crop_positions) - 1)] 474 | 475 | 476 | class MultiScaleRandomCrop(object): 477 | """ 478 | Crop the given PIL.Image to randomly selected size. 479 | A position of cropping is randomly selected. 480 | """ 481 | 482 | def __init__(self, scales, size, interpolation=Image.BILINEAR): 483 | self.scales = scales 484 | self.size = size 485 | self.interpolation = interpolation 486 | 487 | def __call__(self, img): 488 | min_length = min(img.size[0], img.size[1]) 489 | crop_size = int(min_length * self.scale) 490 | 491 | image_width = img.size[0] 492 | image_height = img.size[1] 493 | 494 | x1 = self.tl_x * (image_width - crop_size) 495 | y1 = self.tl_y * (image_height - crop_size) 496 | x2 = x1 + crop_size 497 | y2 = y1 + crop_size 498 | 499 | img = img.crop((x1, y1, x2, y2)) 500 | 501 | return img.resize((self.size, self.size), self.interpolation) 502 | 503 | def randomize_parameters(self): 504 | self.scale = self.scales[random.randint(0, len(self.scales) - 1)] 505 | random.seed(1024) 506 | self.tl_x = random.random() 507 | random.seed(1024) 508 | self.tl_y = random.random() -------------------------------------------------------------------------------- /kinetics400/anno/val400.csv: -------------------------------------------------------------------------------- 1 | path,gt_label,clip_index 2 | abseiling/YqTT34PsD5c_000003_000013.mp4,0,1 3 | air drumming/--nQbRBEz2s_000104_000114.mp4,1,1 4 | answering questions/AqPeHqTDfGE_000068_000078.mp4,2,1 5 | applauding/ieIq7ym_UXQ_000007_000017.mp4,3,1 6 | applying cream/rFee2NCkWQE_000013_000023.mp4,4,1 7 | archery/FzfqEd36YbY_001101_001111.mp4,5,1 8 | arm wrestling/_Lo3hFbum_o_000005_000015.mp4,6,1 9 | arranging flowers/cuOsRai-HCE_000126_000136.mp4,7,1 10 | assembling computer/CB1iIWtDpSI_000431_000441.mp4,8,1 11 | auctioning/6jcDGC4LF5s_001022_001032.mp4,9,1 12 | baby waking up/X66nHKtYtt0_000008_000018.mp4,10,1 13 | baking cookies/LG2hEf9ueAM_000178_000188.mp4,11,1 14 | balloon blowing/qjyGo-e_d6I_000076_000086.mp4,12,1 15 | bandaging/TwSUMZOrLyE_000139_000149.mp4,13,1 16 | barbequing/_7mBVhDgiO8_000019_000029.mp4,14,1 17 | bartending/TuCc2RwG2fM_000354_000364.mp4,15,1 18 | beatboxing/rYnVViYbae0_000000_000010.mp4,16,1 19 | bee keeping/EpbYRgIsQRg_000018_000028.mp4,17,1 20 | belly dancing/cMVkWCb3fE8_000103_000113.mp4,18,1 21 | bench pressing/ehxWC3nDZC8_000003_000013.mp4,19,1 22 | bending back/DA8K3c4HgVo_000003_000013.mp4,20,1 23 | bending metal/U-iQuIgd5ps_000478_000488.mp4,21,1 24 | biking through snow/g3GJvDqtfys_000031_000041.mp4,22,1 25 | blasting sand/NAqrwQ54ptY_000028_000038.mp4,23,1 26 | blowing glass/p2NEs8gon0k_000381_000391.mp4,24,1 27 | blowing leaves/wKgo6AS5C80_000044_000054.mp4,25,1 28 | blowing nose/gu0QuD4zpzg_000030_000040.mp4,26,1 29 | blowing out candles/9IzWImcF3hM_000032_000042.mp4,27,1 30 | bobsledding/uftReOMM9-A_000063_000073.mp4,28,1 31 | bookbinding/hmoPcSFBYPY_000222_000232.mp4,29,1 32 | bouncing on trampoline/bekao5nG02M_000024_000034.mp4,30,1 33 | bowling/8pBjZcOc8MY_000096_000106.mp4,31,1 34 | braiding hair/-dLVSg5JvxY_000022_000032.mp4,32,1 35 | breading or breadcrumbing/-_3E3GBXAUc_000010_000020.mp4,33,1 36 | breakdancing/4T2F4PQ97GE_000008_000018.mp4,34,1 37 | brush painting/YHUeGa8Eu70_000225_000235.mp4,35,1 38 | brushing hair/9LnZrptwj6Q_000314_000324.mp4,36,1 39 | brushing teeth/8NStNQyjIXI_000054_000064.mp4,37,1 40 | building cabinet/CG9DKR4lPC0_001821_001831.mp4,38,1 41 | building shed/6q-XsQgZ8_w_000044_000054.mp4,39,1 42 | bungee jumping/7Goki93f5mo_000018_000028.mp4,40,1 43 | busking/CU6MFCvEct0_000016_000026.mp4,41,1 44 | canoeing or kayaking/cdDu63UKbu0_000164_000174.mp4,42,1 45 | capoeira/lm6ibanrGK8_000000_000010.mp4,43,1 46 | carrying baby/ztAfXKZ0ovM_000141_000151.mp4,44,1 47 | cartwheeling/EiZvgwrHCMk_000000_000010.mp4,45,1 48 | carving pumpkin/oPoLYdOTOt0_000000_000010.mp4,46,1 49 | catching fish/dpfJTo3nywA_000028_000038.mp4,47,1 50 | catching or throwing baseball/AsPjORZU-cU_000055_000065.mp4,48,1 51 | catching or throwing frisbee/RxgW7Hdn4YM_000006_000016.mp4,49,1 52 | catching or throwing softball/kU3qQGVRT-g_000011_000021.mp4,50,1 53 | celebrating/2lBUaUBD9JE_000018_000028.mp4,51,1 54 | changing oil/-aJHPlJTesM_000734_000744.mp4,52,1 55 | changing wheel/EQNTFw62uh8_000251_000261.mp4,53,1 56 | checking tires/wUQduZ3i-VM_000275_000285.mp4,54,1 57 | cheerleading/6LOV6-dkNZE_000251_000261.mp4,55,1 58 | chopping wood/nyFulYDEKFs_000017_000027.mp4,56,1 59 | clapping/M9NORCUCrtE_000003_000013.mp4,57,1 60 | clay pottery making/PP7MtP6BMkY_000193_000203.mp4,58,1 61 | clean and jerk/R6pk7NDa7Mw_000015_000025.mp4,59,1 62 | cleaning floor/vVlrGgL9dxk_000004_000014.mp4,60,1 63 | cleaning gutters/22xdXMMq6XE_000040_000050.mp4,61,1 64 | cleaning pool/AFvEYQkSmfk_000123_000133.mp4,62,1 65 | cleaning shoes/WJEGNo9YETM_000203_000213.mp4,63,1 66 | cleaning toilet/BjS2g1oZj_s_000065_000075.mp4,64,1 67 | cleaning windows/OiN3AgBVB80_000003_000013.mp4,65,1 68 | climbing a rope/NfH4FZhrtvE_000002_000012.mp4,66,1 69 | climbing ladder/70Er7J3srS0_000001_000011.mp4,67,1 70 | climbing tree/aM1AgHyvm4E_000017_000027.mp4,68,1 71 | contact juggling/yymr4YWVFe4_000046_000056.mp4,69,1 72 | cooking chicken/pj8TWS7KEeY_000024_000034.mp4,70,1 73 | cooking egg/Ao3M2TPI3sQ_000294_000304.mp4,71,1 74 | cooking on campfire/BQfDmW1Nodk_000002_000012.mp4,72,1 75 | cooking sausages/52AOa09jJWs_000195_000205.mp4,73,1 76 | counting money/kPCbWDyAcFE_000000_000010.mp4,74,1 77 | country line dancing/suHCOVoGPMU_000475_000485.mp4,75,1 78 | cracking neck/j_EiZph3YKE_000001_000011.mp4,76,1 79 | crawling baby/GpPvqvsqGy0_000006_000016.mp4,77,1 80 | crossing river/luTkBLIT6lU_000036_000046.mp4,78,1 81 | crying/zCEEKnSB_RU_000000_000010.mp4,79,1 82 | curling hair/gwNMVUlBUtY_000068_000078.mp4,80,1 83 | cutting nails/es35biYvLRA_000020_000030.mp4,81,1 84 | cutting pineapple/T5jQWQg2eNc_000000_000010.mp4,82,1 85 | cutting watermelon/LBgRTCVwyik_000042_000052.mp4,83,1 86 | dancing ballet/s_gGtYIrtsc_000118_000128.mp4,84,1 87 | dancing charleston/FQpLIyAfbqI_000023_000033.mp4,85,1 88 | dancing gangnam style/o_TIgx4gb_M_000023_000033.mp4,86,1 89 | dancing macarena/dXIyWMidYa0_000008_000018.mp4,87,1 90 | deadlifting/zvamd5T7yj8_000001_000011.mp4,88,1 91 | decorating the christmas tree/kQDSa-xhsLY_000035_000045.mp4,89,1 92 | digging/42Vx9FGzmkM_000075_000085.mp4,90,1 93 | dining/-vOrVT1CiPQ_000080_000090.mp4,91,1 94 | disc golfing/_owWHGvn_b0_000112_000122.mp4,92,1 95 | diving cliff/1MmjE51PeIE_000015_000025.mp4,93,1 96 | dodgeball/wFIuMu2w9pA_000010_000020.mp4,94,1 97 | doing aerobics/-53DvfE42gE_001767_001777.mp4,95,1 98 | doing laundry/qkd7laDeom0_000098_000108.mp4,96,1 99 | doing nails/UixL7lHSHR8_000040_000050.mp4,97,1 100 | drawing/IPmic5VRb7I_000066_000076.mp4,98,1 101 | dribbling basketball/qoODmONT1a0_000019_000029.mp4,99,1 102 | drinking/15FiZ48tTUU_000045_000055.mp4,100,1 103 | drinking beer/382B3Q3xttk_000000_000010.mp4,101,1 104 | drinking shots/o1hqepKau4A_000004_000014.mp4,102,1 105 | driving car/NUG7kwJ-614_000400_000410.mp4,103,1 106 | driving tractor/WtnQKvOuukE_000081_000091.mp4,104,1 107 | drop kicking/pvuiN-G8-yc_000000_000010.mp4,105,1 108 | drumming fingers/eap32WOJcAU_000108_000118.mp4,106,1 109 | dunking basketball/WC2FOUSNyvE_000006_000016.mp4,107,1 110 | dying hair/-7E9WiX7QfA_000053_000063.mp4,108,1 111 | eating burger/w9G7CpkBBM0_000000_000010.mp4,109,1 112 | eating cake/8QhblWHnNAY_000019_000029.mp4,110,1 113 | eating carrots/V4IaThkaK6Y_000025_000035.mp4,111,1 114 | eating chips/I5Y53-Q9KRo_000444_000454.mp4,112,1 115 | eating doughnuts/HyUF0Uo0f2A_000077_000087.mp4,113,1 116 | eating hotdog/FTOgHjhqlhU_000054_000064.mp4,114,1 117 | eating ice cream/0fCDlKYkRxc_000081_000091.mp4,115,1 118 | eating spaghetti/DiSP2oDGQ1Q_000014_000024.mp4,116,1 119 | eating watermelon/pLA62YSoEoM_000002_000012.mp4,117,1 120 | egg hunting/U9vSW3-zJ9s_000007_000017.mp4,118,1 121 | exercising arm/0wZpjStZtUY_000001_000011.mp4,119,1 122 | exercising with an exercise ball/oj7Qgyz5KK8_000143_000153.mp4,120,1 123 | extinguishing fire/BVXG_JOh9jQ_000002_000012.mp4,121,1 124 | faceplanting/petld-72OXM_000001_000011.mp4,122,1 125 | feeding birds/QJSwBNxKYqg_000120_000130.mp4,123,1 126 | feeding fish/ZtkTAHzih9Q_000084_000094.mp4,124,1 127 | feeding goats/v5Bl68y5ra0_000006_000016.mp4,125,1 128 | filling eyebrows/XycmcISYPA8_000045_000055.mp4,126,1 129 | finger snapping/j6qYhS2W1fM_000001_000011.mp4,127,1 130 | fixing hair/-65aI53dvdE_000022_000032.mp4,128,1 131 | flipping pancake/HIBxq2P0BL0_000004_000014.mp4,129,1 132 | flying kite/hAQJ9GHklS4_000004_000014.mp4,130,1 133 | folding clothes/HvbmGxDuNxs_000035_000045.mp4,131,1 134 | folding napkins/iCtT6ZadoOM_000052_000062.mp4,132,1 135 | folding paper/soHl6SrXlEI_000105_000115.mp4,133,1 136 | front raises/ObO_Gnw1nOQ_000005_000015.mp4,134,1 137 | frying vegetables/1IDdvXnTI60_000123_000133.mp4,135,1 138 | garbage collecting/KxTIEKllIzg_000114_000124.mp4,136,1 139 | gargling/HAPBKE3Qo5A_000217_000227.mp4,137,1 140 | getting a haircut/lVwFn9m8Q_Q_000053_000063.mp4,138,1 141 | getting a tattoo/g8dOsqPBe7A_000657_000667.mp4,139,1 142 | giving or receiving award/LmuS2GreXkc_000033_000043.mp4,140,1 143 | golf chipping/NIf0bxodA9E_000120_000130.mp4,141,1 144 | golf driving/1Q-E6UW1XE8_000011_000021.mp4,142,1 145 | golf putting/VS9uEOvJhzg_000000_000010.mp4,143,1 146 | grinding meat/SErnxQf4ONQ_000230_000240.mp4,144,1 147 | grooming dog/Q9mt0lJjQUA_000105_000115.mp4,145,1 148 | grooming horse/kaVWY-GyXcs_000063_000073.mp4,146,1 149 | gymnastics tumbling/mlzx2bi9nwQ_000059_000069.mp4,147,1 150 | hammer throw/WUrwglFhY64_000002_000012.mp4,148,1 151 | headbanging/ZhDdQmHIM78_000044_000054.mp4,149,1 152 | high jump/M2j1BTibIzs_000000_000010.mp4,151,1 153 | high kick/NdjLKFhn9j0_000004_000014.mp4,152,1 154 | hitting baseball/e8uB0GZsVOQ_000034_000044.mp4,153,1 155 | hockey stop/Nrscg8fLYqY_000049_000059.mp4,154,1 156 | holding snake/6cbXqLP0FHE_000002_000012.mp4,155,1 157 | hopscotch/vxp0SOd2W1E_000002_000012.mp4,156,1 158 | hoverboarding/E1Smsuf6cpE_000147_000157.mp4,157,1 159 | hugging/xWyOTDxm9yQ_000009_000019.mp4,158,1 160 | hula hooping/UjfYNVaZ39Y_000087_000097.mp4,159,1 161 | hurdling/Xa6gI4yGLQo_000000_000010.mp4,160,1 162 | hurling (sport)/ml2eBC_nXrw_000055_000065.mp4,161,1 163 | ice climbing/UM1fUqvFnME_000048_000058.mp4,162,1 164 | ice fishing/GO6YI36E_Do_000140_000150.mp4,163,1 165 | ice skating/vMZLTP9MfZ4_000008_000018.mp4,164,1 166 | ironing/ZgHZ0KgFOSc_000215_000225.mp4,165,1 167 | javelin throw/E5xdkQvnhkc_000002_000012.mp4,166,1 168 | jetskiing/Be59Cot2yGI_000233_000243.mp4,167,1 169 | jogging/kBUt5duOHFU_000005_000015.mp4,168,1 170 | juggling balls/YH801xSLkZM_000000_000010.mp4,169,1 171 | juggling fire/TA2mmXre8HQ_000000_000010.mp4,170,1 172 | juggling soccer ball/WAPctsQ-SwM_000000_000010.mp4,171,1 173 | jumping into pool/kjzgLLaYO8w_000010_000020.mp4,172,1 174 | jumpstyle dancing/QeG2HREr6m0_000003_000013.mp4,173,1 175 | kicking field goal/sR0oOq-qOqs_000015_000025.mp4,174,1 176 | kicking soccer ball/5PML0iLnBD8_000003_000013.mp4,175,1 177 | kissing/LmPjkroyPcY_000739_000749.mp4,176,1 178 | kitesurfing/KOOfe61BIyE_000023_000033.mp4,177,1 179 | knitting/bCa_5xZa4Ug_002346_002356.mp4,178,1 180 | krumping/3JxrK2Jt52Y_000754_000764.mp4,179,1 181 | laughing/UpVXo5Q9JKk_000079_000089.mp4,180,1 182 | laying bricks/N4HdEYIci0I_000037_000047.mp4,181,1 183 | long jump/MrlWkj87rfU_000002_000012.mp4,182,1 184 | lunge/g-XXUD65DyI_000003_000013.mp4,183,1 185 | making a cake/bX6I6jVAQMI_000028_000038.mp4,184,1 186 | making a sandwich/jofgWiVBwqo_000086_000096.mp4,185,1 187 | making bed/yD42KW6cm-A_000820_000830.mp4,186,1 188 | making jewelry/wMWkwQ7HXik_000616_000626.mp4,187,1 189 | making pizza/wxgqu30nSLE_000000_000010.mp4,188,1 190 | making snowman/8kN7EyPBmrI_000082_000092.mp4,189,1 191 | making sushi/Ah2YqA7bmHY_000055_000065.mp4,190,1 192 | making tea/hs2MVCM2LdY_000043_000053.mp4,191,1 193 | marching/_h60EbUbh3I_000026_000036.mp4,192,1 194 | massaging back/zsJ2PmhGM98_000215_000225.mp4,193,1 195 | massaging feet/BwMKdpNAmy4_000090_000100.mp4,194,1 196 | massaging legs/0EJXIQ1ltjo_000013_000023.mp4,195,1 197 | massaging person's head/z-6l_dkR3vE_000299_000309.mp4,196,1 198 | milking cow/DdUTLqyZ5b8_000044_000054.mp4,197,1 199 | mopping floor/-F-aEPmjERo_000043_000053.mp4,198,1 200 | motorcycling/kthzjAS1XS8_000009_000019.mp4,199,1 201 | moving furniture/b9vF-F1LC5g_000003_000013.mp4,200,1 202 | mowing lawn/t5SHfHDj0uw_000006_000016.mp4,201,1 203 | news anchoring/xJMgxnXI0GY_000000_000010.mp4,202,1 204 | opening bottle/gWd5AU5wP0k_000041_000051.mp4,203,1 205 | opening present/vd4uGb1162o_000002_000012.mp4,204,1 206 | paragliding/GF4WEdN_H0s_000191_000201.mp4,205,1 207 | parasailing/GuClMEvE3gM_000055_000065.mp4,206,1 208 | parkour/ptgKO940ISM_000042_000052.mp4,207,1 209 | passing American football (in game)/ixMPVi3Zr9s_000001_000011.mp4,208,1 210 | passing American football (not in game)/RxO7IEU7_I8_000391_000401.mp4,209,1 211 | peeling apples/8qEAQXckcVw_000003_000013.mp4,210,1 212 | peeling potatoes/_3CsQJ6XpHo_000015_000025.mp4,211,1 213 | petting animal (not cat)/tlWjTLpoWLw_000000_000010.mp4,212,1 214 | petting cat/q1GijBRBqjE_000203_000213.mp4,213,1 215 | picking fruit/NTfCraM0XyM_000257_000267.mp4,214,1 216 | planting trees/_WzkPBxP-5g_000096_000106.mp4,215,1 217 | plastering/mdN9BDP0cVY_000032_000042.mp4,216,1 218 | playing accordion/syp1O0cjens_000038_000048.mp4,217,1 219 | playing badminton/tJz980bJ3UI_000065_000075.mp4,218,1 220 | playing bagpipes/fMeaggq0_rA_000032_000042.mp4,219,1 221 | playing basketball/3mIvIgAlniY_000001_000011.mp4,220,1 222 | playing bass guitar/HqsAvuo5XhA_000059_000069.mp4,221,1 223 | playing cards/IVP8pO4Q8Hs_000084_000094.mp4,222,1 224 | playing cello/rsN982-8cvg_000042_000052.mp4,223,1 225 | playing chess/xFq-OJ8HDJs_000185_000195.mp4,224,1 226 | playing clarinet/7g4aL1EX8EI_001210_001220.mp4,225,1 227 | playing controller/gxbUZcsy4EA_000097_000107.mp4,226,1 228 | playing cricket/lgPslaxBQt0_000000_000010.mp4,227,1 229 | playing cymbals/--Y25nDn2Wk_000060_000070.mp4,228,1 230 | playing didgeridoo/2ezT7E6g8Ew_000044_000054.mp4,229,1 231 | playing drums/kXhnTK9TVsU_000076_000086.mp4,230,1 232 | playing flute/wqYzrDwV_o4_000047_000057.mp4,231,1 233 | playing guitar/ysjCIR7SkJU_000141_000151.mp4,232,1 234 | playing harmonica/DpJQShJs2kI_000036_000046.mp4,233,1 235 | playing harp/Ud-INZAw5Ik_000163_000173.mp4,234,1 236 | playing ice hockey/kRWk_-5d5bs_000010_000020.mp4,235,1 237 | playing keyboard/vxVoptVwZp4_000027_000037.mp4,236,1 238 | playing kickball/d5TMlt6P-ug_000317_000327.mp4,237,1 239 | playing monopoly/SsAtR4oD7WY_000000_000010.mp4,238,1 240 | playing organ/b9TfeDnfemw_000047_000057.mp4,239,1 241 | playing paintball/DOL1_JLWeoo_000321_000331.mp4,240,1 242 | playing piano/l4zZtMgNPvU_000009_000019.mp4,241,1 243 | playing poker/-0NQHRndkPI_000004_000014.mp4,242,1 244 | playing recorder/Zl_ey-UqwpY_000001_000011.mp4,243,1 245 | playing saxophone/K06EmNd6t_I_000006_000016.mp4,244,1 246 | playing squash or racquetball/-yUM3WwKQHM_000032_000042.mp4,245,1 247 | playing tennis/VoAJFfutNlg_000060_000070.mp4,246,1 248 | playing trombone/vqNbapex1kU_000015_000025.mp4,247,1 249 | playing trumpet/-BtzVCzSnLk_000073_000083.mp4,248,1 250 | playing ukulele/vE6Cnt7XJrg_000026_000036.mp4,249,1 251 | playing violin/t2XntpSO4Yo_000105_000115.mp4,250,1 252 | playing volleyball/5Wle9ClW4q0_000170_000180.mp4,251,1 253 | playing xylophone/N586DnjSCxo_000000_000010.mp4,252,1 254 | pole vault/9g4Sf8aWIx8_000003_000013.mp4,253,1 255 | presenting weather forecast/lVSiCfeBP8I_000152_000162.mp4,254,1 256 | pull ups/yLVMDD7b0xM_000020_000030.mp4,255,1 257 | pumping fist/V-IqR1THKr4_000015_000025.mp4,256,1 258 | pumping gas/eanhmmKIolc_000044_000054.mp4,257,1 259 | punching bag/3baFNAxC2YI_000012_000022.mp4,258,1 260 | punching person (boxing)/D5iLGttoHr4_000022_000032.mp4,259,1 261 | push up/-B2oGkg1qSI_000012_000022.mp4,260,1 262 | pushing car/-46DNkpyApI_000045_000055.mp4,261,1 263 | pushing cart/p9CIcEEaSEk_000001_000011.mp4,262,1 264 | pushing wheelchair/5gQlgNS5qfY_000023_000033.mp4,263,1 265 | reading book/XoO1uEVNgjM_000058_000068.mp4,264,1 266 | reading newspaper/gKqKWn6Nl0A_000035_000045.mp4,265,1 267 | recording music/864rV9vdAK4_000577_000587.mp4,266,1 268 | riding a bike/Ig-eRsgi6CU_000339_000349.mp4,267,1 269 | riding camel/bGzjObGU_qM_000014_000024.mp4,268,1 270 | riding elephant/j06vowPye30_000009_000019.mp4,269,1 271 | riding mechanical bull/eJpkgBaykQ8_000029_000039.mp4,270,1 272 | riding mountain bike/O95dOpT9T-c_000039_000049.mp4,271,1 273 | riding mule/azD58bwAe7E_000003_000013.mp4,272,1 274 | riding or walking with horse/C9pFs8sDARw_000218_000228.mp4,273,1 275 | riding scooter/FGCNMNjanO4_000013_000023.mp4,274,1 276 | riding unicycle/9RN16I79P9U_000000_000010.mp4,275,1 277 | ripping paper/-Ovwq0kVUx4_000002_000012.mp4,276,1 278 | robot dancing/5hQW4BHjWvM_000061_000071.mp4,277,1 279 | rock climbing/2jXlO2nzHGE_000026_000036.mp4,278,1 280 | rock scissors paper/Kxbdg32t6bU_000001_000011.mp4,279,1 281 | roller skating/_vjX5nPwTBs_000072_000082.mp4,280,1 282 | running on treadmill/BrKuhHIHccg_000049_000059.mp4,281,1 283 | sailing/h1SM1ArgB0E_000034_000044.mp4,282,1 284 | salsa dancing/WW4N7GToB5I_000313_000323.mp4,283,1 285 | sanding floor/EbXC4bGpZ4M_000034_000044.mp4,284,1 286 | scrambling eggs/ojJpJZpACdE_000245_000255.mp4,285,1 287 | scuba diving/64BhyrIZkz0_000002_000012.mp4,286,1 288 | setting table/tSQqcJqGplA_000011_000021.mp4,287,1 289 | shaking hands/lCQ17mGZeVE_000029_000039.mp4,288,1 290 | shaking head/WUOxNQKdRMM_000065_000075.mp4,289,1 291 | sharpening knives/iaQPoVg8Xtw_000468_000478.mp4,290,1 292 | sharpening pencil/ZMMCn1JE0Vc_000001_000011.mp4,291,1 293 | shaving head/K1C_jI8z1F8_000261_000271.mp4,292,1 294 | shaving legs/zvjNnDhUTxE_000034_000044.mp4,293,1 295 | shearing sheep/Vaff3l43A40_000018_000028.mp4,294,1 296 | shining shoes/HhW13wPky1U_000556_000566.mp4,295,1 297 | shooting basketball/Y3oHAIylSrg_000031_000041.mp4,296,1 298 | shooting goal (soccer)/ezJdtQzJ7qI_000021_000031.mp4,297,1 299 | shot put/SQddPtgoQGE_000007_000017.mp4,298,1 300 | shoveling snow/SZRDWgGOpXY_000062_000072.mp4,299,1 301 | shredding paper/KXyOXrWiJGY_000022_000032.mp4,300,1 302 | shuffling cards/_k0w_3JFfmE_000026_000036.mp4,301,1 303 | side kick/sZ8JiPfAoWc_000005_000015.mp4,302,1 304 | sign language interpreting/fKvqQEGGf6E_000031_000041.mp4,303,1 305 | singing/FZrg29zsAe8_000023_000033.mp4,304,1 306 | situp/jTMZX30XTXA_000072_000082.mp4,305,1 307 | skateboarding/kIzdzzMLCJI_000199_000209.mp4,306,1 308 | ski jumping/XQUsRpJ1A_Y_000001_000011.mp4,307,1 309 | skiing (not slalom or crosscountry)/fRiYQEVMcEc_000000_000010.mp4,308,1 310 | skiing crosscountry/pfvt6iYSXXw_000764_000774.mp4,309,1 311 | skiing slalom/Ch_wt_nV2k4_000702_000712.mp4,310,1 312 | skipping rope/xzXJJIni2hQ_000238_000248.mp4,311,1 313 | skydiving/5uw3m1tIvJ0_000057_000067.mp4,312,1 314 | slacklining/iLj4i4fTzn0_000038_000048.mp4,313,1 315 | sled dog racing/yMQMfdV-Fzs_000025_000035.mp4,315,1 316 | smoking/xo_9xPRu7_4_000114_000124.mp4,316,1 317 | smoking hookah/C_QP4vOVTrE_000164_000174.mp4,317,1 318 | snatch weight lifting/827ciUyYK5k_000000_000010.mp4,318,1 319 | sneezing/ce6aUvCKpbU_000000_000010.mp4,319,1 320 | sniffing/u2s0kiGG7AU_000011_000021.mp4,320,1 321 | snorkeling/rsDfe_ikY1I_000010_000020.mp4,321,1 322 | snowboarding/4cjhTsZjNP8_000202_000212.mp4,322,1 323 | snowkiting/ToDS3RIVybY_000025_000035.mp4,323,1 324 | snowmobiling/EgkRnTkj8gc_000003_000013.mp4,324,1 325 | somersaulting/hFYg1xqG5yk_000154_000164.mp4,325,1 326 | spinning poi/by9gw0ipuUg_000002_000012.mp4,326,1 327 | spray painting/zyR32Dm9yek_000019_000029.mp4,327,1 328 | spraying/LJQX3Atdn4k_000043_000053.mp4,328,1 329 | springboard diving/T3b1nxhG9Lo_000026_000036.mp4,329,1 330 | squat/ENkU87uTdfU_000025_000035.mp4,330,1 331 | sticking tongue out/E6ZgFC1L178_000041_000051.mp4,331,1 332 | stomping grapes/gzAmaRypLyI_000062_000072.mp4,332,1 333 | stretching arm/qKiTc6GGT4c_000036_000046.mp4,333,1 334 | stretching leg/-hkrPB2YU50_000612_000622.mp4,334,1 335 | strumming guitar/-2GJPqAglxU_000862_000872.mp4,335,1 336 | surfing crowd/tpruGil1UCs_000038_000048.mp4,336,1 337 | surfing water/-G_tgkmqChg_000072_000082.mp4,337,1 338 | sweeping floor/bHy05OAiL1g_000027_000037.mp4,338,1 339 | swimming backstroke/7aGVsi5ZgMI_000023_000033.mp4,339,1 340 | swimming breast stroke/BX-dyfoGFsE_000168_000178.mp4,340,1 341 | swimming butterfly stroke/aAYaI35qR5Q_000005_000015.mp4,341,1 342 | swing dancing/LVyo14Q5PmY_000006_000016.mp4,342,1 343 | swinging legs/W52Cl1ed1LU_000000_000010.mp4,343,1 344 | swinging on something/ibRyH1Q1bbo_000066_000076.mp4,344,1 345 | sword fighting/_kcVbo4E2JQ_000101_000111.mp4,345,1 346 | tai chi/BbFbo987QEo_000057_000067.mp4,346,1 347 | taking a shower/zW5Gt8bfZbc_000011_000021.mp4,347,1 348 | tango dancing/dFDdr9zxfzc_000101_000111.mp4,348,1 349 | tap dancing/dZ1EkA3BuQ4_000000_000010.mp4,349,1 350 | tapping guitar/7Nqupt1WIn4_000031_000041.mp4,350,1 351 | tapping pen/xcsH3jFtdSg_000026_000036.mp4,351,1 352 | tasting beer/UcAAItCUJrk_000518_000528.mp4,352,1 353 | tasting food/SQCsXDtiARU_000332_000342.mp4,353,1 354 | testifying/O4ystlpCCxM_000010_000020.mp4,354,1 355 | texting/V_LQXRQVrok_000116_000126.mp4,355,1 356 | throwing axe/1YmkhTmmyRc_000002_000012.mp4,356,1 357 | throwing ball/A6JeTfQqm0I_000000_000010.mp4,357,1 358 | throwing discus/gjNdAGf_16Y_000084_000094.mp4,358,1 359 | tickling/W9Ydqjoda9c_000000_000010.mp4,359,1 360 | tobogganing/SWmBChx-7fI_000003_000013.mp4,360,1 361 | tossing coin/Iwg-Had3-wE_000002_000012.mp4,361,1 362 | tossing salad/PcbZKLvO6gc_000181_000191.mp4,362,1 363 | training dog/am3gcomIUa4_000048_000058.mp4,363,1 364 | trapezing/p-E3XWgf3Wk_000012_000022.mp4,364,1 365 | trimming or shaving beard/X9mmMztC1Vo_000366_000376.mp4,365,1 366 | trimming trees/Q_F85_VgKwM_000045_000055.mp4,366,1 367 | triple jump/UergZFP-AdM_000002_000012.mp4,367,1 368 | tying bow tie/c-t7EA00jj8_000016_000026.mp4,368,1 369 | tying knot (not on a tie)/Vdx6g26ZOE0_000002_000012.mp4,369,1 370 | tying tie/DIrYfnfogiA_000148_000158.mp4,370,1 371 | unboxing/5lmmjOhih3U_000046_000056.mp4,371,1 372 | unloading truck/-aKzhHxNXDo_000066_000076.mp4,372,1 373 | using computer/5R1KJn3Pqa8_000066_000076.mp4,373,1 374 | using remote controller (not gaming)/Bj7_KWKEXp8_000046_000056.mp4,374,1 375 | using segway/QQTUQu4emh8_000145_000155.mp4,375,1 376 | vault/A4U2LxAwIm4_000031_000041.mp4,376,1 377 | waiting in line/5V_Ed93k2bI_000059_000069.mp4,377,1 378 | walking the dog/3NlgmP6MDmY_000021_000031.mp4,378,1 379 | washing dishes/oEkXkrSbFU8_000052_000062.mp4,379,1 380 | washing feet/n3vpap_pQ-U_000076_000086.mp4,380,1 381 | washing hair/BhU4HGJ2q4s_000004_000014.mp4,381,1 382 | washing hands/-jtKtX9gGdY_000005_000015.mp4,382,1 383 | water skiing/F1KYDfTyuEI_000040_000050.mp4,383,1 384 | water sliding/N6lBqLeKs8I_000001_000011.mp4,384,1 385 | watering plants/jZfXAIU4rZ4_000073_000083.mp4,385,1 386 | waxing back/P5qR6CoGbk8_000035_000045.mp4,386,1 387 | waxing chest/oRKbez1LpWU_000080_000090.mp4,387,1 388 | waxing eyebrows/hjzI8c63hVo_000011_000021.mp4,388,1 389 | waxing legs/dzeivZlP6tU_000024_000034.mp4,389,1 390 | weaving basket/oD0wHopSNLU_000000_000010.mp4,390,1 391 | welding/5hSYP2XxBGY_000204_000214.mp4,391,1 392 | whistling/KFOWZBfLHrA_000084_000094.mp4,392,1 393 | windsurfing/nDlR90yHqPY_000112_000122.mp4,393,1 394 | wrapping present/zYjHJNadEj4_000246_000256.mp4,394,1 395 | wrestling/UP_iRJv5mPU_000150_000160.mp4,395,1 396 | writing/OrWjyz2bFJQ_000064_000074.mp4,396,1 397 | yawning/SaJWnqViSLo_000023_000033.mp4,397,1 398 | yoga/5NysTi21_D0_000003_000013.mp4,398,1 399 | zumba/BvO4NNTw7Ks_000094_000104.mp4,399,1 400 | headbutting/PzD2BkZye2U_000013_000023.mp4,150,35 401 | slapping/WGxSNBg_tl0_000075_000085.mp4,314,110 402 | --------------------------------------------------------------------------------