Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Realizar identificação de parentesco #33

Closed
vitalwarley opened this issue Aug 20, 2023 · 13 comments
Closed

Realizar identificação de parentesco #33

vitalwarley opened this issue Aug 20, 2023 · 13 comments
Assignees

Comments

@vitalwarley
Copy link
Owner

No description provided.

@vitalwarley vitalwarley self-assigned this Aug 20, 2023
vitalwarley added a commit that referenced this issue Aug 23, 2023
- Adapt `FIW` dataset to return kinship relation
- Copy `train.py` in a new `train_classification.py` to modify training
  loop.

Ref.: #33
@vitalwarley
Copy link
Owner Author

vitalwarley commented Aug 23, 2023

Deixei um treinamento rodando de ontem para hoje e obtive os resultados abaixo. Esse treinamento devia ter ido até a época 160, mas parou na 107, porque os pares de treino acabaram. A razão é que os autores originais fizeram assim. No treinamento para verificação de parentesco, por exemplo, parece que cada par é visto apenas uma vez pelo modelo. Talvez para nosso classo possamos mudar?

plot_v2

Minhas mudanças foram pontuais nos códigos originais

  • Adicionei uma camada de classificação que projeta as embeddings concatenadas para 11 unidades de saída (número de relações)
    • Inicializei-a da mesma forma que os autores inicializam a camada de projeção
  • Troquei a perda contrastiva pela perda de entropia cruzada (cross-entropy)
  • Ajustei o dataset para retornar o tipo de relação
  • Troquei a métrica de AUC para Acurácia

Mantive todo o resto, como SGD com lr=1e-4 e momento = 0.9.

@vitalwarley
Copy link
Owner Author

vitalwarley commented Aug 23, 2023

Permiti que o modelo usasse todo o dataset a cada época e o deixei treinando por 20 épocas na RIG2. Resultados abaixo são insatisfatórios, eu penso.

plot_v3

@vitalwarley
Copy link
Owner Author

vitalwarley commented Aug 24, 2023

Havia inserido uma camada dentro da sequência de classificação

        self.classification = nn.Sequential(
            torch.nn.BatchNorm1d(256),
            torch.nn.ReLU(),
            # add linear, bn1d, relu
            torch.nn.Linear(256, 128), 
            torch.nn.BatchNorm1d(128),
            torch.nn.ReLU(),
            torch.nn.Linear(128, 11),  # number of kin relations
        )

todavia os resultados não melhoraram

plot_v4

O treinamento foi na RIG2, com bs=60, epochs=20, onde cada época vê o dataset. Enquanto escrevo isso, lembro que os dados de treino não são aleatórios. Vou modificar e retreinar.

vitalwarley added a commit that referenced this issue Aug 24, 2023
@vitalwarley
Copy link
Owner Author

Melhorou, mas piorou logo depois.

plot_v5

vitalwarley added a commit that referenced this issue Aug 27, 2023
Also simplified classification layer.

Ref.: #33
@vitalwarley
Copy link
Owner Author

vitalwarley commented Aug 27, 2023

Após a call de sexta, foi identificado os alguns problemas

  • "Esqueci" o softmax após a última camada linear, todavia nn.CrossEntropyLoss espera os logits mesmo -- penso que eu tinha tido essa dúvida, e acabei lendo a doc para decidir.
  • Esqueci de modificar o dataset para que os pares não-parentes formassem uma classe non_kin -- atualmente a classe pode ser qualquer uma para qualquer par, isso é, apenas 11 classes são possíveis.

Após resolver (2e89a1e) esse segundo item, os resultados foram "piores" -- faz sentido, dado que a tarefa ficou mais difícil. Vale ressaltar que o dataset é bem desbalanceado, onde, por exemplo, há 10k amostras para o tipo de parentesco fs, mas menos de 1k para gmgs. Considerando todos os pares e tipos de relacionamentos, temos ainda cerca de 50k non-kin.

plot

@vitalwarley
Copy link
Owner Author

vitalwarley commented Aug 30, 2023

Vou tentar novamente, mas filtrando os quatro pares mais frequentes.

image

vitalwarley added a commit that referenced this issue Aug 30, 2023
Enable class filtering.

Also, add histogram for kinship relations (non-kin included).

Ref.: #33
@vitalwarley
Copy link
Owner Author

vitalwarley commented Aug 30, 2023

Em 12 épocas, a acurácia estagnou em <0.447. Usei apenas as classes: fs, ms, md, fd. Nem non-kin usei -- sem querer. Isso mostra que a tarefa é complexa demais e/ou o modelo é incapaz de aprender os padrões.

@vitalwarley
Copy link
Owner Author

Em 12 épocas, a acurácia estagnou em <0.447. Usei apenas as classes: fs, ms, md, fd. Nem non-kin usei -- sem querer. Isso mostra que a tarefa é complexa demais e/ou o modelo é incapaz de aprender os padrões.

Esse resultado está enviesado porque faltou modificar a saída do modelo.

@vitalwarley vitalwarley changed the title Realizar classificação de parentesco Realizar multiclassificação de parentesco Sep 1, 2023
@vitalwarley vitalwarley changed the title Realizar multiclassificação de parentesco Realizar identificação de parentesco Sep 1, 2023
@vitalwarley
Copy link
Owner Author

Após corrigir o viés acima, isso é, ajustar a saída da rede para o número de classes corretamente, eu repliquei o treinamento de identificação das classes fs, ms, md, fd. Abaixo o resultado

20230902_100025

@vitalwarley
Copy link
Owner Author

Pensei que havia pares non-kin no set de treino, mas não há. Apenas nos sets de validação e teste.

@vitalwarley
Copy link
Owner Author

vitalwarley commented Sep 4, 2023

Pensei que havia pares non-kin no set de treino, mas não há. Apenas nos sets de validação e teste.

A razão para tal está na seção III do artigo

image

In our supervised contrastive learning framework, negative samples are collected by combining positive samples from different families. Typically, the contrastive loss makes samples belonging to the same family close to each other in the feature space, while samples belonging to different families are separated from each other. The hyper-parameter τ is used to control the degree of punishment for hard samples, and the smaller the value of τ , the greater the degree of punishment for hard samples.

def contrastive_loss(x1,x2,beta=0.08):
x1x2=torch.cat([x1,x2],dim=0)
x2x1=torch.cat([x2,x1],dim=0)
cosine_mat=torch.cosine_similarity(torch.unsqueeze(x1x2,dim=1),
torch.unsqueeze(x1x2,dim=0),dim=2)/beta
mask=1.0-torch.eye(2*x1.size(0))
numerators = torch.exp(torch.cosine_similarity(x1x2,x2x1,dim=1)/beta)
denominators=torch.sum(torch.exp(cosine_mat)*mask,dim=1)
return -torch.mean(torch.log(numerators/denominators),dim=0)

Durante o treinamento, x1 e x2 são batches contendo as imagens do indivíduo 1 e 2, respectivamente. Os autores concatenam os batches duas vezes e formam os tensores x1x2 e x2x1. Em seguida, computa-se a similaridade entre todos pares em x1x2, como exemplificado abaixo. A soma do exponencial da matriz de similaridades ao longo das colunas (exceto nas diagonais) forma o denominador.

image

Posteriormente obtém-se a similaridade entre os tensores x1x2 e x2x1. Dado que o batch contém diferentes famílias, isso é, há apenas uma família por par, essa similaridade é basicamente de pares negativos. O exponencial dos elementos (similaridades) de cada matriz consiste do numerador da fórmula.

A ideia geral, ao meu ver, é que a divisão convirja para de 1 a partir da esquerda tal que o negativo do log se aproxime de 0 pela direita. As similaridades para minimizar maximizar estão no numerador, logo seu valor deve tender a 0 (e.g., e^(-1/beta) < 0.0001, para beta = 0.08) 1. Similarmente, as similaridades para maximizar estão no denomidador; apesar de lá também haver similaridades para minimizar, o exponencial da similaridade dos pares positivos (1 coluna em cada linha, logo 1 de n) são bem maiores que zero (e.g., e^(1/beta) > 10000, para beta = 0.08), enquanto que o exponencial da similaridade dos pares negativos (n - 1 elementos) tende zero. Dessa forma, a soma dos exponenciais é dominada pelos pares positivos, o que maximiza o denominador.

image

Agora a questão é: como inserir informações sobre a diferença de idade (e gênero, possivelmente) nessa perda?

@vitalwarley
Copy link
Owner Author

vitalwarley commented Sep 4, 2023

Na verdade, o numerador deve também ser maximizado. x1x2 e x2x1 contém apenas pares positivos. Considere x1 = (a1, b1, c1), x2 = (a2, b2, c2). Temos, então

  x1x2 x2x1  similaridade
0   a1   a2             1
1   b1   b2             1
2   c1   c2             1
3   a2   a1             1
4   b2   b1             1
5   c2   c1             1

Isso reflete a equação 1 do artigo.

Considerando isso, o numerador deve crescer o máximo possível. Abaixo um gráfico exemplificando o processo

image

Esse outro gráfico mostra o que conseguimos ao variar beta

image

@vitalwarley
Copy link
Owner Author

Será realizada em futuras estratégias ainda, possivelmente.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant