diff --git a/README.md b/README.md
index 0993f60..5dec2d1 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,5 @@
+Projeto prático da matéria de Recuperação da Informação do curso de Pós-graduação da Ciência da Computação da UNESP
+
# Recuperação da Informação
Neste texto, apresentamos uma introdução ao projeto prático da matéria de recuperação da informação na UNESP. O objetivo deste projeto é desenvolver um sistema de busca que permita aos usuários encontrar documentos relevantes em uma coleção de textos. Para isso, utilizaremos conceitos e técnicas de recuperação da informação, tais como: indexação, processamento de linguagem natural, modelos de recuperação, medidas de avaliação e feedback de relevância. O projeto será dividido em quatro etapas:
@@ -7,6 +9,8 @@ Neste texto, apresentamos uma introdução ao projeto prático da matéria de re
3. implementação do modelo de recuperação;
4. avaliação do sistema.
+Este trabalho não tem como objetivo fornecer uma ferramenta otimizada, mas sim uma ferramenta funcional com codificação manual, sem o uso de pacotes externos, para uma melhor compreensão das técnicas apresentadas.
+
## Pré-processamento dos documentos
O pré-processamento de texto é uma etapa fundamental para a recuperação da informação, pois visa transformar os documentos em uma representação adequada para a análise e a busca. O pré-processamento envolve técnicas como tokenização, normalização, remoção de stopwords, stemização e lematização, que têm como objetivo reduzir a complexidade e a variabilidade dos textos. Essas técnicas facilitam a identificação de termos relevantes e a comparação entre documentos, melhorando a eficiência e a eficácia dos sistemas de recuperação da informação.
@@ -21,6 +25,22 @@ Um índice invertido de texto é uma estrutura de dados que armazena as ocorrên
O índice invertido é uma ferramenta essencial para a recuperação da informação, pois permite realizar consultas complexas e obter resultados relevantes em um curto espaço de tempo.
+$$TF-IDF = TF(t, d) \cdot IDF(t)$$
+
+Onde:
+
+$TF(t, d)$: representa a frequência do termo t no documento d.
+$IDF(t)$: representa o inverso da frequência do documento (IDF) do termo t.
+
+A fórmula completa do IDF é dada por:
+
+$$IDF(t) = \log \left( \frac{N}{DF(t)} \right)$$
+
+Onde:
+
+$N$ é o número total de documentos na coleção.
+$DF(t)$ é o número de documentos que contêm o termo t.
+
## Implementação do modelo de recuperação
A recuperação da informação é o processo de encontrar e acessar informações relevantes em um grande conjunto de dados. Existem diferentes modelos computacionais que podem ser usados para representar e organizar as informações, bem como para definir e executar as consultas dos usuários. Neste texto, vamos introduzir alguns dos principais modelos de recuperação da informação, como o modelo booleano, o modelo vetorial e o modelo probabilístico. Também vamos discutir as vantagens e desvantagens de cada um deles, e como eles podem ser aplicados em diferentes contextos e domínios.
@@ -29,4 +49,4 @@ A recuperação da informação é o processo de encontrar e acessar informaçõ
A recuperação da informação é uma área que visa encontrar e fornecer informações relevantes para os usuários, a partir de grandes coleções de documentos. Para isso, existem diversos modelos de recuperação da informação, que se baseiam em diferentes princípios e abordagens para representar e comparar os documentos e as consultas dos usuários. A avaliação dos modelos de recuperação da informação é fundamental para verificar a sua eficácia e eficiência, bem como para identificar os seus pontos fortes e fracos. Existem diferentes formas de avaliar os modelos de recuperação da informação, tais como: a avaliação experimental, que utiliza medidas quantitativas e conjuntos de teste padronizados; a avaliação centrada no usuário, que considera as necessidades, preferências e comportamentos dos usuários; e a avaliação comparativa, que analisa as vantagens e desvantagens de diferentes modelos em relação a um critério ou objetivo específico. A escolha do método de avaliação depende do contexto e do propósito da recuperação da informação, bem como dos recursos disponíveis. A avaliação dos modelos de recuperação da informação é essencial para o desenvolvimento e aprimoramento da área, pois permite identificar os problemas existentes e propor soluções inovadoras.
-Ao final do projeto, é esperado que possamos gerar rankings de similaridade de acordo com cada e-mail utilizado como input.
\ No newline at end of file
+Ao final do projeto, é esperado que possamos gerar rankings de similaridade de acordo com cada e-mail utilizado como input.
diff --git a/notebooks/information_retrieval_emails.ipynb b/notebooks/information_retrieval_emails.ipynb
index da918c0..3470670 100644
--- a/notebooks/information_retrieval_emails.ipynb
+++ b/notebooks/information_retrieval_emails.ipynb
@@ -5,12 +5,23 @@
"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",
- "
"
+ "# Recuperação da informação para conjunto de e-mails\n",
+ "\n",
+ "Foram utilizadas as bases `20_newsgroups.tar.gz` e `mini_newsgroups.tar.gz` para o projeto:\n",
+ "\n",
+ "[ICS: E-mail groups](https://kdd.ics.uci.edu/databases/20newsgroups/20newsgroups.html)\n",
+ "\n",
+ "\n",
+ "
Atenção
\n",
+ "
A base de dados possui um total de 22.000 elementos. Destes, 2.000 são utilizados como query, e os outros 20.000 são para consulta. \n",
+ "
\n",
+ " Após a tokenização, o vocabulário pode chegar a 130.000 palavras, resultando em uma matriz com o termo para cada documento, o que pode ocupar até 30GB de RAM.\n",
+ "
\n",
+ " Portanto, é importante ter cuidado ao executar o processo, pois é necessário um grande volume de RAM para sua execução.
\n"
]
},
{
@@ -22,9 +33,15 @@
"# 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"
+ "import pandas as pd # Módulo para trabalhar com dataframes e séries em Python\n",
+ "\n",
+ "from ir.preprocessing import lemmatize_word # Importa a função de lematização de palavras\n",
+ "from ir.tf_idf import tfidf # Importa a função de cálculo de TF-IDF\n",
+ "\n",
+ "from sklearn.metrics.pairwise import linear_kernel"
]
},
{
@@ -34,14 +51,18 @@
"source": [
" \n",
"\n",
- "## Estruturação dos Arquivos\n",
+ "## Leitura dos Arquivos\n",
+ "\n",
+ "Para a pasta da base de dados, os arquivos foram fornecidos em um formato raw, sem indicação de extensão. Cada e-mail é um arquivo dentro de uma pasta que representa um tema.\n",
+ "\n",
+ "Portanto, nesse caso, é necessário percorrer cada pasta para realizar a leitura e armazenamento da base de dados para análises futuras.\n",
"\n",
" "
]
},
{
"cell_type": "code",
- "execution_count": 31,
+ "execution_count": 2,
"metadata": {},
"outputs": [
{
@@ -50,7 +71,7 @@
"0"
]
},
- "execution_count": 31,
+ "execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
@@ -103,212 +124,25 @@
" return database\n",
"\n",
"# tranformation from dict -> dataframe\n",
- "base_doc = pd.DataFrame(process_files(docs))\n",
+ "base_doc = pd.DataFrame(process_files(docs_path))\n",
"\n",
- "base_doc = pd.DataFrame(process_files(doc_dir))\n",
- "\n",
- "# remove database from memory\n",
- "gc.collect()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {},
- "outputs": [
- {
- "ename": "PermissionError",
- "evalue": "[Errno 13] Permission denied: '../data/emails/20_newsgroups/alt.atheism'",
- "output_type": "error",
- "traceback": [
- "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[1;31mPermissionError\u001b[0m Traceback (most recent call last)",
- "Cell \u001b[1;32mIn[5], line 8\u001b[0m\n\u001b[0;32m 5\u001b[0m docs_path \u001b[39m=\u001b[39m \u001b[39m'\u001b[39m\u001b[39m../data/emails/20_newsgroups/\u001b[39m\u001b[39m'\u001b[39m\n\u001b[0;32m 7\u001b[0m \u001b[39m# Import das bases\u001b[39;00m\n\u001b[1;32m----> 8\u001b[0m database_docs \u001b[39m=\u001b[39m read_files(docs_path)\n\u001b[0;32m 9\u001b[0m database_query \u001b[39m=\u001b[39m read_files(query_path)\n\u001b[0;32m 11\u001b[0m base_docs \u001b[39m=\u001b[39m pd\u001b[39m.\u001b[39mDataFrame(database_docs)\n",
- "Cell \u001b[1;32mIn[2], line 3\u001b[0m, in \u001b[0;36mread_files\u001b[1;34m(doc_dir)\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[39mdef\u001b[39;00m \u001b[39mread_files\u001b[39m(doc_dir):\n\u001b[0;32m 2\u001b[0m \u001b[39m# Use a list comprehension to get a list of file paths\u001b[39;00m\n\u001b[1;32m----> 3\u001b[0m database \u001b[39m=\u001b[39m [{\u001b[39m'\u001b[39;49m\u001b[39mfilepath\u001b[39;49m\u001b[39m'\u001b[39;49m: doc_dir,\n\u001b[0;32m 4\u001b[0m \u001b[39m'\u001b[39;49m\u001b[39mfilename\u001b[39;49m\u001b[39m'\u001b[39;49m: filename,\n\u001b[0;32m 5\u001b[0m \u001b[39m'\u001b[39;49m\u001b[39mtext\u001b[39;49m\u001b[39m'\u001b[39;49m: \u001b[39mopen\u001b[39;49m(os\u001b[39m.\u001b[39;49mpath\u001b[39m.\u001b[39;49mjoin(doc_dir, filename), \u001b[39m'\u001b[39;49m\u001b[39mr\u001b[39;49m\u001b[39m'\u001b[39;49m)\u001b[39m.\u001b[39;49mread()\u001b[39m.\u001b[39;49mstrip()}\n\u001b[0;32m 6\u001b[0m \u001b[39mfor\u001b[39;49;00m filename \u001b[39min\u001b[39;49;00m os\u001b[39m.\u001b[39;49mlistdir(doc_dir)]\n\u001b[0;32m 8\u001b[0m \u001b[39mreturn\u001b[39;00m database\n",
- "Cell \u001b[1;32mIn[2], line 5\u001b[0m, in \u001b[0;36m\u001b[1;34m(.0)\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[39mdef\u001b[39;00m \u001b[39mread_files\u001b[39m(doc_dir):\n\u001b[0;32m 2\u001b[0m \u001b[39m# Use a list comprehension to get a list of file paths\u001b[39;00m\n\u001b[0;32m 3\u001b[0m database \u001b[39m=\u001b[39m [{\u001b[39m'\u001b[39m\u001b[39mfilepath\u001b[39m\u001b[39m'\u001b[39m: doc_dir,\n\u001b[0;32m 4\u001b[0m \u001b[39m'\u001b[39m\u001b[39mfilename\u001b[39m\u001b[39m'\u001b[39m: filename,\n\u001b[1;32m----> 5\u001b[0m \u001b[39m'\u001b[39m\u001b[39mtext\u001b[39m\u001b[39m'\u001b[39m: \u001b[39mopen\u001b[39;49m(os\u001b[39m.\u001b[39;49mpath\u001b[39m.\u001b[39;49mjoin(doc_dir, filename), \u001b[39m'\u001b[39;49m\u001b[39mr\u001b[39;49m\u001b[39m'\u001b[39;49m)\u001b[39m.\u001b[39mread()\u001b[39m.\u001b[39mstrip()}\n\u001b[0;32m 6\u001b[0m \u001b[39mfor\u001b[39;00m filename \u001b[39min\u001b[39;00m os\u001b[39m.\u001b[39mlistdir(doc_dir)]\n\u001b[0;32m 8\u001b[0m \u001b[39mreturn\u001b[39;00m database\n",
- "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python311\\site-packages\\IPython\\core\\interactiveshell.py:282\u001b[0m, in \u001b[0;36m_modified_open\u001b[1;34m(file, *args, **kwargs)\u001b[0m\n\u001b[0;32m 275\u001b[0m \u001b[39mif\u001b[39;00m file \u001b[39min\u001b[39;00m {\u001b[39m0\u001b[39m, \u001b[39m1\u001b[39m, \u001b[39m2\u001b[39m}:\n\u001b[0;32m 276\u001b[0m \u001b[39mraise\u001b[39;00m \u001b[39mValueError\u001b[39;00m(\n\u001b[0;32m 277\u001b[0m \u001b[39mf\u001b[39m\u001b[39m\"\u001b[39m\u001b[39mIPython won\u001b[39m\u001b[39m'\u001b[39m\u001b[39mt let you open fd=\u001b[39m\u001b[39m{\u001b[39;00mfile\u001b[39m}\u001b[39;00m\u001b[39m by default \u001b[39m\u001b[39m\"\u001b[39m\n\u001b[0;32m 278\u001b[0m \u001b[39m\"\u001b[39m\u001b[39mas it is likely to crash IPython. If you know what you are doing, \u001b[39m\u001b[39m\"\u001b[39m\n\u001b[0;32m 279\u001b[0m \u001b[39m\"\u001b[39m\u001b[39myou can use builtins\u001b[39m\u001b[39m'\u001b[39m\u001b[39m open.\u001b[39m\u001b[39m\"\u001b[39m\n\u001b[0;32m 280\u001b[0m )\n\u001b[1;32m--> 282\u001b[0m \u001b[39mreturn\u001b[39;00m io_open(file, \u001b[39m*\u001b[39;49margs, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwargs)\n",
- "\u001b[1;31mPermissionError\u001b[0m: [Errno 13] Permission denied: '../data/emails/20_newsgroups/alt.atheism'"
- ]
- }
- ],
- "source": [
- "# caminho das queries \n",
- "query_path = '../data/emails/mini_newsgroups/'\n",
- "\n",
- "# caminho dos documentos\n",
- "docs_path = '../data/emails/20_newsgroups/'\n",
- "\n",
- "# Import das bases\n",
- "database_docs = read_files(docs_path)\n",
- "database_query = read_files(query_path)\n",
- "\n",
- "base_docs = pd.DataFrame(database_docs)\n",
- "base_query = pd.DataFrame(database_query)\n",
+ "base_que = pd.DataFrame(process_files(query_path))\n",
"\n",
"# Marcação das bases\n",
- "base_docs['tag'] = 'doc'\n",
- "base_query['tag'] = 'query'\n",
+ "base_doc['tag'] = 'doc'\n",
+ "base_que['tag'] = 'query'\n",
+ "\n",
+ "# Amostragem para testes\n",
+ "base_doc = base_doc.sample(frac=0.5, random_state=42)\n",
"\n",
"# junção das bases \n",
- "base = pd.concat([base_docs, base_query])\n",
+ "base = pd.concat([base_doc, base_que])\n",
"base.reset_index(drop=True, inplace=True)\n",
"\n",
- "del base_docs, base_query, database_docs, database_query\n",
- "gc.collect()\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " | \n",
- " filepath | \n",
- " filename | \n",
- " text | \n",
- " tag | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " 0 | \n",
- " ../data/emails/20_newsgroups/misc.forsale/ | \n",
- " 70337 | \n",
- " Path: cantaloupe.srv.cs.cmu.edu!rochester!udel... | \n",
- " doc | \n",
- "
\n",
- " \n",
- " 1 | \n",
- " ../data/emails/20_newsgroups/misc.forsale/ | \n",
- " 74150 | \n",
- " Path: cantaloupe.srv.cs.cmu.edu!crabapple.srv.... | \n",
- " doc | \n",
- "
\n",
- " \n",
- " 2 | \n",
- " ../data/emails/20_newsgroups/misc.forsale/ | \n",
- " 74720 | \n",
- " Path: cantaloupe.srv.cs.cmu.edu!das-news.harva... | \n",
- " doc | \n",
- "
\n",
- " \n",
- " 3 | \n",
- " ../data/emails/20_newsgroups/misc.forsale/ | \n",
- " 74721 | \n",
- " Newsgroups: misc.forsale\\nPath: cantaloupe.srv... | \n",
- " doc | \n",
- "
\n",
- " \n",
- " 4 | \n",
- " ../data/emails/20_newsgroups/misc.forsale/ | \n",
- " 74722 | \n",
- " Path: cantaloupe.srv.cs.cmu.edu!crabapple.srv.... | \n",
- " doc | \n",
- "
\n",
- " \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- "
\n",
- " \n",
- " 1095 | \n",
- " ../data/emails/mini_newsgroups/misc.forsale/ | \n",
- " 76927 | \n",
- " Xref: cantaloupe.srv.cs.cmu.edu misc.wanted:31... | \n",
- " query | \n",
- "
\n",
- " \n",
- " 1096 | \n",
- " ../data/emails/mini_newsgroups/misc.forsale/ | \n",
- " 76936 | \n",
- " Newsgroups: misc.forsale\\nSubject: WANTED LCD ... | \n",
- " query | \n",
- "
\n",
- " \n",
- " 1097 | \n",
- " ../data/emails/mini_newsgroups/misc.forsale/ | \n",
- " 76937 | \n",
- " Newsgroups: ingr.forsale,hsv.forsale,misc.fors... | \n",
- " query | \n",
- "
\n",
- " \n",
- " 1098 | \n",
- " ../data/emails/mini_newsgroups/misc.forsale/ | \n",
- " 76940 | \n",
- " Newsgroups: misc.forsale\\nPath: cantaloupe.srv... | \n",
- " query | \n",
- "
\n",
- " \n",
- " 1099 | \n",
- " ../data/emails/mini_newsgroups/misc.forsale/ | \n",
- " 76945 | \n",
- " Xref: cantaloupe.srv.cs.cmu.edu comp.sys.mac.h... | \n",
- " query | \n",
- "
\n",
- " \n",
- "
\n",
- "
1100 rows × 4 columns
\n",
- "
"
- ],
- "text/plain": [
- " filepath filename \n",
- "0 ../data/emails/20_newsgroups/misc.forsale/ 70337 \\\n",
- "1 ../data/emails/20_newsgroups/misc.forsale/ 74150 \n",
- "2 ../data/emails/20_newsgroups/misc.forsale/ 74720 \n",
- "3 ../data/emails/20_newsgroups/misc.forsale/ 74721 \n",
- "4 ../data/emails/20_newsgroups/misc.forsale/ 74722 \n",
- "... ... ... \n",
- "1095 ../data/emails/mini_newsgroups/misc.forsale/ 76927 \n",
- "1096 ../data/emails/mini_newsgroups/misc.forsale/ 76936 \n",
- "1097 ../data/emails/mini_newsgroups/misc.forsale/ 76937 \n",
- "1098 ../data/emails/mini_newsgroups/misc.forsale/ 76940 \n",
- "1099 ../data/emails/mini_newsgroups/misc.forsale/ 76945 \n",
- "\n",
- " text tag \n",
- "0 Path: cantaloupe.srv.cs.cmu.edu!rochester!udel... doc \n",
- "1 Path: cantaloupe.srv.cs.cmu.edu!crabapple.srv.... doc \n",
- "2 Path: cantaloupe.srv.cs.cmu.edu!das-news.harva... doc \n",
- "3 Newsgroups: misc.forsale\\nPath: cantaloupe.srv... doc \n",
- "4 Path: cantaloupe.srv.cs.cmu.edu!crabapple.srv.... doc \n",
- "... ... ... \n",
- "1095 Xref: cantaloupe.srv.cs.cmu.edu misc.wanted:31... query \n",
- "1096 Newsgroups: misc.forsale\\nSubject: WANTED LCD ... query \n",
- "1097 Newsgroups: ingr.forsale,hsv.forsale,misc.fors... query \n",
- "1098 Newsgroups: misc.forsale\\nPath: cantaloupe.srv... query \n",
- "1099 Xref: cantaloupe.srv.cs.cmu.edu comp.sys.mac.h... query \n",
- "\n",
- "[1100 rows x 4 columns]"
- ]
- },
- "execution_count": 4,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "base"
+ "del base_doc, base_que\n",
+ "\n",
+ "# remove database from memory\n",
+ "gc.collect()"
]
},
{
@@ -318,18 +152,18 @@
"source": [
" \n",
"\n",
- "## Processamento de Texto\n",
+ "## Pré-Processamento de Texto\n",
"\n",
- " \n",
+ "Para minimizar possíveis gargalos de processamento e identificação dos termos relevantes, é realizada a remoção de ruídos utilizando regex. Em seguida, é aplicada a tokenização, que consiste na transformação do texto em uma lista de palavras, a fim de possibilitar a aplicação das técnicas de TF-IDF em um modelo vetorial.\n",
"\n",
- "### Transformação de minúsculos\n",
+ " \n",
"\n",
- " "
+ "### Remoção de palavras e transformação de minúsculos\n"
]
},
{
"cell_type": "code",
- "execution_count": 4,
+ "execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
@@ -337,8 +171,7 @@
"# ([^\\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['text'].replace(r'(\\\\[a-z])|([^\\w\\\\])|(\\S+\\d\\S+)', ' ', regex=True)\n",
- "\n",
+ "base['post'] = base['body'].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())\n"
@@ -353,51 +186,60 @@
"\n",
"### Tokenização e Lemmatizer\n",
"\n",
- ""
+ "**Tokenização:** A tokenização de texto é o processo de dividir um texto em unidades menores, chamadas de tokens. Esses tokens podem ser palavras individuais, caracteres, frases ou até mesmo partes específicas de um texto, dependendo do contexto e das necessidades do processamento de linguagem natural. \n",
+ "\n",
+ "**Lemmatize:** A lematização de texto é um processo linguístico que visa reduzir as palavras em sua forma base ou forma lematizada. O objetivo é transformar palavras flexionadas em sua forma canônica, chamada de \"lema\" ou \"base\". Por exemplo, a lematização transforma palavras como \"correndo\" em \"correr\", \"carros\" em \"carro\" e assim por diante."
]
},
{
"cell_type": "code",
- "execution_count": 5,
+ "execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- "0 path cantaloupe srv c cmu edu rochester udel g...\n",
- "1 path from myoakam ci ohio state edu micah r yo...\n",
- "2 path from maureen l eagle newsgroup misc forsa...\n",
- "3 newsgroup misc forsale path from mike diack mi...\n",
- "4 path from jvinson xsoft xerox com jeffrey a vi...\n",
- " ... \n",
- "1095 xref cantaloupe srv c cmu edu newsgroup misc w...\n",
- "1096 newsgroup misc forsale subject want lcd overhe...\n",
- "1097 newsgroup ingr forsale hsv forsale misc forsal...\n",
- "1098 newsgroup misc forsale path cantaloupe srv c c...\n",
- "1099 xref cantaloupe srv c cmu edu path from scott ...\n",
- "Name: post, Length: 1100, dtype: object"
+ "0 todd steve write chuck petch write now it appe...\n",
+ "1 boston globe wednesday april 21 col 4 bodie fo...\n",
+ "2 nl chicago wait til next year new york bunch o...\n",
+ "3 i recent had a case of shingle and my doctor w...\n",
+ "4 for sale 2 amiga commodore amiga best offer ra...\n",
+ " ... \n",
+ "11972 in article huston acces digex com herb huston ...\n",
+ "11973 i just start read thi newsgroup and haven t be...\n",
+ "11974 blesed are those who hunger and thirst for rig...\n",
+ "11975 i m curiou to know if christia ever read book ...\n",
+ "11976 in article prl csi dit csiro au peter lamb wri...\n",
+ "Name: post, Length: 11977, dtype: object"
]
},
- "execution_count": 5,
+ "execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
- "from ir.preprocessing import lemmatize_word\n",
+ "base['post'] = base['post'].apply(lambda x: ' '.join([lemmatize_word(word.lower()) for word in x.split()]))"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Identificação das query / docs\n",
"\n",
- "base['post'].apply(lambda x: ' '.join([lemmatize_word(word.lower()) for word in x.split()]))"
+ "Foi feita uma separação do index das query, para pode fazer uma localização do na base origina após o TF-IDF, dado que o TF-IDF reseta os index dos termos por documento"
]
},
{
"cell_type": "code",
- "execution_count": 6,
+ "execution_count": 36,
"metadata": {},
"outputs": [],
"source": [
- "from ir import tf_idf\n",
- "\n",
- "weight = tf_idf.tfidf(base, 'post').iloc[1:]\n"
+ "d_index = base.query('tag==\"doc\"').index\n",
+ "q_index = base.query('tag==\"query\"').index"
]
},
{
@@ -405,434 +247,298 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "### Identificação das query / docs"
+ "## Processamento dos dados\n",
+ "\n",
+ "Aplicação das técnicas estatísticas no conjunto de palavras por documento\n",
+ "\n",
+ "### TF IDF\n",
+ "\n",
+ "TF-IDF (Term Frequency-Inverse Document Frequency) é uma medida estatística usada para avaliar a importância de um termo em um documento em relação a uma coleção de documentos. É amplamente utilizado em processamento de linguagem natural e recuperação de informações.\n",
+ "\n",
+ "O TF-IDF é calculado levando em consideração dois fatores principais:\n",
+ "\n",
+ "Frequência do termo (TF - Term Frequency): Mede a frequência com que um termo específico aparece em um documento. Quanto mais vezes um termo aparece, maior é sua relevância no documento.\n",
+ "\n",
+ "Frequência inversa do documento (IDF - Inverse Document Frequency): Mede a raridade de um termo em relação a uma coleção de documentos. Quanto menos frequente um termo é em outros documentos da coleção, maior é o seu valor IDF e maior será seu peso para distinguir a importância desse termo no documento atual.\n",
+ "\n",
+ "O TF-IDF é calculado multiplicando-se o TF pelo IDF para cada termo em um documento. Dessa forma, termos frequentes no documento e raros na coleção terão um valor TF-IDF mais alto, indicando sua relevância para o documento em questão.\n",
+ "\n",
+ "Essa medida é amplamente utilizada em tarefas como recuperação de informações, classificação de texto, sumarização automática e agrupamento de documentos."
]
},
{
"cell_type": "code",
- "execution_count": 36,
+ "execution_count": null,
"metadata": {},
"outputs": [],
"source": [
- "d_index = base.query('tag==\"doc\"').index\n",
- "q_index = base.query('tag==\"query\"').index"
+ "weights = tfidf(base, 'post').T"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Ranqueamento\n",
+ "\n",
+ "O ranqueamento de documentos utilizando o TF-IDF (Term Frequency-Inverse Document Frequency) é um método utilizado para ordenar documentos em uma coleção com base na relevância em relação a uma consulta de busca.\n",
+ "\n",
+ "Nesse método, cada documento é representado por um vetor numérico, no qual cada dimensão corresponde a um termo presente na coleção de documentos. O valor de cada dimensão é calculado utilizando a fórmula do TF-IDF, que leva em consideração a frequência do termo no documento e a raridade do termo na coleção."
]
},
{
"cell_type": "code",
- "execution_count": 145,
+ "execution_count": null,
"metadata": {},
"outputs": [],
"source": [
- "import itertools\n",
- "\n",
- "similarity = dict()\n",
- "index_matrix = dict()\n",
- "rank_matrix = dict()\n",
+ "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": null,
+ "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": [
+ "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",
- "for j in q_index:\n",
- " for i in d_index: \n",
- " numerator = np.sum( weight.loc[:,i] * weight.loc[: , j])\n",
- " denominator = np.linalg.norm(weight.loc[:,i])*np.linalg.norm(weight.loc[:,1019])\n",
- " similarity[i] = numerator/denominator\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\n",
"\n",
- " rank_matrix[j] = pd.DataFrame(similarity.values(), columns=['rank']).sort_values(by='rank', ascending=False).head(10).values.tolist()\n",
- " index_matrix[j] = pd.DataFrame(similarity.values(), columns=['rank']).sort_values(by='rank', ascending=False).head(10).index.to_list()\n",
+ "P@N: essa métrica mede a proporção de documentos relevantes presentes entre os 10 primeiros resultados retornados por um sistema de busca em resposta a uma consulta.\n",
"\n",
- " \n"
+ "MAP (Mean Average Precision): o MAP leva em consideração a precisão e a ordenação dos resultados retornados por um sistema de busca em relação a um conjunto de consultas. Ele mede a média das precisões médias de cada consulta."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def calcular_p_n_media(resultados_relevantes, resultados_sistema, n):\n",
+ " \"\"\"\n",
+ " Calcula a média da precisão P@n para um conjunto de consultas e seus resultados relevantes.\n",
+ "\n",
+ " Parâmetros:\n",
+ " - resultados_relevantes (dict): Um dicionário que mapeia cada consulta aos seus resultados relevantes.\n",
+ " - resultados_sistema (dict): Um dicionário que mapeia cada consulta aos resultados retornados pelo sistema.\n",
+ " - n (int): O número de resultados a considerar para o cálculo da precisão.\n",
+ "\n",
+ " Retorno:\n",
+ " - p_n_media (float): A média da precisão P@n para todas as consultas.\n",
+ "\n",
+ " \"\"\"\n",
+ " def calcular_p_n(resultados, relevantes):\n",
+ " \"\"\"\n",
+ " Calcula a precisão P@n para uma lista de resultados e seus resultados relevantes.\n",
+ "\n",
+ " Parâmetros:\n",
+ " - resultados (list): Uma lista de resultados retornados pelo sistema.\n",
+ " - relevantes (list): Uma lista de resultados relevantes para a consulta.\n",
+ "\n",
+ " Retorno:\n",
+ " - p_n (float): A precisão P@n.\n",
+ "\n",
+ " \"\"\"\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"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "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": 153,
+ "execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
- "text/html": [
- "\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " | \n",
- " 1000 | \n",
- " 1001 | \n",
- " 1002 | \n",
- " 1003 | \n",
- " 1004 | \n",
- " 1005 | \n",
- " 1006 | \n",
- " 1007 | \n",
- " 1008 | \n",
- " 1009 | \n",
- " ... | \n",
- " 1090 | \n",
- " 1091 | \n",
- " 1092 | \n",
- " 1093 | \n",
- " 1094 | \n",
- " 1095 | \n",
- " 1096 | \n",
- " 1097 | \n",
- " 1098 | \n",
- " 1099 | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " 0 | \n",
- " [0.6422584945103841] | \n",
- " [0.668743974268336] | \n",
- " [1.008422835773131] | \n",
- " [0.6661363151210968] | \n",
- " [0.8642602181331219] | \n",
- " [0.7417012424961686] | \n",
- " [0.7315442686011049] | \n",
- " [0.9460833202189584] | \n",
- " [0.9746037822064916] | \n",
- " [0.6869123604148133] | \n",
- " ... | \n",
- " [1.1523833456270243] | \n",
- " [0.7956243694544436] | \n",
- " [1.7802942925566625] | \n",
- " [0.5158809769289813] | \n",
- " [0.5234239788184921] | \n",
- " [0.8038496213979783] | \n",
- " [0.6360279187397326] | \n",
- " [1.1259044435676868] | \n",
- " [1.0616162379284384] | \n",
- " [0.6784846202202287] | \n",
- "
\n",
- " \n",
- " 1 | \n",
- " [0.2873172889001637] | \n",
- " [0.17456679249116952] | \n",
- " [0.6332470445844255] | \n",
- " [0.09678526898308248] | \n",
- " [0.537824913541413] | \n",
- " [0.2820702175096787] | \n",
- " [0.6513139955405113] | \n",
- " [0.3597970619791958] | \n",
- " [0.24900044829809295] | \n",
- " [0.14368626326554504] | \n",
- " ... | \n",
- " [0.42456045151374616] | \n",
- " [0.13839258426540738] | \n",
- " [0.1920094056436893] | \n",
- " [0.4608108432879023] | \n",
- " [0.46754863207460967] | \n",
- " [0.635942460180357] | \n",
- " [0.2673113797648495] | \n",
- " [0.09064837068978648] | \n",
- " [0.19426228087688888] | \n",
- " [0.17427577670397354] | \n",
- "
\n",
- " \n",
- " 2 | \n",
- " [0.19584221062188678] | \n",
- " [0.1319897299803032] | \n",
- " [0.08491363433325547] | \n",
- " [0.08737476357264361] | \n",
- " [0.47799964699339453] | \n",
- " [0.20691840972537448] | \n",
- " [0.0713300455225047] | \n",
- " [0.18078764107798664] | \n",
- " [0.11093369090167131] | \n",
- " [0.09580043962698802] | \n",
- " ... | \n",
- " [0.39006994534248846] | \n",
- " [0.09497709201044909] | \n",
- " [0.17705994384084703] | \n",
- " [0.1911406606344065] | \n",
- " [0.19471247373710213] | \n",
- " [0.6126542869398587] | \n",
- " [0.06788233871189489] | \n",
- " [0.07823702305427702] | \n",
- " [0.17319361461646068] | \n",
- " [0.07447944169226609] | \n",
- "
\n",
- " \n",
- " 3 | \n",
- " [0.13903116434341475] | \n",
- " [0.10146093652625415] | \n",
- " [0.08181050400129704] | \n",
- " [0.07523129301857605] | \n",
- " [0.18045913119908524] | \n",
- " [0.20260530333012666] | \n",
- " [0.054813355262948726] | \n",
- " [0.16776960486431058] | \n",
- " [0.10031171790840715] | \n",
- " [0.07826399750895882] | \n",
- " ... | \n",
- " [0.2509003350905366] | \n",
- " [0.08889171346193057] | \n",
- " [0.16005754765559338] | \n",
- " [0.053302833660593664] | \n",
- " [0.053302833660593664] | \n",
- " [0.2514441707424639] | \n",
- " [0.06610690581400588] | \n",
- " [0.07732220562999899] | \n",
- " [0.17148587761263784] | \n",
- " [0.04757751873987604] | \n",
- "
\n",
- " \n",
- " 4 | \n",
- " [0.1129173777348391] | \n",
- " [0.08606053698831793] | \n",
- " [0.07547569629425901] | \n",
- " [0.06970411933742698] | \n",
- " [0.17135272355687187] | \n",
- " [0.20091765863852995] | \n",
- " [0.05469328989879712] | \n",
- " [0.16743762657989103] | \n",
- " [0.09811418008672529] | \n",
- " [0.07488273104320195] | \n",
- " ... | \n",
- " [0.1456676671253771] | \n",
- " [0.08031528425526144] | \n",
- " [0.1591723994058402] | \n",
- " [0.05187299077727413] | \n",
- " [0.04876597436921601] | \n",
- " [0.24540764374264745] | \n",
- " [0.064867860088572] | \n",
- " [0.07458882712067232] | \n",
- " [0.1268769662336863] | \n",
- " [0.04675221931850179] | \n",
- "
\n",
- " \n",
- " 5 | \n",
- " [0.11038217708080131] | \n",
- " [0.08212202043548315] | \n",
- " [0.07432402899651668] | \n",
- " [0.06957535331034335] | \n",
- " [0.11414112796082569] | \n",
- " [0.09766529639479365] | \n",
- " [0.05342228639423025] | \n",
- " [0.11293055713592527] | \n",
- " [0.09499508593239105] | \n",
- " [0.07351917900522721] | \n",
- " ... | \n",
- " [0.1356468036645224] | \n",
- " [0.07846954905194828] | \n",
- " [0.15849239426755599] | \n",
- " [0.04462161696830591] | \n",
- " [0.04472544383210234] | \n",
- " [0.2051558258313172] | \n",
- " [0.06082789393903154] | \n",
- " [0.06855422701443233] | \n",
- " [0.08964124013628569] | \n",
- " [0.043706874358644336] | \n",
- "
\n",
- " \n",
- " 6 | \n",
- " [0.10833574384967115] | \n",
- " [0.08201334401786602] | \n",
- " [0.07412645164725896] | \n",
- " [0.06759708576024981] | \n",
- " [0.09130509649851562] | \n",
- " [0.08716787810262448] | \n",
- " [0.0497899252125642] | \n",
- " [0.09487498299853164] | \n",
- " [0.08477817264550953] | \n",
- " [0.06935710726422203] | \n",
- " ... | \n",
- " [0.13395484290588885] | \n",
- " [0.07651073480529516] | \n",
- " [0.14400058142958222] | \n",
- " [0.04329534404644248] | \n",
- " [0.04462161696830591] | \n",
- " [0.10677052218571517] | \n",
- " [0.05830025911923057] | \n",
- " [0.06718300838215913] | \n",
- " [0.08292563259802246] | \n",
- " [0.04288337427490202] | \n",
- "
\n",
- " \n",
- " 7 | \n",
- " [0.09458970277908005] | \n",
- " [0.08147133735902357] | \n",
- " [0.07118734960890093] | \n",
- " [0.06755116098175724] | \n",
- " [0.08423578168208135] | \n",
- " [0.08564850087282809] | \n",
- " [0.04712198065394311] | \n",
- " [0.08900364470414873] | \n",
- " [0.0845410509094711] | \n",
- " [0.06696048135598477] | \n",
- " ... | \n",
- " [0.12832106795670173] | \n",
- " [0.0742473891955823] | \n",
- " [0.1337598250032541] | \n",
- " [0.03987922316585672] | \n",
- " [0.04329534404644248] | \n",
- " [0.08913041300626738] | \n",
- " [0.05705502660231897] | \n",
- " [0.06310045914518085] | \n",
- " [0.07445114613146177] | \n",
- " [0.04255318648575154] | \n",
- "
\n",
- " \n",
- " 8 | \n",
- " [0.06683185055384143] | \n",
- " [0.08107329389309223] | \n",
- " [0.06992507760853946] | \n",
- " [0.0665144106585746] | \n",
- " [0.07732918671239193] | \n",
- " [0.07767329982049115] | \n",
- " [0.04496152399683175] | \n",
- " [0.07886393345966285] | \n",
- " [0.08159272098702083] | \n",
- " [0.0655222722939256] | \n",
- " ... | \n",
- " [0.12560417304820823] | \n",
- " [0.07411198929338968] | \n",
- " [0.1331408833577327] | \n",
- " [0.03857993879037075] | \n",
- " [0.038711425869337984] | \n",
- " [0.08897777442428674] | \n",
- " [0.05560594182068467] | \n",
- " [0.0626845924656044] | \n",
- " [0.07237739511197822] | \n",
- " [0.041613779283231046] | \n",
- "
\n",
- " \n",
- " 9 | \n",
- " [0.06139453131422424] | \n",
- " [0.07948227337943198] | \n",
- " [0.06689020592169981] | \n",
- " [0.05955785852513209] | \n",
- " [0.07517277782794342] | \n",
- " [0.07765247541664737] | \n",
- " [0.04318953773752061] | \n",
- " [0.07531732464870161] | \n",
- " [0.08098184954929952] | \n",
- " [0.06458414852590263] | \n",
- " ... | \n",
- " [0.12278663409161311] | \n",
- " [0.07365677105558269] | \n",
- " [0.13062404036287226] | \n",
- " [0.03855871951859559] | \n",
- " [0.03855871951859559] | \n",
- " [0.08461722594983144] | \n",
- " [0.053320319118708596] | \n",
- " [0.06258022212397257] | \n",
- " [0.07103356433858925] | \n",
- " [0.04145958334073781] | \n",
- "
\n",
- " \n",
- "
\n",
- "
10 rows × 100 columns
\n",
- "
"
- ],
"text/plain": [
- " 1000 1001 1002 \n",
- "0 [0.6422584945103841] [0.668743974268336] [1.008422835773131] \\\n",
- "1 [0.2873172889001637] [0.17456679249116952] [0.6332470445844255] \n",
- "2 [0.19584221062188678] [0.1319897299803032] [0.08491363433325547] \n",
- "3 [0.13903116434341475] [0.10146093652625415] [0.08181050400129704] \n",
- "4 [0.1129173777348391] [0.08606053698831793] [0.07547569629425901] \n",
- "5 [0.11038217708080131] [0.08212202043548315] [0.07432402899651668] \n",
- "6 [0.10833574384967115] [0.08201334401786602] [0.07412645164725896] \n",
- "7 [0.09458970277908005] [0.08147133735902357] [0.07118734960890093] \n",
- "8 [0.06683185055384143] [0.08107329389309223] [0.06992507760853946] \n",
- "9 [0.06139453131422424] [0.07948227337943198] [0.06689020592169981] \n",
- "\n",
- " 1003 1004 1005 \n",
- "0 [0.6661363151210968] [0.8642602181331219] [0.7417012424961686] \\\n",
- "1 [0.09678526898308248] [0.537824913541413] [0.2820702175096787] \n",
- "2 [0.08737476357264361] [0.47799964699339453] [0.20691840972537448] \n",
- "3 [0.07523129301857605] [0.18045913119908524] [0.20260530333012666] \n",
- "4 [0.06970411933742698] [0.17135272355687187] [0.20091765863852995] \n",
- "5 [0.06957535331034335] [0.11414112796082569] [0.09766529639479365] \n",
- "6 [0.06759708576024981] [0.09130509649851562] [0.08716787810262448] \n",
- "7 [0.06755116098175724] [0.08423578168208135] [0.08564850087282809] \n",
- "8 [0.0665144106585746] [0.07732918671239193] [0.07767329982049115] \n",
- "9 [0.05955785852513209] [0.07517277782794342] [0.07765247541664737] \n",
- "\n",
- " 1006 1007 1008 \n",
- "0 [0.7315442686011049] [0.9460833202189584] [0.9746037822064916] \\\n",
- "1 [0.6513139955405113] [0.3597970619791958] [0.24900044829809295] \n",
- "2 [0.0713300455225047] [0.18078764107798664] [0.11093369090167131] \n",
- "3 [0.054813355262948726] [0.16776960486431058] [0.10031171790840715] \n",
- "4 [0.05469328989879712] [0.16743762657989103] [0.09811418008672529] \n",
- "5 [0.05342228639423025] [0.11293055713592527] [0.09499508593239105] \n",
- "6 [0.0497899252125642] [0.09487498299853164] [0.08477817264550953] \n",
- "7 [0.04712198065394311] [0.08900364470414873] [0.0845410509094711] \n",
- "8 [0.04496152399683175] [0.07886393345966285] [0.08159272098702083] \n",
- "9 [0.04318953773752061] [0.07531732464870161] [0.08098184954929952] \n",
- "\n",
- " 1009 ... 1090 1091 \n",
- "0 [0.6869123604148133] ... [1.1523833456270243] [0.7956243694544436] \\\n",
- "1 [0.14368626326554504] ... [0.42456045151374616] [0.13839258426540738] \n",
- "2 [0.09580043962698802] ... [0.39006994534248846] [0.09497709201044909] \n",
- "3 [0.07826399750895882] ... [0.2509003350905366] [0.08889171346193057] \n",
- "4 [0.07488273104320195] ... [0.1456676671253771] [0.08031528425526144] \n",
- "5 [0.07351917900522721] ... [0.1356468036645224] [0.07846954905194828] \n",
- "6 [0.06935710726422203] ... [0.13395484290588885] [0.07651073480529516] \n",
- "7 [0.06696048135598477] ... [0.12832106795670173] [0.0742473891955823] \n",
- "8 [0.0655222722939256] ... [0.12560417304820823] [0.07411198929338968] \n",
- "9 [0.06458414852590263] ... [0.12278663409161311] [0.07365677105558269] \n",
- "\n",
- " 1092 1093 1094 \n",
- "0 [1.7802942925566625] [0.5158809769289813] [0.5234239788184921] \\\n",
- "1 [0.1920094056436893] [0.4608108432879023] [0.46754863207460967] \n",
- "2 [0.17705994384084703] [0.1911406606344065] [0.19471247373710213] \n",
- "3 [0.16005754765559338] [0.053302833660593664] [0.053302833660593664] \n",
- "4 [0.1591723994058402] [0.05187299077727413] [0.04876597436921601] \n",
- "5 [0.15849239426755599] [0.04462161696830591] [0.04472544383210234] \n",
- "6 [0.14400058142958222] [0.04329534404644248] [0.04462161696830591] \n",
- "7 [0.1337598250032541] [0.03987922316585672] [0.04329534404644248] \n",
- "8 [0.1331408833577327] [0.03857993879037075] [0.038711425869337984] \n",
- "9 [0.13062404036287226] [0.03855871951859559] [0.03855871951859559] \n",
- "\n",
- " 1095 1096 1097 \n",
- "0 [0.8038496213979783] [0.6360279187397326] [1.1259044435676868] \\\n",
- "1 [0.635942460180357] [0.2673113797648495] [0.09064837068978648] \n",
- "2 [0.6126542869398587] [0.06788233871189489] [0.07823702305427702] \n",
- "3 [0.2514441707424639] [0.06610690581400588] [0.07732220562999899] \n",
- "4 [0.24540764374264745] [0.064867860088572] [0.07458882712067232] \n",
- "5 [0.2051558258313172] [0.06082789393903154] [0.06855422701443233] \n",
- "6 [0.10677052218571517] [0.05830025911923057] [0.06718300838215913] \n",
- "7 [0.08913041300626738] [0.05705502660231897] [0.06310045914518085] \n",
- "8 [0.08897777442428674] [0.05560594182068467] [0.0626845924656044] \n",
- "9 [0.08461722594983144] [0.053320319118708596] [0.06258022212397257] \n",
- "\n",
- " 1098 1099 \n",
- "0 [1.0616162379284384] [0.6784846202202287] \n",
- "1 [0.19426228087688888] [0.17427577670397354] \n",
- "2 [0.17319361461646068] [0.07447944169226609] \n",
- "3 [0.17148587761263784] [0.04757751873987604] \n",
- "4 [0.1268769662336863] [0.04675221931850179] \n",
- "5 [0.08964124013628569] [0.043706874358644336] \n",
- "6 [0.08292563259802246] [0.04288337427490202] \n",
- "7 [0.07445114613146177] [0.04255318648575154] \n",
- "8 [0.07237739511197822] [0.041613779283231046] \n",
- "9 [0.07103356433858925] [0.04145958334073781] \n",
- "\n",
- "[10 rows x 100 columns]"
+ "0.5882758350175267"
]
},
- "execution_count": 153,
"metadata": {},
- "output_type": "execute_result"
+ "output_type": "display_data"
}
],
"source": [
- "pd.DataFrame(rank_matrix)"
+ "def average_precision(relevantes, recomendados):\n",
+ " \"\"\"\n",
+ " Calcula a Média de Precisão (Average Precision) para um conjunto de itens relevantes e itens recomendados.\n",
+ "\n",
+ " Parâmetros:\n",
+ " - relevantes (list): Uma lista contendo os itens relevantes.\n",
+ " - recomendados (list): Uma lista contendo os itens recomendados.\n",
+ "\n",
+ " Retorno:\n",
+ " - ap (float): O valor da Média de Precisão.\n",
+ "\n",
+ " \"\"\"\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",
+ "\n",
+ "def mean_average_precision(resultados_relevantes, resultados_sistema):\n",
+ " \"\"\"\n",
+ " Calcula a Média de Precisão (MAP) para um conjunto de consultas, seus resultados relevantes e resultados retornados pelo sistema.\n",
+ "\n",
+ " Parâmetros:\n",
+ " - resultados_relevantes (dict): Um dicionário que mapeia cada consulta aos seus resultados relevantes.\n",
+ " - resultados_sistema (dict): Um dicionário que mapeia cada consulta aos resultados retornados pelo sistema.\n",
+ "\n",
+ " Retorno:\n",
+ " - map (float): O valor da Média de Precisão Média (MAP) para todas as consultas.\n",
+ "\n",
+ " \"\"\"\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"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "\n",
+ "# Aplicar o MAP nas consultas\n",
+ "mean_average_precision(resultados_relevantes, resultados_sistema)"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Conclusão: \n",
+ "\n",
+ "O modelo vetorial apresentou um valor interessante, considerando que não foram levados em conta diversos aspectos presentes no texto. Por exemplo, nos emails, não havia apenas o texto, mas também o destinatário e remetente, organização, título, datas, entre outros.\n",
+ "\n",
+ "Realizando uma recuperação bruta das palavras, foram encontrados valores suficientemente bons para os primeiros 10 arquivos.\n",
+ "\n",
+ "Em possíveis modificações, ainda há muito espaço para melhorias."
]
}
],
diff --git a/notebooks/information_retrieval_movies.ipynb b/notebooks/information_retrieval_movies.ipynb
index 45e5166..c9e0fab 100644
--- a/notebooks/information_retrieval_movies.ipynb
+++ b/notebooks/information_retrieval_movies.ipynb
@@ -5,9 +5,14 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "# Pré-Processamento dos Documentos\n",
+ "# Recuperação da informação para base de Filmes \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",
+ "Foram utilizadas as seguintes bases para o projeto\n",
+ "\n",
+ "[Disney+](https://www.kaggle.com/datasets/shivamb/disney-movies-and-tv-shows) \n",
+ "[HBO Max](https://www.kaggle.com/datasets/dgoenrique/hbo-max-movies-and-tv-shows) \n",
+ "[Netflix](https://www.kaggle.com/datasets/shivamb/netflix-shows) \n",
+ "[Amazon Prime](https://www.kaggle.com/datasets/shivamb/amazon-prime-movies-and-tv-shows) \n",
"\n",
"\n",
" "
@@ -15,7 +20,7 @@
},
{
"cell_type": "code",
- "execution_count": 9,
+ "execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
@@ -25,7 +30,9 @@
"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"
+ "import pandas as pd # Módulo para trabalhar com dataframes e séries em Python\n",
+ "\n",
+ "from ast import literal_eval\n"
]
},
{
@@ -35,14 +42,16 @@
"source": [
" \n",
"\n",
- "## Estruturação dos Arquivos\n",
+ "## Leitura dos Arquivos\n",
+ "\n",
+ "As bases vieram em formato CSV, portanto, só foi utilizado o pandas para leitura e feito um concat\n",
"\n",
" "
]
},
{
"cell_type": "code",
- "execution_count": 10,
+ "execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
@@ -71,7 +80,11 @@
"source": [
" \n",
"\n",
- "## Processamento de Texto\n",
+ "## Pré-Processamento de Texto\n",
+ "\n",
+ "Para minimizar possíveis gargalos de processamento e identificação dos termos relevantes, é realizada a remoção de ruídos utilizando regex. Em seguida, é aplicada a tokenização, que consiste na transformação do texto em uma lista de palavras, a fim de possibilitar a aplicação das técnicas de TF-IDF em um modelo vetorial.\n",
+ "\n",
+ "Além disso, foram feitas alguns processsos adicionais para possibilitar o processamento sem erros\n",
"\n",
" \n"
]
@@ -86,12 +99,11 @@
},
{
"cell_type": "code",
- "execution_count": 11,
+ "execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
- "from ast import literal_eval\n",
- "\n",
+ "# Preenchimento de NAN para variaveis de gêrenos que contém listas como elementos\n",
"base['genres'] = base['genres'].fillna('[]').apply(literal_eval).apply(lambda x: [i for i in x] if isinstance(x, list) else [])"
]
},
@@ -100,15 +112,12 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "\n",
- "### Transformação de minúsculos\n",
- "\n",
- " "
+ "### Remoção de palavras e transformação de minúsculos"
]
},
{
"cell_type": "code",
- "execution_count": 12,
+ "execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
@@ -131,12 +140,18 @@
"\n",
"### Tokenização e Lemmatizer\n",
"\n",
+ "**Tokenização:** A tokenização de texto é o processo de dividir um texto em unidades menores, chamadas de tokens. Esses tokens podem ser palavras individuais, caracteres, frases ou até mesmo partes específicas de um texto, dependendo do contexto e das necessidades do processamento de linguagem natural. \n",
+ "\n",
+ "**Lemmatize:** A lematização de texto é um processo linguístico que visa reduzir as palavras em sua forma base ou forma lematizada. O objetivo é transformar palavras flexionadas em sua forma canônica, chamada de \"lema\" ou \"base\". Por exemplo, a lematização transforma palavras como \"correndo\" em \"correr\", \"carros\" em \"carro\" e assim por diante. \n",
+ "\n",
+ "### Tokenização e Lemmatizer\n",
+ "\n",
""
]
},
{
"cell_type": "code",
- "execution_count": 13,
+ "execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
@@ -150,12 +165,14 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "### Identificação das query / docs"
+ "### Identificação das query / docs\n",
+ "\n",
+ "Foi feita uma separação do index das query, para pode fazer uma localização do na base origina após o TF-IDF, dado que o TF-IDF reseta os index dos termos por documento"
]
},
{
"cell_type": "code",
- "execution_count": 14,
+ "execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
@@ -171,34 +188,58 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "### TF IDF"
+ "## Processamento dos dados\n",
+ "\n",
+ "Aplicação das técnicas estatísticas no conjunto de palavras por documento\n",
+ "\n",
+ "### TF IDF\n",
+ "\n",
+ "TF-IDF (Term Frequency-Inverse Document Frequency) é uma medida estatística usada para avaliar a importância de um termo em um documento em relação a uma coleção de documentos. É amplamente utilizado em processamento de linguagem natural e recuperação de informações.\n",
+ "\n",
+ "O TF-IDF é calculado levando em consideração dois fatores principais:\n",
+ "\n",
+ "Frequência do termo (TF - Term Frequency): Mede a frequência com que um termo específico aparece em um documento. Quanto mais vezes um termo aparece, maior é sua relevância no documento.\n",
+ "\n",
+ "Frequência inversa do documento (IDF - Inverse Document Frequency): Mede a raridade de um termo em relação a uma coleção de documentos. Quanto menos frequente um termo é em outros documentos da coleção, maior é o seu valor IDF e maior será seu peso para distinguir a importância desse termo no documento atual.\n",
+ "\n",
+ "O TF-IDF é calculado multiplicando-se o TF pelo IDF para cada termo em um documento. Dessa forma, termos frequentes no documento e raros na coleção terão um valor TF-IDF mais alto, indicando sua relevância para o documento em questão.\n",
+ "\n",
+ "Essa medida é amplamente utilizada em tarefas como recuperação de informações, classificação de texto, sumarização automática e agrupamento de documentos."
]
},
{
"cell_type": "code",
- "execution_count": 15,
+ "execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
- "from ir.tf_idf import tfidf"
+ "from ir.tf_idf import tfidf\n",
+ "\n",
+ "weights = tfidf(base, 'post').T"
]
},
{
- "cell_type": "code",
- "execution_count": 16,
+ "attachments": {},
+ "cell_type": "markdown",
"metadata": {},
- "outputs": [],
"source": [
- "weights = tfidf(base, 'post').T"
+ "## Ranqueamento\n",
+ "\n",
+ "O ranqueamento de documentos utilizando o TF-IDF (Term Frequency-Inverse Document Frequency) é um método utilizado para ordenar documentos em uma coleção com base na relevância em relação a uma consulta de busca.\n",
+ "\n",
+ "Nesse método, cada documento é representado por um vetor numérico, no qual cada dimensão corresponde a um termo presente na coleção de documentos. O valor de cada dimensão é calculado utilizando a fórmula do TF-IDF, que leva em consideração a frequência do termo no documento e a raridade do termo na coleção."
]
},
{
"cell_type": "code",
- "execution_count": 17,
+ "execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
- "from sklearn.metrics.pairwise import linear_kernel"
+ "from sklearn.metrics.pairwise import linear_kernel\n",
+ "\n",
+ "q_index = base[q_index].index\n",
+ "d_index = base[d_index].index"
]
},
{
@@ -206,60 +247,455 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "### Ranqueamento"
+ "**Importante**\n",
+ "\n",
+ "A celula abaixo trás o mesmo resultado da célula seguinte, porém, com tempo de processamente extremamente maior e maior consumo de RAM. \n",
+ "Recomendo que só seja utilizada, caso deseje compreender o funcionamento do algoritmo e caso tenha uma boa máquina para rodar o processo"
]
},
{
"cell_type": "code",
- "execution_count": 18,
+ "execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
- "q_index = base[q_index].index\n",
- "d_index = base[d_index].index"
+ "# import numpy as np\n",
+ "# from numba import njit, prange\n",
+ "# import sys\n",
+ "\n",
+ "# @njit(parallel=True)\n",
+ "# def calcular_similaridade_cosseno(vetor1, vetor2):\n",
+ "# # Verifica se os vetores têm o mesmo tamanho\n",
+ "# if len(vetor1) != len(vetor2):\n",
+ "# return 0\n",
+ " \n",
+ "# # Calcula o produto interno entre os vetores\n",
+ "# produto_interno = np.dot(vetor1, vetor2)\n",
+ " \n",
+ "# # Calcula a norma dos vetores\n",
+ "# norma_vetor1 = np.linalg.norm(vetor1)\n",
+ "# norma_vetor2 = np.linalg.norm(vetor2)\n",
+ " \n",
+ "# # Calcula a similaridade do cosseno\n",
+ "# if (norma_vetor1 * norma_vetor2) != 0: \n",
+ "# similaridade_cosseno = produto_interno / (norma_vetor1 * norma_vetor2)\n",
+ "# else: \n",
+ "# return 0\n",
+ " \n",
+ "# return similaridade_cosseno\n",
+ "\n",
+ "# rank_geral = {}\n",
+ "\n",
+ "# for q in q_index: \n",
+ "# rank = []\n",
+ "# for d in d_index: \n",
+ "# rank.append(calcular_similaridade_cosseno(weights.iloc[q].to_numpy(), weights.iloc[d].to_numpy()))\n",
+ "# print(f\"\\r query: {q} - doc: {d}\", end=\"\")\n",
+ "# sys.stdout.flush()\n",
+ " \n",
+ "# rank_geral[q] = rank\n"
]
},
{
"cell_type": "code",
- "execution_count": 23,
+ "execution_count": 11,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " 1 | \n",
+ " 2 | \n",
+ " 7 | \n",
+ " 9 | \n",
+ " 11 | \n",
+ " 12 | \n",
+ " 25 | \n",
+ " 33 | \n",
+ " 34 | \n",
+ " 35 | \n",
+ " ... | \n",
+ " 3067 | \n",
+ " 3070 | \n",
+ " 3075 | \n",
+ " 3076 | \n",
+ " 3079 | \n",
+ " 3080 | \n",
+ " 3081 | \n",
+ " 3084 | \n",
+ " 3091 | \n",
+ " 3093 | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 67.368755 | \n",
+ " 0.124803 | \n",
+ " 0.205029 | \n",
+ " 0.238001 | \n",
+ " 0.204541 | \n",
+ " 0.046762 | \n",
+ " 0.441678 | \n",
+ " 13.829039 | \n",
+ " 6.719963 | \n",
+ " 0.962032 | \n",
+ " ... | \n",
+ " 0.069073 | \n",
+ " 0.505155 | \n",
+ " 0.144191 | \n",
+ " 0.124803 | \n",
+ " 0.060839 | \n",
+ " 0.475713 | \n",
+ " 0.290585 | \n",
+ " 0.185641 | \n",
+ " 0.254428 | \n",
+ " 0.285274 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 0.282496 | \n",
+ " 13.334045 | \n",
+ " 0.343334 | \n",
+ " 14.437079 | \n",
+ " 0.475440 | \n",
+ " 0.046762 | \n",
+ " 0.394488 | \n",
+ " 0.400331 | \n",
+ " 0.404862 | \n",
+ " 14.536195 | \n",
+ " ... | \n",
+ " 0.069073 | \n",
+ " 0.601933 | \n",
+ " 0.032989 | \n",
+ " 0.000000 | \n",
+ " 0.386254 | \n",
+ " 0.447286 | \n",
+ " 0.497031 | \n",
+ " 0.461363 | \n",
+ " 0.032989 | \n",
+ " 0.343334 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 13.385497 | \n",
+ " 0.162372 | \n",
+ " 0.205030 | \n",
+ " 3.125362 | \n",
+ " 0.286482 | \n",
+ " 0.046762 | \n",
+ " 6.935597 | \n",
+ " 13.952442 | \n",
+ " 0.409103 | \n",
+ " 0.670516 | \n",
+ " ... | \n",
+ " 0.069074 | \n",
+ " 0.629949 | \n",
+ " 2.518161 | \n",
+ " 0.162372 | \n",
+ " 0.116679 | \n",
+ " 0.089682 | \n",
+ " 2.508806 | \n",
+ " 6.470416 | \n",
+ " 2.519247 | \n",
+ " 0.352836 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " 0.282496 | \n",
+ " 20.525454 | \n",
+ " 0.329257 | \n",
+ " 49.233188 | \n",
+ " 0.593763 | \n",
+ " 4.704261 | \n",
+ " 10.166065 | \n",
+ " 0.632075 | \n",
+ " 0.473186 | \n",
+ " 15.323314 | \n",
+ " ... | \n",
+ " 10.564372 | \n",
+ " 48.295855 | \n",
+ " 2.331051 | \n",
+ " 38.901016 | \n",
+ " 0.329257 | \n",
+ " 0.832429 | \n",
+ " 7.396474 | \n",
+ " 5.345418 | \n",
+ " 2.476327 | \n",
+ " 0.621255 | \n",
+ "
\n",
+ " \n",
+ " 6 | \n",
+ " 0.217132 | \n",
+ " 8.682580 | \n",
+ " 21.944596 | \n",
+ " 15.177606 | \n",
+ " 18.879542 | \n",
+ " 0.061065 | \n",
+ " 22.114967 | \n",
+ " 13.841739 | \n",
+ " 33.477328 | \n",
+ " 2.140575 | \n",
+ " ... | \n",
+ " 0.090200 | \n",
+ " 57.483639 | \n",
+ " 0.000000 | \n",
+ " 4.605783 | \n",
+ " 25.399635 | \n",
+ " 30.052399 | \n",
+ " 5.508488 | \n",
+ " 0.361942 | \n",
+ " 18.499217 | \n",
+ " 7.888895 | \n",
+ "
\n",
+ " \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " 3087 | \n",
+ " 0.000000 | \n",
+ " 11.899035 | \n",
+ " 0.046763 | \n",
+ " 0.223924 | \n",
+ " 0.187207 | \n",
+ " 0.035942 | \n",
+ " 0.398453 | \n",
+ " 13.650255 | \n",
+ " 0.160698 | \n",
+ " 0.371556 | \n",
+ " ... | \n",
+ " 5.021244 | \n",
+ " 15.244205 | \n",
+ " 0.185743 | \n",
+ " 0.124803 | \n",
+ " 0.046762 | \n",
+ " 0.035942 | \n",
+ " 0.135575 | \n",
+ " 5.139717 | \n",
+ " 35.769631 | \n",
+ " 0.271198 | \n",
+ "
\n",
+ " \n",
+ " 3088 | \n",
+ " 0.000000 | \n",
+ " 7.617485 | \n",
+ " 0.000000 | \n",
+ " 10.514286 | \n",
+ " 0.168647 | \n",
+ " 0.000000 | \n",
+ " 0.579445 | \n",
+ " 0.254428 | \n",
+ " 19.564213 | \n",
+ " 12.294900 | \n",
+ " ... | \n",
+ " 11.941905 | \n",
+ " 8.180735 | \n",
+ " 2.145308 | \n",
+ " 0.410559 | \n",
+ " 0.371777 | \n",
+ " 11.941905 | \n",
+ " 2.274933 | \n",
+ " 0.124803 | \n",
+ " 10.217196 | \n",
+ " 20.962194 | \n",
+ "
\n",
+ " \n",
+ " 3089 | \n",
+ " 0.000000 | \n",
+ " 4.985943 | \n",
+ " 0.000000 | \n",
+ " 3.021603 | \n",
+ " 0.168647 | \n",
+ " 0.000000 | \n",
+ " 0.207668 | \n",
+ " 0.129625 | \n",
+ " 0.129625 | \n",
+ " 0.168647 | \n",
+ " ... | \n",
+ " 0.000000 | \n",
+ " 47.407879 | \n",
+ " 68.336970 | \n",
+ " 0.000000 | \n",
+ " 0.000000 | \n",
+ " 0.000000 | \n",
+ " 51.419169 | \n",
+ " 0.000000 | \n",
+ " 2.313954 | \n",
+ " 0.129625 | \n",
+ "
\n",
+ " \n",
+ " 3090 | \n",
+ " 0.282496 | \n",
+ " 0.367535 | \n",
+ " 0.282496 | \n",
+ " 0.492647 | \n",
+ " 13.872681 | \n",
+ " 0.000000 | \n",
+ " 8.798456 | \n",
+ " 0.425049 | \n",
+ " 15.122352 | \n",
+ " 0.530150 | \n",
+ " ... | \n",
+ " 0.000000 | \n",
+ " 36.879271 | \n",
+ " 33.969103 | \n",
+ " 0.000000 | \n",
+ " 5.868926 | \n",
+ " 5.944035 | \n",
+ " 6.093413 | \n",
+ " 5.169273 | \n",
+ " 13.505146 | \n",
+ " 0.382128 | \n",
+ "
\n",
+ " \n",
+ " 3092 | \n",
+ " 0.217132 | \n",
+ " 7.786898 | \n",
+ " 0.295215 | \n",
+ " 11.161694 | \n",
+ " 5.436608 | \n",
+ " 0.062099 | \n",
+ " 34.829182 | \n",
+ " 5.381177 | \n",
+ " 0.350252 | \n",
+ " 0.400540 | \n",
+ " ... | \n",
+ " 0.078423 | \n",
+ " 29.532031 | \n",
+ " 2.824099 | \n",
+ " 0.285756 | \n",
+ " 0.700902 | \n",
+ " 0.368576 | \n",
+ " 8.224981 | \n",
+ " 0.384558 | \n",
+ " 28.515062 | \n",
+ " 0.286205 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
2165 rows × 929 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " 1 2 7 9 11 12 \n",
+ "0 67.368755 0.124803 0.205029 0.238001 0.204541 0.046762 \\\n",
+ "3 0.282496 13.334045 0.343334 14.437079 0.475440 0.046762 \n",
+ "4 13.385497 0.162372 0.205030 3.125362 0.286482 0.046762 \n",
+ "5 0.282496 20.525454 0.329257 49.233188 0.593763 4.704261 \n",
+ "6 0.217132 8.682580 21.944596 15.177606 18.879542 0.061065 \n",
+ "... ... ... ... ... ... ... \n",
+ "3087 0.000000 11.899035 0.046763 0.223924 0.187207 0.035942 \n",
+ "3088 0.000000 7.617485 0.000000 10.514286 0.168647 0.000000 \n",
+ "3089 0.000000 4.985943 0.000000 3.021603 0.168647 0.000000 \n",
+ "3090 0.282496 0.367535 0.282496 0.492647 13.872681 0.000000 \n",
+ "3092 0.217132 7.786898 0.295215 11.161694 5.436608 0.062099 \n",
+ "\n",
+ " 25 33 34 35 ... 3067 3070 \n",
+ "0 0.441678 13.829039 6.719963 0.962032 ... 0.069073 0.505155 \\\n",
+ "3 0.394488 0.400331 0.404862 14.536195 ... 0.069073 0.601933 \n",
+ "4 6.935597 13.952442 0.409103 0.670516 ... 0.069074 0.629949 \n",
+ "5 10.166065 0.632075 0.473186 15.323314 ... 10.564372 48.295855 \n",
+ "6 22.114967 13.841739 33.477328 2.140575 ... 0.090200 57.483639 \n",
+ "... ... ... ... ... ... ... ... \n",
+ "3087 0.398453 13.650255 0.160698 0.371556 ... 5.021244 15.244205 \n",
+ "3088 0.579445 0.254428 19.564213 12.294900 ... 11.941905 8.180735 \n",
+ "3089 0.207668 0.129625 0.129625 0.168647 ... 0.000000 47.407879 \n",
+ "3090 8.798456 0.425049 15.122352 0.530150 ... 0.000000 36.879271 \n",
+ "3092 34.829182 5.381177 0.350252 0.400540 ... 0.078423 29.532031 \n",
+ "\n",
+ " 3075 3076 3079 3080 3081 3084 \n",
+ "0 0.144191 0.124803 0.060839 0.475713 0.290585 0.185641 \\\n",
+ "3 0.032989 0.000000 0.386254 0.447286 0.497031 0.461363 \n",
+ "4 2.518161 0.162372 0.116679 0.089682 2.508806 6.470416 \n",
+ "5 2.331051 38.901016 0.329257 0.832429 7.396474 5.345418 \n",
+ "6 0.000000 4.605783 25.399635 30.052399 5.508488 0.361942 \n",
+ "... ... ... ... ... ... ... \n",
+ "3087 0.185743 0.124803 0.046762 0.035942 0.135575 5.139717 \n",
+ "3088 2.145308 0.410559 0.371777 11.941905 2.274933 0.124803 \n",
+ "3089 68.336970 0.000000 0.000000 0.000000 51.419169 0.000000 \n",
+ "3090 33.969103 0.000000 5.868926 5.944035 6.093413 5.169273 \n",
+ "3092 2.824099 0.285756 0.700902 0.368576 8.224981 0.384558 \n",
+ "\n",
+ " 3091 3093 \n",
+ "0 0.254428 0.285274 \n",
+ "3 0.032989 0.343334 \n",
+ "4 2.519247 0.352836 \n",
+ "5 2.476327 0.621255 \n",
+ "6 18.499217 7.888895 \n",
+ "... ... ... \n",
+ "3087 35.769631 0.271198 \n",
+ "3088 10.217196 20.962194 \n",
+ "3089 2.313954 0.129625 \n",
+ "3090 13.505146 0.382128 \n",
+ "3092 28.515062 0.286205 \n",
+ "\n",
+ "[2165 rows x 929 columns]"
+ ]
+ },
+ "execution_count": 11,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"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)"
+ "rank_geral = pd.DataFrame(rank_geral, index=d_index, columns=q_index)\n",
+ "rank_geral"
]
},
{
"cell_type": "code",
- "execution_count": 78,
+ "execution_count": 12,
"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}"
+ "Query: 3093/3093 - Doc: 697/30922"
]
}
],
"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",
@@ -305,25 +741,52 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "### Métricas"
+ "## Métricas\n",
+ "\n",
+ "P@N: essa métrica mede a proporção de documentos relevantes presentes entre os 10 primeiros resultados retornados por um sistema de busca em resposta a uma consulta.\n",
+ "\n",
+ "MAP (Mean Average Precision): o MAP leva em consideração a precisão e a ordenação dos resultados retornados por um sistema de busca em relação a um conjunto de consultas. Ele mede a média das precisões médias de cada consulta."
]
},
{
"cell_type": "code",
- "execution_count": 89,
+ "execution_count": 13,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
- "Média do P@: 0.719268030139934\n"
+ "Média do P@: 0.7194833153928942\n"
]
}
],
"source": [
"def calcular_p_n_media(resultados_relevantes, resultados_sistema, n):\n",
+ " \"\"\"\n",
+ " Calcula a média da precisão P@n para um conjunto de consultas e seus resultados relevantes.\n",
+ "\n",
+ " Parâmetros:\n",
+ " - resultados_relevantes (dict): Um dicionário que mapeia cada consulta aos seus resultados relevantes.\n",
+ " - resultados_sistema (dict): Um dicionário que mapeia cada consulta aos resultados retornados pelo sistema.\n",
+ " - n (int): O número de resultados a considerar para o cálculo da precisão.\n",
+ "\n",
+ " Retorno:\n",
+ " - p_n_media (float): A média da precisão P@n para todas as consultas.\n",
+ "\n",
+ " \"\"\"\n",
" def calcular_p_n(resultados, relevantes):\n",
+ " \"\"\"\n",
+ " Calcula a precisão P@n para uma lista de resultados e seus resultados relevantes.\n",
+ "\n",
+ " Parâmetros:\n",
+ " - resultados (list): Uma lista de resultados retornados pelo sistema.\n",
+ " - relevantes (list): Uma lista de resultados relevantes para a consulta.\n",
+ "\n",
+ " Retorno:\n",
+ " - p_n (float): A precisão P@n.\n",
+ "\n",
+ " \"\"\"\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",
@@ -337,26 +800,22 @@
" 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}\")"
+ " return p_n_media\n"
]
},
{
"cell_type": "code",
- "execution_count": 85,
+ "execution_count": 14,
"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"
+ "Média do P@10: 0.7194833153928942\n",
+ "Média do P@20: 0.6968245425188377\n",
+ "Média do P@50: 0.6746178686759955\n",
+ "Média do P@100: 0.6589773950484382\n"
]
}
],
@@ -367,22 +826,33 @@
},
{
"cell_type": "code",
- "execution_count": 83,
+ "execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- "0.5882758350175267"
+ "0.5883161088059286"
]
},
- "execution_count": 83,
+ "execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def average_precision(relevantes, recomendados):\n",
+ " \"\"\"\n",
+ " Calcula a Média de Precisão (Average Precision) para um conjunto de itens relevantes e itens recomendados.\n",
+ "\n",
+ " Parâmetros:\n",
+ " - relevantes (list): Uma lista contendo os itens relevantes.\n",
+ " - recomendados (list): Uma lista contendo os itens recomendados.\n",
+ "\n",
+ " Retorno:\n",
+ " - ap (float): O valor da Média de Precisão.\n",
+ "\n",
+ " \"\"\"\n",
" relevancia_cumulativa = 0\n",
" precision_cumulativa = 0\n",
" num_relevantes = len(relevantes)\n",
@@ -398,7 +868,19 @@
"\n",
" return ap\n",
"\n",
+ "\n",
"def mean_average_precision(resultados_relevantes, resultados_sistema):\n",
+ " \"\"\"\n",
+ " Calcula a Média de Precisão (MAP) para um conjunto de consultas, seus resultados relevantes e resultados retornados pelo sistema.\n",
+ "\n",
+ " Parâmetros:\n",
+ " - resultados_relevantes (dict): Um dicionário que mapeia cada consulta aos seus resultados relevantes.\n",
+ " - resultados_sistema (dict): Um dicionário que mapeia cada consulta aos resultados retornados pelo sistema.\n",
+ "\n",
+ " Retorno:\n",
+ " - map (float): O valor da Média de Precisão Média (MAP) para todas as consultas.\n",
+ "\n",
+ " \"\"\"\n",
" map = 0\n",
" num_consultas = len(resultados_relevantes)\n",
"\n",
@@ -411,11 +893,31 @@
" if num_consultas > 0:\n",
" map /= num_consultas\n",
"\n",
- " return map\n",
- "\n",
+ " return map\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
"# Aplicar o MAP nas consultas\n",
- "map_result = mean_average_precision(resultados_relevantes, resultados_sistema)\n",
- "map_result"
+ "mean_average_precision(resultados_relevantes, resultados_sistema)"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Conclusão: \n",
+ "\n",
+ "O modelo vetorial apresentou valores interessante, considerando que não foram levados em conta diversos aspectos presentes na base de dados. Por exemplo, diretor, nota do IMDB, orçamento, genêro, PG e etc\n",
+ "\n",
+ "Realizando uma recuperação bruta das palavras, foram encontrados valores suficientemente bons.\n",
+ "\n",
+ "Para um projeto de recuperação da informação, é um fundamento funcional, porém pensando na expanção para um sistema de recomendação de filmes, existem diversos aspectos que podem e devem ser aprofundados em relação ao sistema apresentado."
]
}
],