Dezember 21, 2025
13 Min. Lesezeit

Bewerbungsfragen für KI-Forschungsmitarbeiter: Der ultimative Leitfaden

interview
career-advice
job-search
Bewerbungsfragen für KI-Forschungsmitarbeiter: Der ultimative Leitfaden
MB

Milad Bonakdar

Autor

Meistern Sie die Grundlagen der KI-Forschung mit wichtigen Bewerbungsfragen zu Deep-Learning-Theorie, Forschungsmethodik, Transformer-Architekturen, Optimierung und modernsten KI-Themen für Forschungsmitarbeiter.


Einführung

KI-Forschungswissenschaftler verschieben die Grenzen der künstlichen Intelligenz durch neuartige Algorithmen, Architekturen und Methoden. Diese Rolle erfordert fundierte theoretische Kenntnisse, starke mathematische Grundlagen, Forschungserfahrung und die Fähigkeit, offene Probleme zu formulieren und zu lösen.

Dieser umfassende Leitfaden behandelt wesentliche Interviewfragen für KI-Forschungswissenschaftler, die von Deep-Learning-Theorie, Transformer-Architekturen, Optimierungstechniken, Forschungsmethodik, Computer Vision, NLP und modernsten KI-Themen reichen. Jede Frage enthält detaillierte Antworten, eine Bewertung der Seltenheit und Schwierigkeitsgrade.


Deep Learning Theorie (5 Fragen)

1. Erklären Sie Backpropagation und die Kettenregel im Detail.

Antwort: Backpropagation berechnet Gradienten effizient mithilfe der Kettenregel.

  • Kettenregel: Für zusammengesetzte Funktionen ist die Ableitung das Produkt der Ableitungen
  • Vorwärtsdurchlauf: Berechnen Sie Ausgaben und cachen Sie Zwischenwerte
  • Rückwärtsdurchlauf: Berechnen Sie Gradienten von der Ausgabe zum Eingang
import numpy as np

# Einfaches neuronales Netzwerk zur Demonstration der Backpropagation
class SimpleNN:
    def __init__(self, input_size, hidden_size, output_size):
        # Initialisieren der Gewichte
        self.W1 = np.random.randn(input_size, hidden_size) * 0.01
        self.b1 = np.zeros((1, hidden_size))
        self.W2 = np.random.randn(hidden_size, output_size) * 0.01
        self.b2 = np.zeros((1, output_size))
    
    def sigmoid(self, x):
        return 1 / (1 + np.exp(-x))
    
    def sigmoid_derivative(self, x):
        return x * (1 - x)
    
    def forward(self, X):
        # Schicht 1
        self.z1 = np.dot(X, self.W1) + self.b1
        self.a1 = self.sigmoid(self.z1)
        
        # Schicht 2
        self.z2 = np.dot(self.a1, self.W2) + self.b2
        self.a2 = self.sigmoid(self.z2)
        
        return self.a2
    
    def backward(self, X, y, output, learning_rate=0.01):
        m = X.shape[0]
        
        # Gradienten der Ausgabeschicht
        # dL/da2 = a2 - y (für binäre Kreuzentropie)
        # dL/dz2 = dL/da2 * da2/dz2 = (a2 - y) * sigmoid'(z2)
        dz2 = output - y
        dW2 = (1/m) * np.dot(self.a1.T, dz2)
        db2 = (1/m) * np.sum(dz2, axis=0, keepdims=True)
        
        # Gradienten der versteckten Schicht (Kettenregel)
        # dL/da1 = dL/dz2 * dz2/da1 = dz2 * W2.T
        # dL/dz1 = dL/da1 * da1/dz1 = dL/da1 * sigmoid'(z1)
        da1 = np.dot(dz2, self.W2.T)
        dz1 = da1 * self.sigmoid_derivative(self.a1)
        dW1 = (1/m) * np.dot(X.T, dz1)
        db1 = (1/m) * np.sum(dz1, axis=0, keepdims=True)
        
        # Gewichte aktualisieren
        self.W2 -= learning_rate * dW2
        self.b2 -= learning_rate * db2
        self.W1 -= learning_rate * dW1
        self.b1 -= learning_rate * db1
    
    def train(self, X, y, epochs=1000):
        for epoch in range(epochs):
            # Vorwärtsdurchlauf
            output = self.forward(X)
            
            # Rückwärtsdurchlauf
            self.backward(X, y, output)
            
            if epoch % 100 == 0:
                loss = -np.mean(y * np.log(output) + (1-y) * np.log(1-output))
                print(f'Epoche {epoch}, Verlust: {loss:.4f}')

# Beispielhafte Verwendung
X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
y = np.array([[0], [1], [1], [0]])  # XOR

nn = SimpleNN(input_size=2, hidden_size=4, output_size=1)
nn.train(X, y, epochs=5000)

Seltenheit: Sehr häufig Schwierigkeit: Schwer


2. Was ist das Problem des verschwindenden Gradienten und wie lösen Sie es?

Antwort: Verschwindende Gradienten treten auf, wenn Gradienten in tiefen Netzwerken extrem klein werden.

  • Ursachen:
    • Sigmoid-/tanh-Aktivierungen (Ableitungen < 1)
    • Tiefe Netzwerke (Gradienten multiplizieren sich)
  • Lösungen:
    • ReLU-Aktivierungen
    • Batch-Normalisierung
    • Residuelle Verbindungen (ResNet)
    • LSTM/GRU für RNNs
    • Sorgfältige Initialisierung (Xavier, He)
import torch
import torch.nn as nn

# Problem: Tiefes Netzwerk mit Sigmoid
class VanishingGradientNet(nn.Module):
    def __init__(self):
        super().__init__()
        self.layers = nn.Sequential(*[
            nn.Sequential(nn.Linear(100, 100), nn.Sigmoid())
            for _ in range(20)  # 20 Schichten
        ])
    
    def forward(self, x):
        return self.layers(x)

# Lösung 1: ReLU-Aktivierung
class ReLUNet(nn.Module):
    def __init__(self):
        super().__init__()
        self.layers = nn.Sequential(*[
            nn.Sequential(nn.Linear(100, 100), nn.ReLU())
            for _ in range(20)
        ])
    
    def forward(self, x):
        return self.layers(x)

# Lösung 2: Residuelle Verbindungen
class ResidualBlock(nn.Module):
    def __init__(self, dim):
        super().__init__()
        self.layers = nn.Sequential(
            nn.Linear(dim, dim),
            nn.ReLU(),
            nn.Linear(dim, dim)
        )
    
    def forward(self, x):
        return x + self.layers(x)  # Skip-Verbindung

class ResNet(nn.Module):
    def __init__(self):
        super().__init__()
        self.blocks = nn.Sequential(*[
            ResidualBlock(100) for _ in range(20)
        ])
    
    def forward(self, x):
        return self.blocks(x)

# Lösung 3: Batch-Normalisierung
class BatchNormNet(nn.Module):
    def __init__(self):
        super().__init__()
        self.layers = nn.Sequential(*[
            nn.Sequential(
                nn.Linear(100, 100),
                nn.BatchNorm1d(100),
                nn.ReLU()
            )
            for _ in range(20)
        ])
    
    def forward(self, x):
        return self.layers(x)

# Gradientenflussanalyse
def analyze_gradients(model, x, y):
    model.zero_grad()
    output = model(x)
    loss = nn.MSELoss()(output, y)
    loss.backward()
    
    # Überprüfen der Gradientengrößen
    for name, param in model.named_parameters():
        if param.grad is not None:
            grad_norm = param.grad.norm().item()
            print(f"{name}: {grad_norm:.6f}")

Seltenheit: Sehr häufig Schwierigkeit: Schwer


3. Erklären Sie Aufmerksamkeitsmechanismen und Selbstaufmerksamkeit.

Antwort: Aufmerksamkeit ermöglicht es Modellen, sich auf relevante Teile der Eingabe zu konzentrieren.

  • Aufmerksamkeit: Gewichtete Summe der Werte basierend auf der Ähnlichkeit von Abfrage und Schlüssel
  • Selbstaufmerksamkeit: Aufmerksamkeit, bei der Abfrage, Schlüssel und Wert aus derselben Quelle stammen
  • Skalierte Dot-Product-Aufmerksamkeit: Q·K^T / √d_k
import torch
import torch.nn as nn
import torch.nn.functional as F
import math

class ScaledDotProductAttention(nn.Module):
    def __init__(self, temperature):
        super().__init__()
        self.temperature = temperature
    
    def forward(self, q, k, v, mask=None):
        """
        q: (Batch, Seq_Len, d_k)
        k: (Batch, Seq_Len, d_k)
        v: (Batch, Seq_Len, d_v)
        """
        # Berechnen der Aufmerksamkeitswerte
        attn = torch.matmul(q, k.transpose(-2, -1)) / self.temperature
        
        # Anwenden der Maske (für Padding oder kausale Aufmerksamkeit)
        if mask is not None:
            attn = attn.masked_fill(mask == 0, -1e9)
        
        # Softmax, um Aufmerksamkeitsgewichte zu erhalten
        attn_weights = F.softmax(attn, dim=-1)
        
        # Anwenden der Aufmerksamkeit auf Werte
        output = torch.matmul(attn_weights, v)
        
        return output, attn_weights

class MultiHeadAttention(nn.Module):
    def __init__(self, d_model, n_heads, dropout=0.1):
        super().__init__()
        assert d_model % n_heads == 0
        
        self.d_model = d_model
        self.n_heads = n_heads
        self.d_k = d_model // n_heads
        
        # Lineare Projektionen
        self.w_q = nn.Linear(d_model, d_model)
        self.w_k = nn.Linear(d_model, d_model)
        self.w_v = nn.Linear(d_model, d_model)
        self.w_o = nn.Linear(d_model, d_model)
        
        self.attention = ScaledDotProductAttention(temperature=math.sqrt(self.d_k))
        self.dropout = nn.Dropout(dropout)
    
    def forward(self, q, k, v, mask=None):
        batch_size = q.size(0)
        
        # Lineare Projektionen und Aufteilung in Köpfe
        q = self.w_q(q).view(batch_size, -1, self.n_heads, self.d_k).transpose(1, 2)
        k = self.w_k(k).view(batch_size, -1, self.n_heads, self.d_k).transpose(1, 2)
        v = self.w_v(v).view(batch_size, -1, self.n_heads, self.d_k).transpose(1, 2)
        
        # Anwenden der Aufmerksamkeit
        output, attn_weights = self.attention(q, k, v, mask)
        
        # Verketten der Köpfe
        output = output.transpose(1, 2).contiguous().view(batch_size, -1, self.d_model)
        
        # Abschließende lineare Projektion
        output = self.w_o(output)
        
        return output, attn_weights

# Beispielhafte Verwendung
d_model = 512
n_heads = 8
seq_len = 10
batch_size = 2

mha = MultiHeadAttention(d_model, n_heads)
x = torch.randn(batch_size, seq_len, d_model)

# Selbstaufmerksamkeit (q, k, v alle aus x)
output, attn = mha(x, x, x)
print(f"Ausgabeform: {output.shape}")
print(f"Form der Aufmerksamkeitsgewichte: {attn.shape}")

Seltenheit: Sehr häufig Schwierigkeit: Schwer


4. Was sind die Unterschiede zwischen Batch-Normalisierung und Layer-Normalisierung?

Antwort: Beide normalisieren Aktivierungen, aber entlang unterschiedlicher Dimensionen.

  • Batch-Normalisierung:
    • Normalisiert über die Batch-Dimension
    • Erfordert Batch-Statistiken
    • Probleme bei kleinen Batches, RNNs
  • Layer-Normalisierung:
    • Normalisiert über die Feature-Dimension
    • Unabhängig von der Batch-Größe
    • Besser für RNNs, Transformer
import torch
import torch.nn as nn

# Batch-Normalisierung
class BatchNormExample(nn.Module):
    def __init__(self, num_features):
        super().__init__()
        self.bn = nn.BatchNorm1d(num_features)
    
    def forward(self, x):
        # x: (Batch_Size, Num_Features)
        # Normalisiert über die Batch-Dimension für jedes Feature
        return self.bn(x)

# Layer-Normalisierung
class LayerNormExample(nn.Module):
    def __init__(self, normalized_shape):
        super().__init__()
        self.ln = nn.LayerNorm(normalized_shape)
    
    def forward(self, x):
        # x: (Batch_Size, Seq_Len, d_Model)
        # Normalisiert über die Feature-Dimension für jedes Sample
        return self.ln(x)

# Manuelle Implementierung
class ManualLayerNorm(nn.Module):
    def __init__(self, normalized_shape, eps=1e-5):
        super().__init__()
        self.eps = eps
        self.gamma = nn.Parameter(torch.ones(normalized_shape))
        self.beta = nn.Parameter(torch.zeros(normalized_shape))
    
    def forward(self, x):
        # Berechnen von Mittelwert und Varianz über die letzte Dimension
        mean = x.mean(dim=-1, keepdim=True)
        var = x.var(dim=-1, keepdim=True, unbiased=False)
        
        # Normalisieren
        x_norm = (x - mean) / torch.sqrt(var + self.eps)
        
        # Skalieren und verschieben
        return self.gamma * x_norm + self.beta

# Vergleich
batch_size, seq_len, d_model = 2, 10, 512

# Batch-Norm (für CNN)
x_cnn = torch.randn(batch_size, d_model, 28, 28)
bn = nn.BatchNorm2d(d_model)
out_bn = bn(x_cnn)

# Layer-Norm (für Transformer)
x_transformer = torch.randn(batch_size, seq_len, d_model)
ln = nn.LayerNorm(d_model)
out_ln = ln(x_transformer)

print(f"Batch-Norm-Ausgabe: {out_bn.shape}")
print(f"Layer-Norm-Ausgabe: {out_ln.shape}")

Seltenheit: Häufig Schwierigkeit: Mittel


5. Erklären Sie die Transformer-Architektur im Detail.

Antwort: Transformer verwenden Selbstaufmerksamkeit zur Sequenzmodellierung ohne Rekurrenz.

Loading diagram...
  • Komponenten:
    • Encoder: Selbstaufmerksamkeit + FFN
    • Decoder: Maskierte Selbstaufmerksamkeit + Cross-Attention + FFN
    • Positionskodierung: Injizieren von Positionsinformationen
    • Mehrköpfige Aufmerksamkeit: Parallele Aufmerksamkeitsmechanismen
import torch
import torch.nn as nn
import math

class PositionalEncoding(nn.Module):
    def __init__(self, d_model, max_len=5000):
        super().__init__()
        
        # Erstellen einer Positionskodierungsmatrix
        pe = torch.zeros(max_len, d_model)
        position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)
        div_term = torch.exp(torch.arange(0, d_model, 2).float() * 
                            (-math.log(10000.0) / d_model))
        
        pe[:, 0::2] = torch.sin(position * div_term)
        pe[:, 1::2] = torch.cos(position * div_term)
        
        pe = pe.unsqueeze(0)
        self.register_buffer('pe', pe)
    
    def forward(self, x):
        return x + self.pe[:, :x.size(1)]

class TransformerEncoderLayer(nn.Module):
    def __init__(self, d_model, n_heads, d_ff, dropout=0.1):
        super().__init__()
        
        # Mehrköpfige Aufmerksamkeit
        self.self_attn = nn.MultiheadAttention(d_model, n_heads, dropout=dropout)
        
        # Feed-Forward-Netzwerk
        self.ffn = nn.Sequential(
            nn.Linear(d_model, d_ff),
            nn.ReLU(),
            nn.Dropout(dropout),
            nn.Linear(d_ff, d_model)
        )
        
        # Layer-Normalisierung
        self.norm1 = nn.LayerNorm(d_model)
        self.norm2 = nn.LayerNorm(d_model)
        
        self.dropout = nn.Dropout(dropout)
    
    def forward(self, x, mask=None):
        # Selbstaufmerksamkeit mit residualer Verbindung
        attn_output, _ = self.self_attn(x, x, x, attn_mask=mask)
        x = self.norm1(x + self.dropout(attn_output))
        
        # Feed-Forward mit residualer Verbindung
        ffn_output = self.ffn(x)
        x = self.norm2(x + self.dropout(ffn_output))
        
        return x

class TransformerEncoder(nn.Module):
    def __init__(self, vocab_size, d_model, n_heads, d_ff, n_layers, dropout=0.1):
        super().__init__()
        
        self.embedding = nn.Embedding(vocab_size, d_model)
        self.pos_encoding = PositionalEncoding(d_model)
        
        self.layers = nn.ModuleList([
            TransformerEncoderLayer(d_model, n_heads, d_ff, dropout)
            for _ in range(n_layers)
        ])
        
        self.dropout = nn.Dropout(dropout)
    
    def forward(self, x, mask=None):
        # Embedding + Positionskodierung
        x = self.embedding(x) * math.sqrt(self.embedding.embedding_dim)
        x = self.pos_encoding(x)
        x = self.dropout(x)
        
        # Anwenden von Encoderschichten
        for layer in self.layers:
            x = layer(x, mask)
        
        return x

# Beispielhafte Verwendung
vocab_size = 10000
d_model = 512
n_heads = 8
d_ff = 2048
n_layers = 6

encoder = TransformerEncoder(vocab_size, d_model, n_heads, d_ff, n_layers)

# Eingabe: (Batch_Size, Seq_Len)
x = torch.randint(0, vocab_size, (2, 10))
output = encoder(x)
print(f"Ausgabeform: {output.shape}")  # (2, 10, 512)

Seltenheit: Sehr häufig Schwierigkeit: Schwer


Forschungsmethodik (4 Fragen)

6. Wie formulieren Sie ein Forschungsproblem und eine Hypothese?

Antwort: Forschung beginnt mit der Identifizierung von Lücken und der Formulierung testbarer Hypothesen.

  • Schritte:
    1. Literaturrecherche: Verstehen des Stands der Technik
    2. Identifizieren einer Lücke: Was fehlt oder kann verbessert werden?
    3. Formulieren einer Hypothese: Spezifische, testbare Behauptung
    4. Entwerfen von Experimenten: Wie kann die Hypothese getestet werden?
    5. Definieren von Metriken: Wie kann der Erfolg gemessen werden?
  • Beispiel:
    • Lücke: Aktuelle Modelle haben Schwierigkeiten mit Langzeitabhängigkeiten
    • Hypothese: Sparse-Aufmerksamkeit kann die Leistung aufrechterhalten und gleichzeitig die Komplexität reduzieren
    • Experiment: Vergleichen von Sparse- vs. Full-Attention bei langen Sequenzen
    • Metriken: Perplexität, Genauigkeit, Inferenzzeit

Seltenheit: Sehr häufig Schwierigkeit: Mittel


7. Wie entwerfen Sie Ablationsstudien?

Antwort: Ablationsstudien isolieren den Beitrag einzelner Komponenten.

  • Zweck: Verstehen, was das Modell zum Funktionieren bringt
  • Methode: Entfernen/Modifizieren einer Komponente nach der anderen
  • Bewährte Verfahren:
    • Kontrollieren aller anderen Variablen
    • Verwenden derselben Zufalls-Seeds
    • Melden von Konfidenzintervallen
    • Testen auf mehreren Datensätzen
# Beispiel für eine Ablationsstudie
class ModelWithAblations:
    def __init__(self, use_attention=True, use_residual=True, use_dropout=True):
        self.use_attention = use_attention
        self.use_residual = use_residual
        self.use_dropout = use_dropout
    
    def build_model(self):
        layers = []
        
        if self.use_attention:
            layers.append(AttentionLayer())
        
        layers.append(FFNLayer())
        
        if self.use_dropout:
            layers.append(nn.Dropout(0.1))
        
        if self.use_residual:
            return ResidualWrapper(nn.Sequential(*layers))
        else:
            return nn.Sequential(*layers)

# Durchführen von Ablationsexperimenten
configs = [
    {'use_attention': True, 'use_residual': True, 'use_dropout': True},   # Vollständiges Modell
    {'use_attention': False, 'use_residual': True, 'use_dropout': True},  # Keine Aufmerksamkeit
    {'use_attention': True, 'use_residual': False, 'use_dropout': True},  # Keine Residuals
    {'use_attention': True, 'use_residual': True, 'use_dropout': False},  # Kein Dropout
]

results = []
for config in configs:
    model = ModelWithAblations(**config)
    accuracy = train_and_evaluate(model, seed=42)
    results.append({**config, 'accuracy': accuracy})

# Analysieren der Ergebnisse
import pandas as pd
df = pd.DataFrame(results)
print(df)

Seltenheit: Sehr häufig Schwierigkeit: Mittel


8. Wie stellen Sie die Reproduzierbarkeit in der Forschung sicher?

Antwort: Reproduzierbarkeit ist entscheidend für die wissenschaftliche Validität.

  • Bewährte Verfahren:
    • Code: Versionskontrolle, klare Dokumentation
    • Daten: Version, Dokumentieren der Vorverarbeitung
    • Umgebung: Docker, requirements.txt
    • Seeds: Fixieren aller Zufalls-Seeds
    • Hyperparameter: Protokollieren aller Einstellungen
    • Hardware: Dokumentieren der GPU/CPU-Spezifikationen
import random
import numpy as np
import torch
import os

def set_all_seeds(seed=42):
    """Setzen von Seeds für die Reproduzierbarkeit"""
    random.seed(seed)
    np.random.seed(seed)
    torch.manual_seed(seed)
    torch.cuda.manual_seed_all(seed)
    os.environ['PYTHONHASHSEED'] = str(seed)
    
    # Deterministische Operationen
    torch.backends.cudnn.deterministic = True
    torch.backends.cudnn.benchmark = False

# Alles protokollieren
import logging
import json

def log_experiment(config, results):
    experiment_log = {
        'timestamp': datetime.now().isoformat(),
        'config': config,
        'results': results,
        'environment': {
            'python_version': sys.version,
            'torch_version': torch.__version__,
            'cuda_version': torch.version.cuda,
            'gpu': torch.cuda.get_device_name(0) if torch.cuda.is_available() else 'CPU'
        }
    }
    
    with open('experiment_log.json', 'w') as f:
        json.dump(experiment_log, f, indent=2)

# Teilen von Code und Modellen
"""
# README.md
## Reproduzierbarkeit

### Umgebung
```bash
conda create -n research python=3.9
conda activate research
pip install -r requirements.txt

Daten

Herunterladen von: [link] Vorverarbeiten: python preprocess.py

Training

python train.py --config configs/experiment1.yaml --seed 42

Evaluation

python evaluate.py --checkpoint checkpoints/best_model.pt

"""


**Seltenheit:** Sehr häufig
**Schwierigkeit:** Leicht

---

### 9. Wie bewerten und vergleichen Sie Modelle fair?

**Antwort:**
Ein fairer Vergleich erfordert eine sorgfältige Versuchsplanung.
- **Überlegungen:**
    - **Gleiche Datenaufteilungen:** Verwenden identischer Trainings-/Validierungs-/Testdaten
    - **Mehrere Läufe:** Melden von Mittelwert und Standardabweichung
    - **Statistische Tests:** T-Test, Wilcoxon
    - **Rechenkosten:** FLOPs, Parameter, Zeit
    - **Mehrere Metriken:** Keine Rosinenpickerei
    - **Mehrere Datensätze:** Generalisierung

```python
import numpy as np
from scipy import stats

class ModelComparison:
    def __init__(self, n_runs=5):
        self.n_runs = n_runs
        self.results = {}
    
    def evaluate_model(self, model_name, model_fn, X_train, y_train, X_test, y_test):
        scores = []
        
        for seed in range(self.n_runs):
            # Setzen des Seeds für diesen Lauf
            set_all_seeds(seed)
            
            # Trainieren des Modells
            model = model_fn()
            model.fit(X_train, y_train)
            
            # Bewerten
            score = model.score(X_test, y_test)
            scores.append(score)
        
        self.results[model_name] = {
            'scores': scores,
            'mean': np.mean(scores),
            'std': np.std(scores),
            'ci_95': stats.t.interval(
                0.95, len(scores)-1,
                loc=np.mean(scores),
                scale=stats.sem(scores)
            )
        }
    
    def compare_models(self, model_a, model_b):
        """Test auf statistische Signifikanz"""
        scores_a = self.results[model_a]['scores']
        scores_b = self.results[model_b]['scores']
        
        # Gepairter T-Test
        statistic, p_value = stats.ttest_rel(scores_a, scores_b)
        
        return {
            'statistic': statistic,
            'p_value': p_value,
            'significant': p_value < 0.05,
            'better_model': model_a if np.mean(scores_a) > np.mean(scores_b) else model_b
        }
    
    def report(self):
        for model_name, result in self.results.items():
            print(f"\n{model_name}:")
            print(f"  Mean: {result['mean']:.4f}")
            print(f"  Std:  {result['std']:.4f}")
            print(f"  95% CI: [{result['ci_95'][0]:.4f}, {result['ci_95'][1]:.4f}]")

# Verwendung
comparison = ModelComparison(n_runs=10)
comparison.evaluate_model('Model A', lambda: ModelA(), X_train, y_train, X_test, y_test)
comparison.evaluate_model('Model B', lambda: ModelB(), X_train, y_train, X_test, y_test)

comparison.report()
result = comparison.compare_models('Model A', 'Model B')
print(f"\nStatistischer Test: p-Wert = {result['p_value']:.4f}")

Seltenheit: Sehr häufig Schwierigkeit: Mittel


Fortgeschrittene Themen (4 Fragen)

10. Erklären Sie kontrastives Lernen und seine Anwendungen.

Antwort: Kontrastives Lernen lernt Repräsentationen, indem es ähnliche und unähnliche Samples vergleicht.

  • Kernidee: Ziehen Sie ähnliche Samples zusammen, stoßen Sie unähnliche auseinander
  • Verlust: InfoNCE, NT-Xent
  • Anwendungen: SimCLR, MoCo, CLIP
import torch
import torch.nn as nn
import torch.nn.functional as F

class ContrastiveLoss(nn.Module):
    def __init__(self, temperature=0.5):
        super().__init__()
        self.temperature = temperature
    
    def forward(self, features):
        """
        features: (2*Batch_Size, Dim) - Paare von augmentierten Samples
        """
        batch_size = features.shape[0] // 2
        
        # Normalisieren der Features
        features = F.normalize(features, dim=1)
        
        # Berechnen der Ähnlichkeitsmatrix
        similarity_matrix = torch.matmul(features, features.T)
        
        # Erstellen von Labels (positive Paare)
        labels = torch.cat([torch.arange(batch_size) + batch_size,
                           torch.arange(batch_size)]).to(features.device)
        
        # Maske zum Entfernen der Selbstähnlichkeit
        mask = torch.eye(2 * batch_size, dtype=torch.bool).to(features.device)
        similarity_matrix = similarity_matrix.masked_fill(mask, -9e15)
        
        # Berechnen des Verlusts
        similarity_matrix = similarity_matrix / self.temperature
        loss = F.cross_entropy(similarity_matrix, labels)
        
        return loss

class SimCLR(nn.Module):
    def __init__(self, encoder, projection_dim=128):
        super().__init__()
        self.encoder = encoder
        self.projection = nn.Sequential(
            nn.Linear(encoder.output_dim, 512),
            nn.ReLU(),
            nn.Linear(512, projection_dim)
        )
    
    def forward(self, x1, x2):
        # Codieren beider augmentierter Ansichten
        h1 = self.encoder(x1)
        h2 = self.encoder(x2)
        
        # Projizieren in den kontrastiven Raum
        z1 = self.projection(h1)
        z2 = self.projection(h2)
        
        # Verketten für den kontrastiven Verlust
        features = torch.cat([z1, z2], dim=0)
        
        return features

# Trainingsschleife
model = SimCLR(encoder, projection_dim=128)
criterion = ContrastiveLoss(temperature=0.5)
optimizer = torch.optim.Adam(model.parameters())

for epoch in range(100):
    for batch in dataloader:
        # Abrufen von zwei augmentierten Ansichten
        x1, x2 = augment(batch)
        
        # Vorwärtsdurchlauf
        features = model(x1, x2)
        loss = criterion(features)
        
        # Rückwärtsdurchlauf
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

Seltenheit: Häufig Schwierigkeit: Schwer


11. Was sind Vision Transformer (ViT) und wie funktionieren sie?

Antwort: Vision Transformer wenden die Transformer-Architektur auf Bilder an.

  • Kernideen:
    • Aufteilen des Bildes in Patches
    • Lineares Embedding der Patches
    • Hinzufügen von Positions-Embeddings
    • Anwenden des Transformer-Encoders
  • Vorteile: Skalierbarkeit, globales rezeptives Feld
  • Herausforderungen: Erfordern große Datensätze
import torch
import torch.nn as nn

class PatchEmbedding(nn.Module):
    def __init__(self, img_size=224, patch_size=16, in_channels=3, embed_dim=768):
        super().__init__()
        self.img_size = img_size
        self.patch_size = patch_size
        self.n_patches = (img_size // patch_size) ** 2
Newsletter subscription

Wöchentliche Karrieretipps, die wirklich funktionieren

Erhalten Sie die neuesten Einblicke direkt in Ihr Postfach

Decorative doodle

Hören Sie auf, sich zu bewerben. Beginnen Sie, eingestellt zu werden.

Verwandeln Sie Ihren Lebenslauf in einen Vorstellungsgespräch-Magneten mit KI-gestützter Optimierung, der von Arbeitssuchenden weltweit vertraut wird.

Kostenlos starten

Diesen Beitrag teilen

Werden Sie 50% Schneller Eingestellt

Arbeitssuchende mit professionellen, KI-optimierten Lebensläufen finden in durchschnittlich 5 Wochen eine Stelle, verglichen mit den üblichen 10. Hören Sie auf zu warten und beginnen Sie mit Vorstellungsgesprächen.