KI Modelldateiformate

Aus TippvomTibb
Version vom 10. Oktober 2026, 13:11 Uhr von Chris T. Ludwig (Diskussion | Beiträge) (Die Seite wurde neu angelegt: „=Allgemeines= Da es recht viele Dateiformate, in denen Modelldaten gespeichert sind, gibt ist für mich wichtig wie und welche Daten in Datei abgelegt werden. Eins vorab. Es sind wohl alle Formate ineinander konvertierbar. Sie lassen sich auch mit Hilfe der WebApp netron [https://netron.app/] visualisieren. =Die Formate im Überblick= Diese Dateiendungen stehen für gängige Machine-Learning- und Deep-Learning-Modellformate: [1, 2] ==.pt / .pth (PyTor…“)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Zur Navigation springen Zur Suche springen

Allgemeines

Da es recht viele Dateiformate, in denen Modelldaten gespeichert sind, gibt ist für mich wichtig wie und welche Daten in Datei abgelegt werden.

Eins vorab. Es sind wohl alle Formate ineinander konvertierbar.

Sie lassen sich auch mit Hilfe der WebApp netron [1] visualisieren.

Die Formate im Überblick

Diese Dateiendungen stehen für gängige Machine-Learning- und Deep-Learning-Modellformate: [1, 2]

.pt / .pth (PyTorch)

Das Standard-Speicherformat von PyTorch (basierend auf Python Pickle). Es speichert Gewichte (state_dict) oder ganze Modelle samt Trainings-Metadaten. Es ist ideal zum Weiter-Trainieren, aber unsicher beim Laden fremder Dateien (Code-Ausführung möglich). [1, 2, 3]

.safetensors (Hugging Face)

Ein von Hugging Face entwickeltes, sicheres Format. Es speichert nur reine Tensordaten neben einem JSON-Header, lädt extrem schnell (Lazy-Loading) und verhindert Sicherheitsrisiken durch schädlichen Python-Code. [1]

.onnx (Open Neural Network Exchange)

Ein herstellerunabhängiges Standardformat für Rechengraphen. Es dient der Interoperabilität, damit ein Modell aus PyTorch auf anderen Runtimes oder Plattformen (z. B. .NET, Mobile, Web) ausgeführt werden kann. [1, 4]

.model (Verschiedene)

Ein generischer Name für Modelldateien (häufig genutzt von Frameworks wie TensorFlow, Scikit-Learn, Keras oder SentencePiece).

.engine / .trt (TensorRT)

Ein hochgradig für NVIDIA-GPUs optimiertes Binärformat. Es wird auf einer spezifischen Hardware-Architektur kompiliert und ist nicht portabel auf andere GPU-Typen, bietet dafür aber maximale Inferenz-Geschwindigkeit. [2, 5]

Typischer Workflow (Pipeline)

Training / Speicherung: Das Modell wird in PyTorch als .pt oder .pth trainiert (oder als .safetensors gesichert). Export: Das Modell wird nach ONNX (.onnx) exportiert, um eine neutrale Zwischenform des Graphen zu erhalten. Optimierung / Inferenz: Über NVIDIA TensorRT (trtexec) wird aus dem ONNX-Modell eine hardware-spezifische .engine- oder .trt-Datei für den schnellen Produktionseinsatz auf GPUs generiert. [2, 4, 5, 6]

Mehr Details zu den Unterschieden findet man im offiziellen Blogbeitrag zu Common AI Model Formats. [1]

[1] https://huggingface.co [2] https://github.com [3] https://techjacksolutions.com [4] https://www.youtube.com [5] https://huggingface.co [6] https://github.com

Die Formate im Detail

.pt / .pth (PyTorch)

Das .pt und .pth Format sind technisch gesehen völlig identisch. Es gibt absolut keinen Unterschied im inneren Aufbau der Dateien. Beide Erweiterungen werden in PyTorch verwendet, um serialisierte Modelle, Gewichte oder Tensoren zu speichern. Die unterschiedlichen Dateiendungen sind lediglich eine Namenskonvention:

  • .pt: Steht schlicht für PyTorch. Es ist heute der empfohlene Standard, da es Verwechslungen vermeidet.
  • .pth: War in älteren PyTorch-Versionen üblich. Der Wechsel zu .pt wurde vollzogen, weil .pth im Python-Ökosystem bereits für Path Configuration Files (Dateien, die dem Python-Suchpfad Verzeichnisse hinzufügen) reserviert ist.

Aufbau

Hinter einer .pt oder .pth Datei verbirgt sich seit PyTorch 1.3 (2019) standardmäßig ein unverschlüsseltes ZIP-Archiv. Wenn du die Dateiendung in .zip änderst, kannst du sie mit jedem gängigen Entpacker (wie 7-Zip oder WinRAR) öffnen. Ein entpacktes PyTorch-Modell (im modernen TorchScript- oder Zip-basierten Format) sieht strukturell meistens so aus:

mein_modell.pt (ZIP-Archiv)
│
├── data.pkl             # Die serialisierten Python-Metadaten (Pickle-Datei)
├── byteorder            # Datei, die die Endianness (z. B. 'little') definiert
├── code/                # (Optional bei TorchScript) Enthält den Python/C++ Code der Modellstruktur
│   ├── __torch__.py
│   └── ...
└── data/                # Ordner mit den eigentlichen Binärdaten
    ├── 0                # Rohdaten-Tensor 1 (z. B. Weights von Layer 1)
    ├── 1                # Rohdaten-Tensor 2 (z. B. Biases von Layer 1)
    └── ...

data.pkl

data.pkl (Der Pickle-Teil) PyTorch nutzt Pythons Pickle-Modul zur Serialisierung. Diese Datei enthält ein Wörterbuch (Python Dictionary), das die Struktur des Modells beschreibt. Es mappt die Namen der Layer (z. B. layer1.weight, layer1.bias) auf die entsprechenden Binärdaten im data/-Ordner.

data Ordner

Hier liegen die tatsächlichen numerischen Werte (die gelernten Gewichte und Biases) als reine, unformatierte Binärdaten (Raw Bytes). PyTorch trennt die Metadaten (Struktur) strikt von den schweren Binärdaten (Gewichten), um das Laden extrem schnell zu machen. Mittels Memory Mapping (mmap) können die Gewichte beim Laden direkt aus der Datei in den RAM oder GPU-VRAM gespiegelt werden, ohne dass Python jede Zahl einzeln parsen muss.

Beschreibung

Je nachdem, wie das Modell in PyTorch gespeichert wurde, unterscheidet sich der logische Inhalt der data.pkl:

Nur die Gewichte (state_dict)

Code: torch.save(model.state_dict(), 'model.pt') Inhalt: Das Archiv enthält nur die reinen Zahlenwerte der Layer. Die eigentliche Python-Klasse (die Architektur des neuronalen Netzes) ist nicht in der Datei. Zum Laden musst du das Modell erst im Code definieren und dann die Gewichte hineinladen (model.load_state_dict(...)).

Das gesamte Modell

Code: torch.save(model, 'model.pt') Inhalt: Pickle speichert hierbei den Pfad zur Python-Klasse und die Gewichte. Achtung: Wenn du die Datei auf einem anderen Computer lädst, auf dem das exakte Python-Skript mit der Modelldefinition fehlt, stürzt der Ladevorgang ab.

TorchScript-Modelle

Code: torch.jit.save(traced_model, 'model.pt') Inhalt: Enthält zusätzlich den serialisierten Code (im Ordner code/). Solche Dateien können komplett ohne Python (z. B. in einer C++ Laufzeitumgebung) geladen und ausgeführt werden.

Beispiel TODO

.safetensors (Hugging Face)

Das .safetensors Format wurde von Hugging Face entwickelt, um die gravierenden Sicherheits- und Performance-Nachteile des klassischen .pt (Pickle)-Formats zu lösen. Im Gegensatz zu .pt ist eine .safetensors-Datei kein ZIP-Archiv, sondern eine einzelne, kontinuierliche Binärdatei. Ihr Aufbau ist extrem minimalistisch, sicher und auf maximale Ladegeschwindigkeit optimiert.

Aufbau

Eine .safetensors-Datei besteht aus exakt drei Abschnitten:

┌───────────────────────────┬────────────────────────────────────────────────────────┬────────────────────────────────────────────────────────┐
│ 1. Header-Größe (8 Bytes) │ 2. JSON-Header (Variabler Text-Bereich)                 │ 3. Tensor-Rohdaten (Reiner Binärblock)                  │
├───────────────────────────┼────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────┤
│ Gibt an, wie viele Bytes  │ Enthält Metadaten und die "Gebrauchsanweisung":        │ Hier liegen alle Gewichte und Biases hintereinander    │
│ der JSON-Header lang ist. │ Welcher Tensor liegt an welcher Byte-Position (Offset)?│ als unformatierte Bytes (z. B. FP16 oder BF16).        │
└───────────────────────────┴────────────────────────────────────────────────────────┴────────────────────────────────────────────────────────┘

Beschreibung

Die ersten 8 Bytes (Header Length)

Die Datei beginnt immer mit einer 64-Bit-Ganzzahl (Unsigned Long in Little-Endian). Diese Zahl sagt dem Parser exakt, wie viele Bytes er ab jetzt lesen muss, um den gesamten Header zu erfassen.

Der JSON-Header (Metadaten & Wegweiser)

Direkt nach den ersten 8 Bytes folgt ein ganz normaler UTF-8-kodierter JSON-String.

Dieser Header enthält:

  • Globale Metadaten (Optional): Im Feld __metadata__ können Infos wie das Erstellungsdatum, das Framework oder Einsatzzwecke stehen.
  • Die Tensor-Map: Für jeden einzelnen Tensor im Modell gibt es einen Eintrag, der beschreibt, wie er heißt, welche Form er hat, welcher Datentyp genutzt wird und wo genau im darauffolgenden Binärblock er liegt.

Der Binärblock (Tensor-Rohdaten)

Direkt nach dem JSON-Header (auf das Byte genau ausgerichtet) folgen die reinen, unkomprimierten numerischen Daten der Tensoren. Es gibt keine Trennzeichen, keine Ordnerstrukturen und keine Kompression. Die Daten liegen genau so im Speicher, wie die Grafikkarte oder CPU sie erwartet.

Da die Daten im Safetensors-Format unkomprimiert und perfekt linear angeordnet sind, kann ein System beim Laden die Datei öffnen und die Adressen im RAM direkt an die GPU übergeben. Die Daten müssen nicht ein einziges Mal im Arbeitsspeicher hin- und herkopiert werden (Zero-Copy).

Code-Beispiel

Beispiel für einen solchen JSON-Header:

{
  "__metadata__": {
    "format": "pt"
  },
  "model.layers.0.self_attn.q_proj.weight": {
    "dtype": "F16",
    "shape":,
    "data_offsets": [0, 33554432]
  },
  "model.layers.0.self_attn.k_proj.weight": {
    "dtype": "F16",
    "shape":,
    "data_offsets": [33554432, 67108864]
  }
}

Hinweis zu den data_offsets: Die Zahlen [0, 33554432] bedeuten: Dieser spezifische Tensor beginnt bei Byte 0 des Binärblocks und endet bei Byte 33.554.432.

.onnx

Das ONNX-Format (Open Neural Network Exchange) ist grundlegend anders aufgebaut als .pt oder .safetensors. Während die anderen Formate primär flache Wörterbücher (Dictionaries) von Tensoren speichern, speichert ONNX einen vollständigen, serialisierten Berechnungsgraphen (Computation Graph). Technisch basiert eine .onnx-Datei auf Protocol Buffers (Protobuf), einem von Google entwickelten Verfahren zur Serialisierung strukturierter Daten.

Aufbau

Die Struktur einer ONNX-Datei ist streng hierarchisch ineinander verschachtelt und folgt der in Protobuf definierten Architektur. Wenn man die Datei logisch zerlegt, sieht sie so aus:

ModelProto (Das Gesamtmodell)
│
├── Metadaten (Version, Ersteller, IR-Version, Opsets)
│
└── GraphProto (Der Berechnungsgraph)
    │
    ├── Input  (Eingangs-Knoten, z. B. Bildgröße)
    ├── Output (Ausgangs-Knoten, z. B. Wahrscheinlichkeiten)
    │
    ├── NodeProto (Die Operationen / Layer)
    │   ├── Node 1: Conv (Faltung)  ───► Verweist auf Inputs, Outputs & Attribute
    │   ├── Node 2: ReLU (Aktivierung)
    │   └── ...
    │
    └── TensorProto (Initializers / Die gelernten Gewichte)
        ├── Gewichte für Conv 1 (Binärdaten)
        └── ...

Beschreibung

ModelProto (Der globale Container)

Das ist die oberste Ebene der Datei. Sie enthält globale Metadaten, die für die Kompatibilität entscheidend sind: ir_version: Die Version der ONNX-Spezifikation. opset_import: Extrem wichtig. Es definiert, welche Version der Operatoren-Bibliothek genutzt wird (z. B. "nutze den AI-Opset Version 15"). Das stellt sicher, dass eine Runtime (wie ONNX Runtime) exakt weiß, wie sie eine Operation (wie z. B. Resize oder LSTM) mathematisch ausführen muss.

GraphProto (Das Netzwerk-Layout)

Der Graph beschreibt den gesamten Datenfluss. Er verbindet die Eingänge mit den Ausgängen über ein Netz aus mathematischen Operationen. Ein Graph hat keine Schleifen (er ist ein Directed Acyclic Graph oder DAG).

NodeProto (Die mathematischen Bausteine)

Jeder "Node" (Knoten) im Graphen entspricht einer mathematischen Operation (z. B. Matrixmultiplikation, Convolutions, Softmax). Ein Node speichert: op_type: Der Name der Operation (z. B. Conv, Add, MatMul). input / output: Strings, die die Kanten des Graphen beschreiben. Wenn Node 1 den Output "tensor_1" erzeugt und Node 2 den Input "tensor_1" erwartet, weiß die Runtime, dass diese beiden Layer hintereinandergeschaltet sind. attribute: Spezifische Einstellungen für diesen Layer (z. B. die Kernel-Größe oder das Stride-Verhalten bei einer Convolution).

TensorProto (Die "Initializer")

Hier liegen die gelernten Gewichte und Biases des Modells. Bei kleineren Modellen liegen diese Parameter direkt eingebettet im jeweiligen TensorProto-Feld als Binärdaten innerhalb der Protobuf-Struktur.

Besonderheit bei großen Modellen (LLMs): Da Protobuf ein striktes Größenlimit von 2 GB pro Datei hat, unterstützt ONNX das Speichern von externen Daten. Die .onnx-Datei enthält dann nur noch die Struktur des Graphen, während die schweren Gewicht-Tensoren in separaten Binärdateien (z. B. model.onnx.data) im selben Verzeichnis abgelegt werden.

Da ONNX den Code in standardisierte mathematische Knoten übersetzt, kann ein in PyTorch trainiertes Modell als ONNX-Datei exportiert und anschließend ohne Python-Laufzeitumgebung direkt auf einer optimierten Engine wie TensorRT (NVIDIA) oder OpenVINO (Intel) mit maximaler Hardware-Ausnutzung ausgeführt werden.