Esperaba hacer una lluvia de ideas un poco sobre el tema del almacenamiento de datos de n- gramas. En mi proyecto, estoy tratando de resolver problemas lingüísticos en los que conozco todos los elementos de datos ( n -1) y quiero adivinar estadísticamente mi n usando la interpolación lineal sobre todos los n -gramas aplicables . (Sí, hay un etiquetador que asigna etiquetas a palabras conocidas de acuerdo con su léxico y un árbol de sufijos que intenta adivinar el tipo de palabra para palabras desconocidas; el componente n -gram discutido aquí tendrá la tarea de resolver la ambigüedad).
Mi enfoque inicial sería simplemente almacenar todos los n -grams observados (para n = 1..3, es decir, monograma, bigram, trigram) datos en las respectivas bases de datos SQL y llamarlo un día. Pero los requisitos de mi proyecto pueden cambiar para incluir otras longitudes de vectores ( n ), y me gustaría que mi aplicación se adapte a 4 gramos sin mucho trabajo (actualizar el esquema, actualizar el código de la aplicación, etc.); idealmente, simplemente le diría a mi aplicación que trabaje con 4 gramos ahora sin tener que cambiar mucho el código (o nada) y entrenar sus datos de una fuente de datos determinada.
Para resumir todos los requisitos:
- Capacidad para almacenar datos de n- gramas (inicialmente para n = {1, 2, 3}
- Capacidad para cambiar qué tipos de n -grams deberían usarse (entre ejecuciones de aplicaciones)
- Capacidad para (re) entrenar datos de n- gramas (entre ejecuciones de aplicaciones)
Capacidad para consultar el almacén de datos (por ejemplo, si he observado A, B, C, me gustaría saber el elemento observado con mayor frecuencia para lo que podría seguir usando mis conjuntos de datos entrenados de 4, 3, 2 y 1 gramo )
Es probable que la aplicación tenga mucha lectura, los conjuntos de datos probablemente no se vuelvan a entrenar con tanta frecuencia
- La solución emplea .NET Framework (hasta 4.0)
Ahora, ¿qué diseño sería mejor para tal tarea?
- Una tabla fija administrada por un servidor SQL (MSSQL, MySQL, ...) para cada n (por ejemplo, tablas dedicadas para bi-gramos, tri-gramos, etc.)
- O una solución de base de datos NoSQL documento que almacena el primer n -1 como la clave del documento, y el propio documento contiene las n frecuencias de valores observados y -ésimos?
- O algo diferente?
fuente
Respuestas:
Dado que no conocerá el rango óptimo de N, definitivamente desea poder cambiarlo. Por ejemplo, si su aplicación predice la probabilidad de que cierto texto sea inglés, probablemente quiera usar caracteres N-gramos para N 3..5. (Eso es lo que encontramos experimentalmente).
No ha compartido detalles sobre su aplicación, pero el problema es lo suficientemente claro. Desea representar datos de N-gram en una base de datos relacional (o una solución basada en documentos NoSQL). Antes de sugerir una solución propia, es posible que desee echar un vistazo a los siguientes enfoques:
Ahora, al no haber leído ninguno de los enlaces anteriores, sugiero un enfoque de base de datos simple y relacional utilizando múltiples tablas, una para cada tamaño de N-gram. Puede poner todos los datos en una sola tabla con las columnas máximas necesarias (es decir, almacenar bigrams y trigrams en ngram_4, dejando las columnas finales nulas), pero recomiendo particionar los datos. Dependiendo de su motor de base de datos, una sola tabla con una gran cantidad de filas puede afectar negativamente el rendimiento.
A continuación, le daré una consulta que devolverá la siguiente palabra más probable dada todas sus tablas de ngram. Pero primero, aquí hay algunos datos de muestra que debe insertar en las tablas anteriores:
Para consultar la siguiente palabra más probable, usaría una consulta como esta.
Si agrega más tablas de ngram, deberá agregar otra cláusula UNION a la consulta anterior. Puede notar que en la primera consulta usé word1 = @ word3. Y en la segunda consulta, word1 = @ word2 AND word2 = @ word3. Eso es porque necesitamos alinear las tres palabras en la consulta para los datos de ngram. Si queremos la siguiente palabra más probable para una secuencia de tres palabras, necesitaremos verificar la primera palabra en los datos de bigramas contra la última palabra de las palabras en la secuencia.
Puede ajustar los parámetros de peso como lo desee. En este ejemplo, supuse que los "n" gramos ordinales más altos serán más confiables.
PD: Estructuraría el código del programa para manejar cualquier número de tablas ngram_N a través de la configuración. Podría cambiar declarativamente el programa para usar el rango de N-gramos N (1..6) después de crear las tablas ngram_5 y ngram_6.
fuente
ngram_2
, la frasebuilding with
tiene freq es 0.5. La misma pregunta con@bigramWeight
, ¿qué es eso? Pensé que freq es que el campo se actualizará cada vez que actualicemos la base de datos. Es decir, si el usuario ingresa más cadena, ¿se volverá a calcular la frecuencia de esta cadena? 0.5 es 0.5 por ciento en tiempo total usado o tasa de apariencia de cada frase?Al contrario de lo que sugieren los demás, sugeriría evitar cualquier estructura de datos más compleja que un hashmap o un almacén de valores clave.
Tenga en cuenta sus requisitos de acceso a datos: a) 99% de solicitudes: consulte ngram "aaa-bbb-ccc" y recupere el valor (o 0) b) 1% de solicitudes: inserte / actualice un recuento de ngram c específico) (C).
La forma más efectiva es recuperarlo con una sola búsqueda. Puede usar un separador fuera de límites (o escapado) para combinar el n-gramo completo en una sola cadena (por ejemplo, "alpha | beta | gamma" para 3gram, "alpha" para unigram, etc.) y simplemente obtener eso ( por el hash de eso). Así es como lo hace una gran cantidad de software de PNL.
Si los datos de su ngram son pequeños (digamos, <1 gb) y se ajustan en la memoria, entonces sugeriría usar una estructura de memoria eficiente en el programa (hashmaps, árboles, intentos, etc.) para evitar sobrecarga; y solo serializar / deserializar a archivos planos. Si sus datos de ngram son terabytes o más, entonces puede elegir NoSQL key-value stores split en múltiples nodos.
Para un rendimiento adicional, es posible que desee reemplazar todas las palabras en todas partes con identificadores enteros para que su algoritmo central no vea ninguna cadena (lenta); entonces es ligeramente diferente implementar la misma idea.
fuente
No es el más eficiente, pero simple y está conectado a la base de datos como lo desea:
wordpos debe tener índices en el documento y pos.
bigrams son:
Luego puede contar () y agrupar su camino a frecuencias y otras cosas.
Para cambiar a trigramas, es fácil generar esta cadena para incluir una palabra3.
He hecho esto antes en realidad (aunque el SQL allí probablemente esté un poco oxidado). Me decidí por un conjunto de archivos planos que podían buscarse fácilmente y luego fluirse del disco. Depende un poco de tu hardware cómo hacerlo mejor.
fuente
Al tratar de mejorar las búsquedas simples de mis aplicaciones para bigrams y trigrams de unigrams, esencialmente, vi su pregunta.
Si uno de los requisitos es la capacidad de consultar un sistema de archivos distribuido o una base de datos, entonces esto también puede ser interesante para usted: el documento Pibiri y Venturini 2018 "Manejo eficiente de conjuntos de datos masivos de N-Gram" describe una manera eficiente de almacenar datos de n-gram en términos de tiempo de ejecución y espacio. Ofrecieron su implementación en https://github.com/jermp/tongrams
Cada "n" de n-gramas se mantiene en una tabla separada a la que se accede mediante una función hash perfecta mínima con capacidades de selección y consulta muy rápidas. Las tablas son estáticas y están construidas por el código principal utilizando la entrada en formato de archivos de texto de n-gramas de Google.
Todavía no he usado el código, pero hay muchas maneras en que podría con sus requisitos abiertos de dónde provienen sus consultas.
Una forma: si el equivalente .NET de un servlet se usa con una base de datos o un almacén de datos, y si necesita conservar espacio de almacenamiento, almacenar cada tabla de ngram en forma binaria en la base de datos / almacén de datos como una tabla es una opción (una base de datos / tabla de almacenamiento de datos para el archivo estático resultante del código ngram eficiente para todos los 1 gramos, otro para los 2 gramos, etc. Las consultas se ejecutarían invocando el código eficiente de n-gram (envuelto para que su servlet pueda acceder a él). Es una solución para crear una base de datos distribuida que utiliza el código eficiente de n-gramas para acceder a los archivos en un sistema de archivos distribuido. Tenga en cuenta que las tablas de bases de datos / almacenes de datos binarios tienen la restricción de tamaño de archivo del sistema de archivos subyacente.
fuente