diff --git a/data/external/20_newsgroups.tar.gz b/data/external/20_newsgroups.tar.gz deleted file mode 100644 index 90fbec1..0000000 Binary files a/data/external/20_newsgroups.tar.gz and /dev/null differ diff --git a/data/external/disney.zip b/data/external/disney.zip deleted file mode 100644 index 70763bb..0000000 Binary files a/data/external/disney.zip and /dev/null differ diff --git a/data/external/hbo.zip b/data/external/hbo.zip deleted file mode 100644 index 0cb2a79..0000000 Binary files a/data/external/hbo.zip and /dev/null differ diff --git a/data/external/mini_newsgroups.tar.gz b/data/external/mini_newsgroups.tar.gz deleted file mode 100644 index e08cfb7..0000000 Binary files a/data/external/mini_newsgroups.tar.gz and /dev/null differ diff --git a/data/external/netflix.zip b/data/external/netflix.zip deleted file mode 100644 index 72aceaf..0000000 Binary files a/data/external/netflix.zip and /dev/null differ diff --git a/data/external/prime.zip b/data/external/prime.zip deleted file mode 100644 index 2a5d159..0000000 Binary files a/data/external/prime.zip and /dev/null differ diff --git a/notebooks/01_exploratory_data.ipynb b/notebooks/01_exploratory_data.ipynb deleted file mode 100644 index 3a2118c..0000000 --- a/notebooks/01_exploratory_data.ipynb +++ /dev/null @@ -1,134 +0,0 @@ -{ - "cells": [ - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Análise exploratória de dados\n", - "\n", - "A análise exploratória de dados é uma etapa fundamental para qualquer projeto que envolva dados. Ela consiste em examinar e estudar as características de um conjunto de dados, como sua distribuição, suas variáveis, suas relações e suas anomalias, antes de aplicar técnicas mais avançadas de estatística ou aprendizagem de máquina. O objetivo da análise exploratória de dados é obter uma compreensão mais profunda dos dados, identificar padrões, tendências e insights que possam orientar a tomada de decisão e a solução de problemas. A análise exploratória de dados pode ser realizada de forma visual, usando gráficos, tabelas e diagramas, ou de forma numérica, usando medidas de tendência central, dispersão, correlação e teste de hipóteses. A escolha dos métodos depende do tipo e da qualidade dos dados disponíveis, bem como da pergunta ou objetivo que se quer responder com a anál\n", - "\n", - "\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "# Importa os módulos necessários\n", - "import numpy as np # Módulo para trabalhar com matrizes e funções matemáticas\n", - "import pandas as pd # Módulo para trabalhar com dataframes e séries em Python\n" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "\n", - "## Estruturação dos Arquivos\n", - "\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "base = pd.read_parquet('../data/processed/base_processed.parquet.gzip')" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[('edu', 72452),\n", - " ('ax', 47799),\n", - " ('c', 27223),\n", - " ('wa', 24454),\n", - " ('line', 23074),\n", - " ('com', 22785),\n", - " ('message', 22263),\n", - " ('subject', 21661),\n", - " ('news', 21081),\n", - " ('date', 20828),\n", - " ('id', 20598),\n", - " ('newsgroups', 20363),\n", - " ('path', 20353),\n", - " ('cmu', 20143),\n", - " ('organization', 20077),\n", - " ('apr', 19593),\n", - " ('gmt', 17725),\n", - " ('one', 16548),\n", - " ('would', 15997),\n", - " ('srv', 15120),\n", - " ('cantaloupe', 15069),\n", - " ('writes', 14685),\n", - " ('1', 13931),\n", - " ('article', 13867),\n", - " ('reference', 13740),\n", - " ('ha', 13217),\n", - " ('net', 13057),\n", - " ('x', 12252),\n", - " ('state', 11585),\n", - " ('sender', 11024)]" - ] - }, - "execution_count": 19, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "import itertools\n", - "import collections\n", - "\n", - "counts_no = collections.Counter(list(itertools.chain(*base['tokens'])))\n", - "\n", - "counts_no.most_common(30)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\n" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.1" - }, - "orig_nbformat": 4 - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/notebooks/02_vector_model.ipynb b/notebooks/02_vector_model.ipynb deleted file mode 100644 index 9404e46..0000000 --- a/notebooks/02_vector_model.ipynb +++ /dev/null @@ -1,166 +0,0 @@ -{ - "cells": [ - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Modelo Vetorial para Recuperação da Informação\n", - "\n", - "O modelo vetorial é um dos métodos mais utilizados para recuperação de informação, que consiste em representar documentos e consultas como vetores em um espaço multidimensional. Cada dimensão corresponde a um termo do vocabulário da coleção de documentos, e o peso de cada termo é calculado com base na sua frequência e relevância. A recuperação de informação é feita comparando a similaridade entre os vetores de documentos e consultas, usando medidas como o produto escalar ou o cosseno do ângulo entre eles. O modelo vetorial permite recuperar documentos que satisfaçam parcialmente a consulta, definindo um limiar de similaridade mínimo aceitável.\n", - "\n", - "\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "# Importa os módulos necessários\n", - "import numpy as np # Módulo para trabalhar com matrizes e funções matemáticas\n", - "import pandas as pd # Módulo para trabalhar com dataframes e séries em Python\n", - "\n", - "from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer\n", - "from sklearn.metrics.pairwise import cosine_similarity" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "- Carregue os documentos em uma lista, onde cada documento é uma string.\n", - "- Instancie o objeto CountVectorizer para transformar o texto em uma matriz de termos.\n", - "- Ajuste e transforme a matriz de termos usando os dados do conjunto de documentos." - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "database = pd.read_parquet('../data/processed/base_processed.parquet.gzip')" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Calcule a similaridade entre as consultas e os documentos:\n", - "- Transforme a consulta em uma matriz de termos.\n", - "- Calcule a similaridade entre a matriz de termos da consulta e a matriz de termos dos documentos usando a função cosine_similarity." - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [], - "source": [ - "# Instancie o objeto CountVectorizer\n", - "vectorizer = CountVectorizer()\n", - "\n", - "# Transforme os documentos em uma matriz de termos\n", - "term_matrix = vectorizer.fit_transform(database['text'])\n" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [], - "source": [ - "with open('../data/emails/mini_newsgroups/alt.atheism/51126', 'r') as file: \n", - " query = file.read()\n", - "\n", - "# Transforme a consulta em uma matriz de termos\n", - "query_vec = vectorizer.transform([query])\n", - "\n", - "# Calcule a similaridade entre a consulta e os documentos\n", - "similarity_scores = cosine_similarity(query_vec, term_matrix)\n" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Recupere os documentos mais relevantes:\n", - "- Classifique os documentos com base em suas pontuações de similaridade.\n", - "- Recupere os documentos mais relevantes." - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "53761 - Score: 0.7457440977032672\n", - "53194 - Score: 0.7438271604938276\n", - "51126 - Score: 0.7377253439645206\n", - "51273 - Score: 0.7142800526817401\n", - "53142 - Score: 0.7017401753421795\n", - "51160 - Score: 0.7001157311738098\n", - "54283 - Score: 0.6967342757044788\n", - "53175 - Score: 0.6939201375033768\n", - "53172 - Score: 0.6869464497590783\n", - "53143 - Score: 0.6855706297881646\n", - "39619 - Score: 0.660578259075816\n", - "53763 - Score: 0.6472975596607513\n", - "53144 - Score: 0.6401055804697865\n", - "101656 - Score: 0.6390178833325828\n", - "53762 - Score: 0.638752210144836\n", - "178451 - Score: 0.6386838743880491\n", - "178846 - Score: 0.6361329120147892\n", - "83796 - Score: 0.6361329120147892\n", - "105113 - Score: 0.6293008682666752\n", - "54241 - Score: 0.6264456087861376\n" - ] - } - ], - "source": [ - "# Classifique os documentos com base em suas pontuações de similaridade\n", - "ranked_docs = sorted(\n", - " list(enumerate(similarity_scores[0])),\n", - " key=lambda x: x[1],\n", - " reverse=True\n", - ")\n", - "\n", - "# Recupere os documentos mais relevantes\n", - "for i, score in ranked_docs[0:20]:\n", - " print(database.iloc[i]['filename'], \" - Score:\", score)\n" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.1" - }, - "orig_nbformat": 4 - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/notebooks/03_tf_idf_model.ipynb b/notebooks/03_tf_idf_model.ipynb deleted file mode 100644 index 9f7cd1d..0000000 --- a/notebooks/03_tf_idf_model.ipynb +++ /dev/null @@ -1,130 +0,0 @@ -{ - "cells": [ - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Modelo Vetorial para Recuperação da Informação\n", - "\n", - "O modelo vetorial é um dos métodos mais utilizados para recuperação de informação, que consiste em representar documentos e consultas como vetores em um espaço multidimensional. Cada dimensão corresponde a um termo do vocabulário da coleção de documentos, e o peso de cada termo é calculado com base na sua frequência e relevância. A recuperação de informação é feita comparando a similaridade entre os vetores de documentos e consultas, usando medidas como o produto escalar ou o cosseno do ângulo entre eles. O modelo vetorial permite recuperar documentos que satisfaçam parcialmente a consulta, definindo um limiar de similaridade mínimo aceitável.\n", - "\n", - "\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Importa os módulos necessários\n", - "import numpy as np # Módulo para trabalhar com matrizes e funções matemáticas\n", - "import pandas as pd # Módulo para trabalhar com dataframes e séries em Python\n", - "import os\n", - "\n", - "from sklearn.feature_extraction.text import CountVectorizer\n", - "from sklearn.metrics.pairwise import cosine_similarity" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "- Carregue os documentos em uma lista, onde cada documento é uma string.\n", - "- Instancie o objeto CountVectorizer para transformar o texto em uma matriz de termos.\n", - "- Ajuste e transforme a matriz de termos usando os dados do conjunto de documentos." - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Calcule a similaridade entre as consultas e os documentos:\n", - "- Transforme a consulta em uma matriz de termos.\n", - "- Calcule a similaridade entre a matriz de termos da consulta e a matriz de termos dos documentos usando a função cosine_similarity." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Instancie o objeto CountVectorizer\n", - "vectorizer = CountVectorizer()\n", - "\n", - "# Transforme os documentos em uma matriz de termos\n", - "term_matrix = vectorizer.fit_transform(database)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "query = \"graphics\"\n", - "\n", - "# Transforme a consulta em uma matriz de termos\n", - "query_vec = vectorizer.transform([query])\n", - "\n", - "# Calcule a similaridade entre a consulta e os documentos\n", - "similarity_scores = cosine_similarity(query_vec, term_matrix)\n" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Recupere os documentos mais relevantes:\n", - "- Classifique os documentos com base em suas pontuações de similaridade.\n", - "- Recupere os documentos mais relevantes." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Classifique os documentos com base em suas pontuações de similaridade\n", - "ranked_docs = sorted(\n", - " list(enumerate(similarity_scores[0])),\n", - " key=lambda x: x[1],\n", - " reverse=True\n", - ")\n", - "\n", - "# Recupere os documentos mais relevantes\n", - "for i, score in ranked_docs:\n", - " print(docs[i], \" - Score:\", score)\n" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.1" - }, - "orig_nbformat": 4 - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/notebooks/backup/00_preprocessing.ipynb b/notebooks/backup/00_preprocessing.ipynb deleted file mode 100644 index d484ba9..0000000 --- a/notebooks/backup/00_preprocessing.ipynb +++ /dev/null @@ -1,303 +0,0 @@ -{ - "cells": [ - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Pré-Processamento dos Documentos\n", - "\n", - "A limpeza dos dados é um processo essencial para garantir a qualidade e a confiabilidade das informações armazenadas em um banco de dados. A limpeza dos dados envolve a identificação e a correção de erros, inconsistências, duplicidades e valores ausentes nos dados. A arquitetura do armazenamento é a forma como os dados são organizados, estruturados e acessados em um banco de dados. Uma das opções de arquitetura é o formato YAML, que significa YAML Ain't Markup Language. O YAML é um formato de serialização de dados que usa uma sintaxe simples e legível para representar estruturas de dados como listas, mapas, sequências e escalares. O YAML é compatível com diversas linguagens de programação e pode ser usado para armazenar dados de forma hierárquica e flexível.\n", - "\n", - "\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "# Importa os módulos necessários\n", - "import os # Módulo para lidar com funções do sistema operacional\n", - "import gc # Módulo para realizar coleta de lixo e gerenciamento de memória\n", - "import yaml # Módulo para trabalhar com arquivos YAML\n", - "import pickle # Módulo para serialização e desserialização de objetos em Python\n", - "import itertools # Módulo para criação de iteráveis\n", - "\n", - "import numpy as np # Módulo para trabalhar com matrizes e funções matemáticas\n", - "import pandas as pd # Módulo para trabalhar com dataframes e séries em Python\n", - "\n", - "import nltk # Módulo para processamento de linguagem natural\n", - "from nltk.corpus import stopwords # Módulo para importar lista de stopwords em inglês\n", - "from spellchecker import SpellChecker # Módulo para correção ortográfica de palavras\n" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "\n", - "## Estruturação dos Arquivos\n", - "\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "0" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Set the directory path to where the data is stored\n", - "doc_dir = '../data/emails/20_newsgroups/'\n", - "\n", - "# Create an empty list to hold the processed data\n", - "database = []\n", - "\n", - "# Iterate over each file in the directory and its subdirectories\n", - "for filepath in os.listdir(doc_dir): \n", - " for filename in os.listdir(f'{doc_dir}{filepath}'):\n", - "\n", - " # Open each file individually and read its contents\n", - " with open(os.path.join(doc_dir, filepath, filename), 'r') as f:\n", - " text_data = f.read().strip()\n", - " \n", - " # Split the header and body of the email\n", - " try:\n", - " header, body = text_data.split('\\n\\n', maxsplit=1)\n", - " except:\n", - " continue\n", - " \n", - " # Convert header to a dictionary\n", - " header_dict = {}\n", - " for line in header.split('\\n'):\n", - " try:\n", - " # Split the key and value in each header field and store them in a dictionary\n", - " key, value = line.strip().split(': ', maxsplit=1)\n", - " header_dict[key] = value\n", - " except:\n", - " # If a header field cannot be split properly, skip it and continue\n", - " continue\n", - " \n", - " # Append the processed data to the list\n", - " database.append({'filepath': filepath, \n", - " 'filename': filename,\n", - " 'text': body, \n", - " **header_dict\n", - " })\n", - "\n", - "# tranformation from dict -> dataframe\n", - "base_inicial = pd.DataFrame(database)\n", - "\n", - "# remove database from memory\n", - "del database\n", - "gc.collect()" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "\n", - "## Processamento de Texto\n", - "\n", - "
\n", - "\n", - "### Transformação de minúsculos\n", - "\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "# Substituindo todos os caracteres que não são letras ou números por espaços em branco, exceto as barras invertidas (\\\\)\n", - "base_inicial['text'] = base_inicial['text'].replace(r'(\\\\[a-z])|([^\\w\\\\])', ' ', regex=True)\n", - "\n", - "# Aplicando as funções str.lower() e str.strip() simultaneamente\n", - "base_inicial['text'] = base_inicial['text'].apply(lambda x: x.lower().strip())\n" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "\n", - "### Remoção de Stopwords\n", - "\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "[nltk_data] Downloading package stopwords to\n", - "[nltk_data] C:\\Users\\kevin\\AppData\\Roaming\\nltk_data...\n", - "[nltk_data] Package stopwords is already up-to-date!\n" - ] - } - ], - "source": [ - "# Faz o download do recurso 'stopwords' do nltk\n", - "nltk.download('stopwords')\n", - "\n", - "# Define a lista de stopwords em inglês usando o módulo stopwords do nltk\n", - "stopwords = stopwords.words('english')\n", - "\n", - "# Aplica a função lambda em cada linha da coluna 'text' da tabela 'base_inicial'\n", - "# A função lambda realiza a tokenização do texto, transforma as palavras em minúsculas e remove as stopwords\n", - "base_inicial['text'] = base_inicial['text'].apply(lambda words: ' '.join(word.lower() for word in words.split() if word not in stopwords))\n" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "\n", - "### Tokenização e Lemmatizer\n", - "\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "[nltk_data] Downloading package wordnet to\n", - "[nltk_data] C:\\Users\\kevin\\AppData\\Roaming\\nltk_data...\n", - "[nltk_data] Package wordnet is already up-to-date!\n", - "[nltk_data] Downloading package punkt to\n", - "[nltk_data] C:\\Users\\kevin\\AppData\\Roaming\\nltk_data...\n", - "[nltk_data] Package punkt is already up-to-date!\n" - ] - } - ], - "source": [ - "nltk.download('wordnet') # faz o download do recurso 'wordnet' do nltk\n", - "nltk.download('punkt') # faz o download do recurso 'punkt' do nltk\n", - "\n", - "# Cria um objeto 'w_tokenizer' da classe 'WhitespaceTokenizer' do nltk para tokenizar o texto por espaços em branco\n", - "w_tokenizer = nltk.tokenize.WhitespaceTokenizer()\n", - "\n", - "# Cria um objeto 'lemmatizer' da classe 'WordNetLemmatizer' do nltk para realizar a lematização das palavras\n", - "lemmatizer = nltk.WordNetLemmatizer()\n", - "\n", - "# Define a função 'lemmatizer_text' que recebe um texto como entrada, tokeniza o texto em palavras e lematiza cada palavra\n", - "def lemmatizer_text(text): \n", - " return [lemmatizer.lemmatize(w) for w in w_tokenizer.tokenize(text)]\n", - "\n", - "# Cria uma nova coluna 'tokens' na tabela 'base_inicial' que contém uma lista de tokens lematizados para cada texto\n", - "base_inicial['tokens'] = base_inicial['text'].map(lemmatizer_text)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "# # Cria uma lista de palavras a partir da lista de tokens\n", - "# w = [j for i in list(itertools.chain(base_inicial['tokens'])) for j in i]\n", - "\n", - "# # Instancia um objeto SpellChecker para correção ortográfica\n", - "# spell = SpellChecker()\n", - "\n", - "# if !os.path.isfile(): \n", - "# # Cria um dicionário com as palavras únicas da lista, faz a correção ortográfica e associa com a palavra original\n", - "# spell_checked = {word: spell.correction(word) for word in pd.Series(w).unique()}\n", - "\n", - "# # Define o caminho do arquivo que irá armazenar o dicionário serializado\n", - "# path = '../references/spellcheck.pickle'\n", - "\n", - "# # Abre o arquivo para gravação em modo binário e escreve o objeto serializado\n", - "# with open(path, 'wb') as file: \n", - "# pickle.dump(spell_checked, file)\n", - "# else: \n", - "# pass" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Export da base" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "path = '../data/processed/base_processed.parquet.gzip'\n", - "\n", - "if os.path.isfile(path): \n", - " answer = input('File already exists, do you want to overwrite? (y/n)')\n", - " if answer.lower() in ['s', 'y']:\n", - " base_inicial.to_parquet(path, compression='gzip')\n", - " else:\n", - " raise FileExistsError('File already exists')\n", - "else: \n", - " base_inicial.to_parquet(path, compression='gzip')" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.1" - }, - "orig_nbformat": 4 - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/notebooks/00_preprocessing.ipynb b/notebooks/information_retrieval_emails.ipynb similarity index 100% rename from notebooks/00_preprocessing.ipynb rename to notebooks/information_retrieval_emails.ipynb diff --git a/notebooks/information_retrieval_movies.ipynb b/notebooks/information_retrieval_movies.ipynb new file mode 100644 index 0000000..be731ec --- /dev/null +++ b/notebooks/information_retrieval_movies.ipynb @@ -0,0 +1,451 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Pré-Processamento dos Documentos\n", + "\n", + "A limpeza dos dados é um processo essencial para garantir a qualidade e a confiabilidade das informações armazenadas em um banco de dados. A limpeza dos dados envolve a identificação e a correção de erros, inconsistências, duplicidades e valores ausentes nos dados. A arquitetura do armazenamento é a forma como os dados são organizados, estruturados e acessados em um banco de dados. Uma das opções de arquitetura é o formato YAML, que significa YAML Ain't Markup Language. O YAML é um formato de serialização de dados que usa uma sintaxe simples e legível para representar estruturas de dados como listas, mapas, sequências e escalares. O YAML é compatível com diversas linguagens de programação e pode ser usado para armazenar dados de forma hierárquica e flexível.\n", + "\n", + "\n", + "
" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "# Importa os módulos necessários\n", + "import os # Módulo para lidar com funções do sistema operacional\n", + "import gc # Módulo para realizar coleta de lixo e gerenciamento de memória\n", + "import sys\n", + "\n", + "import numpy as np # Módulo para trabalhar com matrizes e funções matemáticas\n", + "import pandas as pd # Módulo para trabalhar com dataframes e séries em Python\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "\n", + "## Estruturação dos Arquivos\n", + "\n", + "
" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "disney = pd.read_csv('../data/movies/disney_titles.csv')\n", + "prime = pd.read_csv('../data/movies/prime_titles.csv')\n", + "hbo = pd.read_csv('../data/movies/hbo_titles.csv')\n", + "netflix = pd.read_csv('../data/movies/netflix_titles.csv')\n", + "\n", + "disney['provider'] = 'disney'\n", + "prime['provider'] = 'prime'\n", + "hbo['provider'] = 'hbo'\n", + "netflix['provider'] = 'netflix'\n", + "\n", + "base = pd.concat([disney, prime, hbo, netflix])\n", + "\n", + "del disney, prime, hbo, netflix\n", + "\n", + "base.dropna(ignore_index=True, inplace=True)\n", + "base.reset_index(drop=True, inplace=True)\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "\n", + "## Processamento de Texto\n", + "\n", + "
\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Tratamento dos gêneros" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "from ast import literal_eval\n", + "\n", + "base['genres'] = base['genres'].fillna('[]').apply(literal_eval).apply(lambda x: [i for i in x] if isinstance(x, list) else [])" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "### Transformação de minúsculos\n", + "\n", + "
" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "# (\\[a-z]): para encontrar todos os caracteres que começam com uma barra invertida () seguida por uma letra minúscula (a-z);\n", + "# ([^\\w\\]): para encontrar todos os caracteres que não são letras, números ou barras invertidas ();\n", + "# (\\S+\\d\\S+): para encontrar todos os trechos de texto que contêm um ou mais caracteres não brancos (\\S), \n", + "# seguidos por um dígito (\\d), seguidos por mais um ou mais caracteres não brancos (\\S).\n", + "base['post'] = base['description'].replace(r'(\\\\[a-z])|([^\\w\\\\])|(\\S+\\d\\S+)', ' ', regex=True)\n", + "\n", + "# Aplicando as funções str.lower() e str.strip() simultaneamente\n", + "base['post'] = base['post'].apply(lambda x: x.lower().strip() if isinstance(x, str) else x)\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "\n", + "### Tokenização e Lemmatizer\n", + "\n", + "
" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "from ir.preprocessing import lemmatize_word\n", + "\n", + "base['post'] = base['post'].apply(lambda x: ' '.join([lemmatize_word(word.lower()) for word in x.split()]))\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Identificação das query / docs" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "np.random.seed(42)\n", + "rand = np.random.random(base.shape[0])\n", + "\n", + "d_index = rand < 0.7\n", + "q_index = rand >= 0.7" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### TF IDF" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "from ir.tf_idf import tfidf" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "weights = tfidf(base, 'post').T" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "from sklearn.metrics.pairwise import linear_kernel" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Ranqueamento" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "q_index = base[q_index].index\n", + "d_index = base[d_index].index" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "rank_geral = linear_kernel(weights.iloc[d_index], weights.iloc[q_index])\n", + "rank_geral = pd.DataFrame(rank_geral, index=d_index, columns=q_index)" + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Query: 3093/3093 - Doc: 1730/3092" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " 3 function calls in 0.000 seconds\n", + "\n", + " Ordered by: internal time\n", + "\n", + " ncalls tottime percall cumtime percall filename:lineno(function)\n", + " 1 0.000 0.000 0.000 0.000 {built-in method builtins.exec}\n", + " 1 0.000 0.000 0.000 0.000 :1()\n", + " 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}" + ] + } + ], + "source": [ + "import sys\n", + "import numba\n", + "\n", + "def calcular_resultados_relevantes(q_index: list, base: pd.DataFrame) -> 'resultados_relevantes[dict], resultados_sistema[dict]':\n", + " resultados_sistema = {}\n", + "\n", + " for q in q_index: \n", + " resultados_sistema[q] = rank_geral[q].sort_values(ascending=False).index\n", + "\n", + " resultados_relevantes = {}\n", + "\n", + " for q in q_index:\n", + " q_genre = base.iloc[q]['genres']\n", + "\n", + " k = []\n", + "\n", + " for d in resultados_sistema[q]:\n", + " d_genre = base.iloc[d]['genres']\n", + " \n", + " # Verifica qual lista de gêneros é menor para otimizar a comparação\n", + " if len(d_genre) > len(q_genre):\n", + " comparativo_menor = q_genre\n", + " comparativo_maior = d_genre\n", + " else:\n", + " comparativo_menor = d_genre\n", + " comparativo_maior = q_genre\n", + " \n", + " # Verifica se há pelo menos um gênero em comum entre as listas\n", + " partial_relevance = any(i in comparativo_maior for i in comparativo_menor)\n", + " \n", + " if partial_relevance:\n", + " k.append(d)\n", + " \n", + " print(f'\\rQuery: {q}/{q_index.max()} - Doc: {d}/{d_index.max()}', end='')\n", + " sys.stdout.flush()\n", + "\n", + " resultados_relevantes[q] = k\n", + " \n", + " return resultados_relevantes, resultados_sistema\n", + "\n", + "resultados_relevantes, resultados_sistema = calcular_resultados_relevantes(q_index, base)\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Métricas" + ] + }, + { + "cell_type": "code", + "execution_count": 89, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Média do P@: 0.719268030139934\n" + ] + } + ], + "source": [ + "def calcular_p_n_media(resultados_relevantes, resultados_sistema, n):\n", + " def calcular_p_n(resultados, relevantes):\n", + " if len(resultados) > n:\n", + " resultados = resultados[:n] # Considerar apenas os primeiros n resultados\n", + " num_relevantes = len(set(resultados) & set(relevantes)) # Contar quantos resultados relevantes foram encontrados\n", + " p_n = num_relevantes / n # Calcular a precisão P@n\n", + " return p_n\n", + "\n", + " p_n_total = 0\n", + " for consulta, relevantes in resultados_relevantes.items():\n", + " resultados = resultados_sistema.get(consulta, []) # Obtém os resultados retornados pelo sistema para a consulta\n", + " p_n = calcular_p_n(resultados, relevantes)\n", + " p_n_total += p_n\n", + "\n", + " p_n_media = p_n_total / len(resultados_relevantes)\n", + " return p_n_media\n", + "\n", + "# Utilizando a função para calcular a média do P@n\n", + "p_n_media = calcular_p_n_media(resultados_relevantes, resultados_sistema, n=10)\n", + "print(f\"Média do P@: {p_n_media}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 85, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Média do P@10: 0.719268030139934\n", + "Média do P@20: 0.6967168998923577\n", + "Média do P@50: 0.6745748116254034\n", + "Média do P@100: 0.658902045209902\n" + ] + } + ], + "source": [ + "for x in [10, 20, 50, 100]: \n", + " print(f\"Média do P@{x}: {calcular_p_n_media(resultados_relevantes, resultados_sistema, n=x)}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 83, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.5882758350175267" + ] + }, + "execution_count": 83, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def average_precision(relevantes, recomendados):\n", + " relevancia_cumulativa = 0\n", + " precision_cumulativa = 0\n", + " num_relevantes = len(relevantes)\n", + " ap = 0\n", + "\n", + " for i, rec in enumerate(recomendados):\n", + " if rec in relevantes:\n", + " relevancia_cumulativa += 1\n", + " precision_cumulativa += relevancia_cumulativa / (i + 1)\n", + "\n", + " if num_relevantes > 0:\n", + " ap = precision_cumulativa / num_relevantes\n", + "\n", + " return ap\n", + "\n", + "def mean_average_precision(resultados_relevantes, resultados_sistema):\n", + " map = 0\n", + " num_consultas = len(resultados_relevantes)\n", + "\n", + " for q in resultados_relevantes:\n", + " relevantes = resultados_relevantes[q]\n", + " recomendados = resultados_sistema[q]\n", + " ap = average_precision(relevantes, recomendados)\n", + " map += ap\n", + "\n", + " if num_consultas > 0:\n", + " map /= num_consultas\n", + "\n", + " return map\n", + "\n", + "# Aplicar o MAP nas consultas\n", + "map_result = mean_average_precision(resultados_relevantes, resultados_sistema)\n", + "map_result" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.1" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks/test.ipynb b/notebooks/test.ipynb deleted file mode 100644 index e723d01..0000000 --- a/notebooks/test.ipynb +++ /dev/null @@ -1,138 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "import pandas as pd\n", - "import numpy as np\n", - "\n", - "# Conjunto de documentos\n", - "documents = [\n", - " \"to do is to be to be is to do\",\n", - " \"to be or not to be i am not what i am\",\n", - " \"i think therefore i am do be do be do\",\n", - " \"do do do da da da let it be let it be\"\n", - "]\n", - "\n", - "base = pd.DataFrame({'docs': documents})" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [], - "source": [ - "import pandas as pd\n", - "import numpy as np\n", - "\n", - "# Função que calcula o log na base 2 da frequência das palavras em um documento\n", - "def log_freq(doc):\n", - " \"\"\"\n", - " Calcula o log na base 2 da frequência das palavras em um documento.\n", - "\n", - " Args:\n", - " doc (str): O documento para o qual o log de frequência será calculado.\n", - "\n", - " Returns:\n", - " pandas.Series: A série de palavras e seus logs de frequência.\n", - "\n", - " \"\"\"\n", - " words = doc.split(' ') # Separar o documento em palavras\n", - " freq = pd.Series(words).value_counts() # Contar a frequência de cada palavra\n", - " log_freq = 1 + np.log2(freq) # Calcular o log na base 2 da frequência\n", - " return log_freq\n", - "\n", - "# Função que aplica a função log_freq a cada documento do dataframe\n", - "def ri_tf(dataframe: pd.DataFrame, column: str):\n", - " \"\"\"Calcula o term frequency relativo para cada documento em uma coluna do dataframe.\n", - " Args:\n", - " dataframe (pandas.DataFrame): O dataframe com a coluna desejada.\n", - " column (str): O nome da coluna que contém os documentos.\n", - "\n", - " Returns:\n", - " pandas.DataFrame: O dataframe com os logs de frequência para cada palavra em cada documento.\n", - "\n", - " \"\"\"\n", - " return dataframe[column].apply(log_freq).T\n", - "\n", - "# Função que calcula o IDF (inverse document frequency) de cada termo do corpus\n", - "def ri_idf(dataframe: pd.DataFrame, column: str): \n", - " \"\"\"Calcula o inverse document frequency relativo para cada palavra em uma coluna do dataframe.\n", - " Args:\n", - " dataframe (pandas.DataFrame): O dataframe com a coluna desejada.\n", - " column (str): O nome da coluna que contém os documentos.\n", - "\n", - " Returns:\n", - " dict: Um dicionário com as palavras e seus respectivos IDF relativos.\n", - "\n", - " \"\"\"\n", - " words = [phrase.split(' ') for phrase in dataframe[column]] # Separar cada frase em palavras\n", - "\n", - " df_t = pd.Series([i for j in words for i in j]).value_counts() # Contar a frequência de cada termo\n", - "\n", - " n_i = {} # Dicionário que armazenará a quantidade de documentos que contém cada termo\n", - " idf = {} # Dicionário que armazenará o IDF de cada termo\n", - "\n", - " # Calcular n_i e IDF para cada termo do corpus\n", - " for term in df_t.index: \n", - " n_i[term] = dataframe[column].map(lambda x: term in x).sum() # Quantidade de documentos que contém o termo\n", - " idf[term] = np.log2(dataframe.shape[0]/n_i[term]) # IDF do termo\n", - "\n", - " return idf\n", - "\n", - "# Função que calcula o TF-IDF de cada termo em cada documento do corpus\n", - "def tfidf(dataframe, column): \n", - " \"\"\"Calcula o TF-IDF relativo para cada palavra em cada documento de uma coluna do dataframe.\n", - " Args:\n", - " dataframe (pandas.DataFrame): O dataframe com a coluna desejada.\n", - " column (str): O nome da coluna que contém os documentos.\n", - "\n", - " Ret'urns:\n", - " pandas.DataFrame: O dataframe com os TF-IDFs relativos para cada palavra em cada documento.\n", - "\n", - " \"\"\"'\n", - " tf = ri_tf(dataframe=dataframe, column=column) # Calcular o TF de cada termo em cada documento\n", - " idf = ri_idf(dataframe=dataframe, column=column) # Calcular o IDF de cada termo\n", - "\n", - " df = {}\n", - " for word in tf.index: # Iterar por cada termo do corpus\n", - " df[word] = tf.loc[word]*idf[word] # Calcular o TF-IDF do termo em cada documento\n", - "\n", - " return pd.DataFrame.from_dict(df, orient='index') # Retornar os resultados em um DataFrame\n" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.1" - }, - "orig_nbformat": 4 - }, - "nbformat": 4, - "nbformat_minor": 2 -}