# Задача классификации изображений: метрики, loss-функции, семплирование > Учебно-исследовательский раздел методички (научный руководитель — мнс Павленко Б.В.). > Контекст применения: HPO (Optuna) для EdgeNeXt на датасете NarutoSign (multi-class классификация знаков-печатей). --- ## 1. Постановка задачи multi-class классификации Дана обучающая выборка $\{(x_i, y_i)\}_{i=1}^{N}$, где $x_i$ — изображение, $y_i \in \{1, \dots, C\}$ — метка одного из $C$ взаимоисключающих классов (multi-class, в отличие от multi-label, где классы не исключают друг друга). Модель $f_\theta$ выдаёт вектор **логитов** (необработанных скоров) $z = f_\theta(x) \in \mathbb{R}^{C}$. ### Softmax Логиты переводятся в распределение вероятностей по классам функцией softmax: $$ p_k = \mathrm{softmax}(z)_k = \frac{e^{z_k}}{\sum_{j=1}^{C} e^{z_j}}, \qquad \sum_{k=1}^{C} p_k = 1,\; p_k \in (0,1). $$ Softmax инвариантен к сдвигу: $\mathrm{softmax}(z) = \mathrm{softmax}(z + c)$, поэтому на практике вычитают $\max_k z_k$ для численной устойчивости (log-sum-exp trick). ### One-hot и целевое распределение Истинная метка $y$ кодируется **one-hot** вектором $q \in \{0,1\}^{C}$: $q_k = \mathbb{1}[k = y]$. Это «жёсткое» (hard) целевое распределение. «Мягкие» (soft) цели $q_k \in [0,1]$ возникают при label smoothing, mixup/cutmix и knowledge distillation (см. §3). ### Top-1 / top-k accuracy Предсказание top-1: $\hat{y} = \arg\max_k p_k$. **Top-k** считает пример верным, если истинная метка попала в множество $k$ наибольших по вероятности классов: $$ \text{top-}k\text{-acc} = \frac{1}{N}\sum_{i=1}^{N} \mathbb{1}\!\left[\, y_i \in \mathrm{TopK}_k\big(p^{(i)}\big)\,\right]. $$ Top-5 — историческая метрика ImageNet (1000 классов). Для задач с малым $C$ (например, 12 знаков-печатей) top-k при $k \geq 2$ малоинформативна; основная метрика — top-1. --- ## 2. Метрики Базовые величины для класса $c$ из confusion matrix (one-vs-rest): $TP_c$ (true positive), $FP_c$, $FN_c$, $TN_c$. Обозначим $n_c$ — число истинных объектов класса $c$, $N = \sum_c n_c$. | Метрика | Формула | Диапазон | Чувствительность к дисбалансу | |---|---|---|---| | Accuracy (top-1) | $\dfrac{\sum_c TP_c}{N}$ | $[0,1]$ | **Высокая** (доминирует majority-класс) | | Balanced accuracy | $\dfrac{1}{C}\sum_c \dfrac{TP_c}{n_c} = \dfrac{1}{C}\sum_c \mathrm{Recall}_c$ | $[0,1]$ | Низкая (макро-усреднение recall) | | Top-k accuracy | см. §1 | $[0,1]$ | Высокая | | Precision (класс $c$) | $P_c = \dfrac{TP_c}{TP_c + FP_c}$ | $[0,1]$ | — | | Recall (класс $c$) | $R_c = \dfrac{TP_c}{TP_c + FN_c}$ | $[0,1]$ | — | | F1 (класс $c$) | $F1_c = \dfrac{2 P_c R_c}{P_c + R_c}$ | $[0,1]$ | — | | Macro-F1 | $\dfrac{1}{C}\sum_c F1_c$ | $[0,1]$ | **Низкая** (классы равновесны) | | Micro-F1 | $\dfrac{2\sum_c TP_c}{2\sum_c TP_c + \sum_c FP_c + \sum_c FN_c}$ | $[0,1]$ | Высокая ($=$ accuracy в multi-class) | | Weighted-F1 | $\sum_c \dfrac{n_c}{N} F1_c$ | $[0,1]$ | Высокая (вес $\propto$ частоте) | | MCC | см. ниже | $[-1,1]$ | Низкая (учитывает все 4 клетки) | | Cohen's $\kappa$ | см. ниже | $[-1,1]$ | Низкая (поправка на случай) | | ROC-AUC (OvR) | площадь под ROC, усреднённая | $[0,1]$ | Зависит от усреднения | | PR-AUC (OvR) | площадь под precision-recall | $[0,1]$ | **Низкая** (лучше для редких классов) | | ECE | см. §2.5 | $[0,1]$, ниже лучше | — (про калибровку) | ### 2.1 Macro / micro / weighted — когда какая - **Micro**: агрегирует TP/FP/FN по всем классам, затем считает метрику. В multi-class с single-label **micro-F1 = micro-precision = micro-recall = accuracy**. Отражает производительность «на объект», доминирует majority-класс. - **Macro**: метрика считается по каждому классу, затем простое среднее. Каждый класс весит одинаково → редкие классы влияют наравне с частыми. Главный выбор при дисбалансе. - **Weighted**: macro со взвешиванием по $n_c$ → возвращает доминирование majority-класса, маскирует провал на редких классах. | Сценарий | Рекомендуемое усреднение | |---|---| | Сбалансированные классы, важна общая доля верных | micro / accuracy | | Дисбаланс, все классы одинаково важны | **macro** | | Дисбаланс, но важность $\propto$ частоте в проде | weighted | [scikit-learn — precision_recall_fscore_support / averaging](https://scikit-learn.org/stable/modules/model_evaluation.html#precision-recall-f-measure-metrics) ### 2.2 Confusion matrix $M \in \mathbb{N}^{C \times C}$, $M_{ij}$ = число объектов истинного класса $i$, предсказанных как $j$. Диагональ — верные. Нормировка по строкам ($M_{ij}/n_i$) даёт **per-class accuracy** = recall класса $i$. Самый информативный диагностический инструмент: показывает *какие* классы путаются (для NarutoSign — визуально похожие печати). [sklearn.confusion_matrix](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.confusion_matrix.html) ### 2.3 Matthews Correlation Coefficient (MCC) Корреляция Пирсона между предсказанным и истинным классом. Multi-class форма ([sklearn.matthews_corrcoef](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.matthews_corrcoef.html)): $$ \mathrm{MCC} = \frac{\sum_k\sum_l\sum_m (M_{kk}M_{lm} - M_{kl}M_{mk})} {\sqrt{\sum_k\big(\sum_l M_{kl}\big)\big(\sum_{k'\neq k}\sum_{l'} M_{k'l'}\big)}\;\sqrt{\sum_k\big(\sum_l M_{lk}\big)\big(\sum_{k'\neq k}\sum_{l'} M_{l'k'}\big)}}. $$ $\mathrm{MCC}=1$ — идеал, $0$ — случай, $-1$ — полное расхождение. Высокий MCC требует хороших результатов по **всем** классам, поэтому это надёжная сводная метрика при дисбалансе. ### 2.4 Cohen's kappa $$ \kappa = \frac{p_o - p_e}{1 - p_e}, $$ где $p_o$ — наблюдаемая accuracy, $p_e = \sum_c \frac{(\text{предсказано } c)\cdot(\text{истинно } c)}{N^2}$ — ожидаемое согласие «по случайности». Учитывает базовый уровень случайного угадывания. [sklearn.cohen_kappa_score](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.cohen_kappa_score.html) ### 2.5 ROC-AUC / PR-AUC (one-vs-rest) Для multi-class каждый класс берётся как «positive», остальные — «negative» (**OvR**), по вероятностям $p_c$ строится кривая, площади усредняются (macro / weighted). ROC-AUC = $P(p_c^{+} > p_c^{-})$ для случайной пары. При сильном дисбалансе ROC-AUC оптимистична (огромное число $TN$ распухает specificity), поэтому для редких классов предпочтительна **PR-AUC** (average precision), не использующая $TN$. [sklearn.roc_auc_score (multi_class='ovr')](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.roc_auc_score.html) · [average_precision_score](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.average_precision_score.html) ### 2.6 Калибровка (Expected Calibration Error, ECE) Уверенность $\hat{p}_i = \max_k p_k^{(i)}$ должна совпадать с фактической accuracy. Разбиваем $[0,1]$ на $B$ бинов $\{b_m\}$: $$ \mathrm{ECE} = \sum_{m=1}^{B} \frac{|b_m|}{N}\,\big|\,\mathrm{acc}(b_m) - \mathrm{conf}(b_m)\,\big|. $$ Современные сети **переуверены** (over-confident); label smoothing и temperature scaling снижают ECE (Müller et al., 2019, [«When Does Label Smoothing Help?»](https://arxiv.org/abs/1906.02629); Guo et al., 2017, [«On Calibration of Modern Neural Networks»](https://arxiv.org/abs/1706.04599)). ### 2.7 Главная метрика при дисбалансе При дисбалансе **accuracy вводит в заблуждение**: модель, предсказывающая только majority-класс, даёт высокую accuracy при нулевом recall на редких классах. Главными метриками выбирают **macro-F1** или **balanced accuracy** (= macro-recall, [sklearn.balanced_accuracy_score](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.balanced_accuracy_score.html)), т.к. они усредняют по классам с равным весом. Различие: balanced accuracy смотрит только на recall; macro-F1 балансирует precision и recall — предпочтительна, когда важны и пропуски, и ложные срабатывания. **MCC** — надёжная вторичная сводка. Для целей Optuna в качестве `objective` рекомендуется **macro-F1** (или balanced accuracy) на валидации. --- ## 3. Loss-функции Везде $p_k$ — softmax-вероятность, $y$ — истинный класс, $p_y$ — вероятность истинного класса. ### 3.1 Cross-Entropy (CE) $$ \mathcal{L}_{\mathrm{CE}} = -\sum_{k=1}^{C} q_k \log p_k = -\log p_y \quad (\text{для one-hot } q). $$ Базовый loss. В PyTorch `nn.CrossEntropyLoss` принимает **логиты** (применяет log-softmax внутри). ### 3.2 Label Smoothing CE Smooth-цель: $q_k^{LS} = (1-\varepsilon)\,\mathbb{1}[k=y] + \dfrac{\varepsilon}{C}$ (равномерно размазывает $\varepsilon$ по всем классам). $$ \mathcal{L}_{\mathrm{LS}} = -\sum_{k=1}^{C} q_k^{LS}\log p_k = (1-\varepsilon)\big(-\log p_y\big) + \frac{\varepsilon}{C}\sum_{k=1}^{C}\big(-\log p_k\big). $$ Типично $\varepsilon \in [0.05, 0.1]$. Уменьшает переуверенность, улучшает калибровку и обобщение (Szegedy et al., 2016, [Inception-v3/ Rethinking the Inception Architecture](https://arxiv.org/abs/1512.00567); анализ — Müller et al., 2019, [arXiv:1906.02629](https://arxiv.org/abs/1906.02629)). Не борется напрямую с дисбалансом. ### 3.3 Focal Loss Снижает вклад «лёгких» (хорошо классифицированных) примеров фактором $(1-p_y)^\gamma$ (Lin et al., 2017, [«Focal Loss for Dense Object Detection» / RetinaNet, arXiv:1708.02002](https://arxiv.org/abs/1708.02002)): $$ \mathcal{L}_{\mathrm{FL}} = -\alpha_y\,(1 - p_y)^{\gamma}\,\log p_y. $$ - $\gamma$ — focusing parameter (типично $\gamma = 2$); при $\gamma=0$ сводится к CE. - $\alpha_y$ — балансирующий вес класса (опционально). При $p_y \to 1$ множитель $(1-p_y)^\gamma \to 0$ → лёгкие примеры почти не дают градиента, обучение фокусируется на трудных. Хорош при дисбалансе и большом числе «лёгких» фоновых примеров. ### 3.4 Class-Balanced Loss (effective number) Переход от «числа сэмплов» к «эффективному числу» — учёт перекрытия близких изображений (Cui et al., 2019, CVPR, [arXiv:1901.05555](https://arxiv.org/abs/1901.05555)): $$ E_{n_c} = \frac{1 - \beta^{\,n_c}}{1 - \beta}, \qquad \beta = \frac{N-1}{N} \in [0,1). $$ Вес класса $\propto 1/E_{n_c}$, нормированный так, что $\sum_c w_c = C$: $$ w_c = \frac{1 - \beta}{1 - \beta^{\,n_c}}. $$ Подставляется как мультипликатор в любой базовый loss (CB-CE, CB-Focal): $$ \mathcal{L}_{\mathrm{CB}} = w_y \cdot \mathcal{L}_{\mathrm{base}}(p, y). $$ При $\beta \to 0$ → нет ребалансировки; $\beta \to 1$ → вес $\propto 1/n_c$ (обратная частота). Типично $\beta \in \{0.99, 0.999, 0.9999\}$. ### 3.5 Weighted CE (class weights) Частный случай: вес $\propto$ обратной частоте, $w_c = \dfrac{N}{C\, n_c}$ (нормировка опциональна): $$ \mathcal{L}_{\mathrm{wCE}} = -w_y \log p_y. $$ В PyTorch — аргумент `weight` в `nn.CrossEntropyLoss`. Простейшая мера против дисбаланса. ### 3.6 LDAM (кратко) Label-Distribution-Aware Margin (Cao et al., 2019, NeurIPS, [arXiv:1906.07413](https://arxiv.org/abs/1906.07413)) добавляет **класс-зависимый отступ** в логит истинного класса перед softmax, увеличивая margin для редких классов: $$ \mathcal{L}_{\mathrm{LDAM}} = -\log \frac{e^{\,z_y - \Delta_y}}{e^{\,z_y - \Delta_y} + \sum_{k \neq y} e^{z_k}}, \qquad \Delta_c = \frac{K}{n_c^{1/4}}. $$ Маленький $n_c$ → больший margin $\Delta_c$ → строже decision boundary для minority. Обычно в связке с **DRW** (deferred re-weighting). Теоретически обоснован margin-based generalization bound. ### 3.7 Soft-target / KD-loss (кратко) Knowledge Distillation (Hinton et al., 2015, [arXiv:1503.02531](https://arxiv.org/abs/1503.02531)): студент учится на «мягких» вероятностях teacher с температурой $T$: $$ \mathcal{L}_{\mathrm{KD}} = (1-\lambda)\,\mathcal{L}_{\mathrm{CE}}(p^{S}, y) + \lambda\,T^2\,\mathrm{KL}\!\big(p^{T}_{/T}\,\|\,p^{S}_{/T}\big), $$ где $p_{/T} = \mathrm{softmax}(z/T)$. Множитель $T^2$ компенсирует масштаб градиентов. Soft-target несёт «dark knowledge» о близости классов (релевантно для визуально похожих печатей). ### 3.8 Таблица «когда какой loss» | Loss | Когда применять | Гиперпараметры | Борется с дисбалансом | |---|---|---|---| | CE | baseline, сбалансированные данные | — | нет | | Label Smoothing CE | переуверенность, регуляризация, калибровка | $\varepsilon$ | нет | | Focal | дисбаланс + много «лёгких» примеров | $\gamma$, $\alpha$ | частично (по трудности) | | Weighted CE | умеренный дисбаланс, быстрый фикс | веса $w_c$ | да (по частоте) | | Class-Balanced (eff. number) | сильный/long-tail дисбаланс | $\beta$, базовый loss | да (эфф. число) | | LDAM (+DRW) | long-tail, нужен margin для minority | $K$, расписание DRW | да (margin) | | KD / soft-target | есть teacher, похожие классы | $T$, $\lambda$ | косвенно | --- ## 4. Семплирование и борьба с дисбалансом ### 4.1 Random shuffle vs WeightedRandomSampler - **Random shuffle** (`shuffle=True`): равномерная выборка без замены → батчи отражают исходное распределение классов → редкие классы редко попадают в батч. - **WeightedRandomSampler**: семплирование с вероятностью $\propto$ весу объекта. Для класс-балансировки вес объекта $i$ класса $c$: $w_i = \dfrac{1}{n_c}$ (обратная частота). Тогда вероятность вытянуть любой класс одинакова → батчи приблизительно сбалансированы. Семплирование **с заменой** (`replacement=True`) → minority-объекты повторяются (фактический oversampling). [PyTorch WeightedRandomSampler](https://pytorch.org/docs/stable/data.html#torch.utils.data.WeightedRandomSampler) ### 4.2 Class-balanced batch sampling Гарантирует фиксированное число объектов на класс в каждом батче (например, $P$ классов × $K$ объектов). Полезно для metric learning и когда нужна детерминированная балансировка батча, а не вероятностная как у WeightedRandomSampler. ### 4.3 Oversampling / undersampling - **Oversampling** minority (дублирование / random oversampling): риск **переобучения** на повторённых картинках — смягчается аугментацией. - **Undersampling** majority: теряется информация, но ускоряет эпоху. - Библиотека [imbalanced-learn](https://imbalanced-learn.org/stable/) (`RandomOverSampler`, `RandomUnderSampler`) — для табличных/признаковых данных. ### 4.4 Почему SMOTE плохо подходит для сырых изображений SMOTE (Chawla et al., 2002, [JAIR](https://www.jair.org/index.php/jair/article/view/10302)) генерирует синтетические объекты линейной интерполяцией между соседями в **признаковом пространстве**. На сырых пикселях это даёт нефизичные, «призрачные» изображения (наложение/двоение): пиксельное пространство невыпукло и не семантично — линейная смесь двух картинок печатей не является валидной картинкой. Если применять — то в пространстве эмбеддингов предобученной сети, не на пикселях. Для изображений предпочтительнее **аугментация** и sampler-балансировка. ### 4.5 Аугментация как «семплирование» Аугментация расширяет эффективное распределение, заменяя грубое дублирование. Особенно полезна для редких классов как «умный oversampling». | Метод | Суть | Цель | Источник | |---|---|---|---| | RandAugment | случайный выбор $N$ операций силой $M$ из набора | сильная регуляризация, 2 гиперпараметра | Cubuk et al., 2019, [arXiv:1909.13719](https://arxiv.org/abs/1909.13719) | | mixup | $\tilde{x}=\lambda x_i+(1-\lambda)x_j$, $\tilde{y}=\lambda y_i+(1-\lambda)y_j$, $\lambda\sim\mathrm{Beta}(\alpha,\alpha)$ | линейная регуляризация, soft-target | Zhang et al., 2018, [arXiv:1710.09412](https://arxiv.org/abs/1710.09412) | | CutMix | вырезает патч из $x_j$ и вставляет в $x_i$, метка $\propto$ площади | локальные признаки + регуляризация | Yun et al., 2019, [arXiv:1905.04899](https://arxiv.org/abs/1905.04899) | mixup/cutmix дают **мягкие метки** → совместимы с CE по soft-target и сами по себе улучшают калибровку. ### 4.6 Стратифицированный split Train/val/test делятся с сохранением пропорций классов (stratified) — иначе редкий класс может полностью отсутствовать в валидации, и метрика по нему неопределена. [sklearn StratifiedShuffleSplit / train_test_split(stratify=y)](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.StratifiedShuffleSplit.html). Для маленьких датасетов — **StratifiedKFold**. --- ## 5. Связка loss × sampler (не дублировать компенсацию) Дисбаланс компенсируют **либо** на уровне данных (sampler/oversampling), **либо** на уровне loss (class weights / CB / focal $\alpha$) — **но не обоими сразу с одинаковой силой**, иначе minority-классы переусиливаются: модель переобучается на них, recall редких растёт ценой обвала precision и общего качества. | Комбинация | Эффект | Рекомендация | |---|---|---| | shuffle + CE | без компенсации | baseline | | WeightedSampler + CE | компенсация в данных | OK | | shuffle + weighted/CB/focal CE | компенсация в loss | OK | | WeightedSampler + weighted CE | **двойная** компенсация | избегать | | WeightedSampler + focal ($\alpha$=1) | sampler + фокус по трудности | приемлемо (разные механизмы) | | mild sampler + mild class weights | частичная × частичная | допустимо при настройке | Влияние на метрики: ребалансировка (любым способом) поднимает **macro-F1 / balanced accuracy / recall редких классов**, но обычно слегка снижает **overall accuracy / micro-F1**. Это ожидаемый и приемлемый trade-off при дисбалансе. Решение — какую метрику оптимизировать (см. §2.7). --- ## 6. Гиперпараметры для Optuna | Гиперпараметр | Тип Optuna | Диапазон / значения | Комментарий | |---|---|---|---| | `loss_type` | categorical | `{ce, ls_ce, focal, weighted_ce, cb_focal}` | выбор семейства loss | | `label_smoothing` | float | $[0.0, 0.2]$ | активен для ce/ls_ce | | `focal_gamma` | float | $[0.5, 5.0]$ | активен для focal/cb_focal | | `focal_alpha` | float | $[0.25, 1.0]$ | балансирующий вес | | `cb_beta` | categorical / float | $\{0.99, 0.999, 0.9999\}$ | для class-balanced | | `use_weighted_sampler` | bool (categorical) | `{True, False}` | sampler-балансировка | | `mixup_alpha` | float | $[0.0, 0.4]$ (0 = off) | $\mathrm{Beta}(\alpha,\alpha)$ | | `cutmix_alpha` | float | $[0.0, 1.0]$ (0 = off) | вероятность через отд. флаг | | `randaug_N` / `randaug_M` | int | $N\in[1,3]$, $M\in[5,15]$ | сила аугментации | Важно: задать **условную логику** (Optuna conditional / pruning), чтобы не подбирать одновременно `use_weighted_sampler=True` и `loss_type=weighted_ce` (см. §5). Целевая функция (`direction='maximize'`) — **macro-F1** или **balanced accuracy** на валидации. [Optuna docs](https://optuna.readthedocs.io/en/stable/). --- ## 7. Практические PyTorch-сниппеты ### 7.1 WeightedRandomSampler ```python import numpy as np import torch from torch.utils.data import DataLoader, WeightedRandomSampler labels = np.array(train_labels) # shape (N,), class indices class_counts = np.bincount(labels) # n_c per class class_weights = 1.0 / class_counts # w_c = 1 / n_c (inverse freq) sample_weights = class_weights[labels] # per-sample weight sampler = WeightedRandomSampler( weights=torch.as_tensor(sample_weights, dtype=torch.double), num_samples=len(sample_weights), # one epoch length replacement=True, # required for oversampling ) # NB: shuffle must be False when a sampler is passed loader = DataLoader(train_ds, batch_size=64, sampler=sampler) ``` ### 7.2 Focal Loss (multi-class) ```python import torch import torch.nn as nn import torch.nn.functional as F class FocalLoss(nn.Module): """Multi-class focal loss; expects raw logits.""" def __init__(self, gamma: float = 2.0, alpha: torch.Tensor | None = None): super().__init__() self.gamma = gamma self.alpha = alpha # per-class weights, shape (C,) def forward(self, logits: torch.Tensor, target: torch.Tensor) -> torch.Tensor: logp = F.log_softmax(logits, dim=1) # (B, C) logp_t = logp.gather(1, target[:, None]).squeeze(1) # log p_y p_t = logp_t.exp() # p_y loss = -((1 - p_t) ** self.gamma) * logp_t if self.alpha is not None: loss = self.alpha.to(logits.device)[target] * loss return loss.mean() ``` ### 7.3 Label smoothing в nn.CrossEntropyLoss ```python import torch.nn as nn # Built-in since PyTorch 1.10; optional per-class weight for imbalance. criterion = nn.CrossEntropyLoss(label_smoothing=0.1, weight=class_weight_tensor) loss = criterion(logits, target) # logits: raw (B, C) ``` ### 7.4 Расчёт macro-F1 / balanced accuracy (sklearn) ```python from sklearn.metrics import f1_score, balanced_accuracy_score, classification_report y_pred = logits.argmax(dim=1).cpu().numpy() y_true = target.cpu().numpy() macro_f1 = f1_score(y_true, y_pred, average="macro") bal_acc = balanced_accuracy_score(y_true, y_pred) # = macro-recall # Per-class breakdown (precision / recall / F1 / support): print(classification_report(y_true, y_pred, digits=4)) ``` --- ## Источники - Lin et al., 2017 — Focal Loss / RetinaNet: [arXiv:1708.02002](https://arxiv.org/abs/1708.02002) - Cui et al., 2019 — Class-Balanced Loss (effective number): [arXiv:1901.05555](https://arxiv.org/abs/1901.05555) - Cao et al., 2019 — LDAM: [arXiv:1906.07413](https://arxiv.org/abs/1906.07413) - Szegedy et al., 2016 — Label Smoothing (Inception-v3): [arXiv:1512.00567](https://arxiv.org/abs/1512.00567) - Müller et al., 2019 — When Does Label Smoothing Help?: [arXiv:1906.02629](https://arxiv.org/abs/1906.02629) - Guo et al., 2017 — Calibration of Modern Neural Networks (ECE): [arXiv:1706.04599](https://arxiv.org/abs/1706.04599) - Hinton et al., 2015 — Knowledge Distillation: [arXiv:1503.02531](https://arxiv.org/abs/1503.02531) - Zhang et al., 2018 — mixup: [arXiv:1710.09412](https://arxiv.org/abs/1710.09412) - Yun et al., 2019 — CutMix: [arXiv:1905.04899](https://arxiv.org/abs/1905.04899) - Cubuk et al., 2019 — RandAugment: [arXiv:1909.13719](https://arxiv.org/abs/1909.13719) - Chawla et al., 2002 — SMOTE: [JAIR](https://www.jair.org/index.php/jair/article/view/10302) - scikit-learn — [Model evaluation metrics](https://scikit-learn.org/stable/modules/model_evaluation.html), [balanced_accuracy_score](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.balanced_accuracy_score.html), [matthews_corrcoef](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.matthews_corrcoef.html) - [imbalanced-learn](https://imbalanced-learn.org/stable/) · [PyTorch data sampling](https://pytorch.org/docs/stable/data.html) · [Optuna](https://optuna.readthedocs.io/en/stable/)