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 |