Infarondus commited on
Commit
35e20f4
·
verified ·
1 Parent(s): 7d48698

Delete README_convnext_binding.md

Browse files
Files changed (1) hide show
  1. README_convnext_binding.md +0 -282
README_convnext_binding.md DELETED
@@ -1,282 +0,0 @@
1
- ---
2
- license: apache-2.0
3
- language:
4
- - ru
5
- - en
6
- base_model:
7
- - facebook/convnext-tiny-224
8
- - facebook/dinov2-small
9
- pipeline_tag: image-classification
10
- tags:
11
- - manuscript
12
- - bookbinding
13
- - cultural-heritage
14
- - digital-humanities
15
- - convnext
16
- - fine-tuned
17
- library_name: timm
18
- ---
19
-
20
- # Kleine-Marchen — Binding Detector (ConvNeXt-Tiny)
21
-
22
- Модель на базе **ConvNeXt-Tiny (ImageNet-22k)** для определения является ли изображение фотографией переплёта рукописи.
23
-
24
- Используется как **первая ступень** в двухэтапном пайплайне классификации переплётов рукописей РГБ.
25
-
26
- ---
27
-
28
- ## Назначение
29
-
30
- Бинарная классификация:
31
-
32
- - **Класс 1 — переплёт**: изображение является фотографией крышки переплёта рукописи
33
- - **Класс 0 — не переплёт**: страница текста, разворот, предметная съёмка и т.д.
34
-
35
- Модель решает задачу фильтрации при массовом скачивании изображений из цифровых архивов рукописей, где первые страницы оцифровки содержат как переплёты, так и текстовые страницы.
36
-
37
- ---
38
-
39
- ## Метрики
40
-
41
- | Метрика | Значение |
42
- |---|---|
43
- | Accuracy (валидация) | **96%** |
44
-
45
- ---
46
-
47
- ## Данные
48
-
49
- - **Источник**: фотографии из фондов РГБ
50
- - **Размер**: ~500 изображений на каждый класс
51
- - **Классы**: переплёт / не переплёт (страницы текста, развороты)
52
- - **Разрешение при обучении**: 320×320 px
53
-
54
- ---
55
-
56
- ## Архитектура
57
-
58
- **Базовая модель**: `convnext_tiny.fb_in22k` (ImageNet-22k pretrain, 28M параметров)
59
-
60
- **Стратегия обучения**: обучение только классификационной головы при замороженном бэкбоне.
61
-
62
- ---
63
-
64
- ## Использование
65
-
66
- Готовые скрипты доступны в репозитории:
67
-
68
- **[https://github.com/Infarondus/Kleine-marchen](https://github.com/Infarondus/Kleine-marchen)**
69
-
70
- ### Быстрый старт
71
-
72
- ```python
73
- import torch
74
- import timm
75
- import numpy as np
76
- from PIL import Image
77
- import albumentations as A
78
- from albumentations.pytorch import ToTensorV2
79
-
80
- IMAGE_SIZE = 320
81
-
82
- transform = A.Compose([
83
- A.LongestMaxSize(max_size=IMAGE_SIZE),
84
- A.PadIfNeeded(min_height=IMAGE_SIZE, min_width=IMAGE_SIZE,
85
- border_mode=0, value=[255, 255, 255]),
86
- A.Normalize(mean=[0.485, 0.456, 0.406],
87
- std=[0.229, 0.224, 0.225]),
88
- ToTensorV2(),
89
- ])
90
-
91
- device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
92
- model = timm.create_model('convnext_tiny_in22k', pretrained=False, num_classes=2)
93
- ckpt = torch.load('kleine-marchen_preprocess.pth', map_location=device, weights_only=False)
94
- model.load_state_dict(ckpt['model_state_dict'])
95
- model.to(device).eval()
96
-
97
- img = np.array(Image.open('page.jpg').convert('RGB'))
98
- tensor = transform(image=img)['image'].unsqueeze(0).to(device)
99
- with torch.no_grad():
100
- probs = torch.softmax(model(tensor), dim=1)[0]
101
-
102
- print(f"Не переплёт: {probs[0]:.1%} | Переплёт: {probs[1]:.1%}")
103
- ```
104
-
105
- ---
106
-
107
- ## Место в пайплайне
108
-
109
- Эта модель используется совместно с `binding-srednik-dinov2`:
110
-
111
- ```
112
- Изображение → [ConvNeXt: переплёт?] → [DINOv2: есть средник?] → Результат
113
- ```
114
-
115
- Скрипт двухступенчатого скрапера `scrape_bindings_v2.py` из репозитория **Kleine-Marchen** реализует этот пайплайн полностью.
116
-
117
- ---
118
-
119
- ## Ограничения
120
-
121
- - Не предназначена для определения типа переплёта или его элементов — только факт наличия переплёта на снимке
122
- - При сильно нестандартных условиях съёмки (белый фон, крупный план фрагмента) точность может снижаться
123
-
124
- ---
125
-
126
- # Kleine-Marchen — Binding Srednik Detector (DINOv2 Ensemble)
127
-
128
- Ансамбль из 5 моделей на базе **DINOv2 ViT-Small** для классификации переплётов рукописей по наличию **средника** — центрального декоративного элемента крышки переплёта.
129
-
130
- Модель разработана в рамках исследования рукописного фонда Российской государственной библиотеки (РГБ).
131
-
132
- ---
133
-
134
- ## Назначение
135
-
136
- ��одель решает задачу бинарной классификации изображений переплётов:
137
-
138
- - **Класс 1 — со средником**: на крышке переплёта присутствует средник
139
- - **Класс 0 — без средника**: средник отсутствует
140
-
141
- Модель предназначена для автоматической предварительной сортировки больших коллекций фотографий переплётов рукописей. Окончательная верификация результатов производится специалистом.
142
-
143
- ---
144
-
145
- ## Метрики
146
-
147
- Оценка проводилась методом 5-fold стратифицированной кросс-валидации.
148
-
149
- | Метрика | Значение |
150
- |---|---|
151
- | Accuracy (OOF Ensemble) | **94.50%** |
152
- | F1-macro (OOF Ensemble) | **0.9450** |
153
- | Precision | 0.9454 |
154
- | Recall | 0.9450 |
155
-
156
- **Confusion Matrix (OOF, все 5 фолдов):**
157
-
158
- | | Предсказано: без средника | Предсказано: со средником |
159
- |---|---|---|
160
- | **Реально: без средника** | 471 | 20 |
161
- | **Реально: со средником** | 34 | 457 |
162
-
163
- ---
164
-
165
- ## Данные
166
-
167
- - **Источник**: фотографии переплётов рукописей из фондов РГБ
168
- - **Размер обучающей выборки**: 567 изображений на каждый класс (1134 итого)
169
- - **Формат**: цветные фотографии переплётов на тёмном фоне
170
- - **Разрешение при обучении**: 280×280 px
171
-
172
- Датасет собирался итеративно: после каждого цикла обучения производился анализ ошибок и доразметка сложных случаев (изношенные переплёты, пограничные экземпляры).
173
-
174
- ---
175
-
176
- ## Архитектура
177
-
178
- **Базовая модель**: `vit_small_patch14_dinov2.lvd142m` (DINOv2 ViT-Small, 22M параметров)
179
-
180
- **Голова классификатора**:
181
- ```
182
- LayerNorm(384) → Linear(384→256) → GELU → Dropout(0.3) → Linear(256→2)
183
- ```
184
-
185
- **Стратегия обучения**: двухфазный fine-tuning
186
- - Фаза 1 (6 эпох): обучение только головы, LR = 5e-4
187
- - Фаза 2 (20 эпох): голова + последние 4 блока ViT, дифференциальный LR (голова: 3e-5, бэкбон: 2e-6)
188
-
189
- **Ансамбль**: 5 моделей (по одной на каждый фолд) с усреднением вероятностей + TTA (5 аугментаций)
190
-
191
- ---
192
-
193
- ## Использование
194
-
195
- Готовые скрипты для обучения, оценки и инференса доступны в репозитории:
196
-
197
- **[https://github.com/Infarondus/Kleine-marchen](https://github.com/Infarondus/Kleine-marchen)**
198
-
199
- ### Быстрый старт
200
-
201
- ```python
202
- import torch
203
- import torch.nn as nn
204
- import torch.nn.functional as F
205
- import timm
206
- import numpy as np
207
- from PIL import Image
208
- import albumentations as A
209
- from albumentations.pytorch import ToTensorV2
210
-
211
- MODEL_NAME = 'vit_small_patch14_dinov2.lvd142m'
212
- IMAGE_SIZE = 280
213
- DINO_MEAN = [0.485, 0.456, 0.406]
214
- DINO_STD = [0.229, 0.224, 0.225]
215
-
216
- def build_model():
217
- backbone = timm.create_model(
218
- MODEL_NAME, pretrained=False, num_classes=0,
219
- img_size=IMAGE_SIZE, dynamic_img_size=True,
220
- )
221
- head = nn.Sequential(
222
- nn.LayerNorm(backbone.embed_dim),
223
- nn.Linear(backbone.embed_dim, 256),
224
- nn.GELU(),
225
- nn.Dropout(0.3),
226
- nn.Linear(256, 2),
227
- )
228
- class DinoClassifier(nn.Module):
229
- def __init__(self, b, h):
230
- super().__init__()
231
- self.backbone, self.head = b, h
232
- def forward(self, x):
233
- return self.head(self.backbone(x))
234
- return DinoClassifier(backbone, head)
235
-
236
- transform = A.Compose([
237
- A.LongestMaxSize(max_size=IMAGE_SIZE),
238
- A.PadIfNeeded(min_height=IMAGE_SIZE, min_width=IMAGE_SIZE,
239
- border_mode=0, value=[255, 255, 255]),
240
- A.Normalize(mean=DINO_MEAN, std=DINO_STD),
241
- ToTensorV2(),
242
- ])
243
-
244
- # Загрузка модели
245
- device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
246
- model = build_model().to(device)
247
- ckpt = torch.load('fold_1_km.pth', map_location=device, weights_only=False)
248
- model.load_state_dict(ckpt['model_state_dict'])
249
- model.eval()
250
-
251
- # Инференс
252
- img = np.array(Image.open('binding.jpg').convert('RGB'))
253
- tensor = transform(image=img)['image'].unsqueeze(0).to(device)
254
- with torch.no_grad():
255
- probs = F.softmax(model(tensor), dim=1)[0]
256
-
257
- print(f"Без средника: {probs[0]:.1%} | Со средником: {probs[1]:.1%}")
258
- ```
259
-
260
- ### Рекомендуемый порог
261
-
262
- При использовании ан��амбля рекомендуется порог **0.55–0.75** для класса «со средником» в зависимости от допустимого уровня ложных срабатываний.
263
-
264
- ---
265
-
266
- ## Ограничения
267
-
268
- - Модель обучена на фотографиях переплётов РГБ и может хуже работать на изображениях из других коллекций (domain shift)
269
- - Сильно изношенные переплёты с плохо читаемым средником являются наиболее сложными случаями
270
- - Не предназначена для работы с изображениями страниц, не являющихся переплётами — для фильтрации используйте модель `binding-detector-convnext` на первом этапе
271
-
272
- ---
273
- ## Цитирование
274
- Если вы используете эту модель в исследовании, пожалуйста, укажите репозиторий:
275
- ```
276
- @misc{kleine-marchen-binding,
277
- author = {Infarondus},
278
- title = {Kleine-Marchen — Binding Detector (ConvNeXt-Tiny)},
279
- year = {2026},
280
- url = {https://github.com/Infarondus/Kleine-marchen}
281
- }
282
- ```