{ "cells": [ { "attachments": { "imagen.png": { "image/png": "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" } }, "cell_type": "markdown", "metadata": { "id": "4zSSlTgxLAwK" }, "source": [ "![imagen.png](attachment:imagen.png)\n", "## Spacy: Named Entity Recognition Model\n", "Basado en el tutorial: https://spacy.io/universe/project/video-spacy-course-es\n", "

SpaCy es una librería de software para procesamiento de lenguajes naturales, reconocimiento de nombres de entidades, análisis de redes, visualización de datos, análisis, visual analysis, análisis de contenidos, enriching, anotación desarrollado por Matt Honnibal y programado en lenguaje Python. Licencia: Licencia MIT

" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Requirement already satisfied: spacy[transformers] in /home/jorgek/anaconda3/lib/python3.11/site-packages (3.8.2)\n", "Requirement already satisfied: spacy-legacy<3.1.0,>=3.0.11 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from spacy[transformers]) (3.0.12)\n", "Requirement already satisfied: spacy-loggers<2.0.0,>=1.0.0 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from spacy[transformers]) (1.0.5)\n", "Requirement already satisfied: murmurhash<1.1.0,>=0.28.0 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from spacy[transformers]) (1.0.10)\n", "Requirement already satisfied: cymem<2.1.0,>=2.0.2 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from spacy[transformers]) (2.0.8)\n", "Requirement already satisfied: preshed<3.1.0,>=3.0.2 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from spacy[transformers]) (3.0.9)\n", "Collecting thinc<8.4.0,>=8.3.0 (from spacy[transformers])\n", " Using cached thinc-8.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.9 MB)\n", "Requirement already satisfied: wasabi<1.2.0,>=0.9.1 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from spacy[transformers]) (1.1.3)\n", "Requirement already satisfied: srsly<3.0.0,>=2.4.3 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from spacy[transformers]) (2.4.8)\n", "Requirement already satisfied: catalogue<2.1.0,>=2.0.6 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from spacy[transformers]) (2.0.10)\n", "Requirement already satisfied: weasel<0.5.0,>=0.1.0 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from spacy[transformers]) (0.4.1)\n", "Requirement already satisfied: typer<1.0.0,>=0.3.0 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from spacy[transformers]) (0.12.5)\n", "Requirement already satisfied: tqdm<5.0.0,>=4.38.0 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from spacy[transformers]) (4.65.0)\n", "Requirement already satisfied: requests<3.0.0,>=2.13.0 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from spacy[transformers]) (2.29.0)\n", "Requirement already satisfied: pydantic!=1.8,!=1.8.1,<3.0.0,>=1.7.4 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from spacy[transformers]) (2.9.2)\n", "Requirement already satisfied: jinja2 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from spacy[transformers]) (3.1.2)\n", "Requirement already satisfied: setuptools in /home/jorgek/anaconda3/lib/python3.11/site-packages (from spacy[transformers]) (67.8.0)\n", "Requirement already satisfied: packaging>=20.0 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from spacy[transformers]) (23.0)\n", "Requirement already satisfied: langcodes<4.0.0,>=3.2.0 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from spacy[transformers]) (3.4.1)\n", "Requirement already satisfied: numpy>=1.19.0 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from spacy[transformers]) (2.0.2)\n", "Collecting spacy-transformers<1.4.0,>=1.1.2 (from spacy[transformers])\n", " Downloading spacy_transformers-1.3.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (197 kB)\n", "\u001b[2K \u001b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m197.7/197.7 kB\u001b[0m \u001b[31m2.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m MB/s\u001b[0m eta \u001b[36m0:00:01\u001b[0m\n", "\u001b[?25hRequirement already satisfied: language-data>=1.2 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from langcodes<4.0.0,>=3.2.0->spacy[transformers]) (1.2.0)\n", "Requirement already satisfied: annotated-types>=0.6.0 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from pydantic!=1.8,!=1.8.1,<3.0.0,>=1.7.4->spacy[transformers]) (0.7.0)\n", "Requirement already satisfied: pydantic-core==2.23.4 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from pydantic!=1.8,!=1.8.1,<3.0.0,>=1.7.4->spacy[transformers]) (2.23.4)\n", "Requirement already satisfied: typing-extensions>=4.6.1 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from pydantic!=1.8,!=1.8.1,<3.0.0,>=1.7.4->spacy[transformers]) (4.6.3)\n", "Requirement already satisfied: charset-normalizer<4,>=2 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from requests<3.0.0,>=2.13.0->spacy[transformers]) (2.0.4)\n", "Requirement already satisfied: idna<4,>=2.5 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from requests<3.0.0,>=2.13.0->spacy[transformers]) (3.4)\n", "Requirement already satisfied: urllib3<1.27,>=1.21.1 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from requests<3.0.0,>=2.13.0->spacy[transformers]) (1.26.16)\n", "Requirement already satisfied: certifi>=2017.4.17 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from requests<3.0.0,>=2.13.0->spacy[transformers]) (2023.5.7)\n", "Requirement already satisfied: transformers<4.37.0,>=3.4.0 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from spacy-transformers<1.4.0,>=1.1.2->spacy[transformers]) (4.29.2)\n", "Requirement already satisfied: torch>=1.8.0 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from spacy-transformers<1.4.0,>=1.1.2->spacy[transformers]) (2.0.1)\n", "Collecting spacy-alignments<1.0.0,>=0.7.2 (from spacy-transformers<1.4.0,>=1.1.2->spacy[transformers])\n", " Downloading spacy_alignments-0.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (313 kB)\n", "\u001b[2K \u001b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m314.0/314.0 kB\u001b[0m \u001b[31m2.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m MB/s\u001b[0m eta \u001b[36m0:00:01\u001b[0m:01\u001b[0m\n", "\u001b[?25hRequirement already satisfied: blis<1.1.0,>=1.0.0 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from thinc<8.4.0,>=8.3.0->spacy[transformers]) (1.0.1)\n", "Requirement already satisfied: confection<1.0.0,>=0.0.1 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from thinc<8.4.0,>=8.3.0->spacy[transformers]) (0.1.5)\n", "Requirement already satisfied: click>=8.0.0 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from typer<1.0.0,>=0.3.0->spacy[transformers]) (8.0.4)\n", "Requirement already satisfied: shellingham>=1.3.0 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from typer<1.0.0,>=0.3.0->spacy[transformers]) (1.5.4)\n", "Requirement already satisfied: rich>=10.11.0 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from typer<1.0.0,>=0.3.0->spacy[transformers]) (13.9.3)\n", "Requirement already satisfied: cloudpathlib<1.0.0,>=0.7.0 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from weasel<0.5.0,>=0.1.0->spacy[transformers]) (0.20.0)\n", "Requirement already satisfied: smart-open<8.0.0,>=5.2.1 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from weasel<0.5.0,>=0.1.0->spacy[transformers]) (5.2.1)\n", "Requirement already satisfied: MarkupSafe>=2.0 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from jinja2->spacy[transformers]) (2.1.1)\n", "Requirement already satisfied: marisa-trie>=0.7.7 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from language-data>=1.2->langcodes<4.0.0,>=3.2.0->spacy[transformers]) (1.2.1)\n", "Requirement already satisfied: markdown-it-py>=2.2.0 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from rich>=10.11.0->typer<1.0.0,>=0.3.0->spacy[transformers]) (2.2.0)\n", "Requirement already satisfied: pygments<3.0.0,>=2.13.0 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from rich>=10.11.0->typer<1.0.0,>=0.3.0->spacy[transformers]) (2.15.1)\n", "Requirement already satisfied: filelock in /home/jorgek/anaconda3/lib/python3.11/site-packages (from torch>=1.8.0->spacy-transformers<1.4.0,>=1.1.2->spacy[transformers]) (3.9.0)\n", "Requirement already satisfied: sympy in /home/jorgek/anaconda3/lib/python3.11/site-packages (from torch>=1.8.0->spacy-transformers<1.4.0,>=1.1.2->spacy[transformers]) (1.11.1)\n", "Requirement already satisfied: networkx in /home/jorgek/anaconda3/lib/python3.11/site-packages (from torch>=1.8.0->spacy-transformers<1.4.0,>=1.1.2->spacy[transformers]) (2.8.4)\n", "Requirement already satisfied: huggingface-hub<1.0,>=0.14.1 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from transformers<4.37.0,>=3.4.0->spacy-transformers<1.4.0,>=1.1.2->spacy[transformers]) (0.15.1)\n", "Requirement already satisfied: pyyaml>=5.1 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from transformers<4.37.0,>=3.4.0->spacy-transformers<1.4.0,>=1.1.2->spacy[transformers]) (6.0)\n", "Requirement already satisfied: regex!=2019.12.17 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from transformers<4.37.0,>=3.4.0->spacy-transformers<1.4.0,>=1.1.2->spacy[transformers]) (2022.7.9)\n", "Requirement already satisfied: tokenizers!=0.11.3,<0.14,>=0.11.1 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from transformers<4.37.0,>=3.4.0->spacy-transformers<1.4.0,>=1.1.2->spacy[transformers]) (0.13.2)\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Requirement already satisfied: fsspec in /home/jorgek/anaconda3/lib/python3.11/site-packages (from huggingface-hub<1.0,>=0.14.1->transformers<4.37.0,>=3.4.0->spacy-transformers<1.4.0,>=1.1.2->spacy[transformers]) (2023.4.0)\n", "Requirement already satisfied: mdurl~=0.1 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from markdown-it-py>=2.2.0->rich>=10.11.0->typer<1.0.0,>=0.3.0->spacy[transformers]) (0.1.0)\n", "Requirement already satisfied: mpmath>=0.19 in /home/jorgek/anaconda3/lib/python3.11/site-packages (from sympy->torch>=1.8.0->spacy-transformers<1.4.0,>=1.1.2->spacy[transformers]) (1.2.1)\n", "Installing collected packages: spacy-alignments, thinc, spacy-transformers\n", " Attempting uninstall: thinc\n", " Found existing installation: thinc 9.1.1\n", " Uninstalling thinc-9.1.1:\n", " Successfully uninstalled thinc-9.1.1\n", "Successfully installed spacy-alignments-0.9.1 spacy-transformers-1.3.5 thinc-8.3.2\n", "Note: you may need to restart the kernel to use updated packages.\n" ] } ], "source": [ "# Instalaciones necesarias\n", "#%pip install -U numpy # actualizacion de Numpy\n", "#%pip install -U spacy # instalacion y/o actualizacion de Spacy\n", "#%pip install -U h5py thinc # instalacion y/o actualizacion de h5py y thinc \n", "#%pip install -U thinc\n", "#%pip install -U spacy[transformers]" ] }, { "cell_type": "markdown", "metadata": { "id": "_3K7oE8SKaQl" }, "source": [ "## Inicio\n", "### Requerimientos: Librerias" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "id": "fcodkn0Dot0D" }, "outputs": [], "source": [ "# Librerias\n", "import spacy\n", "from spacy.lang.es import Spanish" ] }, { "cell_type": "markdown", "metadata": { "id": "Al21TRcGKt6c" }, "source": [ "### Elementos basicos para el Analisis de un texto" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "id": "RTHRlEKIo7NV" }, "outputs": [], "source": [ "# Un texto en español\n", "texto01=\"Lo que hay que saber del dólar hoy lunes 20 de marzo en Argentina, con información completa y actualizada sobre la cotización del dólar en el Banco Nación, en el mercado mayorista y los datos del Banco Central.\"\n", "texto02=\"Ella comió pizza\"" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "# Pipeline en español\n", "nlp01=Spanish()" ] }, { "cell_type": "markdown", "metadata": { "id": "l6P-keVPKyFd" }, "source": [ "## 1. El objeto DOC\n", "El objeto DOC es el resultado del procesamiento de un texto con el modelo NLP Stacy. Es una lista de palabras (incluyendo numeros y signos de puntuación). Se comporta como una lista. A cada elemento de esa lista se lo llama \"tocken\". " ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Cantidad de tokens (palabras, numeros + signos de puntuacion): 41\n" ] } ], "source": [ "# El objeto DOC: aplicacion de NLP al TEXTO\n", "doc01 = nlp01(texto01)\n", "print(\"Cantidad de tokens (palabras, numeros + signos de puntuacion):\",len(doc01))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1.1. Un token del texto\n", "Al comportarse como una lista de python, al objeto DOC simple y natural obtenerles un token desde su indice." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Obteniendo un token dentro del texto: token01= saber\n", "Obteniendo otro token dentro del texto: token02= 20\n", "Obteniendo otro token dentro del texto: token03= ,\n" ] } ], "source": [ "# Elementos desde su indice:\n", "token01=doc01[4]\n", "token02=doc01[9]\n", "token03=doc01[14]\n", "print(\"Obteniendo un token dentro del texto: token01=\",token01)\n", "print(\"Obteniendo otro token dentro del texto: token02=\",token02)\n", "print(\"Obteniendo otro token dentro del texto: token03=\",token03)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1.2. Tipo de elemento\n", "Se puede saber qué tipo de elemento es cada token: si es una palabra (is_alpha), un signo de puntuación (is_punct) o un número (is_digit)." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "token\tis_alpha\tis_digit\tis_punct\t\n", "saber\tTrue\t\tFalse\t\tFalse\t\n", "20\tFalse\t\tTrue\t\tFalse\t\n", ",\tFalse\t\tFalse\t\tTrue\t\n" ] } ], "source": [ "print(\"{}\\t{}\\t{}\\t{}\\t\".format(\"token\", \"is_alpha\", \"is_digit\", \"is_punct\"))\n", "print(\"{}\\t{}\\t\\t{}\\t\\t{}\\t\".format(token01, token01.is_alpha, token01.is_digit, token01.is_punct))\n", "print(\"{}\\t{}\\t\\t{}\\t\\t{}\\t\".format(token02, token02.is_alpha, token02.is_digit, token02.is_punct))\n", "print(\"{}\\t{}\\t\\t{}\\t\\t{}\\t\".format(token03, token03.is_alpha, token03.is_digit, token03.is_punct))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1.3. Una porcion del texto: Span\n", "Gracias a que DOC se comporta como una lista de python, para obtenerle una porcion (span) hago un slice o recorte de la lista (objeto DOC) presentando indice de inicio y fin (sin incluirlo): " ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Obteniendo una porcion del texto: Lo que hay que saber\n" ] } ], "source": [ "# Span: un recorte de la lista\n", "unSpan=doc01[0:5]\n", "print(\"Obteniendo una porcion del texto: \",unSpan)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2. Atributos Linguisticos en contexto\n", "Modelos pre-entrenados les permiten a Spacy identificar atributos linguisticos en contexto, dependencias sintacticas y entidades nominales.\n", "Por ejemplo: puede identificar si un span consiste en el nombre y apellido de una persona.
\n", "Mas informacion: https://spacy.io/usage/linguistic-features\n", "### 2.1. El paquete es_core_news_sm\n", "Contiene modelos entrenados con noticias en español. Para poder usarlo, primero debe poder descargarse.
\n", "$ python -m spacy download es_core_news_sm
\n", "El mismo puede cargarse (luego de la descarga):
\n", "spacy.load('es_core_news_sm')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2. Atributos Linguisticos en contexto\n", "Modelos pre-entrenados les permiten a Spacy identificar atributos linguisticos en contexto, dependencias sintacticas y entidades nominales.\n", "Por ejemplo: puede identificar si un span consiste en el nombre y apellido de una persona.
\n", "Mas informacion: https://spacy.io/usage/linguistic-features\n", "### 2.1. El paquete es_core_news_sm\n", "Contiene modelos entrenados con noticias en español. Para poder usarlo, primero debe poder descargarse.
\n", "El mismo puede cargarse (luego de la descarga):
\n", "spacy.load('es_core_news_sm')" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "El texto: Lo que hay que saber del dólar hoy lunes 20 de marzo en Argentina, con información completa y actualizada sobre la cotización del dólar en el Banco Nación, en el mercado mayorista y los datos del Banco Central.\n" ] } ], "source": [ "#!python -m spacy download es_core_news_sm\n", "print(\"El texto: \",texto01)\n", "# Inicialización: el pipeline\n", "nlp02 = spacy.load(\"es_core_news_sm\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2.2. Identificacion de Categorias Gramaticales (.pos_):\n", "Las categorias gramaticales (part of speech) son: Verbo, sustantivos, pronombres, adjetivos, etc. \n", "Spacy permite identificar las categorías gramaticales y las entidades nominales de las palabras de un texto." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "texto\t\tcategoria\n", "Lo\t\tPRON\t\tél\n", "que\t\tPRON\t\tque\n", "hay\t\tAUX\t\thaber\n", "que\t\tSCONJ\t\tque\n", "saber\t\tVERB\t\tsaber\n", "del\t\tADP\t\tdel\n", "dólar\t\tNOUN\t\tdólar\n", "hoy\t\tADV\t\thoy\n", "lunes\t\tNOUN\t\tlunes\n", "20\t\tNUM\t\t20\n", "de\t\tADP\t\tde\n", "marzo\t\tNOUN\t\tmarzo\n", "en\t\tADP\t\ten\n", "Argentina\t\tPROPN\t\tArgentina\n", ",\t\tPUNCT\t\t,\n", "con\t\tADP\t\tcon\n", "información\t\tNOUN\t\tinformación\n", "completa\t\tADJ\t\tcompleto\n", "y\t\tCCONJ\t\ty\n", "actualizada\t\tADJ\t\tactualizado\n", "sobre\t\tADP\t\tsobre\n", "la\t\tDET\t\tel\n", "cotización\t\tNOUN\t\tcotización\n", "del\t\tADP\t\tdel\n", "dólar\t\tNOUN\t\tdólar\n", "en\t\tADP\t\ten\n", "el\t\tDET\t\tel\n", "Banco\t\tPROPN\t\tBanco\n", "Nación\t\tPROPN\t\tNación\n", ",\t\tPUNCT\t\t,\n", "en\t\tADP\t\ten\n", "el\t\tDET\t\tel\n", "mercado\t\tNOUN\t\tmercado\n", "mayorista\t\tADJ\t\tmayorista\n", "y\t\tCCONJ\t\ty\n", "los\t\tDET\t\tel\n", "datos\t\tNOUN\t\tdato\n", "del\t\tADP\t\tdel\n", "Banco\t\tPROPN\t\tBanco\n", "Central\t\tPROPN\t\tCentral\n", ".\t\tPUNCT\t\t.\n" ] } ], "source": [ "# El objeto DOC\n", "doc01=nlp02(texto01)\n", "print(\"{}\\t\\t{}\".format(\"texto\", \"categoria\"))\n", "for token in doc01:\n", " print(\"{}\\t\\t{}\\t\\t{}\".format(token.text, token.pos_,token.lemma_))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Nota: nlp02 es una instancia de \"es_core_news_sm\". Si no lo usamos, y en su lugar utilizamos nlp01 (instancia de stacy.spanish()), veremos que no se obtienen estos resultados" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2.3. Dependencias Sintacticas (.dep_)\n", "Un analisis sintactico permite obtener sujeto y predicado, udentificando básicamente el núcleo de la oración. Spacy permite identificar estas dependencias.\n" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "texto\t\tAnalisis Sintactico\tDependencia\n", "Ella\t\tnsubj\t\t\tcomió\n", "comió\t\tROOT\t\t\tcomió\n", "pizza\t\tobj\t\t\tcomió\n" ] } ], "source": [ "# Ejemplo de dependencias sintacticas de un texto:\n", "doc02=nlp02(texto02)\n", "# -> Sujeto: --> \"Ella\"\n", "# -> Predicado: --> \"comio pizza\"\n", "# -> Nucleo: --> \"comio\"\n", "# -> Objeto Directo: --> \"pizza\"\n", "print(\"{}\\t\\t{}\\t{}\".format(\"texto\", \"Analisis Sintactico\", \"Dependencia\"))\n", "for token in doc02:\n", " print(\"{}\\t\\t{}\\t\\t\\t{}\".format(token.text, token.dep_,token.head.text))" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "token\tis_alpha\tis_digit\tis_punct\t\n", "Ella\tTrue\t\tFalse\t\tFalse\t\n", "comió\tTrue\t\tFalse\t\tFalse\t\n", "pizza\tTrue\t\tFalse\t\tFalse\t\n" ] } ], "source": [ "# Probaremos 1.2. (ver qué tipo de token es cada uno) con nlp02 aplicado al texto corto\n", "print(\"{}\\t{}\\t{}\\t{}\\t\".format(\"token\", \"is_alpha\", \"is_digit\", \"is_punct\"))\n", "print(\"{}\\t{}\\t\\t{}\\t\\t{}\\t\".format(doc02[0], doc02[0].is_alpha, doc02[0].is_digit, doc02[0].is_punct))\n", "print(\"{}\\t{}\\t\\t{}\\t\\t{}\\t\".format(doc02[1], doc02[1].is_alpha, doc02[1].is_digit, doc02[1].is_punct))\n", "print(\"{}\\t{}\\t\\t{}\\t\\t{}\\t\".format(doc02[2], doc02[2].is_alpha, doc02[2].is_digit, doc02[2].is_punct))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2.4. Nombres Propios o Entidades Nominales\n", "Spacy puede identificar nombres propios y decir que tipo de nombre propio es: locacion, organizacion, persona, entre otros. Se los llama \"entidades nominales\" (doc.ent).\n", "El nombre: ent.text\n", "El tipo: ent.label_" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Nombre\tTipo\n", "Argentina\tLOC\n", "Banco Nación\tORG\n", "Banco Central\tORG\n" ] } ], "source": [ "# Para este ejemplo utilizaremos el ejemplo de Texto01 que tiene varios nombres propios.\n", "doc03=nlp02(texto01)\n", "print(\"{}\\t{}\".format(\"Nombre\", \"Tipo\"))\n", "for ent in doc03.ents:\n", " print(\"{}\\t{}\".format(ent.text, ent.label_))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Observacion: Banco Nación fue detectado como una LOC y no como una ORG. Es por la palabra Nación. No sucede lo mismo para Banco Provincia, ni para Banco Municipal, ni Banco Provincial, ni Banco Nacional." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1. Explicacion de algunas Categorias de .pos_:\n", "Tipo\tExplicacion\n", "PRON\tpronoun\n", "AUX\tauxiliary\n", "SCONJ\tsubordinating conjunction\n", "VERB\tverb\n", "ADP\tadposition\n", "ADV\tadverb\n", "2. Explicacion de algunas Categorias de .dep_:\n", "nsubj\tnominal subject\n", "ROOT\troot\n", "noun\tobject\n", "3. Explicacion de algunas Categorias de .ent.label_:\n", "LOC: Non-GPE locations, mountain ranges, bodies of water\n", "ORG: Companies, agencies, institutions, etc.\n" ] } ], "source": [ "# Explicacion:\n", "print(\"1. Explicacion de algunas Categorias de .pos_:\")\n", "print(\"{}\\t{}\".format(\"Tipo\", \"Explicacion\"))\n", "print(\"{}\\t{}\".format(\"PRON\", spacy.explain(\"PRON\")))\n", "print(\"{}\\t{}\".format(\"AUX\", spacy.explain(\"AUX\")))\n", "print(\"{}\\t{}\".format(\"SCONJ\", spacy.explain(\"SCONJ\")))\n", "print(\"{}\\t{}\".format(\"VERB\", spacy.explain(\"VERB\")))\n", "print(\"{}\\t{}\".format(\"ADP\", spacy.explain(\"ADP\")))\n", "print(\"{}\\t{}\".format(\"ADV\", spacy.explain(\"ADV\")))\n", "print(\"2. Explicacion de algunas Categorias de .dep_:\")\n", "print(\"{}\\t{}\".format(\"nsubj\", spacy.explain(\"nsubj\")))\n", "print(\"{}\\t{}\".format(\"ROOT\", spacy.explain(\"ROOT\")))\n", "print(\"{}\\t{}\".format(\"noun\", spacy.explain(\"obj\")))\n", "print(\"3. Explicacion de algunas Categorias de .ent.label_:\")\n", "print(\"LOC: \",spacy.explain(\"LOC\"))\n", "print(\"ORG: \",spacy.explain(\"ORG\"))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3. Patrones basados en reglas\n", "Reglas para encontrar palabras y claves en el texto. A diferencia de las ReGex, Spacy trabaja sobre objetos DOC y tokens en lugar del uso de strings en las ReGex.\n", "Es mas flexible ya que no solo podemos buscar textos sino también otros atributos léxicos. Por ejemplo: encontrar \"araña\" solo si es VERBO y no si es sustantivo. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3.1. Patrones de coincidencias (Matcher)\n", "Un patrón agregado al Matcher consiste en una lista de diccionarios. Cada diccionario describe un token y sus atributos." ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "res= [(3060392928464876464, 7, 9)]\n", "Resultado: Adidas ZX\n" ] } ], "source": [ "from spacy.matcher import Matcher\n", "# nlp=spacy.load(\"es_core_news_sm\")# --> ya lo tenemos: nlp02\n", "texto03=\"Nuevos diseños de zapatillas en la colección Adidas ZX\"\n", "# Iniciar el matcher\n", "matcher01=Matcher(nlp02.vocab)\n", "# Agregar un patron al matcher\n", "patron01=[{\"TEXT\":\"Adidas\"},{\"TEXT\":\"ZX\"}]\n", "# matcher.add(\"Identificador del patron que fue buscado, callback (opcional),el patron\")\n", "matcher01.add(\"PATRON_ADIDAS\",[patron01])\n", "# procesar el texto\n", "doc04=nlp02(texto03)\n", "# aplicar el matcher01 sobre el doc\n", "res=matcher01(doc04)\n", "# que es res?:\n", "print(\"res=\",res)\n", "# ID_Patron: res[i][0]\n", "# INICIO de la coincidencia: res[i][1]\n", "# FIN de la coincidencia: res[i][2]\n", "spanRes=doc04[res[0][1]:res[0][2]]\n", "print(\"Resultado: \",spanRes)" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "¿ Quien ganó la copa Mundial FIFA 2022 ? ... Argentina\n", "¿ Quien salió segundo ? ... Francia\n" ] } ], "source": [ "# Otro ejemplo:\n", "texto04=\"Argentina ganó la copa Mundial FIFA 2022. Francia salió segundo.\"\n", "doc04=nlp02(texto04)\n", "patron01=[{\"POS\":\"PROPN\",\"OP\":\"?\"},{\"LEMMA\":\"ganar\",\"POS\":\"VERB\"},{\"LOWER\":\"la\"},{\"LOWER\":\"copa\"},{\"LOWER\":\"mundial\"},{\"LOWER\":\"fifa\"},{\"IS_DIGIT\":True},{\"IS_PUNCT\":True}]\n", "patron02=[{\"POS\":\"PROPN\",\"OP\":\"?\"},{\"LEMMA\":\"salir\",\"POS\":\"VERB\"},{\"LOWER\":\"segundo\"},{\"IS_PUNCT\":True}]\n", "matcher04a=Matcher(nlp02.vocab)\n", "matcher04a.add(\"FIFA_PATRON\",[patron01])\n", "matcher04b=Matcher(nlp02.vocab)\n", "matcher04b.add(\"FIFA_PATRON\",[patron02])\n", "res1=matcher04a(doc04)\n", "res2=matcher04b(doc04)\n", "# Preguntas:\n", "print(\"¿ Quien \",doc04[res1[0][1]+1:res1[0][2]-1],\"? ... \",doc04[res1[0][1]])\n", "print(\"¿ Quien \",doc04[res2[0][1]+1:res2[0][2]-1],\"? ... \",doc04[res2[0][1]])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 4. Estructuras de datos en Spacy\n", "### 4.1. Vocab\n", "#### Hashes en Vocab\n", "Para reducir memoria, en Vocab se almacenan los hashes de los strings y no los strings. Es por eso que se tienen que guardar la referencia bidireccional." ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "hash del string: 4509832299175612861\n", "el string hasheado es: Cerveza\n" ] } ], "source": [ "# string a hash\n", "unString=\"Cerveza\"\n", "hashString=nlp02.vocab.strings[unString]\n", "print(\"hash del string:\",hashString)\n", "# string del hash\n", "elString=nlp02.vocab.strings[hashString]\n", "print(\"el string hasheado es:\",elString)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Lexemas\n", "Un objeto Lexeme es una entrada en el vocabulario. Contiene información del contexto (a diferencia de pos_ y dep_)" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Cerveza 4509832299175612861 True\n" ] } ], "source": [ "# El lexema del sring Cerveza\n", "lexema=nlp02.vocab[unString]\n", "# imprimir los atributos del lexema\n", "print(lexema.text,lexema.orth,lexema.is_alpha)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 4.2. DOC\n", "Un DOC puede armarse a partir de una lista." ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "¿Qué hora es?\n" ] } ], "source": [ "# importamos la clase Doc\n", "from spacy.tokens import Doc\n", "# Las palabras de la frase y los espacios\n", "wordsDeUnaFrase=[\"¿\",\"Qué\",\"hora\",\"es\",\"?\"]\n", "espacios=[False,True,True,False,False]\n", "# Creación del Doc\n", "elDoc=Doc(nlp02.vocab,words=wordsDeUnaFrase,spaces=espacios)\n", "print(elDoc)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 4.3. Span\n", "Un Span es un slice (una porcion) de un doc, con al menos un tocken. Un Span también puede armarse manualmente. Argumentos: doc, inicio, fin." ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Qué hora\n" ] } ], "source": [ "# importamos la clase Span\n", "from spacy.tokens import Span\n", "# armamos el span\n", "elSpan=Span(elDoc,1,3)\n", "print(elSpan)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 5. Similitud semantica\n", "Spacy provee herramientas para calcular la similitud semantica entre docs, span y tokens.
\n", "Importante: para usar medidas de similitud semantica no alcanza con los modelos \"_sm\" sino que se requiere al menos uno mediano \"_md\" o bien el grande \"_lg\"." ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [], "source": [ "# Descargamos el modelo mediano\n", "#!python -m spacy download es_core_news_md\n", "# Inicialización: el pipeline\n", "nlp03 = spacy.load(\"es_core_news_md\")" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Texto 5 ¡Qué rica cerveza!\n", "Texto 6 ¡Qué buen vino!\n", "Similaridad(Texto 5, Texto 6)= 0.9236639738082886\n", "\n", "Texto 7 Mi celular tiene poca batería\n", "Similaridad(Texto 5, Texto 7)= 0.21833710372447968\n" ] } ], "source": [ "# recordando el string anterior:\n", "texto05=\"¡Qué rica cerveza!\"\n", "doc05=nlp03(texto05)\n", "print(\"Texto 5\",doc05)\n", "# declaro otro string\n", "\n", "texto06=\"¡Qué buen vino!\"\n", "doc06=nlp03(texto06)\n", "print(\"Texto 6\",doc06)\n", "# Imprimir la similaridad entre las frases\n", "print(\"Similaridad(Texto 5, Texto 6)=\",doc05.similarity(doc06))\n", "print(\"\")\n", "texto07=\"Mi celular tiene poca batería\"\n", "doc07=nlp03(texto07)\n", "print(\"Texto 7\",doc07)\n", "# Imprimir la similaridad entre las frases\n", "print(\"Similaridad(Texto 5, Texto 7)=\",doc05.similarity(doc07))\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pueden compararse objetos algo diferentes" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "unaParte= rica cerveza\n", "Similaridad(Texto 5, unSpan)= 0.4644829034805298\n" ] } ], "source": [ "# Obtenemos un Span de doc02\n", "unSpan=Span(doc05,2,4)\n", "print(\"unaParte =\",unSpan)\n", "# Comparamos Frase_1 con unSpan\n", "print(\"Similaridad(Texto 5, unSpan)=\",doc05.similarity(unSpan))\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 6. Combinando modelos estadisticos y reglas\n", "Usar patrones basados en modelos estadísticos (Matchers) es de utilidad al querer generalizar basado en pocos ejemplos (ver si un span es una ORG). En cambio, el uso de reglas permite trabajar sobre conjuntos finitos (por ejemplo: listado de Paises)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 6.1. Patrones basados en reglas\n", "Phrase Matcher permite hallar las coincidencias en una frase pero accediendo a los tokens. Es decir, podremos armar un patron a partir de los atributos de cada token.\n", "Pueden hallarse listas de palabras en grandes volúmenes de texto más rápida y eficientemente que el Matcher()." ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Res= []\n", "span resultado: Adidas ZX\n" ] } ], "source": [ "# Ejemplo: Dentro de una frase, hallar una subfrase con phraseMatcher()\n", "#\n", "# Importar la clase\n", "from spacy.matcher import PhraseMatcher\n", "# una frase\n", "texto07=\"Yo tengo un perro labrador dorado de 25 hg.\"\n", "doc07=nlp03(texto07)\n", "subFrase=\"labrador dorado\"\n", "docSubFrase=nlp03(subFrase)\n", "# Creo el matcher\n", "matcher=PhraseMatcher(nlp03.vocab)\n", "# El patron\n", "patron=nlp03(docSubFrase) # OBS: no hay que armar dict, solo pasar la subFrase\n", "matcher.add(\"PERRO\",[patron])\n", "# Resultado\n", "res=matcher(doc03)\n", "print(\"Res=\",res)\n", "# Mostrar Span resultado\n", "for match_id,start,end in res:\n", " spanRes=doc03[start:end]\n", "print(\"span resultado:\",spanRes)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 7. Personalizacion del Pipeline\n", "El pipeline utiliza informacion de los modelos entrenados de spacy. Sin embargo, puede agregarse mas informacion a los modelos, utiles por ejemplo para: agregar entidades.\n", "### 7.1. Componentes del pipeline\n", "* Tagger: Crea etiquetas POS entre otras\n", "* Parser: Crea etiquetas de dependencias head, dep, sent, etc\n", "* NER: Crea etiquetas nominales ent\n", "* Textcat: Clasifica al texto" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Componentes del pipeline nlp03: ['tok2vec', 'morphologizer', 'parser', 'attribute_ruler', 'lemmatizer', 'ner']\n", "Detalle del pipeline nlp03: [('tok2vec', ), ('morphologizer', ), ('parser', ), ('attribute_ruler', ), ('lemmatizer', ), ('ner', )]\n" ] } ], "source": [ "# Nombres de componentes del pipeline:\n", "print(\"Componentes del pipeline nlp03:\",nlp03.pipe_names)\n", "print(\"Detalle del pipeline nlp03:\",nlp03.pipeline)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 7.2. Componentes personalizados del Pipeline\n", "Pueden agregarse funcionalidades al Pipeline. Por ejemplo, modificar un texto. Puede agregarse metadatos personalizados a los documentos. Pueden actualizarse atributos como los doc.ents" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Pipeline: ['contarDoc', 'tok2vec', 'morphologizer', 'parser', 'attribute_ruler', 'lemmatizer', 'ner']\n" ] } ], "source": [ "# Ejemplo: Se creará una componente que imprime en pantalla la cant. de palabras del doc\n", "#\n", "# Un pipeline:\n", "nlp04=spacy.load(\"es_core_news_sm\")\n", "# La funcion:\n", "@nlp04.component(\"contarDoc\")\n", "def contarTokens (doc):\n", " # Imprime la long. del Doc:\n", " print(\"Longitud del documento: \",len(doc))\n", " return doc\n", "# Añade la componente al inicio del pipeline\n", "nlp04.add_pipe(\"contarDoc\",first=True)\n", "# Imprime los nombres de las componentes\n", "print(\"Pipeline:\",nlp04.pipe_names)" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Longitud del documento: 12\n", "Texto: Argentina ganó la copa Mundial FIFA 2022. Francia salió segundo.\n" ] } ], "source": [ "# Procesamos un texto:\n", "doc05=nlp04(texto04)\n", "print(\"Texto:\",doc05)" ] } ], "metadata": { "colab": { "name": "Named entity recognition using spacy model.ipynb", "provenance": [] }, "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.3" } }, "nbformat": 4, "nbformat_minor": 1 }