Vectores de palabras y vectores de texto

introducción

Los vectores de palabras y los vectores de texto son modelos matemáticos utilizados en el procesamiento del lenguaje natural (PLN) para representar datos de texto.

vector de palabra:

  1. Codificación One-Hot: cada palabra está representada por un vector muy largo, la longitud del vector es el tamaño del diccionario, solo un elemento es 1 y los demás son 0.
  2. TF-IDF: Considera la frecuencia de palabras en los documentos y la frecuencia inversa de los documentos en todo el corpus.
  3. Word2Vec: aprende el vector de palabras a través del modelo de red neuronal, de modo que palabras semánticamente similares también sean similares en el espacio vectorial.
  4. GloVe: vectores globales, que generan vectores de palabras basados ​​en la matriz de coocurrencia y las proporciones relativas de palabras relacionadas.
  5. FastText: Similar a Word2Vec, pero considera la subestructura de caracteres dentro de las palabras.

Vector de texto:

  1. Bolsa de palabras (BoW): el texto se representa como una colección de palabras, independientemente del orden de las palabras.
  2. TF-IDF: Cada palabra del texto está representada por su valor TF-IDF.
  3. Vectores de párrafo (Doc2Vec): similar a Word2Vec, pero tiene un único vector para todo el documento.
  4. Vectores de palabras promedio: vectores de palabras promedio de todas las palabras de un texto.
    10.BERT, GPT: utilice un modelo de lenguaje previamente entrenado para obtener el vector de incrustación de cada palabra o de la oración/párrafo completo.
  5. RNN, LSTM, GRU: para texto de secuencia, estas redes recurrentes pueden capturar la información de tiempo en el texto y generar una representación de la secuencia completa.

Los vectores de palabras y los vectores de texto se utilizan ampliamente en tareas de PNL como clasificación de texto, recuperación de información, análisis de sentimientos y traducción automática. Pueden capturar eficazmente la información semántica del texto y utilizarse en varios modelos de aprendizaje automático.

1. Vectorización de texto

  • Para la máquina, los caracteres no tienen significado, sólo la diferencia.
  • Es imposible describir la relación entre palabras y palabras, palabras y palabras, y texto y texto sólo mediante el uso de caracteres.
  • Convertir texto a vectores puede describir mejor la relación entre textos
  • Después de la vectorización, se pueden habilitar una gran cantidad de algoritmos de aprendizaje automático, lo cual es de gran valor.
  • El texto se compone de palabras y caracteres. Si desea convertir texto en vectores, primero debe poder convertir palabras y caracteres en vectores.
  • Todos los vectores deben tener la misma dimensión n, podemos llamar a este espacio de n dimensiones un espacio semántico

Yo [0,78029002 0,77010974 0,07479124 0,4106988]
Amor [0,14092194 0,63690971 0,73774712 0,42768218]
Beijing [0,95780568 0,51903789 0,7661 5855 0,6399924]
Tiananmén [0,73861383 0,49694373 0,13213538 0,41237077]

2. Codificación one-hot

La codificación One-Hot es un método para representar variables categóricas, que se utiliza a menudo en el procesamiento del lenguaje natural y otras aplicaciones de aprendizaje automático. En este esquema de codificación, cada categoría o palabra única está representada por un vector de todos 0 excepto uno en el que es 1. La posición de este "1" suele estar determinada por el índice de la palabra o categoría en el vocabulario o lista de categorías.

Por ejemplo, si tenemos un vocabulario: ['manzana', 'plátano', 'naranja'], la codificación One-Hot correspondiente puede ser la siguiente: 'manzana': [1, 0, 0] 'plátano': [
0
, 1, 0]
'naranja': [0, 0, 1]

La ventaja de la codificación One-Hot es que es simple y efectiva, pero también tiene desventajas, como que no puede capturar la relación entre palabras (por ejemplo, "manzana" y "plátano" son frutas). Además, cuando el vocabulario es grande, la codificación One-Hot puede consumir mucha memoria y recursos computacionales, ya que cada palabra requiere un vector igual al tamaño del vocabulario.

Al vectorizar texto, la frecuencia de las palabras también se puede considerar
buena buena [0, 0, 0, 1, 0]
buena buena [0, 0, 0, 2, 0]

A veces no es necesario preparar un vocabulario con anticipación y construirlo temporalmente. Por
ejemplo, para realizar tareas de comparación de texto, ingrese en pares. En este momento, la dimensión puede cambiar en cualquier momento.
inserte la descripción de la imagen aquí

codificación one-hot - desventajas

  • Si hay muchas palabras, la dimensión del vector de codificación será muy alta, el vector será muy escaso (la mayoría de las posiciones son cero) y la carga de cálculo será muy pesada (maldición de la dimensionalidad)
  • Los vectores de codificación no pueden reflejar la similitud semántica entre palabras, solo pueden distinguirlas

3. Vector de palabras: word2vec

Word2Vec es un modelo para generar vectores de palabras, propuesto por los investigadores de Google Mikolov et al. en 2013. A diferencia de la codificación One-Hot, Word2Vec genera vectores densos y de baja dimensión que pueden capturar la relación semántica entre palabras.

Word2Vec tiene dos arquitecturas principales:

  1. Skip-gram: Dada una palabra, predice su contexto.
  2. Bolsa continua de palabras (CBOW): dado un contexto, predice la palabra del medio.

Word2Vec está entrenado con una gran cantidad de datos de texto para capturar la relación de coexistencia entre palabras y codificar esta información en vectores de baja dimensión. Estos vectores tienen muchas propiedades interesantes, como que palabras similares se asignan a puntos similares en el espacio vectorial.

Por ejemplo, Word2Vec es capaz de capturar analogías como "Rey - Hombre + Mujer = Reina".

Las ventajas de Word2Vec incluyen:

  • Capture relaciones de palabras complejas.
  • La dimensión del vector es relativamente baja, lo que ahorra recursos informáticos y de almacenamiento.

Las desventajas incluyen:

  • Se requiere una gran cantidad de datos para el entrenamiento.
  • No maneja bien la polisemia en el texto.

Esperamos obtener un vector de palabras para que la relación del vector pueda reflejar la relación semántica, como:
cos (hola, hola) > cos (hola, clima)
, es decir, la similitud del significado de las palabras se refleja en la similitud de los vectores.

Rey - hombre = reina - mujer,
es decir, el vector puede reflejar la relación entre palabras mediante operaciones numéricas.

Al mismo tiempo, no importa cuántas palabras haya, la dimensión del vector debe ser fija.

3.1 Vector de palabras: basado en el modelo de lenguaje

Los métodos de generación de vectores de palabras basados ​​en modelos de lenguaje son fundamentalmente diferentes de las tecnologías de incrustación de palabras como Word2Vec. En tales métodos, los vectores de palabras se generan como subproducto de un modelo de lenguaje previamente entrenado. Estos modelos incluyen memoria a corto plazo (LSTM), unidad recurrente cerrada (GRU) o arquitecturas más avanzadas como Transformer.

La tarea principal de un modelo de lenguaje es predecir la siguiente palabra dada una secuencia de palabras. Esta predicción se basa en la información contextual de toda la secuencia de palabras. Durante el proceso de entrenamiento, los vectores de palabras aprendidos por el modelo pueden capturar información semántica y gramatical rica.

ELMo (Incrustaciones de modelos de lenguaje) y BERT (Representaciones de codificador bidireccional de Transformers) son dos métodos típicos de generación de vectores de palabras basados ​​en modelos de lenguaje.

ventaja:

  1. Puede capturar información semántica más rica y compleja, incluida la desambiguación del sentido de las palabras.
  2. Los vectores de palabras resultantes suelen ser más precisos porque las predicciones se basan en el contexto completo.
  3. Aplicable a diversas tareas de PNL, que incluyen, entre otras, clasificación de texto, reconocimiento de entidades nombradas y sistemas de respuesta a preguntas.

defecto:

  1. La complejidad computacional es alta y requiere más recursos informáticos.
  2. Debido a la complejidad de la arquitectura del modelo, se requiere cierta experiencia para su ajuste.

Las incrustaciones de palabras basadas en modelos de lenguaje se han utilizado ampliamente en muchas aplicaciones de PNL debido a su alta flexibilidad y precisión.

4 vectores de Word - word2vec basado en windows

4.1 Vector de palabras: cómo entrenar

Plantea una hipótesis:
dos palabras son semánticamente similares si aparecen en el texto con palabras similares antes y después de ellas.

como:
inserte la descripción de la imagen aquí

Con base en las ideas antes mencionadas, intentamos usar las palabras en la ventana (o las palabras circundantes) para representar (predecir) la palabra del medio.
inserte la descripción de la imagen aquí

o use la palabra del medio para indicar las palabras circundantes
inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

Incrustaciones de palabras: el problema del entrenamiento

  1. El uso de vectores one-hot en la capa de salida enfrentará la maldición de la dimensionalidad, porque el vocabulario puede ser muy extenso.
  2. convergencia lenta

códecbow.py
_

#coding:utf8

import torch
import torch.nn as nn
import numpy as np


"""
基于pytorch的词向量CBOW
模型部分
"""

class CBOW(nn.Module):
    def __init__(self, vocab_size, embedding_size, window_length):
        super(CBOW, self).__init__()
        self.word_vectors = nn.Embedding(vocab_size, embedding_size)
        self.pooling = nn.AvgPool1d(window_length)
        self.projection_layer = nn.Linear(embedding_size, vocab_size)

    def forward(self, context):
        context_embedding = self.word_vectors(context)
        context_embedding = self.pooling(context_embedding.transpose(1, 2)).squeeze()
        pred = self.projection_layer(context_embedding)
        return pred

vocab_size = 8  #词表大小
embedding_size = 4  #人为指定的向量维度
window_length = 4  #窗口长度
model = CBOW(vocab_size, embedding_size, window_length)
#假如选取一个词窗口【1,2,3,4,5】·
context = torch.LongTensor([[1,2,4,5]])
pred = model(context)  #训练目标是输出3
print("预测值:", pred)

print("词向量矩阵")
print(model.state_dict()["word_vectors.weight"])

5. Árbol de Huffman

Codifica en binario todas las palabras para que cumplan con las siguientes características

  1. Diferentes palabras se codifican de manera diferente
  2. El código de cada palabra no pasará a ser el prefijo de otro código de palabra, es decir, si una palabra está codificada como 011, no puede haber ninguna palabra codificada como 0111 o 0110 o 011001, etc.
  3. La longitud total del código de palabras construido es la más pequeña y cuanto mayor es la frecuencia, más corto es el código.

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

el código

"""
    构建霍夫曼树
"""


class HuffmanNode:
    def __init__(self, word_id, frequency):
        self.word_id = word_id  # 叶子结点存词对应的id, 中间节点存中间节点id
        self.frequency = frequency  # 存单词频次
        self.left_child = None
        self.right_child = None
        self.father = None
        self.Huffman_code = []  # 霍夫曼码(左1右0)
        self.path = []  # 根到叶子节点的中间节点id


class HuffmanTree:
    def __init__(self, wordid_frequency_dict):
        self.word_count = len(wordid_frequency_dict)  # 单词数量
        self.wordid_code = dict()
        self.wordid_path = dict()
        self.root = None
        unmerge_node_list = [HuffmanNode(wordid, frequency) for wordid, frequency in
                             wordid_frequency_dict.items()]  # 未合并节点list
        self.huffman = [HuffmanNode(wordid, frequency) for wordid, frequency in
                        wordid_frequency_dict.items()]  # 存储所有的叶子节点和中间节点
        # 构建huffman tree
        self.build_tree(unmerge_node_list)
        # 生成huffman code
        self.generate_huffman_code_and_path()

    def merge_node(self, node1, node2):
        sum_frequency = node1.frequency + node2.frequency
        mid_node_id = len(self.huffman)  # 中间节点的value存中间节点id
        father_node = HuffmanNode(mid_node_id, sum_frequency)
        if node1.frequency >= node2.frequency:
            father_node.left_child = node1
            father_node.right_child = node2
        else:
            father_node.left_child = node2
            father_node.right_child = node1
        self.huffman.append(father_node)
        return father_node

    def build_tree(self, node_list):
        while len(node_list) > 1:
            i1 = 0  # 概率最小的节点
            i2 = 1  # 概率第二小的节点
            if node_list[i2].frequency < node_list[i1].frequency:
                [i1, i2] = [i2, i1]
            for i in range(2, len(node_list)):
                if node_list[i].frequency < node_list[i2].frequency:
                    i2 = i
                    if node_list[i2].frequency < node_list[i1].frequency:
                        [i1, i2] = [i2, i1]
            father_node = self.merge_node(node_list[i1], node_list[i2])  # 合并最小的两个节点
            if i1 < i2:
                node_list.pop(i2)
                node_list.pop(i1)
            elif i1 > i2:
                node_list.pop(i1)
                node_list.pop(i2)
            else:
                raise RuntimeError('i1 should not be equal to i2')
            node_list.insert(0, father_node)  # 插入新节点
        self.root = node_list[0]

    def generate_huffman_code_and_path(self):
        stack = [self.root]
        while len(stack) > 0:
            node = stack.pop()
            # 顺着左子树走
            while node.left_child or node.right_child:
                code = node.Huffman_code
                path = node.path
                node.left_child.Huffman_code = code + [1]
                node.right_child.Huffman_code = code + [0]
                node.left_child.path = path + [node.word_id]
                node.right_child.path = path + [node.word_id]
                # 把没走过的右子树加入栈
                stack.append(node.right_child)
                node = node.left_child
            word_id = node.word_id
            word_code = node.Huffman_code
            word_path = node.path
            self.huffman[word_id].Huffman_code = word_code
            self.huffman[word_id].path = word_path
            # 把节点计算得到的霍夫曼码、路径  写入词典的数值中
            self.wordid_code[word_id] = word_code
            self.wordid_path[word_id] = word_path

    # 获取所有词的正向节点id和负向节点id数组
    def get_all_pos_and_neg_path(self):
        positive = []  # 所有词的正向路径数组
        negative = []  # 所有词的负向路径数组
        for word_id in range(self.word_count):
            pos_id = []  # 存放一个词 路径中的正向节点id
            neg_id = []  # 存放一个词 路径中的负向节点id
            for i, code in enumerate(self.huffman[word_id].Huffman_code):
                if code == 1:
                    pos_id.append(self.huffman[word_id].path[i])
                else:
                    neg_id.append(self.huffman[word_id].path[i])
            positive.append(pos_id)
            negative.append(neg_id)
        return positive, negative


def main():
    words = "你 我 他 你们 我们 他们 它们"
    freqs = "50 10 8 7 6 3 2"
    word_to_id = dict((word, i) for i, word in enumerate(words.split()))
    print(word_to_id)
    word_frequency = dict((word_to_id[x], int(y)) for x, y in zip(words.split(), freqs.split()))
    tree = HuffmanTree(word_frequency)
    word_code = dict((word, tree.wordid_code[word_to_id[word]]) for word in words.split())
    print(word_code)


if __name__ == '__main__':
    main()

6. Muestreo negativo-muestreo negativo

El entrenamiento de vectores de palabras finalmente usa softmax como función de activación para obtener la distribución de palabras predichas
en una matriz V.
Si hay muchos elementos en V, el cálculo lleva mucho tiempo.
Durante la retropropagación, actualizar todos los pesos juntos lleva mucho tiempo. .

Alternativas
En lugar de calcular la probabilidad de todas las palabras, seleccione solo ciertas palabras para calcular su probabilidad.
inserte la descripción de la imagen aquí

Utilice la función sigmoidea para calcular la probabilidad una por una, en lugar de softmax,
solo actualice la matriz de peso de la parte seleccionada de la palabra
inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

7. El guante se basa en una matriz de coocurrencia.

7.1 Vector de palabra guante

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

  • Transformación del problema:
  • Dados los vectores de palabras de tres palabras, después de que Va, Vb y Vc se asignan mediante una determinada función, la relación debe estar cerca de la relación de probabilidad de co-ocurrencia de ABC.
  • Es decir, el objetivo es encontrar un vector tal que f(Va, Vb, Vc) = P(A|B)/P(A|C)
  • El valor predicho pertenece al problema de regresión y la función de pérdida utiliza el error cuadrático medio.
  • Dado en el documento de diseño de f es f(Va, Vb, Vc) = (Va - Vb) Vc

7.2 Guante frente a word2vec

Glove permite que el modelo vea la información de todo el texto a través de la matriz de coocurrencia, mientras que el modelo word2vec ha estado mirando una ventana determinada.
inserte la descripción de la imagen aquí

8. Resumen del entrenamiento de vectores de palabras.

  1. Formular objetivos de entrenamiento basados ​​en algunas suposiciones sobre la relación entre palabras.
  2. Modelo de diseño, tome el vector de palabras como entrada
  3. Inicialice aleatoriamente el vector de palabras y comience a entrenar
  4. Durante el proceso de entrenamiento, el vector de palabras se ajusta continuamente como parámetro para obtener cierta información semántica.
  5. Utilice los vectores de palabras entrenados para tareas posteriores

Problemas con vectores de palabras:

  • Los vectores de palabras son "estáticos". Utilice un vector fijo para cada palabra, sin considerar el contexto
  • El caso de la polisemia. Sandía- Apple- Huawei
  • Hay muchos factores que afectan el efecto:
    Selección de dimensión, inicialización aleatoria, skip-gram/cbow/glove, calidad de segmentación de palabras, truncamiento de frecuencia de palabras, palabras no registradas, tamaño de ventana, número de iteraciones, condiciones de parada, calidad del corpus, etc.
  • No existen buenas métricas de evaluación directa. a menudo necesita ser evaluado con tareas posteriores

9. Aplicación de vectores de palabras

9.1 Aplicación de vectores de palabras: búsqueda de sinónimos

inserte la descripción de la imagen aquí

9.2 Aplicación de vector de palabras: vector de oración o vector de texto

  1. Dividir una oración o un fragmento de texto en varias palabras.
  2. Encuentra el vector de palabras correspondiente a cada palabra.
  3. Todos los vectores de palabras se suman y promedian o se pasan a través de varios modelos de red para obtener vectores de texto.
  4. Utilice vectores de texto para calcular similitudes o realizar agrupaciones, etc.

9.3 Aplicación de vectores de palabras - KMeans

  • Seleccione aleatoriamente k puntos como centroides iniciales
  • repetir
  • Asigne cada punto al centroide más cercano, formando k grupos
  • Vuelva a calcular los centroides para cada grupo.
  • hasta
  • El centroide no cambia

código
kmeans.py

import numpy as np
import random
import sys
'''
Kmeans算法实现
原文链接:https://blog.csdn.net/qingchedeyongqi/article/details/116806277
'''

class KMeansClusterer:  # k均值聚类
    def __init__(self, ndarray, cluster_num):
        self.ndarray = ndarray
        self.cluster_num = cluster_num
        self.points = self.__pick_start_point(ndarray, cluster_num)

    def cluster(self):
        result = []
        for i in range(self.cluster_num):
            result.append([])
        for item in self.ndarray:
            distance_min = sys.maxsize
            index = -1
            for i in range(len(self.points)):
                distance = self.__distance(item, self.points[i])
                if distance < distance_min:
                    distance_min = distance
                    index = i
            result[index] = result[index] + [item.tolist()]
        new_center = []
        for item in result:
            new_center.append(self.__center(item).tolist())
        # 中心点未改变,说明达到稳态,结束递归
        if (self.points == new_center).all():
            sum = self.__sumdis(result)
            return result, self.points, sum
        self.points = np.array(new_center)
        return self.cluster()

    def __sumdis(self,result):
        #计算总距离和
        sum=0
        for i in range(len(self.points)):
            for j in range(len(result[i])):
                sum+=self.__distance(result[i][j],self.points[i])
        return sum

    def __center(self, list):
        # 计算每一列的平均值
        return np.array(list).mean(axis=0)

    def __distance(self, p1, p2):
        #计算两点间距
        tmp = 0
        for i in range(len(p1)):
            tmp += pow(p1[i] - p2[i], 2)
        return pow(tmp, 0.5)

    def __pick_start_point(self, ndarray, cluster_num):
        if cluster_num < 0 or cluster_num > ndarray.shape[0]:
            raise Exception("簇数设置有误")
        # 取点的下标
        indexes = random.sample(np.arange(0, ndarray.shape[0], step=1).tolist(), cluster_num)
        points = []
        for index in indexes:
            points.append(ndarray[index].tolist())
        return np.array(points)

x = np.random.rand(100, 8)
kmeans = KMeansClusterer(x, 10)
result, centers, distances = kmeans.cluster()
print(result)
print(centers)
print(distances)

word2vec_kmeans.py

#!/usr/bin/env python3  
#coding: utf-8

#基于训练好的词向量模型进行聚类
#聚类采用Kmeans算法
import math
import re
import json
import jieba
import numpy as np
from gensim.models import Word2Vec
from sklearn.cluster import KMeans
from collections import defaultdict

#输入模型文件路径
#加载训练好的模型
def load_word2vec_model(path):
    model = Word2Vec.load(path)
    return model

def load_sentence(path):
    sentences = set()
    with open(path, encoding="utf8") as f:
        for line in f:
            sentence = line.strip()
            sentences.add(" ".join(jieba.cut(sentence)))
    print("获取句子数量:", len(sentences))
    return sentences

#将文本向量化
def sentences_to_vectors(sentences, model):
    vectors = []
    for sentence in sentences:
        words = sentence.split()  #sentence是分好词的,空格分开
        vector = np.zeros(model.vector_size)
        #所有词的向量相加求平均,作为句子向量
        for word in words:
            try:
                vector += model.wv[word]
            except KeyError:
                #部分词在训练中未出现,用全0向量代替
                vector += np.zeros(model.vector_size)
        vectors.append(vector / len(words))
    return np.array(vectors)


def main():
    model = load_word2vec_model("model.w2v") #加载词向量模型
    sentences = load_sentence("titles.txt")  #加载所有标题
    vectors = sentences_to_vectors(sentences, model)   #将所有标题向量化

    n_clusters = int(math.sqrt(len(sentences)))  #指定聚类数量
    print("指定聚类数量:", n_clusters)
    kmeans = KMeans(n_clusters)  #定义一个kmeans计算类
    kmeans.fit(vectors)          #进行聚类计算

    sentence_label_dict = defaultdict(list)
    for sentence, label in zip(sentences, kmeans.labels_):  #取出句子和标签
        sentence_label_dict[label].append(sentence)         #同标签的放到一起
    for label, sentences in sentence_label_dict.items():
        print("cluster %s :" % label)
        for i in range(min(10, len(sentences))):  #随便打印几个,太多了看不过来
            print(sentences[i].replace(" ", ""))
        print("---------")

if __name__ == "__main__":
    main()


Ventajas de KMeans:

  • Es rápido y puede soportar una gran cantidad de datos.
  • Cuando la muestra tiene características uniformes obvias, el efecto es bueno.

Desventajas de KMeans:
Establecer artificialmente el número de grupos.
El centro de inicialización afecta el efecto, lo que da como resultado resultados inestables. Es
sensible a muestras especiales individuales y afectará en gran medida la posición del centro del grupo.
No es adecuado para categorías múltiples o datos discretos.

Algunos consejos para utilizar KMeans:

  • Primero establezca más categorías de agrupación
  • Después de agrupar, calcule la distancia promedio dentro de la clase.
  • Después de ordenar, descarte las categorías inferiores dentro de la clase.
  • Puedes probar la distancia euclidiana, la distancia del coseno u otras distancias al calcular la distancia.
  • Para agrupar textos breves, recuerde deduplicar primero y realizar otros preprocesamientos.

10. Resumen de vectores de palabras

  1. Cambio cualitativo: convertir caracteres discretos en valores continuos
  2. La similitud de la semántica está representada por la similitud de los vectores.
  3. El entrenamiento de vectores de palabras se basa en muchas suposiciones que no son del todo correctas, pero los vectores de palabras entrenados sobre esta base son significativos.
  4. Una excelente manera de trabajar con texto sin etiquetar

Supongo que te gusta

Origin blog.csdn.net/m0_63260018/article/details/132486761
Recomendado
Clasificación