Russischer multimodaler KI-Radiologe: ViT + ruGPT-3 Kaggle-Anleitung
Die Entwicklung medizinischer KI-Lösungen auf Russisch stößt auf einen Mangel an einsatzbereiten Tools und Datensätzen. Dieser Artikel führt durch eine praxisnahe Fallstudie zum Zusammenbau und Training eines VisionEncoderDecoder-Modells, das aus Röntgenbildern medizinische Berichte generiert – durch Kombination des ViT-Bildencoders mit dem ruGPT-3-Sprachmodell.
Architekturentscheidungen und Modellanpassungen
Der Aufbau eines multimodalen Modells von Grund auf erfordert enorme Rechenleistung. Eine klügere Variante ist die Kombination vortrainierter Komponenten mit der VisionEncoderDecoderModel-Architektur von Hugging Face. Als Encoder zur Extraktion visueller Merkmale wählten wir google/vit-base-patch16-224-in21k. Der Decoder basiert auf dem russischsprachigen Modell ai-forever/rugpt3small_based_on_gpt2.
Hauptproblem: ruGPT-3 unterstützt nativ keine Cross-Attention, um Daten vom Encoder zu empfangen. Die Lösung besteht in einer Anpassung der Modellkonfiguration vor der Initialisierung:
from transformers import AutoConfig, AutoModelForCausalLM, AutoModel
encoder = AutoModel.from_pretrained("google/vit-base-patch16-224-in21k")
decoder_config = AutoConfig.from_pretrained("ai-forever/rugpt3small_based_on_gpt2")
decoder_config.is_decoder = True
decoder_config.add_cross_attention = True
decoder = AutoModelForCausalLM.from_pretrained("ai-forever/rugpt3small_based_on_gpt2", config=decoder_config)
Nach dem Zusammenbau initialisiert das Modell neue Gewichte für Cross-Attention- und Projektionsschichten, die beim Training feinjustiert werden.
Datenaufbereitung und -verarbeitung
Es gibt keine fertigen russischen Datensätze, die Röntgenbilder mit medizinischen Berichten paaren. Deshalb wurden wir kreativ: Wir nutzten den englischen Indiana University Chest X-Ray (IU X-Ray)-Datensatz mit rund 7.500 Bildern und Berichten. Die Berichte wurden direkt in der Kaggle-Umgebung mit dem Helsinki-NLP/opus-mt-en-ru-Modell ins Russische übersetzt.
Die Dateiverwaltung in Kaggle hat ihre Tücken. Standard-Bildlader sehen oft nur Vorschaubilder. Für eine korrekte Zuordnung scannen wir das Dateisystem gründlich:
import os
file_map = {}
for root, dirs, files in os.walk('/kaggle/input'):
for file in files:
if file.lower().endswith(('.png', '.jpg', '.jpeg')):
base_name = os.path.splitext(file)[0]
file_map[base_name] = os.path.join(root, file)
So stellen wir eine zuverlässige Verknüpfung von CSV-Identifikatoren mit den tatsächlichen Bildpfaden sicher.
Trainingsprozess und Fehlerbehebung
Das Training lief auf zwei NVIDIA T4 GPUs mit Mixed Precision (fp16) und Gradient Accumulation (gradient_accumulation_steps=4), um eine virtuelle Batch-Größe von 32 effizient zu erreichen.
Häufige Probleme und Lösungen:
- Absturz beim Speichern von Checkpoints: Seq2SeqTrainer scheitert in manchen Transformers-Versionen bei benutzerdefinierten Komposita-Modellen. Lösung: Zwischenspeicherungen deaktivieren (save_strategy="no") und Generierungsparameter manuell über GenerationConfig vor dem finalen Speichern handhaben.
- Kaggle-Sitzungs-Timeouts: Automatische Herunterfahrungen bei langen Trainings verhindern, indem ein einfaches JavaScript-Snippet in der Browser-Konsole periodische Klicks simuliert.
Ergebnisse, Inferenz und Deployment
Nach 15 Epochen erzeugt das Modell kohärente russische medizinische Berichte mit korrekter Fachterminologie. Es erkennt grundlegende Muster wie freie Lungen, Pneumothorax-Anzeichen und Kardiomegalie. Der kleine Datensatz führt gelegentlich zu Halluzinationen – z. B. Erwähnung fehlender Medizingeräte.
Beispiel für einfache Inferenz:
import torch
from transformers import VisionEncoderDecoderModel, ViTImageProcessor, AutoTokenizer
from PIL import Image
model_id = "livadies/Russian-Radiologist-ruGPT-ViT"
model = VisionEncoderDecoderModel.from_pretrained(model_id)
feature_extractor = ViTImageProcessor.from_pretrained(model_id)
tokenizer = AutoTokenizer.from_pretrained(model_id)
image = Image.open("xray.jpg").convert("RGB")
pixel_values = feature_extractor(images=image, return_tensors="pt").pixel_values
generated_ids = model.generate(pixel_values, max_length=128, num_beams=4)
print(tokenizer.decode(generated_ids[0], skip_special_tokens=True))
Eine Gradio-Demo läuft auf Hugging Face Spaces mit CPU und benötigt 10–15 Sekunden pro Generierung. Der vollständige Quellcode – inklusive Datenpipelines und Trainings-Notebooks – ist im öffentlichen Repository verfügbar.
Wichtige Erkenntnisse
- Hybride Architektur: Erfolgreiche Verschmelzung von vortrainiertem ViT-Bildencoder und ruGPT-3-Sprachmodell durch Hinzufügen von Cross-Attention via Konfigurationsanpassung.
- Datenumgehung: Mangel an russischen Medizindatensätzen überwunden durch Übersetzung englischer Datensätze und Umgang mit Kaggle-Dateipeculiaritäten.
- Praktische Fixes: Fehlerhafte Autosaves in Seq2SeqTrainer deaktiviert und Sitzungs-Timeouts verhindert für stabiles Langzeittraining.
- Proof of Concept: Kleines Datensatz-Modell validiert Vision + Language-Architektur für strukturierte russische medizinische Textgenerierung.
- Offen und zugänglich: Vollständiger Code und interaktive Demo öffentlich für Community-Studium, Tests und Erweiterungen.
— Editorial Team
Noch keine Kommentare.