File size: 2,863 Bytes
6b3e488
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
---
license: apache-2.0
library_name: slim
tags:
  - skeleton-action-recognition
  - self-supervised-learning
  - action-recognition
  - pytorch
---

# SLiM

Encoders from **Less is More: Compact-Token Masked Feature Learning for Skeleton Representation
Learning**.

- Paper: https://arxiv.org/abs/2603.10648
- Project page: https://kaist-viclab.github.io/SLiM_site/
- Code: https://github.com/KAIST-VICLab/SLiM

SLiM patchifies a 64-frame skeleton clip with `P_T = 8`, `P_J = 1` into a compact `8 x 25` token
grid and trains a ViT encoder (8 blocks, dim 256, 8 heads) against an EMA teacher with masked
feature prediction and global-local contrastive learning. No coordinate decoder is used, and
downstream inference costs 3.59 GFLOPs.

## Available checkpoints

One encoder per evaluation protocol, each in its own subfolder. Linear evaluation uses a frozen
encoder, a linear classifier and a single joint stream.

| subfolder | protocol | epoch | Top-1 (%) |
| --- | --- | ---: | ---: |
| `ntu60_xsub`  | NTU RGB+D 60 X-Sub  | 120 | 87.9 |
| `ntu60_xview` | NTU RGB+D 60 X-View | 150 | 93.2 |

**NTU RGB+D 120 weights are coming** and will be added here as `ntu120_xsub` and `ntu120_xset`.

## Usage

```bash
git clone https://github.com/KAIST-VICLab/SLiM && cd SLiM
pip install -r requirements.txt huggingface_hub safetensors
```

xFormers and a CUDA GPU are required β€” the temporal-RoPE attention has no CPU path.

```python
import torch
from slim.hub import SLiMEncoder

model = SLiMEncoder.from_pretrained("JeonghyeokDo/SLiM", subfolder="ntu60_xsub").eval().cuda()

# clips: (B, 3, 64, 25, M) β€” coordinates, frames, joints, people
clips = torch.zeros(2, 3, 64, 25, 1).cuda()
with torch.no_grad():
    feats = model.get_intermediate_layers(clips, 4, return_class_token=True)
patch_tokens, cls_token = feats[-1]   # (B, 200, 256), (B, 256)
```

Evaluate each encoder on its own protocol only. Inputs follow the repository's preprocessing:
clips are resampled to 64 frames, one person per token sequence, coordinates shifted so that
joint 1 of the first frame is the origin.

## Files

```
ntu60_xsub/
β”œβ”€β”€ config.json, model.safetensors      encoder β€” load with subfolder="ntu60_xsub"
└── linear/                             the trained linear-probe grid behind the number above
ntu60_xview/
β”œβ”€β”€ config.json, model.safetensors      encoder β€” load with subfolder="ntu60_xview"
└── linear/
```

See the repository README for the evaluation commands.

## Citation

```bibtex
@article{do2026slim,
  title   = {Less is More: Compact-Token Masked Feature Learning for Skeleton Representation Learning},
  author  = {Do, Jeonghyeok and Chen, Yun and Youk, Geunhyuk and Kim, Munchurl},
  journal = {arXiv preprint arXiv:2603.10648},
  year    = {2026}
}
```

Built on [DINOv2](https://github.com/facebookresearch/dinov2) (Apache 2.0).