dezembro 21, 2025
15 min de leitura

Perguntas de Entrevista para Cientista de Dados Sênior sobre ML, Produto e MLOps

interview
career-advice
job-search
Perguntas de Entrevista para Cientista de Dados Sênior sobre ML, Produto e MLOps
Milad Bonakdar

Milad Bonakdar

Autor

Prepare-se para entrevistas sênior com perguntas práticas sobre tradeoffs de ML, engenharia de atributos, implantação, monitoramento, testes A/B e decisões de negócio.


Introdução

Em uma entrevista para cientista de dados sênior, prepare-se para explicar não só como os modelos funcionam, mas como você os escolhe, coloca em produção, monitora e comunica. Boas respostas conectam tradeoffs estatísticos a métricas de produto, qualidade dos dados, restrições de implantação e decisões das partes interessadas.

Use este guia para praticar os temas que costumam separar candidatos seniores de perfis intermediários: viés e variância, desenho de atributos, dados desbalanceados, monitoramento de modelos, testes A/B, MLOps e fundamentos de deep learning. Ao responder, acrescente um exemplo de projeto, o risco que você controlou e a métrica que acompanharia após o lançamento.


Aprendizado de Máquina Avançado (6 Perguntas)

1. Explique o tradeoff bias-variance.

Resposta: O tradeoff bias-variance descreve a relação entre a complexidade do modelo e o erro de previsão.

  • Bias (Viés): Erro de simplificar demais as suposições (underfitting)
  • Variance (Variância): Erro de sensibilidade às flutuações dos dados de treinamento (overfitting)
  • Tradeoff: Diminuir o bias aumenta a variância e vice-versa
  • Objetivo: Encontrar o equilíbrio ideal que minimize o erro total
Loading diagram...
import numpy as np
from sklearn.model_selection import learning_curve
from sklearn.tree import DecisionTreeRegressor
import matplotlib.pyplot as plt

# Gerar dados
X = np.random.rand(100, 1) * 10
y = 2 * X + 3 + np.random.randn(100, 1) * 2

# Modelo de alto bias (max_depth=1)
high_bias = DecisionTreeRegressor(max_depth=1)

# Modelo de alta variância (max_depth=20)
high_variance = DecisionTreeRegressor(max_depth=20)

# Modelo ideal (max_depth=3)
optimal = DecisionTreeRegressor(max_depth=3)

# As curvas de aprendizado mostram o tradeoff bias-variance
train_sizes, train_scores, val_scores = learning_curve(
    optimal, X, y.ravel(), cv=5, train_sizes=np.linspace(0.1, 1.0, 10)
)

print(f"Score de treinamento: {train_scores.mean():.2f}")
print(f"Score de validação: {val_scores.mean():.2f}")

Raridade: Muito Comum Dificuldade: Difícil


2. O que é regularização e explique a regularização L1 vs L2.

Resposta: A regularização adiciona um termo de penalidade à função de perda para evitar o overfitting.

  • L1 (Lasso):
    • Penalidade: Soma dos valores absolutos dos coeficientes
    • Efeito: Modelos esparsos (alguns coeficientes tornam-se exatamente 0)
    • Uso: Seleção de recursos
  • L2 (Ridge):
    • Penalidade: Soma dos coeficientes quadrados
    • Efeito: Diminui os coeficientes em direção a 0 (mas não exatamente 0)
    • Uso: Quando todos os recursos são potencialmente relevantes
  • Elastic Net: Combina L1 e L2
from sklearn.linear_model import Lasso, Ridge, ElasticNet
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
import numpy as np

# Gerar dados com muitos recursos
X, y = make_regression(n_samples=100, n_features=20, n_informative=10, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)

# Regularização L1 (Lasso)
lasso = Lasso(alpha=1.0)
lasso.fit(X_train, y_train)
print(f"Coeficientes Lasso: {np.sum(lasso.coef_ != 0)} não zero de {len(lasso.coef_)}")

# Regularização L2 (Ridge)
ridge = Ridge(alpha=1.0)
ridge.fit(X_train, y_train)
print(f"Coeficientes Ridge: {np.sum(ridge.coef_ != 0)} não zero de {len(ridge.coef_)}")

# Elastic Net (L1 + L2)
elastic = ElasticNet(alpha=1.0, l1_ratio=0.5)
elastic.fit(X_train, y_train)

print(f"\nScore Lasso: {lasso.score(X_test, y_test):.3f}")
print(f"Score Ridge: {ridge.score(X_test, y_test):.3f}")
print(f"Score Elastic Net: {elastic.score(X_test, y_test):.3f}")

Raridade: Muito Comum Dificuldade: Média


3. Explique os métodos de ensemble: Bagging vs Boosting.

Resposta: Os métodos de ensemble combinam vários modelos para melhorar o desempenho.

  • Bagging (Bootstrap Aggregating):
    • Treinar modelos em paralelo em subconjuntos aleatórios
    • Reduz a variância
    • Exemplo: Random Forest
  • Boosting:
    • Treinar modelos sequencialmente, cada um corrigindo erros anteriores
    • Reduz o bias
    • Exemplos: AdaBoost, Gradient Boosting, XGBoost
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split, cross_val_score

# Carregar dados
data = load_breast_cancer()
X_train, X_test, y_train, y_test = train_test_split(
    data.data, data.target, test_size=0.3, random_state=42
)

# Bagging - Random Forest
rf = RandomForestClassifier(n_estimators=100, random_state=42)
rf.fit(X_train, y_train)
rf_score = rf.score(X_test, y_test)

# Boosting - Gradient Boosting
gb = GradientBoostingClassifier(n_estimators=100, random_state=42)
gb.fit(X_train, y_train)
gb_score = gb.score(X_test, y_test)

print(f"Precisão do Random Forest (Bagging): {rf_score:.3f}")
print(f"Precisão do Gradient Boosting: {gb_score:.3f}")

# Validação cruzada
rf_cv = cross_val_score(rf, data.data, data.target, cv=5)
gb_cv = cross_val_score(gb, data.data, data.target, cv=5)

print(f"\nScores CV do RF: {rf_cv.mean():.3f} (+/- {rf_cv.std():.3f})")
print(f"\nScores CV do GB: {gb_cv.mean():.3f} (+/- {gb_cv.std():.3f})")

Raridade: Muito Comum Dificuldade: Difícil


4. O que é validação cruzada e por que o k-fold é melhor do que a divisão treino-teste?

Resposta: A validação cruzada avalia o desempenho do modelo de forma mais robusta do que uma única divisão treino-teste.

  • K-Fold CV:
    • Divide os dados em k folds
    • Treina k vezes, cada vez usando um fold diferente como validação
    • Calcula a média dos resultados
  • Benefícios:
    • Estimativa de desempenho mais confiável
    • Usa todos os dados para treinamento e validação
    • Reduz a variância na estimativa de desempenho
  • Variações: Stratified K-Fold, Leave-One-Out, Time Series Split
from sklearn.model_selection import cross_val_score, KFold, StratifiedKFold
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_iris

data = load_iris()
X, y = data.data, data.target

model = LogisticRegression(max_iter=200)

# K-Fold padrão
kfold = KFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_val_score(model, X, y, cv=kfold)
print(f"Scores CV K-Fold: {scores}")
print(f"Média: {scores.mean():.3f} (+/- {scores.std():.3f})")

# K-Fold estratificado (preserva a distribuição da classe)
stratified_kfold = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
stratified_scores = cross_val_score(model, X, y, cv=stratified_kfold)
print(f"\nScores CV K-Fold estratificado: {stratified_scores}")
print(f"Média: {stratified_scores.mean():.3f} (+/- {stratified_scores.std():.3f})")

# Validação cruzada personalizada
from sklearn.model_selection import cross_validate

cv_results = cross_validate(
    model, X, y, cv=5,
    scoring=['accuracy', 'precision_macro', 'recall_macro'],
    return_train_score=True
)

print(f"\nPrecisão do teste: {cv_results['test_accuracy'].mean():.3f}")
print(f"Precisão do teste: {cv_results['test_precision_macro'].mean():.3f}")
print(f"Recall do teste: {cv_results['test_recall_macro'].mean():.3f}")

Raridade: Muito Comum Dificuldade: Média


5. Explique as técnicas de redução de dimensionalidade (PCA, t-SNE).

Resposta: A redução de dimensionalidade reduz o número de recursos, preservando as informações.

  • PCA (Principal Component Analysis):
    • Transformação linear
    • Encontra direções de máxima variância
    • Preserva a estrutura global
    • Rápido, interpretável
  • t-SNE (t-Distributed Stochastic Neighbor Embedding):
    • Transformação não linear
    • Preserva a estrutura local
    • Bom para visualização
    • Mais lento, não para extração de recursos
from sklearn.decomposition import PCA
from sklearn.manifold import TSNE
from sklearn.datasets import load_digits
import matplotlib.pyplot as plt

# Carregar dados de alta dimensão
digits = load_digits()
X, y = digits.data, digits.target

print(f"Formato original: {X.shape}")

# PCA - reduzir para 2 dimensões
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X)
print(f"Formato PCA: {X_pca.shape}")
print(f"Taxa de variância explicada: {pca.explained_variance_ratio_}")
print(f"Variância total explicada: {pca.explained_variance_ratio_.sum():.3f}")

# t-SNE - reduzir para 2 dimensões
tsne = TSNE(n_components=2, random_state=42)
X_tsne = tsne.fit_transform(X)
print(f"Formato t-SNE: {X_tsne.shape}")

# PCA para extração de recursos (manter 95% da variância)
pca_95 = PCA(n_components=0.95)
X_reduced = pca_95.fit_transform(X)
print(f"\nComponentes para 95% da variância: {pca_95.n_components_}")
print(f"Formato reduzido: {X_reduced.shape}")

Raridade: Comum Dificuldade: Difícil


6. O que é a curva ROC e AUC? Quando você a usaria?

Resposta: A curva ROC (Receiver Operating Characteristic) plota a taxa de verdadeiros positivos versus a taxa de falsos positivos em vários limiares.

  • AUC (Area Under Curve): Métrica única que resume o ROC
    • AUC = 1.0: Classificador perfeito
    • AUC = 0.5: Classificador aleatório
    • AUC < 0.5: Pior que aleatório
  • Casos de uso:
    • Comparar modelos
    • Conjuntos de dados desequilibrados
    • Quando você precisa escolher um limite
from sklearn.metrics import roc_curve, roc_auc_score, auc
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_breast_cancer
import matplotlib.pyplot as plt

# Carregar dados
data = load_breast_cancer()
X_train, X_test, y_train, y_test = train_test_split(
    data.data, data.target, test_size=0.3, random_state=42
)

# Treinar modelo
model = LogisticRegression(max_iter=10000)
model.fit(X_train, y_train)

# Obter previsões de probabilidade
y_pred_proba = model.predict_proba(X_test)[:, 1]

# Calcular a curva ROC
fpr, tpr, thresholds = roc_curve(y_test, y_pred_proba)
roc_auc = auc(fpr, tpr)

print(f"AUC: {roc_auc:.3f}")

# Alternativa: cálculo direto da AUC
auc_score = roc_auc_score(y_test, y_pred_proba)
print(f"AUC (direto): {auc_score:.3f}")

# Encontrar o limite ideal (estatística J de Youden)
optimal_idx = np.argmax(tpr - fpr)
optimal_threshold = thresholds[optimal_idx]
print(f"Limite ideal: {optimal_threshold:.3f}")

Raridade: Muito Comum Dificuldade: Média


Engenharia de Recursos (4 Perguntas)

7. Quais técnicas você usa para engenharia de recursos?

Resposta: A engenharia de recursos cria novos recursos a partir de dados existentes para melhorar o desempenho do modelo.

  • Técnicas:
    • Codificação: One-hot, label, target encoding
    • Escalonamento: StandardScaler, MinMaxScaler
    • Binning: Discretizar variáveis contínuas
    • Recursos polinomiais: Termos de interação
    • Específicos do domínio: Recursos de data, recursos de texto
    • Agregações: Estatísticas de grupo
from sklearn.preprocessing import StandardScaler, OneHotEncoder, PolynomialFeatures
import pandas as pd
import numpy as np

# Dados de amostra
df = pd.DataFrame({
    'age': [25, 30, 35, 40, 45],
    'salary': [50000, 60000, 75000, 80000, 90000],
    'department': ['IT', 'HR', 'IT', 'Finance', 'HR'],
    'date': pd.date_range('2023-01-01', periods=5)
})

# Codificação One-hot
df_encoded = pd.get_dummies(df, columns=['department'], prefix='dept')

# Escalonamento
scaler = StandardScaler()
df_encoded[['age_scaled', 'salary_scaled']] = scaler.fit_transform(
    df_encoded[['age', 'salary']]
)

# Binning
df_encoded['age_group'] = pd.cut(df['age'], bins=[0, 30, 40, 100], labels=['young', 'mid', 'senior'])

# Recursos de data
df_encoded['year'] = df['date'].dt.year
df_encoded['month'] = df['date'].dt.month
df_encoded['day_of_week'] = df['date'].dt.dayofweek

# Recursos polinomiais
poly = PolynomialFeatures(degree=2, include_bias=False)
poly_features = poly.fit_transform(df[['age', 'salary']])

# Recursos de interação
df_encoded['age_salary_interaction'] = df['age'] * df['salary']

print(df_encoded.head())

Raridade: Muito Comum Dificuldade: Média


8. Como você lida com conjuntos de dados desequilibrados?

Resposta: Conjuntos de dados desequilibrados têm distribuições de classe desiguais, o que pode influenciar os modelos.

  • Técnicas:
    • Reamostragem:
      • Oversampling da classe minoritária (SMOTE)
      • Undersampling da classe majoritária
    • Pesos de classe: Penalizar a classificação incorreta da classe minoritária
    • Métodos de ensemble: Random Forest balanceado
    • Avaliação: Use precisão, recall, F1, não apenas precisão
    • Detecção de anomalias: Tratar a minoria como anomalia
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report, confusion_matrix
from imblearn.over_sampling import SMOTE
from imblearn.under_sampling import RandomUnderSampler

# Criar conjunto de dados desequilibrado
X, y = make_classification(
    n_samples=1000, n_features=20, n_informative=15,
    n_classes=2, weights=[0.9, 0.1], random_state=42
)

print(f"Distribuição de classe: {np.bincount(y)}")

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# 1. Sem lidar com o desequilíbrio
model_baseline = LogisticRegression()
model_baseline.fit(X_train, y_train)
y_pred_baseline = model_baseline.predict(X_test)
print("\nBaseline (sem tratamento):")
print(classification_report(y_test, y_pred_baseline))

# 2. SMOTE (Synthetic Minority Over-sampling)
smote = SMOTE(random_state=42)
X_train_smote, y_train_smote = smote.fit_resample(X_train, y_train)
print(f"\nApós SMOTE: {np.bincount(y_train_smote)}")

model_smote = LogisticRegression()
model_smote.fit(X_train_smote, y_train_smote)
y_pred_smote = model_smote.predict(X_test)
print("\nCom SMOTE:")
print(classification_report(y_test, y_pred_smote))

# 3. Pesos de classe
model_weighted = LogisticRegression(class_weight='balanced')
model_weighted.fit(X_train, y_train)
y_pred_weighted = model_weighted.predict(X_test)
print("\nCom pesos de classe:")
print(classification_report(y_test, y_pred_weighted))

Raridade: Muito Comum Dificuldade: Média


9. Explique as técnicas de seleção de recursos.

Resposta: A seleção de recursos identifica os recursos mais relevantes para a modelagem.

  • Métodos:
    • Métodos de filtro: Testes estatísticos (correlação, qui-quadrado)
    • Métodos de wrapper: Eliminação recursiva de recursos (RFE)
    • Métodos incorporados: Lasso, importância de recursos baseada em árvore
    • Redução de dimensionalidade: PCA (diferente da seleção)
from sklearn.feature_selection import SelectKBest, chi2, RFE, SelectFromModel
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_breast_cancer
from sklearn.preprocessing import MinMaxScaler

# Carregar dados
data = load_breast_cancer()
X, y = data.data, data.target

# 1. Método de filtro - SelectKBest com qui-quadrado
X_scaled = MinMaxScaler().fit_transform(X)
selector_chi2 = SelectKBest(chi2, k=10)
X_chi2 = selector_chi2.fit_transform(X_scaled, y)
print(f"Recursos originais: {X.shape[1]}")
print(f"Recursos selecionados (chi2): {X_chi2.shape[1]}")

# 2. Método Wrapper - Eliminação Recursiva de Recursos
rf = RandomForestClassifier(n_estimators=100, random_state=42)
rfe = RFE(estimator=rf, n_features_to_select=10)
X_rfe = rfe.fit_transform(X, y)
print(f"Recursos selecionados (RFE): {X_rfe.shape[1]}")
print(f"Ranking de recursos: {rfe.ranking_}")

# 3. Método incorporado - Importância de recursos baseada em árvore
rf.fit(X, y)
importances = rf.feature_importances_
indices = np.argsort(importances)[::-1]

print("\nTop 10 recursos por importância:")
for i in range(10):
    print(f"{i+1}. {data.feature_names[indices[i]]}: {importances[indices[i]]:.4f}")

# SelectFromModel
selector_model = SelectFromModel(rf, threshold='median', prefit=True)
X_selected = selector_model.transform(X)
print(f"\nRecursos selecionados (importância): {X_selected.shape[1]}")

Raridade: Comum Dificuldade: Média


10. Como você lida com variáveis categóricas com alta cardinalidade?

Resposta: Variáveis categóricas de alta cardinalidade têm muitos valores únicos.

  • Técnicas:
    • Codificação de destino: Substituir pela média do destino
    • Codificação de frequência: Substituir pela frequência
    • Incorporação: Aprender representações densas (redes neurais)
    • Agrupamento: Combinar categorias raras em "Outros"
    • Hashing: Hash para número fixo de buckets
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split

# Dados de amostra com alta cardinalidade
df = pd.DataFrame({
    'city': np.random.choice([f'City_{i}' for i in range(100)], 1000),
    'target': np.random.randint(0, 2, 1000)
})

print(f"Cidades únicas: {df['city'].nunique()}")

# 1. Codificação de destino
target_means = df.groupby('city')['target'].mean()
df['city_target_encoded'] = df['city'].map(target_means)

# 2. Codificação de frequência
freq = df['city'].value_counts()
df['city_frequency'] = df['city'].map(freq)

# 3. Agrupamento de categorias raras
freq_threshold = 10
rare_cities = freq[freq < freq_threshold].index
df['city_grouped'] = df['city'].apply(lambda x: 'Other' if x in rare_cities else x)

print(f"\nApós o agrupamento: {df['city_grouped'].nunique()} valores únicos")

# 4. Codificação de hash (usando a biblioteca category_encoders)
# from category_encoders import HashingEncoder
# encoder = HashingEncoder(cols=['city'], n_components=10)
# df_hashed = encoder.fit_transform(df)

print(df[['city', 'city_target_encoded', 'city_frequency', 'city_grouped']].head())

Raridade: Comum Dificuldade: Difícil


Implementação e Produção de Modelos (4 Perguntas)

11. Como você implementa um modelo de aprendizado de máquina em produção?

Resposta: A implementação de modelos torna os modelos disponíveis para uso no mundo real.

  • Etapas:
    1. Serialização do modelo: Salvar o modelo (pickle, joblib, ONNX)
    2. Desenvolvimento de API: Criar API REST (Flask, FastAPI)
    3. Containerização: Docker para consistência
    4. Implementação: Plataformas de nuvem (AWS, GCP, Azure)
    5. Monitoramento: Rastrear desempenho, drift
    6. CI/CD: Testes e implementação automatizados
# 1. Treinar e salvar o modelo
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris
import joblib

# Treinar modelo
data = load_iris()
model = RandomForestClassifier()
model.fit(data.data, data.target)

# Salvar modelo
joblib.dump(model, 'model.joblib')

# 2. Criar API com FastAPI
from fastapi import FastAPI
import numpy as np

app = FastAPI()

# Carregar modelo
model = joblib.load('model.joblib')

@app.post("/predict")
def predict(features: list):
    # Converter para array numpy
    X = np.array(features).reshape(1, -1)
    prediction = model.predict(X)
    probability = model.predict_proba(X)
    
    return {
        "prediction": int(prediction[0]),
        "probability": probability[0].tolist()
    }

# 3. Dockerfile
"""
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
"""

# 4. Uso
# curl -X POST "http://localhost:8000/predict" \
#      -H "Content-Type: application/json" \
#      -d '{"features": [5.1, 3.5, 1.4, 0.2]}'

Raridade: Muito Comum Dificuldade: Difícil


12. O que é monitoramento de modelo e por que é importante?

Resposta: O monitoramento do modelo rastreia o desempenho do modelo em produção.

  • O que monitorar:
    • Métricas de desempenho: Precisão, precisão, recall
    • Data Drift: Alterações na distribuição de entrada
    • Concept Drift: Alterações na relação de destino
    • Métricas do sistema: Latência, taxa de transferência, erros
  • Ações:
    • Alertas quando o desempenho se degrada
    • Retreinar com novos dados
    • Testes A/B de novos modelos
import numpy as np
from scipy import stats

# Simular dados de produção
training_data = np.random.normal(0, 1, 1000)
production_data = np.random.normal(0.5, 1.2, 1000)  # Deriva

# Detectar data drift usando o teste de Kolmogorov-Smirnov
statistic, p_value = stats.ks_2samp(training_data, production_data)

print(f"Estatística KS: {statistic:.4f}")
print(f"Valor P: {p_value:.4f}")

if p_value < 0.05:
    print("Data drift detectado! Considere retreinar o modelo.")
else:
    print("Nenhuma deriva significativa detectada.")

# Monitorar o desempenho do modelo
class ModelMonitor:
    def __init__(self, model):
        self.model = model
        self.predictions = []
        self.actuals = []
        
    def log_prediction(self, X, y_pred, y_true=None):
        self.predictions.append(y_pred)
        if y_true is not None:
            self.actuals.append(y_true)
    
    def get_accuracy(self):
        if len(self.actuals) == 0:
            return None
        return np.mean(np.array(self.predictions) == np.array(self.actuals))
    
    def check_drift(self, new_data, reference_data):
        statistic, p_value = stats.ks_2samp(new_data, reference_data)
        return p_value < 0.05

# Uso
monitor = ModelMonitor(model)
# monitor.log_prediction(X, y_pred, y_true)
# accuracy = monitor.get_accuracy()

Raridade: Comum Dificuldade: Média


13. Explique o teste A/B no contexto do aprendizado de máquina.

Resposta: O teste A/B compara duas versões (controle versus tratamento) para determinar qual tem melhor desempenho.

  • Processo:
    1. Dividir o tráfego aleatoriamente
    2. Servir modelos diferentes para cada grupo
    3. Coletar métricas
    4. Teste estatístico para determinar o vencedor
  • Métricas: Taxa de conversão, receita, engajamento
  • Testes estatísticos: teste t, qui-quadrado, métodos Bayesianos
import numpy as np
from scipy import stats

# Simular resultados de teste A/B
# Grupo de controle (Modelo A)
control_conversions = 520
control_visitors = 10000

# Grupo de tratamento (Modelo B)
treatment_conversions = 580
treatment_visitors = 10000

# Calcular taxas de conversão
control_rate = control_conversions / control_visitors
treatment_rate = treatment_conversions / treatment_visitors

print(f"Taxa de conversão de controle: {control_rate:.4f}")
print(f"Taxa de conversão de tratamento: {treatment_rate:.4f}")
print(f"Aumento: {((treatment_rate - control_rate) / control_rate * 100):.2f}%")

# Teste de significância estatística (teste z de duas proporções)
pooled_rate = (control_conversions + treatment_conversions) / (control_visitors + treatment_visitors)
se = np.sqrt(pooled_rate * (1 - pooled_rate) * (1/control_visitors + 1/treatment_visitors))
z_score = (treatment_rate - control_rate) / se
p_value = 2 * (1 - stats.norm.cdf(abs(z_score)))

print(f"\nZ-score: {z_score:.4f}")
print(f"Valor P: {p_value:.4f}")

if p_value < 0.05:
    print("O resultado é estatisticamente significativo!")
    if treatment_rate > control_rate:
        print("O tratamento (Modelo B) é melhor.")
    else:
        print("O controle (Modelo A) é melhor.")
else:
    print("Nenhuma diferença estatisticamente significativa.")

# Cálculo do tamanho da amostra
from statsmodels.stats.power import zt_ind_solve_power

required_sample = zt_ind_solve_power(
    effect_size=0.02,  # Efeito mínimo detectável
    alpha=0.05,
    power=0.8,
    alternative='two-sided'
)
print(f"\nTamanho da amostra necessário por grupo: {int(required_sample)}")

Raridade: Comum Dificuldade: Difícil


14. O que é MLOps e por que é importante?

Resposta: MLOps (Machine Learning Operations) aplica princípios de DevOps a sistemas de ML.

  • Componentes:
    • Controle de versão: Código, dados, modelos
    • Testes automatizados: Testes de unidade, integração, modelo
    • Pipelines CI/CD: Implantação automatizada
    • Monitoramento: Desempenho, detecção de drift
    • Reprodutibilidade: Rastreamento de experimentos
  • Ferramentas: MLflow, Kubeflow, DVC, Weights & Biases
# Exemplo: MLflow para rastreamento de experimentos
import mlflow
import mlflow.sklearn
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

# Carregar dados
data = load_iris()
X_train, X_test, y_train, y_test = train_test_split(
    data.data, data.target, test_size=0.3, random_state=42
)

# Iniciar execução MLflow
with mlflow.start_run():
    # Registrar parâmetros
    n_estimators = 100
    max_depth = 5
    mlflow.log_param("n_estimators", n_estimators)
    mlflow.log_param("max_depth", max_depth)
    
    # Treinar modelo
    model = RandomForestClassifier(
        n_estimators=n_estimators,
        max_depth=max_depth,
        random_state=42
    )
    model.fit(X_train, y_train)
    
    # Avaliar
    y_pred = model.predict(X_test)
    accuracy = accuracy_score(y_test, y_pred)
    
    # Registrar métricas
    mlflow.log_metric("accuracy", accuracy)
    
    # Registrar modelo
    mlflow.sklearn.log_model(model, "random_forest_model")
    
    print(f"Precisão: {accuracy:.3f}")
    print(f"ID da execução: {mlflow.active_run().info.run_id}")

# Controle de versão com DVC
"""
# Inicializar DVC
dvc init

# Rastrear dados
dvc add data/train.csv
git add data/train.csv.dvc .gitignore
Newsletter subscription

Dicas de carreira semanais que realmente funcionam

Receba as últimas ideias diretamente na sua caixa de entrada

Destaque-se para Recrutadores e Conquiste o Emprego dos Seus Sonhos

Junte-se a milhares que transformaram suas carreiras com currículos impulsionados por IA que passam no ATS e impressionam gerentes de contratação.

Comece a criar agora

Compartilhar esta publicação

Seja Contratado 50% Mais Rápido

Candidatos que usam currículos profissionais aprimorados por IA conseguem vagas em uma média de 5 semanas comparado às 10 padrão. Pare de esperar e comece a fazer entrevistas.