<jupyter_start><jupyter_text>Libs e Dados<jupyter_code># change directory
%cd ..
import os
import numpy as np
import pandas as pd
from scipy.sparse import load_npz
from src.Text_Mining import TopicClustering
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.preprocessing import normalize
data = pd.read_parquet("data/articles_processed.parquet")
tf    = load_npz('models/tf_unigram_articles.npz')
tfidf = load_npz('models/tfidf_unigram_articles.npz')
vocabulary = pd.read_csv("models/vocabulary_unigram_articles.csv").ngrams
doc_top_wals = np.load(f'models/doc_topics_wals_unigram_articles.npy').astype('float32')
word_top_wals = np.load(f'models/word_topics_wals_unigram_articles.npy').astype('float32')

assert tf.shape == tfidf.shape, 'Rever BOW'
assert tf.shape[0] == data.shape[0], 'Rever BOW'
assert tf.shape[0] == doc_top_wals.shape[0], 'Rever Modelagem de Tópicos'
assert word_top_wals.shape[1] == doc_top_wals.shape[1], 'Rever Modelagem de Tópicos'
data.head()
data.shape<jupyter_output><empty_output><jupyter_text>Verificando Vocabulário **Palavras Mais Comuns**<jupyter_code>words_df = pd.DataFrame({"word":vocabulary.values, 'freq': np.asarray(tf.sum(axis=0))[0]}
                       ).sort_values('freq', ascending=False)
words_df.head(20).T<jupyter_output><empty_output><jupyter_text>**Top 250 words**<jupyter_code>'  '.join(words_df.iloc[:250].word)<jupyter_output><empty_output><jupyter_text>Modelos de Tópicos  Resumo dos modelos de tópicos Criando resumo de tópicos por palavras por weight e relevância<jupyter_code>%%time
topwords_relevance_df_wals_topic, top5_words_relevance_wals_topic = TopicClustering.view_topics(word_top_wals, vocabulary, relevance=True, n_top_words=50)
topwords_weight_df_wals_topic, top5_words_weight_wals_topic       = TopicClustering.view_topics(word_top_wals, vocabulary, relevance=False, n_top_words=50)<jupyter_output>CPU times: user 2.8 s, sys: 47.1 ms, total: 2.84 s
Wall time: 2.84 s<jupyter_text>**Os dataframes com as top 50 palavras para cada tópico**<jupyter_code>topwords_relevance_df_wals_topic<jupyter_output><empty_output><jupyter_text>**Visualização as séries de top5 palavras para cada tópico: permite uma visualização muito mais rápida**<jupyter_code>df_words5_topics = pd.DataFrame({"topic_words_weight": top5_words_weight_wals_topic,
                                 "topic_words_relevance": top5_words_relevance_wals_topic})
df_words5_topics<jupyter_output><empty_output><jupyter_text>Modelos de Clusterização Rígida **Carregandos os dados da clusterização**<jupyter_code>clustering_extensive_50  = np.load('models/clusters_extensive_50_outputs.npz')
clustering_intensive_200 = np.load('models/clusters_intensive_200_outputs.npz')
data['cluster_ext_50']  = clustering_extensive_50['index']
data['cluster_int_200'] = clustering_intensive_200['index']<jupyter_output><empty_output><jupyter_text>Resumo de ClusterizaçãoDa mesma maneira que foi realizado para os tópicos, o resumos dos clusters se fará por palavras.  Clusterização Extensiva<jupyter_code>%%time
word_cluster_ext_50 = TopicClustering.get_word_cluster_matrix(data.cluster_ext_50, tf).astype('float32')
topwords_relevance_df_ext_50, top5_words_relevance_ext_50 = TopicClustering.view_topics(word_cluster_ext_50, vocabulary, relevance=True, n_top_words=50)
topwords_weight_df_ext_50, top5_words_weight_ext_50       = TopicClustering.view_topics(word_cluster_ext_50, vocabulary, relevance=False, n_top_words=50)
df_words5_clusters_ext_50 = pd.DataFrame({'n_instances': data.cluster_ext_50.value_counts(),
                                          "cluster_words_weight": top5_words_weight_ext_50, 
                                          "cluster_words_relevance": top5_words_relevance_ext_50})<jupyter_output><empty_output><jupyter_text>**Série das top5 dos clusters**<jupyter_code>df_words5_clusters_ext_50<jupyter_output><empty_output><jupyter_text>Clusterização Intensiva<jupyter_code>%%time
word_cluster_int_200 = TopicClustering.get_word_cluster_matrix(data.cluster_int_200, tf).astype('float32')
topwords_relevance_df_int_200, top5_words_relevance_int_200 = TopicClustering.view_topics(word_cluster_int_200, vocabulary, relevance=True, n_top_words=50)
topwords_weight_df_int_200, top5_words_weight_int_200       = TopicClustering.view_topics(word_cluster_int_200, vocabulary, relevance=False, n_top_words=50)
df_words5_clusters_int_200 = pd.DataFrame({'n_instances': data.cluster_int_200.value_counts(),
                                           "cluster_words_weight": top5_words_weight_int_200, 
                                           "cluster_words_relevance": top5_words_relevance_int_200})<jupyter_output><empty_output><jupyter_text>**Série das top5 dos clusters**<jupyter_code>df_words5_clusters_int_200<jupyter_output><empty_output><jupyter_text>**Visualizando parte do dataframe das top50**<jupyter_code>topwords_relevance_df_int_200.iloc[:10, :7]<jupyter_output><empty_output><jupyter_text>**Uma amostra das top5**<jupyter_code>df_words5_clusters_int_200.sample(10)<jupyter_output><empty_output><jupyter_text>Diagnóstico de Categorias  1. Salvando dataframe da clusterização extensiva para rotulação de assuntos<jupyter_code>df_words5_clusters_ext_50.reset_index(
                                      ).rename(columns={'index':'cluster'}
                                               ).to_csv('reports/extensive_clusters.csv',index=False)<jupyter_output><empty_output><jupyter_text>2. Rotulação em Assuntos Principais e Secundários   3. Avaliação dos Rótulos **Lendo o arquivo após rotulação manual**O arquivo está disponível no [link](https://docs.google.com/spreadsheets/d/12lQq2AH9EUMTp-afz4l_MzsAEwBIhcZQwtAP4HzOu74/editgid=1235989610)<jupyter_code>ext_clusters = pd.read_csv('reports/extensive_clusters.csv')
# fix
ext_clusters = ext_clusters.applymap(lambda x: 'indefinido' if x=='indefinido ' else x)<jupyter_output><empty_output><jupyter_text>**Número de assuntos distintos**<jupyter_code>ext_clusters.nunique()[-2:]<jupyter_output><empty_output><jupyter_text>**Assuntos Principais Distintos**<jupyter_code>print(pd.Series(ext_clusters.assunto_princ.unique()).sort_values().values)
resum_assuntos = ext_clusters.groupby("assunto_princ"
                                          ).agg({'n_instances':'sum',
                                                 'cluster': 'nunique',
                                                 'assunto_sec':'nunique'}
                                                ).sort_values("n_instances", 
                                                              ascending=False)

resum_assuntos.columns = ["n_instances", 'n_cluster', 'n_assunto_secundario']
resum_assuntos<jupyter_output><empty_output><jupyter_text>4. Avaliando um Categoria Individualmente: Esportes  Definindo todos os clusters da clusterização extensiva que são de Esportes<jupyter_code>ext_clusters_esportes = [3, 6, 14, 16, 24, 40, 45]
ext_clusters.loc[ext_clusters_esportes]<jupyter_output><empty_output><jupyter_text>Consulta na clusterização intensiva **Consultando os clusters de clusterização intensiva para os documentos cujo os clusters extensivos sejam de esportes**<jupyter_code>contagem_clusters_int_esportes = data.query('cluster_ext_50 in @ext_clusters_esportes').cluster_int_200.value_counts()
esportes_ext_data = data.query("cluster_ext_50 in @ext_clusters_esportes")
esportes_intensive = pd.DataFrame({'% de noticias':esportes_ext_data.cluster_int_200.value_counts(normalize=True)*100,
                                   'n de noticias':esportes_ext_data.cluster_int_200.value_counts()}
                                   ).join(df_words5_clusters_int_200)
futebol_intensive.head(11)<jupyter_output><empty_output><jupyter_text>**Vê se uma maior Especificação e qualidade na clusterização intensiva**Segundo o framework, não se faz rotulação da base completa de clusterização intensiva, mas especialmente nesse exemplo será feito por motivos didáticosO arquivo de rotulação dos clusters intensivos está disponível no [link](https://docs.google.com/spreadsheets/d/1QLRhLSokSrnY7F_AoaHwUSufip1IlJneTXws8Vv1bFE/editgid=579318358) **Lendo após rotulação**<jupyter_code>int_clusters = pd.read_csv('reports/intensive_clusters.csv')<jupyter_output><empty_output><jupyter_text>fazendo a mesma consulta, agr com os assuntos rotulados<jupyter_code>esportes_ext_data = data.query("cluster_ext_50 in @ext_clusters_esportes")
esportes_intensive = pd.DataFrame({'% de noticias':esportes_ext_data.cluster_int_200.value_counts(normalize=True)*100,
                                   'n de noticias':esportes_ext_data.cluster_int_200.value_counts()}
                                   ).join(int_clusters)
futebol_intensive.head(11)<jupyter_output><empty_output><jupyter_text>**Seguindo a mesma ideia para um assunto secundário específico: futebol (cluster extensivo 3)**<jupyter_code># relembrando clusters exensivos de esportes
ext_clusters.loc[ext_clusters_esportes]
futebol_data = data.query("cluster_ext_50 == 3")
futebol_intensive = pd.DataFrame({'% de noticias':futebol_data.cluster_int_200.value_counts(normalize=True)*100,
                                  'n de noticias':futebol_data.cluster_int_200.value_counts()}
                                  ).join(int_clusters)
futebol_intensive.head(9)
futebol_data = data.query("cluster_wals_50==3")
futebol_intensive = pd.DataFrame({'% de noticias':futebol_data.cluster_wals_200.value_counts(normalize=True)*100,
              'n de noticias':futebol_data.cluster_wals_200.value_counts()}
            ).join(art.iloc[:,:-1]).head(20)<jupyter_output><empty_output><jupyter_text>**Vê se uma maior especificação do tema futebol, o que pode se tornar categorias distintas e hierarquias, aqui entra a parte artística do framework**  5.Validação: visualizando amostras de um cluster intensivo  Para criar categorias, utilize sempre os clusters intensivos, por ser de maior qualidade e especificidade Vendo uma amostra específica de futebol. Vou pegar o da Seleção Brasileira (cluster intensivo 83), que joga hoje, 04/06/2021, dia da publicação do artigo.Obs: minha predição diz que hoje tem gol do gabigol.<jupyter_code>data.query("cluster_int_200==83").sample(10).iloc[:, [0,1, -1,-2]]<jupyter_output><empty_output><jupyter_text>Vê se a altíssima qualidade da clusterização intensiva. Pra se ter uma noção, esportes representam 21 clusters e 18 assuntos secundários distintos.<jupyter_code>resum_assuntos = int_clusters.groupby('Assunto Princ.'
                                          ).agg({'n_instances':'sum',
                                                 'cluster': 'nunique',
                                                 'Assunto Sec.':'nunique'}
                                                ).sort_values("n_instances", 
                                                              ascending=False)

resum_assuntos.columns = ["n_instances", 'n_cluster', 'n_assunto_secundario']
resum_assuntos.head(30)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09554604244466709, 'fraction_numerical': 0.028600054649785954, 'mean_word_length': 4.766806722689076, 'pattern_counts': {'":': 7, '<': 96, '<?xml version=': 0, '>': 96, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 39, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '24', 'dir': 'jupyter-structured-clean-dedup', 'id': '158728', 'license': 'MIT', 'n_tokens_mistral': 4037, 'n_tokens_neox': 3759, 'n_words': 592, 'path': 'notebooks/01.prospecao_categorias.ipynb', 'repo_name': 'victor-pontes/text_mining_medium', 'size': '10979'}