Questão nº 23
Questão de Ciência de Dados · FGV CVM 2024 (nº 23)
Considere o código python a seguir.
```python
import torch
from torch import nn, Tensor
class CVMNet(nn.Module):
def __init__(self,
dim_in: int,
dim_hidden: int,
n_classes: int):
super().__init__()
self.i_layer = nn.Linear(dim_in, dim_hidden)
self.h_layer = nn.Sequential(
nn.Linear(dim_hidden, dim_hidden // 2),
nn.Tanh()
)
self.o_layer = nn.Sequential(
nn.Dropout(0.2),
nn.Linear(dim_hidden // 2, n_classes),
nn.Softmax(dim=-1)
)
def forward(self, x: Tensor):
return self.o_layer(self.h_layer(self.i_layer(x)))
model = CVMNet(400, 100, 3)
pred = model(torch.eye(20).flatten()).detach()
```
Sobre a variável pred, é correto afirmar que:
- Aseus gradientes foram preparados para a retropropagação;
- Bseus valores, quando somados, resultam em 1.0; (alternativa correta)
- Csua dimensão é 50;
- Dseus valores serão os mesmos para qualquer execução do código;
- Esua dimensão é 1.
Resposta comentada
Gabarito Alternativa B
A função de ativação Softmax é usada em redes neurais para transformar um vetor de números reais em uma distribuição de probabilidades. Isso significa que cada valor de saída estará entre 0 e 1, e a soma de todos os valores de saída será exatamente 1.0, representando a probabilidade de uma entrada pertencer a cada uma das classes disponíveis.
(A) Incorreta: A chamada .detach() na linha pred = model(torch.eye(20).flatten()).detach() serve justamente para remover o tensor pred do grafo de computação, impedindo que seus gradientes sejam calculados ou preparados para a retropropagação. Isso é útil quando você precisa do valor de um tensor, mas não quer que ele contribua para o cálculo de gradientes.
(B) Correta: A camada final da rede (o_layer) inclui nn.Softmax(dim=-1). A função Softmax é projetada para converter as saídas de uma camada linear (logits) em probabilidades. Consequentemente, a soma dos valores resultantes ao longo da dimensão especificada (neste caso, dim=-1, que é a dimensão das classes) será sempre 1.0. Como n_classes é 3, pred terá 3 valores, e a soma desses 3 valores será 1.0.
(C) Incorreta: Vamos rastrear as dimensões:
- Entrada
x:torch.eye(20).flatten()resulta em um tensor de20 * 20 = 400elementos. i_layer:nn.Linear(400, 100)transforma a entrada de 400 para 100 dimensões.h_layer:nn.Linear(100, 100 // 2)transforma de 100 para 50 dimensões (oTanhnão altera a dimensão).o_layer:nn.Linear(50, n_classes)transforma de 50 paran_classes = 3dimensões (oDropoute oSoftmaxnão alteram a dimensão).
Portanto, a dimensão final depredé 3, não 50.
(D) Incorreta: Os pesos e vieses das camadasnn.Linearsão inicializados aleatoriamente por padrão quando o modelo é criado. Além disso, a camadann.Dropout(0.2)introduz aleatoriedade ao zerar 20% das entradas durante oforward(a menos que o modelo esteja no modoeval(), o que não é o caso aqui). Sem fixar uma semente aleatória (torch.manual_seed()) e/ou carregar pesos pré-treinados, os valores depredserão diferentes a cada execução do código.
(E) Incorreta: Conforme explicado na alternativa C, a dimensão final depredé 3, correspondente ao número de classes (n_classes), não 1.
Fonte: FGV CVM 2024 Analista CVM - Ciência de Dados (Perfil 7) (Caderno Tipo 1). Reproduzida para fins de estudo.