def testar_num_topics( self, modelo, num_topicos=[20, 50, 100, 200, 300, 400, 500, 1000, 1500], perc_fichas=0.2, vetor_testes=None, tipo_teste='similaridade'): ''' Testa a coerência dos modelos gerados por tópicos para uma lista de quantidade de tópicos para encontrar o melhor número de tópicos para o modelo com relação ao corpus. Parâmetros: modelo (str) --> Modelo a ser testado: "lda", "lsi" ou "doc2vec". num_topicos (list de int) --> Lista de números de tópicos a serem testados (default: [20, 50, 100, 200, 300, 400, 500, 1000, 1500]) per_fichas (float) --> Percentual de fichas do corpus a serem considerados para o teste (default: 0.2) vetor_teste (list de tuple) --> Lista de pares de fichas para testes de similaridade. É ignorado se o teste é o "u_mass" (default: None) tipo_testes (str) --> Tipo de teste: "u_mass" ou "similaridade" (default: "similaridade") Retorno: um dicionário de dicionários. A chave do dicionário principal é o número de tópicos e, para cada número de tópicos, há outro dicionário com as seguintes chaves: "medida" --> Valor de coerência calculado para o modelo com aquele número de tópicos. "modelo" --> O modelo gerado para aquele número de tópicos ''' # Verifica se o teste para o modelo foi implantado if modelo not in ['lda', 'lsi', 'doc2vec']: print( f'O modelo {modelo} ou não é de tópico ou não foi implantado.') return if tipo_teste not in ['u_mass', 'similaridade']: print(f'O tipo de teste {tipo_teste} não foi implementado.') return if modelo == 'doc2vec' and tipo_teste == 'u_mass': print( 'O teste de coerência com u_mass não pode ser usado para o modelo doc2vec.' ) return # Iniciando as variáveis para os testes resultado = {} arq_index = os.path.join(self.corpus._pastas['indices'], f'{self.corpus._link_nome}_testes.idx') if vetor_testes: flat = list(zip(*vetor_testes)) fichas_incluir = set(flat[0]) fichas_incluir.update(flat[1]) else: fichas_incluir = None # Define os corpus de treinamento e o corpus parcial if modelo == 'lsi': bow = self.corpus.corpus(tipo='bow') corpus_parcial = bow.fatiar(perc_fichas=perc_fichas, incluir=fichas_incluir) model_tfidf = self['tfidf'] or TfidfModel( corpus=corpus_parcial, id2word=self.corpus.dicionario()) corpus_train = model_tfidf[corpus_parcial] elif modelo == 'lda': bow = self.corpus.corpus(tipo='bow') corpus_parcial = corpus_train = bow.fatiar(perc_fichas=perc_fichas, incluir=fichas_incluir) elif modelo == 'doc2vec': corpus_tagged = self.corpus.corpus(tipo='tagged') corpus_parcial = corpus_train = corpus_tagged.fatiar( perc_fichas=perc_fichas, incluir=fichas_incluir) # Obtém a relação dos ids_fichas do corpus parcial if fichas_incluir: ids_fichas = corpus_parcial.fichas() else: ids_fichas = list(range(len(corpus_parcial))) # Faz o teste para cada quantidade de tópicos for num in tqdm(num_topicos): print(f'Criando modelo "{modelo}" para num_topics={num}') # Treina os modelo solicitado if modelo == 'lda': model = LdaModel(corpus=corpus_train, id2word=self.corpus.dicionario(), num_topics=num) elif modelo == 'lsi': model = LsiModel(corpus=corpus_train, id2word=self.corpus.dicionario(), num_topics=num) elif modelo == 'doc2vec': model = Doc2Vec(vector_size=num, workers=mp.cpu_count() / 2, alpha=self._modelos[modelo]['alpha'], min_alpha=self._modelos[modelo]['min_alpha']) # Obtém o vocabulário do corpus para treinar o modelo Doc2Vec model.build_vocab(corpus_train) # Treina o modelo Doc2Vec model.train(corpus_train, total_examples=model.corpus_count, epochs=model.epochs) # Salva o modelo construído para o número de tópicos da iteração resultado[num] = {'modelo': model} # Realiza o teste de coerência if tipo_teste == 'u_mass': # Calcula a coerência do modelo para o número de tópicos setado print( f'Calculando o score de coerência do modelo "{modelo}" para num_topics={num}' ) cm = CoherenceModel(model=model, corpus=corpus_train, coherence='u_mass') resultado[num]['medida'] = cm.get_coherence() print(f'Score u_mass = {resultado[num]["medida"]}') # Realiza o teste de similaridade elif tipo_teste == 'similaridade': # Define o corpus para a matriz de similaridade if modelo == 'doc2vec': corpus = Doc2VecCorpus(model) else: corpus = model[corpus_train] # Calcula a similaridade do modelo para o número de tópicos setado print( f'Calculando o score de similaridade do modelo "{modelo}" para num_topics={num}' ) index = Similarity(output_prefix=arq_index, corpus=corpus, num_features=num) medidas = [] for ficha_query, ficha_target in vetor_testes: id_query = self.corpus.ficha2id(ficha_query) query = ids_fichas.index(id_query) id_target = self.corpus.ficha2id(ficha_target) target = ids_fichas.index(id_target) posicao, _ = self._obter_posicao_target( index, query, target) medidas.append(1 / posicao) valores = pd.Series(medidas) resultado[num]['medida'] = valores.median() print(f'Score similaridade = {resultado[num]["medida"]}') return resultado