File size: 5,480 Bytes
bf91a4a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# dataFunctions.py
# Adaptado para português brasileiro com BERTimbau
# Original: Alcalde-Llergo et al. (2025)

import os
import numpy as np
import config
# torch e transformers são usados apenas em getBERTimbauEmbeddings()
# (etapa de treino). O import fica dentro da função para não exigir
# essas dependências pesadas em produção (app de inferência).


def getData(filename):
    """Lê o captions.txt e retorna dicionário {imagem: legenda} e tamanho máximo."""
    data       = dict()
    max_length = 0

    with open(filename, 'r', encoding='utf-8') as f:
        for line in f.read().split('\n'):
            line = line.split()
            if len(line) < 2:
                continue
            image      = line[0]
            caption    = line[1:]
            max_length = max(max_length, len(caption))
            if image not in data:
                data[image] = ' '.join(caption)

    max_length += 2  # espaço para tokens START e STOP
    return data, max_length


def getLexicon(data):
    """Extrai vocabulário único de todas as legendas."""
    lex = set()
    for key in data:
        [lex.update(d.split()) for d in data[key].split()]
    lex.update(config.START.split())
    lex.update(config.STOP.split())
    return lex


def getDataArrays(data, train_list):
    """Lê lista de imagens e retorna arrays de imagens e legendas com START/STOP."""
    images_array   = []
    captions_array = []

    with open(train_list, 'r', encoding='utf-8') as f:
        for image in f.read().split('\n'):
            image = image.strip()
            if not image or image not in data:
                continue
            images_array.append(image)
            captions_array.append(
                f'{config.START} {data[image]} {config.STOP}'
            )

    return images_array, captions_array


def getTokenizers(lex):
    """Cria mapeamentos palavra → índice e índice → palavra."""
    idxtoword = {}
    wordtoidx = {}
    idx = 1
    for word in lex:
        wordtoidx[word] = idx
        idxtoword[idx]  = word
        idx += 1
    return idxtoword, wordtoidx


def getTokensArrays(captions_array, wordtoidx):
    """Converte legendas em sequências de índices numéricos."""
    token_captions_array = []
    for caption in captions_array:
        tokens = []
        for word in caption.split():
            if word in wordtoidx:
                tokens.append(wordtoidx[word])
        token_captions_array.append(tokens)
    return token_captions_array


def getBERTimbauEmbeddings(lex):
    """

    Gera embeddings para cada palavra do vocabulário usando BERTimbau.



    BERTimbau é um modelo BERT treinado em português brasileiro

    pelo NLP-USP (neuralmind/bert-base-portuguese-cased).



    Substitui:

      - SBW-vectors-300-min5.txt (espanhol, 300 dims)

      - wiki-news-300d-1M.vec    (inglês,   300 dims)



    Retorna dicionário {palavra: vetor numpy 768 dims}

    """
    import torch
    from transformers import BertTokenizer, BertModel

    print(f'Carregando BERTimbau: {config.EMBEDDING_NAME}')

    # Carrega tokenizador e modelo BERTimbau do HuggingFace
    tokenizer = BertTokenizer.from_pretrained(config.EMBEDDING_NAME)
    model     = BertModel.from_pretrained(config.EMBEDDING_NAME)
    model.eval()  # modo inferência — desativa dropout

    embeddings = {}
    palavras   = list(lex)

    print(f'Gerando embeddings para {len(palavras)} palavras...')

    with torch.no_grad():  # sem gradiente — economiza memória
        for palavra in palavras:
            # Tokeniza a palavra individualmente
            inputs = tokenizer(
                palavra,
                return_tensors='pt',  # tensores PyTorch
                truncation=True,
                max_length=10
            )

            # Gera embedding via BERTimbau
            outputs = model(**inputs)

            # Média dos tokens como representação da palavra
            # last_hidden_state: (1, n_tokens, 768)
            vetor = outputs.last_hidden_state.mean(dim=1).squeeze()
            embeddings[palavra] = vetor.numpy()

    print(f'BERTimbau: {len(embeddings)} embeddings gerados (768 dims)')
    return embeddings


def getEmbeddingMatrix(embeddings, vocab_size, wordtoidx):
    """

    Monta a matriz de embeddings para inicializar a camada Embedding.

    Dimensão: (vocab_size x EMBEDDING_SIZE)

    """
    embedding_matrix = np.zeros((vocab_size, config.EMBEDDING_SIZE))

    encontrados = 0
    for word, i in wordtoidx.items():
        vetor = embeddings.get(word)
        if vetor is not None:
            embedding_matrix[i] = vetor
            encontrados += 1

    print(f'Embedding matrix: {encontrados}/{len(wordtoidx)} palavras mapeadas')
    return embedding_matrix


def getEmbeddings():
    """

    Método original do autor — mantido para compatibilidade.

    Lê arquivo de embeddings estáticos no formato word2vec.

    """
    embeddings      = {}
    embeddings_path = os.path.join('data', config.EMBEDDING_NAME)

    with open(embeddings_path, 'rb') as f:
        for line in f:
            values = line.split()
            word   = values[0]
            coefs  = np.asarray(values[1:], dtype='float32')
            embeddings[word] = coefs

    print(f'Encontrados {len(embeddings)} word vectors')
    return embeddings