{"id":33329342,"url":"https://github.com/dcajiao/basicmotions-classification-with-shapeformer","last_synced_at":"2026-05-01T21:02:16.096Z","repository":{"id":324461717,"uuid":"1097303919","full_name":"DCajiao/BasicMotions-classification-with-ShapeFormer","owner":"DCajiao","description":"Data Analytics project focused on the implementation and improvement of an architecture for time series classification, deployment, and productive implementation.","archived":false,"fork":false,"pushed_at":"2025-11-15T23:36:14.000Z","size":3284,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-11-16T01:23:04.023Z","etag":null,"topics":["docker","mha","python","shapeformer","streamlit","time-series-classification","transformers"],"latest_commit_sha":null,"homepage":"","language":"Dockerfile","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DCajiao.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-15T23:03:31.000Z","updated_at":"2025-11-15T23:36:18.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/DCajiao/BasicMotions-classification-with-ShapeFormer","commit_stats":null,"previous_names":["dcajiao/basicmotions-classification-with-shapeformer"],"tags_count":null,"template":false,"template_full_name":"DCajiao/python-uv-docker-template","purl":"pkg:github/DCajiao/BasicMotions-classification-with-ShapeFormer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DCajiao%2FBasicMotions-classification-with-ShapeFormer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DCajiao%2FBasicMotions-classification-with-ShapeFormer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DCajiao%2FBasicMotions-classification-with-ShapeFormer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DCajiao%2FBasicMotions-classification-with-ShapeFormer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DCajiao","download_url":"https://codeload.github.com/DCajiao/BasicMotions-classification-with-ShapeFormer/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DCajiao%2FBasicMotions-classification-with-ShapeFormer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32512670,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-30T13:12:12.517Z","status":"online","status_checked_at":"2026-05-01T02:00:05.856Z","response_time":64,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","mha","python","shapeformer","streamlit","time-series-classification","transformers"],"created_at":"2025-11-20T16:01:53.926Z","updated_at":"2026-05-01T21:02:16.085Z","avatar_url":"https://github.com/DCajiao.png","language":"Dockerfile","funding_links":[],"categories":[],"sub_categories":[],"readme":"# BasicMotions Classification with ShapeFormer\n\nA data analytics project focused on the implementation and deployment of **ShapeFormer**, a state-of-the-art transformer-based architecture for multivariate time series classification.\n\n## Base Paper\n\n**Title:** ShapeFormer: Shapelet Transformer for Multivariate Time Series Classification\n\n**Authors:** Xuan-May Le, Ling Luo, Uwe Aickelin, Minh-Tuan Tran\n\n**Publication:** KDD 2024 (30th ACM SIGKDD Conference on Knowledge Discovery and Data Mining)\n\n**Original Repository:** [xuanmay2701/shapeformer](https://github.com/xuanmay2701/shapeformer)\n\n---\n\n## Overview\n\nShapeFormer is a novel deep learning architecture that combines **class-specific** and **generic** transformer modules to achieve state-of-the-art performance on multivariate time series classification (MTSC) tasks. This implementation extends the original work with a focus on practical deployment and production-ready inference for basic motion classification.\n\n### Key Achievement\n\nShapeFormer achieved the **highest accuracy ranking** across all 30 UEA multivariate time series datasets, with an average rank of 2.5 and top-1 performance on 15 datasets.\n\n---\n\n## Model Architecture \u0026 Main Innovations\n\n### Core Architecture\n\nShapeFormer addresses a critical limitation of existing transformer-based MTSC methods: **existing methods focus exclusively on generic features while ignoring class-specific features**. This leads to poor performance on:\n\n1. **Imbalanced datasets** – where generic features favor majority classes\n2. **Similar overall patterns** – where fine-grained class distinctions matter\n\nThe architecture consists of two complementary transformer modules:\n\n#### 1. **Class-Specific Transformer Module**\n\nCaptures discriminative class-specific features through:\n\n- **Offline Shapelet Discovery (OSD)**: Extracts high-quality shapelets from training data using Perceptually Important Points (PIPs), reducing computational complexity from 45M to ~5,900 candidates per dataset\n- **Shapelet Filter**: Finds best-fit subsequences for each shapelet and computes difference features between shapelets and their matching subsequences\n- **Dynamic Shapelet Optimization**: Shapelets are treated as learnable parameters and optimized during training\n- **Position Embedding**: Captures spatial information using start index, end index, and variable positions\n- **Transformer Encoder**: Multi-head attention mechanism that assigns higher attention scores to features within the same class\n\n#### 2. **Generic Transformer Module**\n\nExtracts generic features across all classes through:\n\n- **CNN Feature Extraction**: Two convolutional blocks with Conv1D layers (kernel size = 8) to capture temporal patterns and inter-variable correlations\n- **Transformer Encoder**: Standard multi-head attention mechanism with learnable position embeddings\n- **Average Pooling**: Aggregates features into a single class token\n\n### Main Innovations\n\n| Innovation | Impact |\n|-----------|--------|\n| **Dual-module architecture** | Leverages both class-specific and generic features for superior discrimination |\n| **Offline Shapelet Discovery for MTS** | Efficiently extracts discriminative subsequences; 7,600x reduction in shapelet candidates |\n| **Shapelet Filter with difference features** | Captures relative changes between shapelets and input series, not just absolute distances |\n| **Dynamic shapelet optimization** | Shapelets adapt during training rather than remaining fixed |\n| **Selective class token design** | Uses only the highest information gain shapelet token instead of averaging all tokens |\n| **Position-aware shapelet embeddings** | Encodes temporal and variable location information for better discrimination |\n\n---\n\n## Theoretical Architecture Summary\n\n### Shapelet Discovery Phase (Preprocessing)\n\n```\nInput: Training dataset D with M time series, T time steps, D variables\nOutput: Shapelet pool S with N shapelets per class\n\n1. Shapelet Extraction:\n   - Identify Perceptually Important Points (PIPs) based on reconstruction distance\n   - Extract shapelet candidates from windows around consecutive PIPs\n   - For each PIP: maximum 3 candidates generated → ~5,900 candidates total\n\n2. Shapelet Selection:\n   - Compute Perceptual Subsequence Distance (PSD) to all training instances\n   - Calculate optimal information gain for each candidate\n   - Select top N shapelets ranked by information gain for each class\n```\n\n### Inference Phase\n\n```\nFor each input time series X:\n\n1. Class-Specific Path:\n   ├─ Shapelet Filter: Find best-fit subsequences for each shapelet\n   ├─ Difference Feature: Compute ΔF = P(s_m) - P(x_matched)\n   ├─ Position Embedding: Encode shapelet location information\n   ├─ Transformer Encoder: Multi-head attention → Z_spe\n   └─ Class Token: Use first token (Z_spe_1) from highest information gain shapelet\n\n2. Generic Path:\n   ├─ CNN Block 1: Conv1D for temporal pattern extraction\n   ├─ CNN Block 2: Conv1D for inter-variable correlation\n   ├─ Transformer Encoder: Multi-head attention → Z_gen\n   └─ Class Token: Average pooling → Z_gen\n\n3. Classification:\n   ├─ Concatenate: [Z_spe, Z_gen]\n   ├─ Linear Classification Head: softmax(Linear([Z_spe, Z_gen]))\n   └─ Output: Class prediction\n```\n\n### Key Hyperparameters\n\n| Parameter | Default | Purpose |\n|-----------|---------|---------|\n| Number of PIPs (n_pips) | 0.2T | Controls shapelet discovery granularity |\n| Window size | Dataset-dependent | Search radius for best-fit subsequences |\n| Number of shapelets (N) | Dataset-dependent | Shapelets per class for class-specific module |\n| Embedding size (d_spe) | 128 | Class-specific feature dimension |\n| Embedding size (d_gen) | 32 | Generic feature dimension |\n| Attention heads | 16 | Multi-head attention heads |\n| Dropout ratio | 0.4 | Regularization |\n| Conv kernel size | 8 | CNN filter kernel size |\n\n---\n\n## Installation \u0026 Setup\n\nThe project requires Python 3.12 and uses the uv package manager for fast, reproducible dependency installation. The system can be deployed either locally for development or via Docker for production and isolated environments.\n\n### Prerequisites\n\n| Component\t| Version\t| Purpose |\n|-----------|---------|---------|\n| Python\t| 3.12.x\t| Runtime environment |\n| uv |\tLatest |\tFast Python package manager |\n| Docker |\t20.10+ | Container runtime (optional) |\n| Git |\tAny\t| Repository cloning |\n\n### Local Development Setup\n\n1. Clone Repository\n\n```bash\ngit clone https://github.com/DCajiao/BasicMotions-classification-with-ShapeFormer.git\ncd BasicMotions-classification-with-ShapeFormer\n```\n\n2. Create Virtual Environment\nThe virtual environment is excluded from version control via gitignore\n```bash\nuv venv\nsource .venv/bin/activate  # Linux/macOS\n# or\n.venv\\Scripts\\activate  # Windows\n```\n\n3. Install Dependencies\nThe project defines 22 core dependencies in pyproject.toml\n```bash\nuv pip install -e .\n```\n\n\n\n### Docker Installation\n\n```bash\n# Build Docker image\ndocker build -t shapeformer:latest .\n\n# Run container\ndocker run -p 8501:8501 shapeformer:latest\n```\n\n---\n\n## Usage Guide\n\n### Quick Start with Streamlit\n\nThe repository includes an interactive Streamlit application for real-time inference and visualization:\n\n```bash\n# Run Streamlit app\nstreamlit run app.py\n\n# Access at: http://localhost:8501\n```\n\n### Training\n\nFor training with the BasicMotions dataset, run the following command:\n\n```bash\npython main.py --dataset_pos=1 --num_shapelet=10 --window_size=80 --pre_shapelet_discovery=0 --processes=12 --epochs=100 --lr=0.001 --weight_decay=5e-4 --dropout=0.2 --shape_embed_dim=128 --pos_embed_dim=128 --emb_size=64 --local_embed_dim=48 --local_pos_dim=48 --dim_ff=256 --num_heads=4 --local_num_heads=4 --num_pip=0.1\n\n```\n\n### Inference on Single Instance\n\nFor command-line inference, use:\n\n```bash\npython infer_shapeformer.py --ts_path \"Dataset/UEA/Multivariate_ts/BasicMotions/BasicMotions_TEST.ts\" --checkpoint \"Results/Dataset/UEA/2025-11-16_12-02/checkpoints/BasicMotionsmodel_last.pth\" --shapelet_pkl \"store/BasicMotions_80.pkl\" --config \"Results/Dataset/UEA/2025-11-16_12-02/configuration.json\" --device cpu\n```\n\n---\n\n## Model Weights \u0026 Inference\n\n### Loading Pre-trained Weights\n\n```python\nimport torch\nfrom shapeformer import ShapeFormer\n\n# Initialize model with same architecture as saved weights\nmodel = ShapeFormer(\n    num_classes=4,\n    num_variables=6,\n    num_shapelets_per_class=10,\n    embedding_size_specific=128,\n    embedding_size_generic=32\n)\n\n# Load pre-trained weights\ncheckpoint = torch.load('shapeformer_basicmotions.pth')\nmodel.load_state_dict(checkpoint['model_state_dict'])\nmodel.eval()\n\n# Optional: Load optimizer state for continued training\noptimizer = torch.optim.RAdam(model.parameters())\noptimizer.load_state_dict(checkpoint['optimizer_state_dict'])\nepoch = checkpoint['epoch']\n```\n\n### Shapelet Loading\n\nShapelets are pre-computed during the training phase and stored separately:\n\n```python\nimport pickle\nimport numpy as np\n\n# Load shapelet pool\nwith open('shapelets_pool.pkl', 'rb') as f:\n    shapelets = pickle.load(f)\n\n# Shapelet structure:\n# {\n#     'shapelets': [M x L x D] array of shapelet values,\n#     'start_indices': [M] array of start positions,\n#     'end_indices': [M] array of end positions,\n#     'variables': [M] array of variable indices,\n#     'class_labels': [M] array of class assignments\n# }\n\nprint(f\"Number of shapelets: {len(shapelets['shapelets'])}\")\nprint(f\"Shapelet length: {shapelets['shapelets'][0].shape[0]}\")\n```\n---\n\n## Experimental Results\n\nShapeFormer achieves state-of-the-art performance on UEA MTSC benchmark:\n\n| Metric | Value |\n|--------|-------|\n| Average Rank | 2.5 |\n| Top-1 Datasets | 15/30 (50%) |\n| Statistical Significance | p-value \u003c 0.05 |\n| Performance vs. WHEN | +0.617 rank improvement |\n| Performance vs. SVP-T | +2.783 rank improvement |\n\n### Dataset-Specific Performance\n\n- **BasicMotions**: 100.0% accuracy\n- **AtrialFibrillation**: 66.0% accuracy (challenging imbalanced dataset)\n- **Japanese Vowels**: 99.7% accuracy\n- **NATOPS**: 98.9% accuracy\n\n---\n\n## 🔧 Configuration\n\n### Hyperparameter Tuning\n\nModify `config.yaml` for custom settings:\n\n```yaml\n# Shapelet Discovery\nshapelet_discovery:\n  num_pips: 0.2  # Fraction of time series length\n  window_size: 100  # Search radius for best-fit subsequences\n  num_shapelets_per_class: 10\n\n# Model Architecture\nmodel:\n  num_classes: 4\n  num_variables: 6\n  embedding_size_specific: 128\n  embedding_size_generic: 32\n  attention_heads: 16\n  dropout: 0.4\n\n# Training\ntraining:\n  batch_size: 16\n  epochs: 200\n  learning_rate: 0.01\n  weight_decay: 5e-4\n  optimizer: radam\n```\n\n---\n\n\n### Local Deployment\n\n```bash\n# Run Streamlit in production mode\nstreamlit run app.py\n```\n\n---\n\n## 📖 Documentation\n\nFor detailed information, refer to:\n\n- **Original Paper**: [arXiv:2405.14608](https://arxiv.org/abs/2405.14608)\n- **Original Repository**: [xuanmay2701/shapeformer](https://github.com/xuanmay2701/shapeformer)\n- **UEA Archive**: [timeseriesclassification.com](http://timeseriesclassification.com/)\n\n---\n\n## Citation\n\nIf you use this implementation in your research, please cite the original paper:\n\n```bibtex\n@inproceedings{le2024shapeformer,\n  title={ShapeFormer: Shapelet Transformer for Multivariate Time Series Classification},\n  author={Le, Xuan-May and Luo, Ling and Aickelin, Uwe and Tran, Minh-Tuan},\n  booktitle={Proceedings of the 30th ACM SIGKDD Conference on Knowledge Discovery and Data Mining},\n  year={2024}\n}\n```\n\n---\n\n**Last Updated:** November 2025  \n**Status:** Active Development  \n**Version:** 1.0.0","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdcajiao%2Fbasicmotions-classification-with-shapeformer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdcajiao%2Fbasicmotions-classification-with-shapeformer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdcajiao%2Fbasicmotions-classification-with-shapeformer/lists"}