За последние годы искусственный интеллект и машинное обучение прошли долгий путь, а достижения в этой области позволяют исследователям и разработчикам достигать беспрецедентных результатов. Модель CLIP (Contrastive Language–Image Pretraining) от OpenAI, ставшая революционным прорывом в области искусственного интеллекта, использует преимущества мультимодальных возможностей. , предлагает исключительную способность понимать и связывать текст и изображения, CLIP обладает огромным потенциалом во множестве приложений, особенно в нулевой классификации, как обсуждалось в моем предыдущем посте.



Итак, не было бы интересно взять эту мощную модель и настроить ее для удовлетворения наших уникальных потребностей?

Но прежде чем мы углубимся в код, давайте сначала заложим основу, разобравшись с концепцией тонкой настройки и ее значением, особенно в контексте модели CLIP.

Что такое тонкая настройка?

В машинном обучении тонкая настройка — это процесс использования предварительно обученной модели и небольшой «настройки» ее параметров для адаптации к новой аналогичной задаче. Зачем нам это делать? Есть несколько причин:

  1. Экономит ресурсы. Обучение большой модели с нуля требует значительных вычислительных ресурсов и времени. Используя предварительно обученную модель, мы можем использовать шаблоны, которые она уже изучила, уменьшая требуемые ресурсы.
  2. Использование трансферного обучения. Это важная часть тонкой настройки. Идея состоит в том, что знания, полученные при решении одной проблемы, могут быть применены к другой, но связанной с ней проблеме. Например, модель, обученная на большом наборе данных общих изображений (например, ImageNet), научилась распознавать различные особенности изображений. Эти знания можно перенести на более конкретную задачу, например, распознавание типов одежды на изображениях.
  3. Сделки с ограниченными данными. Во многих случаях у нас может не быть достаточно большого набора данных для нашей конкретной задачи. Точная настройка предварительно обученной модели на меньшем наборе данных может помочь предотвратить переоснащение, поскольку модель уже изучила общие функции из большего набора данных, на котором она изначально обучалась.

Почему тонкая настройка CLIP?

Модель CLIP, как мы упоминали ранее, обучена понимать и сопоставлять изображения и текст одновременно. Это достигается обучением модели на большом массиве интернет-текста и изображений. Однако это обобщенное обучение может не сделать его экспертом в понимании определенных конкретных или специализированных типов изображений или текста. Несмотря на то, что предварительно обученная модель CLIP является мощной, для того, чтобы по-настоящему использовать ее возможности для конкретной задачи или области, точная настройка является важным шагом.

В следующих разделах этой статьи вы найдете пошаговое руководство по тонкой настройке модели CLIP с вашим собственным набором данных с помощью Python.

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

Начальная часть скрипта посвящена импорту необходимых библиотек и модулей. Сюда входят json для обработки данных, PIL для обработки изображений и torch и clip для загрузки и тонкой настройки модели. После этого скрипт загружает пользовательский набор данных JSON и соответствующий набор изображений из определенных путей.

import json
from PIL import Image

import torch
import torch.nn as nn
from torch.utils.data import DataLoader

import clip
from transformers import CLIPProcessor, CLIPModel

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

Здесь мы будем использовать набор данных Indo Fashion Dataset, доступный на Kaggle. Он состоит из 106 тыс. изображений и 15 уникальных категорий одежды. Равномерно распределены классы в валидационной и тестовой выборке, состоящей из 500 образцов на класс для детальной классификации индийской этнической одежды.

Наш скрипт Python начинается с загрузки пользовательского набора данных, расположенного по адресу «путь к train_data.json», и соответствующего набора изображений по адресу «путь к набору обучающих данных». '. Эти пути должны быть заменены вашими собственными путями. Данные хранятся в формате JSON, который мы повторяем для создания нашего пользовательского набора данных.

with open(json_path, 'r') as f:
    input_data = []
    for line in f:
        obj = json.loads(line)
        input_data.append(obj)

Загрузите модель CLIP и процессор

Установите библиотеку трансформаторов, предоставленную добрыми людьми из 🤗 Hugging Face, используя pip.

pip install transformers

Затем мы загружаем предварительно обученную модель CLIP из концентратора моделей 🤗 Hugging Face, а также соответствующий процессор для данных текста и изображения.

model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")
processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32")

Эти строки загружают предварительно обученную модель и ее процессор, закладывая основу для тонкой настройки, которую мы выполним позже.

Пользовательский набор данных и DataLoader

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

class image_title_dataset():
    def __init__(self, list_image_path,list_txt):
        # Initialize image paths and corresponding texts
        self.image_path = list_image_path
        # Tokenize text using CLIP's tokenizer
        self.title  = clip.tokenize(list_txt)

    def __len__(self):
        return len(self.title)

    def __getitem__(self, idx):
        # Preprocess image using CLIP's preprocessing function
        image = preprocess(Image.open(self.image_path[idx]))
        title = self.title[idx]
        return image, title
  

Затем объект DataLoader в PyTorch помогает нам эффективно загружать эти данные партиями в процессе обучения.

Тонкая настройка и обучение модели

После загрузки наших данных мы подготавливаем нашу модель к тонкой настройке. Мы выбираем оптимизатор, в данном случае оптимизатор Адама, со скоростью обучения 5e-5 и некоторыми специфическими параметрами.

Затем мы определяем нашу функцию потерь nn.CrossEntropyLoss(), которая будет использоваться для расчета потерь на каждом этапе процесса обучения.

optimizer = torch.optim.Adam(model.parameters(), lr=5e-5,betas=(0.9,0.98),eps=1e-6,weight_decay=0.2)
loss_img = nn.CrossEntropyLoss()
loss_txt = nn.CrossEntropyLoss()

num_epochs = 30
for epoch in range(num_epochs):
    pbar = tqdm(train_dataloader, total=len(train_dataloader))
    for batch in pbar:
        optimizer.zero_grad()

        images,texts = batch 
        
        images= images.to(device)
        texts = texts.to(device)

        # Forward pass
        logits_per_image, logits_per_text = model(images, texts)

        # Compute loss
        ground_truth = torch.arange(len(images),dtype=torch.long,device=device)
        total_loss = (loss_img(logits_per_image,ground_truth) + loss_txt(logits_per_text,ground_truth))/2

        # Backward pass
        total_loss.backward()
        if device == "cpu":
            optimizer.step()
        else : 
            convert_models_to_fp32(model)
            optimizer.step()
            clip.model.convert_weights(model)

        pbar.set_description(f"Epoch {epoch}/{num_epochs}, Loss: {total_loss.item():.4f}")

Сам цикл обучения включает в себя несколько этапов:

  1. Мы начинаем каждую эпоху с инициализации индикатора выполнения с помощью tqdm, чтобы отслеживать наш прогресс.
  2. В каждой итерации мы загружаем набор изображений и соответствующие подписи к ним.
  3. Данные передаются через нашу модель, генерируя прогнозы.
  4. Эти прогнозы сравниваются с истинной реальностью для расчета потерь.
  5. Эта потеря затем распространяется обратно по сети для обновления параметров модели.

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

Полную реализацию кода можно найти в моем репозитории github!

Ссылки:

  1. https://github.com/openai/CLIP
  2. https://www.kaggle.com/datasets/validmodel/indo-fashion-dataset
  3. https://github.com/openai/CLIP/issues/83