CTR-GCN: Channel-wise Topology Refinement Graph Convolution

repository·main·Indexed 18 days ago

https://github.com/uason-chen/ctr-gcn

Official implementation of Channel-wise Topology Refinement Graph Convolution for skeleton-based action recognition. The library supports NTU RGB+D 60, NTU RGB+D 120, and NW-UCLA datasets, providing a pipeline for data processing, training, testing, and multi-modality ensembling (joint, bone, and motion). It requires Python >= 3.6 and PyTorch >= 1.1.0.

Tokens
2.9K
Snippets
8
Records
10
Agent score
13%

What's inside CTR-GCN

  1. Test trained models

    main

    To evaluate a model saved in a specific <work_dir>, use the --phase test flag. You must provide the configuration file from the work directory and the path to the weights file (.pt).

    python main.py --config <work_dir>/config.yaml --work-dir <work_dir> --phase test --save-score True --weights <work_dir>/xxx.pt --device 0
  2. Install CTR-GCN dependencies

    main

    To set up the development environment, ensure you have Python >= 3.6 and PyTorch >= 1.1.0 installed. You can install the required dependencies using the provided requirements.txt file and the torchlight package.

    1. Create an Anaconda virtual environment.
    2. Install dependencies via pip.
    3. Install torchlight in editable mode.
    pip install -r requirements.txt
    pip install -e torchlight
  3. Train CTR-GCN models

    main

    Training is performed using main.py. You can specify configurations, models, and modalities via command-line arguments.

    Basic Training

    To train the standard CTRGCN on NTU RGB+D 120 cross-subject:

    python main.py --config config/nturgbd120-cross-subject/default.yaml --work-dir work_dir/ntu120/csub/ctrgcn --device 0

    Training with different modalities (Bone or Velocity)

    For NTU datasets, use --train_feeder_args and --test_feeder_args to set bone=True or vel=True.

    python main.py --config config/nturgbd120-cross-subject/default.yaml --train_feeder_args bone=True --test_feeder_args bone=True --work-dir work_dir/ntu120/csub/ctrgcn_bone --device 0

    For NW-UCLA, modify data_path in the feeder args to bone, motion, or bone motion:

    python main.py --config config/ucla/default.yaml --work-dir work_dir/ucla/ctrgcn_xxx --device 0

    Training a custom model

    Place your model file your_model.py in the ./model directory and reference it using the --model flag with the format model.your_model.Model.

    python main.py --config config/nturgbd120-cross-subject/default.yaml --model model.your_model.Model --work-dir work_dir/ntu120/csub/your_model --device 0
    # Example: training CTRGCN on NTU RGB+D 120 cross subject under bone modality
    python main.py --config config/nturgbd120-cross-subject/default.yaml --train_feeder_args bone=True --test_feeder_args bone=True --work-dir work_dir/ntu120/csub/ctrgcn_bone --device 0
  4. Prepare NTU RGB+D and NW-UCLA datasets

    main

    CTR-GCN supports NTU RGB+D 60, NTU RGB+D 120, and NW-UCLA datasets.

    NTU RGB+D 60 and 120

    1. Request the dataset from the official source.
    2. Download the skeleton-only files:
      • nturgbd_skeletons_s001_to_s017.zip (for NTU 60)
      • nturgbd_skeletons_s018_to_s032.zip (for NTU 120)
    3. Extract these files into ./data/nturgbd_raw.

    NW-UCLA

    1. Download the dataset from Dropbox.
    2. Move the all_sqe folder to ./data/NW-UCLA.

    Required Directory Structure

    Ensure your data follows this layout:

    - data/
      - NW-UCLA/
        - all_sqe
      - ntu/
      - ntu120/
      - nturgbd_raw/
        - nturgb+d_skeletons/     # from s001_to_s017.zip
        - nturgb+d_skeletons120/  # from s018_to_s032.zip
  5. Process NTU RGB+D skeleton data

    main

    After downloading the raw NTU RGB+D files, you must run a three-step processing pipeline to generate the usable dataset. Navigate to the appropriate data directory (./data/ntu or ./data/ntu120) and execute the following scripts in order:

    1. Get raw skeletons: python get_raw_skes_data.py
    2. Denoise: python get_raw_denoised_data.py (removes bad skeletons)
    3. Transform: python seq_transformation.py (centers the skeleton to the first frame)
    cd ./data/ntu
    python get_raw_skes_data.py
    python get_raw_denoised_data.py
    python seq_transformation.py
  6. Load model weights with partial matching

    main

    When loading weights via the Processor.load_model() method, the system supports:

    1. Format Support: Both .pt (PyTorch) and .pkl (Pickle) files.
    2. Weight Stripping: It automatically removes the module. prefix (common when loading DataParallel models) from keys.
    3. Selective Loading: Using the --ignore-weights flag, you can specify substrings of weight names to be excluded from the state dict. This is useful for fine-tuning models where certain layers (like the final classification head) need to be re-initialized.
    4. Partial Matching: If the loaded weights do not perfectly match the model's state_dict, the system attempts to update the model's state with the available weights rather than failing.
  7. Run CTR-GCN via CLI

    main

    The main.py script serves as the primary entrypoint for training and testing the CTR-GCN model. It uses a configuration-first approach where parameters can be defined in a YAML file, overridden by command-line arguments.

    Parameter Priority: Command Line Arguments > YAML Config File > Default Values.

    To run the script, you must specify the --phase (either train or test) and provide a --config path. If testing, you must also provide --weights pointing to a .pt or .pkl model file.

    # Example: Training
    python main.py --phase train --config ./config/nturgbd-cross-view/test_bone.yaml --work-dir ./my_experiment
    
    # Example: Testing a specific model
    python main.py --phase test --config ./config/nturgbd-cross-view/test_bone.yaml --weights ./work_dir/runs/model-epoch-10.pt
  8. Ensemble multiple modalities

    main

    To combine results from different modalities (joint, bone, motion, and bone-motion) for a final ensemble, use the ensemble.py script. You must provide the dataset type and the directory paths where each modality's results were stored.

    # Example: ensemble four modalities of CTRGCN on NTU RGB+D 120 cross subject
    python ensemble.py --datasets ntu120/xsub --joint-dir work_dir/ntu120/csub/ctrgcn --bone-dir work_dir/ntu120/csub/ctrgcn_bone --joint-motion-dir work_dir/ntu120/csub/ctrgcn_motion --bone-motion-dir work_dir/ntu120/csub/ctrgcn_bone_motion
    python ensemble.py --datasets ntu120/xsub --joint-dir work_dir/ntu120/csub/ctrgcn --bone-dir work_dir/ntu120/csub/ctrgcn_bone --joint-motion-dir work_dir/ntu120/csub/ctrgcn_motion --bone-motion-dir work_dir/ntu120/csub/ctrgcn_bone_motion
  9. Use the Processor class to manage training and evaluation

    main

    The Processor class is the core orchestration engine. It handles model initialization, data loading, optimizer setup, and the execution of training and evaluation loops.

    Key Methods:

    • start(): The main entrypoint. If phase is train, it runs the training loop and then evaluates the best model. If phase is test, it runs evaluation on the provided weights.
    • train(epoch, save_model=False): Executes one epoch of training, calculates loss/accuracy, and optionally saves the model.
    • eval(epoch, save_score=False, loader_name=['test'], wrong_file=None, result_file=None): Executes evaluation. It can optionally output a wrong_file (containing indices and incorrect predictions) and a result_file (containing correct/incorrect labels) for error analysis.
    # Conceptual usage within the script
    processor = Processor(arg)
    processor.start()
  10. Configure CTR-GCN via CLI arguments

    main

    The following command-line arguments are available to control the execution of the CTR-GCN pipeline. Many arguments use DictAction (via torchlight), allowing you to pass nested dictionary configurations for the model and data loaders directly from the CLI.

    # Processor Arguments
    --work-dir: Path to store results and logs
    --config: Path to the YAML configuration file
    --phase: Execution mode ('train' or 'test')
    --save-score: Boolean; if true, stores classification scores
    
    # Visualization & Debugging
    --seed: Random seed for reproducibility
    --log-interval: Interval for printing messages
    --save-interval: Interval for saving models
    --save-epoch: Starting epoch for model saving
    --eval-interval: Interval for evaluation
    --print-log: Boolean; whether to print logs to console
    --show-topk: List of integers (e.g., --show-topk 1 5) for Top-K accuracy
    
    # Feeder (Data Loader) Arguments
    --feeder: Python class path for the data loader (e.g., 'feeder.feeder')
    --num-worker: Number of worker threads for data loading
    --train-feeder-args: Dictionary of arguments for the training feeder
    --test-feeder-args: Dictionary of arguments for the test feeder
    
    # Model Arguments
    --model: Python class path for the model
    --model-args: Dictionary of arguments for the model
    --weights: Path to pre-trained weights
    --ignore-weights: List of weight names to ignore during initialization
    
    # Optimizer Arguments
    --base-lr: Initial learning rate
    --step: List of epochs for learning rate reduction
    --device: List of GPU indices (e.g., --device 0 1)
    --optimizer: Optimizer type ('SGD' or 'Adam')
    --nesterov: Boolean; use Nesterov momentum
    --batch-size: Training batch size
    --test-batch-size: Testing batch size
    --start-epoch: Starting epoch for training
    --num-epoch: Total number of epochs
    --weight-decay: Weight decay value
    --lr-decay-rate: Decay rate for learning rate
    --warm_up_epoch: Number of warm-up epochs