Powrót do strony głównej

MLOps na bezpłatnych GPU: przetwarzanie archiwów PDF

Artykuł omawia dwa praktyczne projekty: weterynaryjny screening oparty na CV i generowanie obrazów w stylu Imperium Rosyjskiego. Główny fokus — techniczne rozwiązania do pracy z ograniczonymi zasobami: ZeroGPU, PyMuPDF, filtrowanie według dyspersji jasności i wymuszone zarządzanie pamięcią.

MLOps bez budżetu: jak przetworzyliśmy 9 GB przedrewolucyjnych czasopism
Advertisement 728x90

MLOps na granicy możliwości: jak przetworzyć 9 GB archiwów prasy przedrewolucyjnej na bezpłatnych GPU

AI-Vet-Scanner rozwiązuje problem wieloklasowej klasyfikacji obrazów bydła. Kluczowym wymogiem jest zerowy koszt dla użytkownika końcowego. Dlatego zrezygnowaliśmy z tradycyjnego wdrożenia na stałym GPU. Zamiast tego wykorzystaliśmy mechanizm ZeroGPU w Hugging Face Spaces: model jest ładowany do pamięci tylko na czas przetwarzania jednego zapytania, a następnie całkowicie zwalniany. To osiągnięto poprzez:

  • Użycie transformers + accelerate z lazy loading modelem;
  • Przymusowe wyładowanie modelu (model.cpu(); del model) po inferencji;
  • Wyłączenie buforowania pośrednich tensorów przez torch.inference_mode();
  • Rezerwację fallbacka wyłącznie na CPU w przypadku niedostępności GPU.

Taki podejście gwarantuje niezawodność nawet przy szczytowych obciążeniach — nie ma stanu, który mógłby "zaciąć się" w pamięci. Inferencja pozostaje bezpłatna i skalowalna bez ręcznego zarządzania instancjami.

Przetwarzanie 9,24 GB archiwum PDF: walka z OOM i dyskiem

Drugi projekt — przygotowanie datasetu dla SDXL LoRA — napotkał fundamentalny problem: 9,24 GB skanów czasopisma „Wiestnik Mody” (1885–1917) nie da się całościowo załadować na 20 GB miejsca na dysku i 16 GB RAM. Standardowe narzędzia, takie jak pdf2image + Poppler, natychmiast wywołują OOM ze względu na buforowanie wszystkich stron w RAM.

Google AdInline article slot

Zamieniliśmy je na optymalizowany pipeline oparty na PyMuPDF (fitz). Jego kluczowe zalety to:

  • Brak pełnego ładowania dokumentu do pamięci;
  • Renderowanie ściśle po jednej stronie;
  • Obsługa kompresowanego renderowania (np. matrix=fitz.Matrix(2, 2) dla 2× upscalingu bez pośredniego powiększania w RAM);
  • Wbudowana obsługa warstw PDF i metadanych.

Filtracja według dyssypacji: matematyka zamiast detektora

Spośród ponad 300 stron PDF 70% to kolumny tekstowe. Szkolenie YOLO do detekcji grafik jest nieuzasadnione: zbyt mało anotacji, wysoki overhead. Zastosowaliśmy szybki heurystyczny filtr oparty na OpenCV:

def is_image_page(cv_img, min_variance=45):
    gray = cv2.cvtColor(cv_img, cv2.COLOR_RGB2GRAY)
    return gray.std() > min_variance

Standardowe odchylenie odświeżonej jasności jest niezawodnym wskaźnikiem trudności wizualnej: strony tekstowe dają σ ≈ 15–30, grafiki i ilustracje — σ ≥ 50–90. Takie podejście zmniejszyło objętość przetwarzanych danych o 73% bez utraty istotnych próbek.

Google AdInline article slot

Zarządzanie pamięcią: GC jako część pipeline

Po filtracji i zmniejszeniu rozmiaru do 1024×1024 (LANCZOS) wykonujemy przymusową czyszczenie:

  • del cv_img, gray;
  • gc.collect();
  • torch.cuda.empty_cache() (dla przypadków, gdy używamy akceleracji CUDA);
  • Zapis JPEG z jakością 92 (PIL.Image.save(..., quality=92)), aby minimalizować rozmiar bez widocznej straty szczegółów.

To zapobiega nagromadzeniu plików tymczasowych i wyciekom pamięci podczas długich cyklów przetwarzania. Bez tego kroku 20 GB dysku zapełnia się w ciągu około 12 godzin.

Co jest ważne

  • ZeroGPU to nie funkcja Hugging Face, a wzór: dynamiczne ładowanie/wyładowanie modeli w momencie zapytania, a nie stały hosting.
  • PyMuPDF jest 4,2× szybszy od pdf2image przy przetwarzaniu wielostronicowych PDF i zużywa o 87% mniej RAM.
  • Dyssypacja jasności to ważny i szybki marker do filtracji ilustracji w archiwach historycznych; nie wymaga szkolenia i działa na CPU.
  • Przymusowe gc.collect() i empty_cache() powinny być częścią każdego etapu przetwarzania, jeśli limity zasobów są surowe.
  • Wszystkie operacje (rendering, filtr, resize, save) wykonujemy w ścisłym porządku bez buforowania pośrednich tablic.

Na obecnym etapie autopilot przetwarza około 1400 stron na godzinę na T4 GPU. Po zakończeniu ekstrakcji archiwum ZIP zostanie przekazane do pipeline'u szkoleniowego SDXL LoRA z fine-tuningiem na 500 epok. Celowy prompt zawiera semantyczne mieszanie współczesnych obiektów i stylów historycznych — np. „cyber-monokl w stylu grafiki z lat 90. XIX wieku”. Techniczna trudność tutaj nie polega na generacji, ale na zapewnieniu czystości i reprezentatywności datasetu. To właśnie ten etap decyduje o jakości finalnej modelu — zwłaszcza przy niewielkich objętościach celowych klas.

Google AdInline article slot

Inżynierska wartość takich projektów polega na pokazaniu, że wydajność nie zawsze zależy od budżetu, a od precyzji wyboru narzędzi i głębokiego zrozumienia ograniczeń. MLOps „na kolanie” to nie kompromis, a dyscyplina, w której każdy wywołanie gc.collect() i każda linia w fitz.Matrix() ma wymierny efekt.

— Editorial Team

Advertisement 728x90

Czytaj dalej