Обучение моделей timm. Связка с fastai. Data Engineering.. Data Engineering. DevOps.. Data Engineering. DevOps. искусственные нейронные сети.. Data Engineering. DevOps. искусственные нейронные сети. искусственный интеллект.. Data Engineering. DevOps. искусственные нейронные сети. искусственный интеллект. конвейер.. Data Engineering. DevOps. искусственные нейронные сети. искусственный интеллект. конвейер. Машинное обучение.

Решал задачу поиска оптимальной модели для классификации собственного датасета изображений (в основном искал на HuggingFace) и столкнулся с моделями timm. Старый конвейер dvc не работал с этими моделями и пришлось искать решение. Вообще почему именно timm?

Как сказано в руководстве:

«timm` – это библиотека глубокого обучения, созданная Россом Уайтманом, и представляет собой коллекцию моделей компьютерного зрения SOTA, слоев, утилит, оптимизаторов, планировщиков, загружающих данных, а также обучающих / валидационных скриптов с возможностью воспроизведения результатов обучения ImageNet.

Вопросы сразу же отпали и я стал изучать какие виды там представлены.

Действительно, в библиотеки timm представлено огромное количество моделей и их версий, обученных на разных данных. Так можно увидеть список интересующих вас моделей:

import timm
pd.DataFrame(timm.list_models('vit_*'))
Рис 1. Вывод

Рис 1. Вывод

Указав pretrain=True, выведем предобученные версии моделей.

Приступим к обучению!

Подготовка данных

Исходные данные: csv файле с описанием изображений и принадлежность их к классу и сами изображения. Первым делом я сформировал две директории (train, validate), в которых были папки с названием класса и изображениями соответственно (стандартная структура для любых обработчиков)

├── train
│   ├── ex_class_1
│   │   ├── image_1.png
│   │   ├── image_2.png
│   │   ├── image_3.png
│   │   ├── image_4.png
│   │   └── image_5.png
│   ├── ex_class_2
│   │   ├── image_1.png
│   │   ├── image_2.png
│   │   ├── image_3.png
│   │   ├── image_4.png
│   │   └── image_5.png
│   └── ex_class_3
└── validate
├── ex_class_1
├── ex_class_2
└── ex_class_3

Вот пример кода:

import os
import csv
import argparse
from sklearn.model_selection import train_test_split
from tqdm import tqdm
from PIL import Image
import pandas as pd

def resize_and_normalize(image_path, output_path, size=(256, 256), format='JPEG'):
    image = Image.open(image_path)
    image = image.resize(size)
    if image.mode in ['RGBA', 'P']:
        image = image.convert('RGB')
    image.save(output_path, format=format)

def preprocess_dataset(input_dir, output_dir, csv_path, test_size=0.2):
  os.makedirs(output_dir, exist_ok=True)
  data = pd.read_csv(csv_path)
  
  for label in data['class'].unique():
      os.makedirs(os.path.join(output_dir, 'train', label), exist_ok=True)
      os.makedirs(os.path.join(output_dir, 'test', label), exist_ok=True)
  
  # Split data into training and testing
  train_df, test_df = train_test_split(data, test_size=test_size, random_state=22)
  
  
  # Process train images with a progress bar
  for _, row in tqdm(train_df.iterrows(), total=len(train_df), desc='Processing train images'):
      image_path = os.path.join(input_dir, row['image'] + '.jpg')
      if os.path.exists(image_path):
          output_path = os.path.join(output_dir, 'train', row['class'], row['image'] + .jpg')
          resize_and_normalize(image_path, output_path)
  for _, row in tqdm(test_df.iterrows(), total=len(test_df), desc='Processing test images'):
      image_path = os.path.join(input_dir, row['image'] + '.jpg')
      if os.path.exists(image_path):
          output_path = os.path.join(output_dir, 'test', row['class'], row['image'] + '.jpg')
          resize_and_normalize(image_path, output_path)

Обучение моделей. Fastai и dvc pipeline

После того, как мы подготовили данные. можно приступать к обучению модели. Я для удобства перенес все интересующие меня модели в текстовый файл.

Импортируем необходимые библиотеки:

import os
import argparse
import timm
from fastai.vision.all import *
from fastai.metrics import *
from dvclive import Live
from dvclive.fastai import DVCLiveCallback
from torchvision import transforms
import torch

После был создан словарь метрик:

METRICS = {
    "accuracy": accuracy,
    "accuracy_multi": accuracy_multi,
    "error_rate": error_rate,
    "top_k_accuracy": top_k_accuracy,
    "Precision": Precision(average='macro'),
    "Recall": Recall(average='macro'),
    "F1Score": F1Score(average='macro'),
    "RocAuc": RocAuc(),  # Note: RocAucScore is used for both binary and multi-class ROC AUC
    "RocAucBinary": RocAucBinary(),  # Note: RocAucScore is used for both binary and multi-class ROC AUC
    "FBeta": FBeta,
    "BalancedAccuracy": BalancedAccuracy(),
    "F1ScoreMulti": F1ScoreMulti,
}

Сделано было для удобного использования и применения интересующих метрик в params.yaml (кому не знаком dvc рекомендую ознакомиться). Вот так выглядит yaml:

model:
  arch: vit_base_patch8_224
train:
  epochs: 50
  batch_size: 16
metrics:
- accuracy
- Precision
- Recall
- error_rate

Функция по созданию блока данных:

def get_dls(data_path, bs, model_cfg):
    print('Start create DataBlock')
    if not os.path.exists(data_path):
        raise ValueError(f"Data path {data_path} does not exist.")

    mean = list(model_cfg['mean'])
    std = list(model_cfg['std'])
    size = model_cfg['input_size'][1]

    dblock = DataBlock(
        blocks=(ImageBlock, CategoryBlock),
        get_items=get_image_files,
        splitter=GrandparentSplitter(train_name='train', valid_name='test'),
        get_y=parent_label,
        item_tfms=Resize(size),
        batch_tfms=[*aug_transforms(),Normalize.from_stats(mean=mean, std=std, cuda=True),],
    )
    dls = dblock.dataloaders(data_path, bs=bs)
    return dls

model_cfg содержит конфигурации модели, позже будет понятно откуда он берётся.

DataBlock – Высокоуровневый API от Fastai, позволяющий просто и удобно получить данные в DataLoaders.

blocks – указывается кортеж используемых данных.

get_items=get_image_files – получение путей до изображений.

splitter=GrandparentSplitter(train_name='train', valid_name='test') – для разделения данных на обучающую и тестовую выборку будет произведет поиск папок test, train.

get_y=parent_label – метки изображениям будут присваиваться исходя из названия родительской директории.

item_tfms=Resize(size) – Изменения, применяемые к каждым изображениям.

batch_tfms=[*aug_transforms(),Normalize.from_stats(mean=mean, std=std, - cuda=True),] – изменения, применяемые к батчам.

После формирования блока данных, можно приступать к обучению.

def train_model(data_path, output_path, params_file):
    with open(params_file, 'r') as f:
        params = yaml.safe_load(f)

    epochs = params['train']['epochs']
    batch_size = params['train']['batch_size']
    metric_names = params['metrics']
    metrics = [METRICS[name] for name in metric_names if name in METRICS]

    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    model = timm.create_model(params['model']['arch'], pretrained=True, num_classes=3)
    model = model.to(device)
    model_cfg = model.default_cfg

    dls = get_dls(data_path,batch_size, model_cfg)
    print('Start fine_tune')
    learn = Learner(dls, model, metrics=metrics)
    learn = Learner(dls, model, metrics=metrics)
    lrs = learn.lr_find(suggest_funcs=(minimum, steep, valley, slide), show_plot = False)
    lr = lrs[3]
    with Live('dvctrain', report='md') as live:
        learn.fine_tune(epochs, lrs.valley, cbs = [SaveModelCallback(min_delta=0.01, monitor = 'accuracy'),DVCLiveCallback(live=live)])

model_cfg = model.default_cfg – возвращает конфигурацию модели

Рис 2. Конфигурация модели

Рис 2. Конфигурация модели

Хотел бы обратить внимание на строку lrs = learn.lr_find(suggest_funcs=(minimum, steep, valley, slide), show_plot = False) , которая позволяет определилить learning rate, наиболее подходящий для ваших данных (более подробно можно ознакомиться тут. Только не забудьте включить VPN).

Вот и весь код! Всего двумя функциями можно без проблем провести эксперименты и подобрать модель классификации изображений! Здесь я не углублялся в процесс создания конвейера dvc, в хабре можно найти материал по этой теме. В следующей статье разберем процесс оценки модели после обучения.

Удачи!

Автор: RadAI

Источник

Рейтинг@Mail.ru
Rambler's Top100