dezembro 21, 2025
14 min de leitura

Perguntas para Entrevista de Cientista de Pesquisa em IA: Guia Completo

interview
career-advice
job-search
Perguntas para Entrevista de Cientista de Pesquisa em IA: Guia Completo
Milad Bonakdar

Milad Bonakdar

Autor

Domine os fundamentos da pesquisa em IA com perguntas essenciais para entrevistas, abrangendo teoria de aprendizado profundo, metodologia de pesquisa, arquiteturas de transformadores, otimização e tópicos de IA de ponta para cientistas de pesquisa.


Introdução

Cientistas de Pesquisa em IA expandem as fronteiras da inteligência artificial por meio de algoritmos, arquiteturas e metodologias inovadoras. Esta função exige profundo conhecimento teórico, sólidas bases matemáticas, experiência em pesquisa e a capacidade de formular e resolver problemas em aberto.

Este guia abrangente aborda as principais perguntas de entrevistas para Cientistas de Pesquisa em IA, abrangendo teoria de aprendizado profundo, arquiteturas de transformadores, técnicas de otimização, metodologia de pesquisa, visão computacional, PNL e tópicos de IA de ponta. Cada pergunta inclui respostas detalhadas, avaliação de raridade e classificações de dificuldade.


Teoria do Aprendizado Profundo (5 Perguntas)

1. Explique o backpropagation e a regra da cadeia em detalhes.

Resposta: O Backpropagation computa gradientes de forma eficiente usando a regra da cadeia.

  • Regra da Cadeia: Para funções compostas, a derivada é o produto das derivadas
  • Passagem Direta (Forward Pass): Calcula as saídas e armazena em cache os valores intermediários
  • Passagem Inversa (Backward Pass): Calcula os gradientes da saída para a entrada
import numpy as np

# Rede neural simples para demonstrar backpropagation
class SimpleNN:
    def __init__(self, input_size, hidden_size, output_size):
        # Inicializa os pesos
        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):
        # Camada 1
        self.z1 = np.dot(X, self.W1) + self.b1
        self.a1 = self.sigmoid(self.z1)
        
        # Camada 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]
        
        # Gradientes da camada de saída
        # dL/da2 = a2 - y (para entropia cruzada binária)
        # 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)
        
        # Gradientes da camada oculta (regra da cadeia)
        # 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)
        
        # Atualiza os pesos
        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):
            # Passagem direta
            output = self.forward(X)
            
            # Passagem inversa
            self.backward(X, y, output)
            
            if epoch % 100 == 0:
                loss = -np.mean(y * np.log(output) + (1-y) * np.log(1-output))
                print(f'Epoch {epoch}, Loss: {loss:.4f}')

# Exemplo de uso
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)

Raridade: Muito Comum Dificuldade: Difícil


2. O que é o problema do desaparecimento do gradiente e como você o resolve?

Resposta: O desaparecimento dos gradientes ocorre quando os gradientes se tornam extremamente pequenos em redes profundas.

  • Causas:
    • Ativações Sigmoid/tanh (derivadas < 1)
    • Redes profundas (gradientes multiplicam)
  • Soluções:
    • Ativações ReLU
    • Normalização em lote (Batch normalization)
    • Conexões residuais (ResNet)
    • LSTM/GRU para RNNs
    • Inicialização cuidadosa (Xavier, He)
import torch
import torch.nn as nn

# Problema: Rede profunda com 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 camadas
        ])
    
    def forward(self, x):
        return self.layers(x)

# Solução 1: Ativação ReLU
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)

# Solução 2: Conexões residuais
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)  # Conexão de salto (Skip connection)

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)

# Solução 3: Normalização em lote (Batch Normalization)
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)

# Análise do fluxo de gradiente
def analyze_gradients(model, x, y):
    model.zero_grad()
    output = model(x)
    loss = nn.MSELoss()(output, y)
    loss.backward()
    
    # Verifica as magnitudes do gradiente
    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}")

Raridade: Muito Comum Dificuldade: Difícil


3. Explique os mecanismos de atenção e autoatenção.

Resposta: A atenção permite que os modelos se concentrem em partes relevantes da entrada.

  • Atenção: Soma ponderada de valores com base na similaridade entre consulta (query) e chave (key)
  • Autoatenção: Atenção onde consulta (query), chave (key) e valor (value) vêm da mesma fonte
  • Atenção de Produto Escalar (Scaled Dot-Product Attention): 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)
        """
        # Calcula as pontuações de atenção
        attn = torch.matmul(q, k.transpose(-2, -1)) / self.temperature
        
        # Aplica a máscara (para padding ou atenção causal)
        if mask is not None:
            attn = attn.masked_fill(mask == 0, -1e9)
        
        # Softmax para obter os pesos de atenção
        attn_weights = F.softmax(attn, dim=-1)
        
        # Aplica a atenção aos valores
        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
        
        # Projeções lineares
        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)
        
        # Projeções lineares e divisão em cabeças
        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)
        
        # Aplica a atenção
        output, attn_weights = self.attention(q, k, v, mask)
        
        # Concatena as cabeças
        output = output.transpose(1, 2).contiguous().view(batch_size, -1, self.d_model)
        
        # Projeção linear final
        output = self.w_o(output)
        
        return output, attn_weights

# Exemplo de uso
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)

# Autoatenção (q, k, v todos de x)
output, attn = mha(x, x, x)
print(f"Output shape: {output.shape}")
print(f"Attention weights shape: {attn.shape}")

Raridade: Muito Comum Dificuldade: Difícil


4. Quais são as diferenças entre normalização em lote (batch normalization) e normalização de camada (layer normalization)?

Resposta: Ambas normalizam as ativações, mas ao longo de dimensões diferentes.

  • Normalização em Lote (Batch Normalization):
    • Normaliza ao longo da dimensão do lote
    • Requer estatísticas do lote
    • Problemas com lotes pequenos, RNNs
  • Normalização de Camada (Layer Normalization):
    • Normaliza ao longo da dimensão da característica
    • Independente do tamanho do lote
    • Melhor para RNNs, Transformers
import torch
import torch.nn as nn

# Normalização em Lote
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)
        # Normaliza ao longo da dimensão do lote para cada característica
        return self.bn(x)

# Normalização de Camada
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)
        # Normaliza ao longo da dimensão da característica para cada amostra
        return self.ln(x)

# Implementação manual
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):
        # Calcula a média e a variância ao longo da última dimensão
        mean = x.mean(dim=-1, keepdim=True)
        var = x.var(dim=-1, keepdim=True, unbiased=False)
        
        # Normaliza
        x_norm = (x - mean) / torch.sqrt(var + self.eps)
        
        # Escala e desloca
        return self.gamma * x_norm + self.beta

# Comparação
batch_size, seq_len, d_model = 2, 10, 512

# Batch Norm (para CNN)
x_cnn = torch.randn(batch_size, d_model, 28, 28)
bn = nn.BatchNorm2d(d_model)
out_bn = bn(x_cnn)

# Layer Norm (para 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 output: {out_bn.shape}")
print(f"Layer Norm output: {out_ln.shape}")

Raridade: Comum Dificuldade: Média


5. Explique a arquitetura do transformador em detalhes.

Resposta: Os transformadores usam autoatenção para modelagem de sequência sem recorrência.

Loading diagram...
  • Componentes:
    • Codificador (Encoder): Autoatenção + FFN
    • Decodificador (Decoder): Autoatenção mascarada + atenção cruzada + FFN
    • Codificação Posicional (Positional Encoding): Injeta informações de posição
    • Atenção Multi-Cabeça (Multi-Head Attention): Mecanismos de atenção paralelos
import torch
import torch.nn as nn
import math

class PositionalEncoding(nn.Module):
    def __init__(self, d_model, max_len=5000):
        super().__init__()
        
        # Cria a matriz de codificação posicional
        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__()
        
        # Atenção multi-cabeça
        self.self_attn = nn.MultiheadAttention(d_model, n_heads, dropout=dropout)
        
        # Rede feed-forward
        self.ffn = nn.Sequential(
            nn.Linear(d_model, d_ff),
            nn.ReLU(),
            nn.Dropout(dropout),
            nn.Linear(d_ff, d_model)
        )
        
        # Normalização de camada
        self.norm1 = nn.LayerNorm(d_model)
        self.norm2 = nn.LayerNorm(d_model)
        
        self.dropout = nn.Dropout(dropout)
    
    def forward(self, x, mask=None):
        # Autoatenção com conexão residual
        attn_output, _ = self.self_attn(x, x, x, attn_mask=mask)
        x = self.norm1(x + self.dropout(attn_output))
        
        # Feed-forward com conexão residual
        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 + codificação posicional
        x = self.embedding(x) * math.sqrt(self.embedding.embedding_dim)
        x = self.pos_encoding(x)
        x = self.dropout(x)
        
        # Aplica as camadas do codificador
        for layer in self.layers:
            x = layer(x, mask)
        
        return x

# Exemplo de uso
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)

# Entrada: (batch_size, seq_len)
x = torch.randint(0, vocab_size, (2, 10))
output = encoder(x)
print(f"Output shape: {output.shape}")  # (2, 10, 512)

Raridade: Muito Comum Dificuldade: Difícil


Metodologia de Pesquisa (4 Perguntas)

6. Como você formula um problema de pesquisa e uma hipótese?

Resposta: A pesquisa começa com a identificação de lacunas e a formulação de hipóteses testáveis.

  • Etapas:
    1. Revisão da Literatura: Entender o estado da arte
    2. Identificar a Lacuna: O que está faltando ou pode ser melhorado?
    3. Formular a Hipótese: Afirmação específica e testável
    4. Projetar Experimentos: Como testar a hipótese?
    5. Definir Métricas: Como medir o sucesso?
  • Exemplo:
    • Lacuna: Os modelos atuais têm dificuldades com dependências de longo alcance
    • Hipótese: A atenção esparsa pode manter o desempenho enquanto reduz a complexidade
    • Experimento: Comparar atenção esparsa vs atenção total em sequências longas
    • Métricas: Perplexidade, precisão, tempo de inferência

Raridade: Muito Comum Dificuldade: Média


7. Como você projeta estudos de ablação?

Resposta: Os estudos de ablação isolam a contribuição de componentes individuais.

  • Propósito: Entender o que faz o modelo funcionar
  • Método: Remover/modificar um componente de cada vez
  • Melhores Práticas:
    • Controlar todas as outras variáveis
    • Usar as mesmas sementes aleatórias
    • Relatar intervalos de confiança
    • Testar em vários conjuntos de dados
# Exemplo de estudo de ablação
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)

# Executa experimentos de ablação
configs = [
    {'use_attention': True, 'use_residual': True, 'use_dropout': True},   # Modelo completo
    {'use_attention': False, 'use_residual': True, 'use_dropout': True},  # Sem atenção
    {'use_attention': True, 'use_residual': False, 'use_dropout': True},  # Sem residual
    {'use_attention': True, 'use_residual': True, 'use_dropout': False},  # Sem dropout
]

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

# Analisa os resultados
import pandas as pd
df = pd.DataFrame(results)
print(df)

Raridade: Muito Comum Dificuldade: Média


8. Como você garante a reprodutibilidade na pesquisa?

Resposta: A reprodutibilidade é fundamental para a validade científica.

  • Melhores Práticas:
    • Código: Controle de versão, documentação clara
    • Dados: Versão, documentar o pré-processamento
    • Ambiente: Docker, requirements.txt
    • Sementes: Fixar todas as sementes aleatórias
    • Hiperparâmetros: Registrar todas as configurações
    • Hardware: Documentar as especificações da GPU/CPU
import random
import numpy as np
import torch
import os

def set_all_seeds(seed=42):
    """Define sementes para reprodutibilidade"""
    random.seed(seed)
    np.random.seed(seed)
    torch.manual_seed(seed)
    torch.cuda.manual_seed_all(seed)
    os.environ['PYTHONHASHSEED'] = str(seed)
    
    # Operações determinísticas
    torch.backends.cudnn.deterministic = True
    torch.backends.cudnn.benchmark = False

# Registrar tudo
import logging
import json

def log_experiment(config, results):
    experiment_log = {
        'timestamp': datetime.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)

# Compartilhar código e modelos
"""
# README.md
## Reprodutibilidade

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

Dados

Baixar de: [link] Pré-processar: python preprocess.py

Treinamento

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

Avaliação

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

"""


**Raridade:** Muito Comum
**Dificuldade:** Fácil

---

### 9. Como você avalia e compara modelos de forma justa?

**Resposta:**
A comparação justa requer um projeto experimental cuidadoso.
- **Considerações:**
    - **Mesmas divisões de dados:** Usar conjuntos de treinamento/validação/teste idênticos
    - **Múltiplas execuções:** Relatar média e desvio padrão
    - **Testes estatísticos:** Teste T, Wilcoxon
    - **Custo computacional:** FLOPs, parâmetros, tempo
    - **Múltiplas métricas:** Não escolher a dedo
    - **Múltiplos conjuntos de dados:** Generalização

```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):
            # Define a semente para esta execução
            set_all_seeds(seed)
            
            # Treina o modelo
            model = model_fn()
            model.fit(X_train, y_train)
            
            # Avalia
            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):
        """Teste de significância estatística"""
        scores_a = self.results[model_a]['scores']
        scores_b = self.results[model_b]['scores']
        
        # Teste T pareado
        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}]")

# Uso
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"\nStatistical test: p-value = {result['p_value']:.4f}")

Raridade: Muito Comum Dificuldade: Média


Tópicos Avançados (4 Perguntas)

10. Explique o aprendizado contrastivo e suas aplicações.

Resposta: O aprendizado contrastivo aprende representações comparando amostras semelhantes e diferentes.

  • Ideia Chave: Aproximar amostras semelhantes, afastar as diferentes
  • Perda (Loss): InfoNCE, NT-Xent
  • Aplicações: 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) - pares de amostras aumentadas
        """
        batch_size = features.shape[0] // 2
        
        # Normaliza as características
        features = F.normalize(features, dim=1)
        
        # Calcula a matriz de similaridade
        similarity_matrix = torch.matmul(features, features.T)
        
        # Cria rótulos (pares positivos)
        labels = torch.cat([torch.arange(batch_size) + batch_size,
                           torch.arange(batch_size)]).to(features.device)
        
        # Máscara para remover a auto-similaridade
        mask = torch.eye(2 * batch_size, dtype=torch.bool).to(features.device)
        similarity_matrix = similarity_matrix.masked_fill(mask, -9e15)
        
        # Calcula a perda
        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):
        # Codifica ambas as visões aumentadas
        h1 = self.encoder(x1)
        h2 = self.encoder(x2)
        
        # Projeta para o espaço contrastivo
        z1 = self.projection(h1)
        z2 = self.projection(h2)
        
        # Concatena para a perda contrastiva
        features = torch.cat([z1, z2], dim=0)
        
        return features

# Loop de treinamento
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:
        # Obtém duas visões aumentadas
        x1, x2 = augment(batch)
        
        # Passagem direta
        features = model(x1, x2)
        loss = criterion(features)
        
        # Passagem inversa
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

Raridade: Comum Dificuldade: Difícil


11. O que são Vision Transformers (ViT) e como eles funcionam?

Resposta: Vision Transformers aplicam a arquitetura de transformadores a imagens.

  • Ideias Chave:
    • Dividir a imagem em patches
    • Incorporação linear de patches
    • Adicionar incorporações posicionais
    • Aplicar o codificador do transformador
  • Vantagens: Escalabilidade, campo receptivo global
  • Desafios: Requer grandes conjuntos de dados
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
        
        # Convol
Newsletter subscription

Dicas de carreira semanais que realmente funcionam

Receba as últimas ideias diretamente na sua caixa de entrada

Pare de Se Candidatar. Comece a Ser Contratado.

Transforme seu currículo em um ímã de entrevistas com otimização impulsionada por IA em que candidatos a emprego em todo o mundo confiam.

Comece grátis

Compartilhar esta publicação

Duplique Seus Retornos de Entrevista

Candidatos que adaptam seus currículos à descrição da vaga obtêm 2,5 vezes mais entrevistas. Use nossa IA para personalizar automaticamente seu CV para cada candidatura instantaneamente.