Whatsapp Telegram Telegram Call Anrufen

Implementierung von Transformern: Aufbau in PyTorch, vorgefertigte Modelle und Feinabstimmung


1. Aufbau eines Transformers von Grund auf in PyTorch

Der Aufbau eines Transformers von Grund auf umfasst die Implementierung der grundlegenden Komponenten des Modells, einschließlich des Encoders, Decoders, Multi-Head Attention und Feed-Forward Netzwerken.

Hier ist ein vereinfachtes Beispiel für die Implementierung eines Transformers in PyTorch:

import torch
import torch.nn as nn
import torch.nn.functional as F

class MultiHeadAttention(nn.Module):
    def __init__(self, d_model, num_heads):
        super(MultiHeadAttention, self).__init__()
        assert d_model % num_heads == 0
        self.d_k = d_model // num_heads
        self.num_heads = num_heads
        self.linear_q = nn.Linear(d_model, d_model)
        self.linear_k = nn.Linear(d_model, d_model)
        self.linear_v = nn.Linear(d_model, d_model)
        self.linear_out = nn.Linear(d_model, d_model)

    def forward(self, q, k, v, mask=None):
        batch_size = q.size(0)
        q = self.linear_q(q).view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2)
        k = self.linear_k(k).view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2)
        v = self.linear_v(v).view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2)

        scores = torch.matmul(q, k.transpose(-2, -1)) / torch.sqrt(torch.tensor(self.d_k, dtype=torch.float32))
        if mask is not None:
            scores = scores.masked_fill(mask == 0, -1e9)
        attention = F.softmax(scores, dim=-1)
        x = torch.matmul(attention, v).transpose(1, 2).contiguous().view(batch_size, -1, self.d_k * self.num_heads)
        return self.linear_out(x)

class EncoderLayer(nn.Module):
    def __init__(self, d_model, num_heads, d_ff, dropout=0.1):
        super(EncoderLayer, self).__init__()
        self.self_attn = MultiHeadAttention(d_model, num_heads)
        self.ffn = nn.Sequential(
            nn.Linear(d_model, d_ff),
            nn.ReLU(),
            nn.Linear(d_ff, d_model)
        )
        self.norm1 = nn.LayerNorm(d_model)
        self.norm2 = nn.LayerNorm(d_model)
        self.dropout1 = nn.Dropout(dropout)
        self.dropout2 = nn.Dropout(dropout)

    def forward(self, x, mask=None):
        x2 = self.norm1(x)
        x = x + self.dropout1(self.self_attn(x2, x2, x2, mask))
        x2 = self.norm2(x)
        x = x + self.dropout2(self.ffn(x2))
        return x

class Encoder(nn.Module):
    def __init__(self, vocab_size, d_model, num_layers, num_heads, d_ff, dropout=0.1):
        super(Encoder, self).__init__()
        self.embedding = nn.Embedding(vocab_size, d_model)
        self.layers = nn.ModuleList([EncoderLayer(d_model, num_heads, d_ff, dropout) for _ in range(num_layers)])
        self.norm = nn.LayerNorm(d_model)

    def forward(self, src, mask=None):
        x = self.embedding(src)
        for layer in self.layers:
            x = layer(x, mask)
        return self.norm(x)

class Transformer(nn.Module):
    def __init__(self, src_vocab_size, tgt_vocab_size, d_model, num_layers, num_heads, d_ff, dropout=0.1):
        super(Transformer, self).__init__()
        self.encoder = Encoder(src_vocab_size, d_model, num_layers, num_heads, d_ff, dropout)
        self.decoder = Encoder(tgt_vocab_size, d_model, num_layers, num_heads, d_ff, dropout)  # Vereinfachung
        self.linear = nn.Linear(d_model, tgt_vocab_size)

    def forward(self, src, tgt, src_mask=None, tgt_mask=None):
        memory = self.encoder(src, src_mask)
        output = self.decoder(tgt, tgt_mask)  # Vereinfachung
        return self.linear(output)

# Beispielnutzung
src_vocab_size = 10000
tgt_vocab_size = 10000
d_model = 512
num_layers = 6
num_heads = 8
d_ff = 2048

model = Transformer(src_vocab_size, tgt_vocab_size, d_model, num_layers, num_heads, d_ff)
src = torch.randint(0, src_vocab_size, (32, 10))  # (Batchgröße, Sequenzlänge)
tgt = torch.randint(0, tgt_vocab_size, (32, 10))

output = model(src, tgt)
print(output.shape)  # Erwartet: (Batchgröße, Sequenzlänge, tgt_vocab_size)

Erklärung:

  • MultiHeadAttention: Implementiert die Multi-Head Attention Mechanik.
  • EncoderLayer: Implementiert eine einzelne Schicht des Encoders mit Self-Attention und einem Feed-Forward Netzwerk.
  • Encoder: Stapelt mehrere Encoder-Schichten und fügt eine Einbettungsschicht hinzu.
  • Transformer: Kombiniert den Encoder und Decoder (hier vereinfacht, um den gleichen Encoder zu verwenden) und fügt eine lineare Transformation hinzu, um die Ausgabewahrscheinlichkeiten zu berechnen.

2. Vorgefertigte Transformer-Modelle (BERT, GPT, etc.)

Vorgefertigte Transformer-Modelle wie BERT und GPT wurden auf riesigen Textkorpora vortrainiert und sind für verschiedene NLP-Aufgaben sehr leistungsfähig. Diese Modelle sind in Frameworks wie Hugging Face's Transformers leicht zugänglich.

Beispiel mit Hugging Face Transformers:

from transformers import BertTokenizer, BertModel, GPT2Tokenizer, GPT2LMHeadModel

# BERT
bert_tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
bert_model = BertModel.from_pretrained('bert-base-uncased')

# Beispiel-Text
text = "Hello, my dog is cute"
inputs = bert_tokenizer(text, return_tensors="pt")
outputs = bert_model(**inputs)
print(outputs.last_hidden_state.shape)  # Erwartet: (Batchgröße, Sequenzlänge, versteckte Größe)

# GPT-2
gpt2_tokenizer = GPT2Tokenizer.from_pretrained('gpt2')
gpt2_model = GPT2LMHeadModel.from_pretrained('gpt2')

# Beispiel-Text
inputs = gpt2_tokenizer("Hello, my dog is cute", return_tensors="pt")
outputs = gpt2_model(**inputs, labels=inputs["input_ids"])
loss = outputs.loss
logits = outputs.logits
print(logits.shape)  # Erwartet: (Batchgröße, Sequenzlänge, Vokabulargröße)

Erklärung:

  • BERT: Tokenisiert den Eingabetext und gibt die versteckten Zustände aus.
  • GPT-2: Tokenisiert den Eingabetext und gibt die Logits und den Verlust zurück, was für Textgenerierungsaufgaben nützlich ist.

3. Feinabstimmung vorgefertigter Modelle

Feinabstimmung (Fine-Tuning) ist der Prozess, bei dem ein vortrainiertes Modell auf eine spezifische Aufgabe angepasst wird. Dies wird oft durch zusätzliches Training auf einem kleineren, aufgabenspezifischen Datensatz erreicht.

Beispiel für die Feinabstimmung eines BERT-Modells für die Textklassifikation:

from transformers import BertTokenizer, BertForSequenceClassification, Trainer, TrainingArguments

# Modell und Tokenizer laden
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertForSequenceClassification.from_pretrained('bert-base-uncased', num_labels=2)

# Beispiel-Datensatz
train_texts = ["I love this!", "I hate this!"]
train_labels = [1, 0]
train_encodings = tokenizer(train_texts, truncation=True, padding=True)
train_dataset = torch.utils.data.Dataset()
train_dataset.encodings = train_encodings
train_dataset.labels = train_labels

# Trainer-Setup
training_args = TrainingArguments(
    output_dir='./results',
    num_train_epochs=3,
    per_device_train_batch_size=16,
    per_device_eval_batch_size=64,
    warmup_steps=500,
    weight_decay=0.01,
    logging_dir='./logs',
)

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=train_dataset,
    eval_dataset=train_dataset,
)

# Training
trainer.train()


Erklärung:

  • BertForSequenceClassification: Ein BERT-Modell, das für die Sequenzklassifikation angepasst ist.
  • Trainer: Hugging Face's Trainer API vereinfacht den Trainingsprozess und die Feinabstimmung.

Dieses Beispiel zeigt, wie ein vortrainiertes BERT-Modell auf eine spezifische Textklassifikationsaufgabe angepasst werden kann. Die Feinabstimmung nutzt die vortrainierten Gewichte und passt sie an den neuen Datensatz an, um die Leistung für die spezifische Aufgabe zu optimieren.


CEO Image

Ali Ajjoub

info@ajjoub.com

Adresse 0049-15773651670

Adresse Jacob-winter-platz,1 01239 Dresden

Buchen Sie jetzt Ihren Termin für eine umfassende und individuelle Beratung.

Termin Buchen

Kontaktieren Sie uns

Lassen Sie uns K o n t a k t aufnehmen!