/
maissimilar_short_v5.py
144 lines (103 loc) · 4.14 KB
/
maissimilar_short_v5.py
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
'''
Criado em 1/3/2021
Derivado de maissimilar_v5
Modificações:
Não utiliza modelo NLP
Utiliza vetores armazenados em HDF5
Por Alexandre Uchoa
'''
#import re
import h5py
import numpy as np
import pandas as pd
#from time import time
from pathlib import Path
relative_path = Path(__file__).parent
pasta = {}
pasta['main'] = relative_path.as_posix() + '/'
pasta['modelos']= relative_path.as_posix() + '/modelos/'
pasta['estudos']= relative_path.as_posix() + '/estudos/'
pasta_main = pasta['main']
pasta_modelos = pasta['modelos']
pasta_estudos = pasta['estudos']
#------------------------------------------------------------------------------
# Determina a similaridade entre tags de entidades
# a partir de representações de distribuição geradas preiviamente
#------------------------------------------------------------------------------
class MaisSimilar_Short(object):
def __init__(self, modelo_fn=None):
self.pasta_modelos = pasta_modelos
self.pasta_estudos = pasta_estudos
self.tipo_producao = 'teses'
self.usa_hdf5 = True
self.load_modelo_hdf5(modelo_fn=modelo_fn)
def load_modelo_hdf5(self, modelo_fn=None):
if modelo_fn is None:
if self.tipo_producao.startswith('tese'):
modelo_fn = "0_d2v-teses_model.mm"
elif self.tipo_producao == 'artigos_analise':
modelo_fn = '7_d2v-mix-artigos-analise_model.mm'
elif self.tipo_producao.startswith('artigo'):
modelo_fn = "0_d2v_artigos-entidades_model.mm"
elif self.tipo_producao.startswith('topico'):
modelo_fn = "0_d2v-teses-topicos_model.mm"
else:
modelo_fn = "0_d2v-teses-topicos_model.mm"
print("*** Assumindo modelo:", modelo_fn)
else:
if modelo_fn[-3:] != '.mm': modelo_fn += '.mm'
# Forma nomes de arquivos
self.docvecs_dv_fn = modelo_fn + ".docvecs.vectors_docs.hdf5"
index_dv_fn = modelo_fn + ".docvecs.index_docs.npy"
# Cria DF com indices dos docvecs e tags
self.d2v_index = pd.DataFrame(np.load(pasta_modelos + index_dv_fn),\
columns=['tags'])
self.d2v_index.set_index('tags',inplace=True,drop=True)
self.d2v_index = self.d2v_index.assign(pos=range(len(self.d2v_index)))
# Abre HDF5 com docvecs
h5py_f1 = h5py.File(pasta_modelos + self.docvecs_dv_fn, 'r')
self.d2v_docvecs = h5py_f1['docvecs']
def _tags_cosine_v2(self, tag1, df_tags2, primeiros=20, sim_minima=.0):
# Separa os docvecs correspondentes
if tag1 not in df_tags2.index:
df_tags2 = df_tags2.append(self.d2v_index.loc[tag1], \
ignore_index=False)
df_tags2.sort_values('pos', inplace=True)
np_so_docvecs = self.d2v_docvecs[df_tags2['pos'].to_list()]
vec_tag1 = np_so_docvecs[df_tags2.index == tag1]
vec_tag2 = np_so_docvecs
cosine = self.cosine(vec_tag1[0], vec_tag2)
# Aproveita TAGS (de areas) de vecs
if primeiros == 0:
primeiros = len(df_tags2)
# Ordena decrescente e retorna somente os # primeiros casos
df_tags2['SIMILARIDADE'] = cosine
df_tags2.sort_values('SIMILARIDADE', ascending=False, inplace=True)
# Se tiver sido fornecida uma similaridade minima (piso), ela eh usada...
if sim_minima is not None:
return df_tags2[df_tags2['SIMILARIDADE'] >= sim_minima][:primeiros]
else:
return df_tags2[:primeiros]
# Calcula similaridade entre 2 ou mais vetores por cosseno
def cosine(self, vec1, vecs):
# Cosine similarity function with NumPy
# Se vec2 forem multiplos vetores...
if vecs.shape[0] > 1:
return np.dot(vecs, vec1) / (np.linalg.norm(vec1) * \
np.linalg.norm(vecs, axis=1))
else:
return np.dot(vecs, vec1) / (np.linalg.norm(vec1) * \
np.linalg.norm(vecs))
def get_doctags_pos_por_tags_hdf5(self, df_tags):
# df_tags: qq DF q tenha tags como indice
if type(df_tags) == list:
df_tags = pd.DataFrame(index=df_tags)
# So preserva registros cujos tags estejam no d2v_model
df_tags = df_tags[df_tags.index.isin(self.d2v_index.index)]
# Adiciona posicao dos DOCVECS ao DF com metadados
df_tags = df_tags.join(self.d2v_index, rsuffix='_INDEX')
# Ordena df_dados segundo ordem crescente da posicao dos DOCVECS
df_tags.sort_values('pos', inplace=True)
# Separa posicoes dos tags de df_dados
pos_vecs = df_tags['pos'].to_list()
return pos_vecs, df_tags