stefanosgikas commited on
Commit
d2d4110
·
verified ·
1 Parent(s): 0eb12ac

Update README.md

Browse files
Files changed (1) hide show
  1. README.md +230 -3
README.md CHANGED
@@ -1,3 +1,230 @@
1
- ---
2
- license: mit
3
- ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ language:
4
+ - en
5
+ library_name: pytorch
6
+ pipeline_tag: feature-extraction
7
+ tags:
8
+ - affective-computing
9
+ - pain-assessment
10
+ - foundation-model
11
+ - vision
12
+ - embeddings
13
+ - pytorch
14
+ - timm
15
+ thumbnail: docs/painformer_overview.png
16
+ pretty_name: PainFormer
17
+ model-index:
18
+ - name: PainFormer
19
+ results: []
20
+ ---
21
+
22
+ # PainFormer
23
+
24
+ A Vision Foundation Model for Affective Computing
25
+
26
+ > **PainFormer** · **19.60 M parameters** · **5.82 GFLOPs** · **160-D embeddings** · **PyTorch ≥ 2.0**
27
+
28
+ ---
29
+
30
+ ## Paper
31
+
32
+ [**PainFormer: A Vision Foundation Model for Automatic Pain Assessment**](https://ieeexplore.ieee.org/document/11150483)
33
+
34
+ ---
35
+
36
+ ## Highlights
37
+
38
+ | Feature | Description |
39
+ | ---------------------- | ---------------------------------------------------------- |
40
+ | **Pre-training scale** | Multi-task pre-training on **14 tasks / 10.9 M samples**. |
41
+ | **Parameters** | **19.60 M** (PainFormer encoder). |
42
+ | **Compute** | **5.82 GFLOPs** at 224×224 input. |
43
+ | **Embeddings** | Fixed **160-D** output vectors. |
44
+
45
+ <br/>
46
+
47
+ <p align="center">
48
+ <img src="docs/painformer_overview.png" alt="PainFormer overview" width="100%"/>
49
+ </p>
50
+
51
+ <p align="center"><b>Figure&nbsp;1.</b> PainFormer overview.</p>
52
+
53
+ <p align="center">
54
+ <img src="docs/painformer_architecture.png" alt="PainFormer architecture" width="100%"/>
55
+ </p>
56
+
57
+ <p align="center"><b>Figure&nbsp;2.</b> PainFormer architecture.</p>
58
+
59
+ ---
60
+
61
+ ## Table of Contents
62
+
63
+ 1. [Pre-trained checkpoint](#pre-trained-checkpoint)
64
+ 2. [Quick start](#quick-start)
65
+ * [Extract embeddings](#extract-embeddings)
66
+ 3. [Fine-tuning](#fine-tuning)
67
+ 4. [Citation](#citation)
68
+ 5. [Licence & acknowledgements](#licence--acknowledgements)
69
+ 6. [Contact](#contact)
70
+
71
+ ---
72
+
73
+ ## Pre-trained Weights
74
+
75
+ Get the weights from the **[GitHub Releases](https://github.com/GkikasStefanos/PainFormer/releases)**.
76
+
77
+ | File | Size |
78
+ | ---------------- | ------- |
79
+ | `painformer.pth` | **TBA** |
80
+
81
+ ```bash
82
+ # download the latest checkpoint
83
+ auto=https://github.com/GkikasStefanos/PainFormer/releases/latest/download/painformer.pth
84
+ curl -L -o painformer.pth "$auto"
85
+
86
+ # optional: verify
87
+ sha256sum painformer.pth
88
+ ```
89
+
90
+ The checkpoint contains **one key**:
91
+
92
+ ```text
93
+ model_state_dict # PainFormer backbone weights
94
+ ```
95
+ ---
96
+
97
+ ## Quick start
98
+
99
+ > Assumes **PyTorch ≥ 2.0** and **timm ≥ 0.9** are installed.
100
+
101
+ ### Extract embeddings
102
+
103
+ ```python
104
+ import torch
105
+ from timm.models import create_model
106
+ from architecture import painformer
107
+ from PIL import Image
108
+ from torchvision import transforms
109
+
110
+ # ---------------------------------------------------------------
111
+ # Setup ---------------------------------------------------------
112
+ # ---------------------------------------------------------------
113
+ device = "cuda" if torch.cuda.is_available() else "cpu"
114
+
115
+ # VGG-Face2 statistics used during pretraining
116
+ normalize = transforms.Normalize(
117
+ mean=[0.6068, 0.4517, 0.3800],
118
+ std=[0.2492, 0.2173, 0.2082]
119
+ )
120
+ to_tensor = transforms.Compose([
121
+ transforms.Resize((224, 224)),
122
+ transforms.ToTensor(),
123
+ normalize
124
+ ])
125
+
126
+ # ---------------------------------------------------------------
127
+ # Load PainFormer -----------------------------------------------
128
+ # ---------------------------------------------------------------
129
+ model = create_model('painformer').to(device)
130
+ state = torch.load('./checkpoints/painformer.pth', map_location=device)
131
+ model.load_state_dict(state['model_state_dict'], strict=False)
132
+
133
+ # expose embeddings (remove classification head)
134
+ model.head = torch.nn.Identity()
135
+ model.eval()
136
+
137
+ # ---------------------------------------------------------------
138
+ # One image → 160-D embedding -----------------------------------
139
+ # ---------------------------------------------------------------
140
+ img = Image.open('frame.png').convert('RGB')
141
+ x = to_tensor(img).unsqueeze(0).to(device) # [1, 3, 224, 224]
142
+
143
+ with torch.no_grad():
144
+ emb = model(x) # [1, 160]
145
+ emb = emb.squeeze(0) # [160]
146
+
147
+ print("Embedding shape:", tuple(emb.shape)) # (160,)
148
+ ```
149
+
150
+ ---
151
+
152
+ ## Fine-tuning
153
+
154
+ Add your own classification/regression head and (optionally) un-freeze the backbone:
155
+
156
+ ```python
157
+ import torch, torch.nn as nn
158
+ from timm.models import create_model
159
+ from architecture import painformer
160
+
161
+ # ---------------------------------------------------------------
162
+ # Setup ----------------------------------------------------------
163
+ # ---------------------------------------------------------------
164
+ device = "cuda" if torch.cuda.is_available() else "cpu"
165
+ num_classes = 3 # set to your task
166
+
167
+ # Backbone → 160-D embeddings
168
+ model = create_model('painformer').to(device)
169
+ state = torch.load('painformer.pth', map_location=device)
170
+ model.load_state_dict(state['model_state_dict'], strict=False)
171
+
172
+ # freeze if you only need fixed embeddings
173
+ for p in model.parameters():
174
+ p.requires_grad = False
175
+
176
+ # simple head (example)
177
+ head = nn.Sequential(
178
+ nn.ELU(),
179
+ nn.Linear(160, num_classes)
180
+ ).to(device)
181
+
182
+ optimizer = torch.optim.Adam(head.parameters(), lr=1e-3)
183
+ criterion = nn.CrossEntropyLoss()
184
+
185
+ # one step (sketch)
186
+ def step(x, y):
187
+ model.eval()
188
+ with torch.no_grad():
189
+ z = model(x) # [B, 160]
190
+ logits = head(z) # [B, C]
191
+ loss = criterion(logits, y)
192
+ return loss, logits
193
+
194
+ # --- optional: end-to-end fine-tune ---
195
+ for p in model.parameters():
196
+ p.requires_grad = True
197
+ optimizer = torch.optim.AdamW(
198
+ list(model.parameters()) + list(head.parameters()),
199
+ lr=3e-4, weight_decay=0.05
200
+ )
201
+ ```
202
+
203
+ ---
204
+
205
+ ## Citation
206
+
207
+ ```bibtex
208
+ @ARTICLE{gkikas_painformer_2025,
209
+ author={Gkikas, Stefanos and Rojas, Raul Fernandez and Tsiknakis, Manolis},
210
+ journal={IEEE Transactions on Affective Computing},
211
+ title={PainFormer: a Vision Foundation Model for Automatic Pain Assessment},
212
+ year={2025},
213
+ volume={},
214
+ number={},
215
+ pages={1-18},
216
+ doi={10.1109/TAFFC.2025.3605475}
217
+ }
218
+ ```
219
+
220
+ ---
221
+
222
+ ## Licence & acknowledgements
223
+
224
+ * Code & weights: **MIT Licence** – see [`LICENSE`](./LICENSE)
225
+
226
+ ---
227
+
228
+ ## Contact
229
+
230
+ Email **Stefanos Gkikas:** gkikas[at]ics[dot]forth[dot]gr / gikasstefanos[at]gmail[dot]com