Étant donné que vous ne connaissez pas la plage optimale de N, vous voulez certainement pouvoir la changer. Par exemple, si votre application prédit la probabilité qu'un certain texte soit anglais, vous voudrez probablement utiliser des caractères N-grammes pour N 3..5. (C'est ce que nous avons découvert expérimentalement.)
Vous n'avez pas partagé les détails de votre application, mais le problème est suffisamment clair. Vous souhaitez représenter des données N-gramme dans une base de données relationnelle (ou une solution basée sur des documents NoSQL). Avant de suggérer ma propre solution, vous voudrez peut-être examiner les approches suivantes:
- Comment stocker au mieux les ngrams Google dans une base de données?
- Stockage de n-grammes dans la base de données dans <n nombre de tables
- Gestion du Google Web 1T 5 grammes avec la base de données relationnelle
Maintenant, n'ayant lu aucun des liens ci-dessus, je suggère une approche de base de données relationnelle simple utilisant plusieurs tables, une pour chaque taille de N-gramme. Vous pouvez mettre toutes les données dans une seule table avec le maximum de colonnes nécessaires (c'est-à-dire stocker les bigrammes et les trigrammes dans ngram_4, en laissant les dernières colonnes nulles), mais je recommande de partitionner les données. Selon votre moteur de base de données, une seule table avec un grand nombre de lignes peut avoir un impact négatif sur les performances.
create table ngram_1 (
word1 nvarchar(50),
frequency FLOAT,
primary key (word1));
create table ngram_2 (
word1 nvarchar(50),
word2 nvarchar(50),
frequency FLOAT,
primary key (word1, word2));
create table ngram_3 (
word1 nvarchar(50),
word2 nvarchar(50),
word3 nvarchar(50),
frequency FLOAT,
primary key (word1, word2, word3));
create table ngram_4 (
word1 nvarchar(50),
word2 nvarchar(50),
word3 nvarchar(50),
word4 nvarchar(50),
frequency FLOAT,
primary key (word1, word2, word3, word4));
Ensuite, je vais vous donner une requête qui retournera le mot suivant le plus probable étant donné toutes vos tables de ngram. Mais d'abord, voici quelques exemples de données que vous devez insérer dans les tableaux ci-dessus:
INSERT [ngram_2] ([word1], [word2], [frequency]) VALUES (N'building', N'with', 0.5)
INSERT [ngram_2] ([word1], [word2], [frequency]) VALUES (N'hit', N'the', 0.1)
INSERT [ngram_2] ([word1], [word2], [frequency]) VALUES (N'man', N'hit', 0.2)
INSERT [ngram_2] ([word1], [word2], [frequency]) VALUES (N'the', N'bat', 0.7)
INSERT [ngram_2] ([word1], [word2], [frequency]) VALUES (N'the', N'building', 0.3)
INSERT [ngram_2] ([word1], [word2], [frequency]) VALUES (N'the', N'man', 0.4)
INSERT [ngram_2] ([word1], [word2], [frequency]) VALUES (N'with', N'the', 0.6)
INSERT [ngram_3] ([word1], [word2], [word3], [frequency]) VALUES (N'building', N'with', N'the', 0.5)
INSERT [ngram_3] ([word1], [word2], [word3], [frequency]) VALUES (N'hit', N'the', N'building', 0.3)
INSERT [ngram_3] ([word1], [word2], [word3], [frequency]) VALUES (N'man', N'hit', N'the', 0.2)
INSERT [ngram_3] ([word1], [word2], [word3], [frequency]) VALUES (N'the', N'building', N'with', 0.4)
INSERT [ngram_3] ([word1], [word2], [word3], [frequency]) VALUES (N'the', N'man', N'hit', 0.1)
INSERT [ngram_3] ([word1], [word2], [word3], [frequency]) VALUES (N'with', N'the', N'bat', 0.6)
INSERT [ngram_4] ([word1], [word2], [word3], [word4], [frequency]) VALUES (N'building', N'with', N'the', N'bat', 0.5)
INSERT [ngram_4] ([word1], [word2], [word3], [word4], [frequency]) VALUES (N'hit', N'the', N'building', N'with', 0.3)
INSERT [ngram_4] ([word1], [word2], [word3], [word4], [frequency]) VALUES (N'man', N'hit', N'the', N'building', 0.2)
INSERT [ngram_4] ([word1], [word2], [word3], [word4], [frequency]) VALUES (N'the', N'building', N'with', N'the', 0.4)
INSERT [ngram_4] ([word1], [word2], [word3], [word4], [frequency]) VALUES (N'the', N'man', N'hit', N'the', 0.1)
Pour interroger le mot suivant le plus probable, vous utiliseriez une requête comme celle-ci.
DECLARE @word1 NVARCHAR(50) = 'the'
DECLARE @word2 NVARCHAR(50) = 'man'
DECLARE @word3 NVARCHAR(50) = 'hit'
DECLARE @bigramWeight FLOAT = 0.2;
DECLARE @trigramWeight FLOAT = 0.3
DECLARE @fourgramWeight FLOAT = 0.5
SELECT next_word, SUM(frequency) AS frequency
FROM (
SELECT word2 AS next_word, frequency * @bigramWeight AS frequency
FROM ngram_2
WHERE word1 = @word3
UNION
SELECT word3 AS next_word, frequency * @trigramWeight AS frequency
FROM ngram_3
WHERE word1 = @word2
AND word2 = @word3
UNION
SELECT word4 AS next_word, frequency * @fourgramWeight AS frequency
FROM ngram_4
WHERE word1 = @word1
AND word2 = @word2
AND word3 = @word3
) next_words
GROUP BY next_word
ORDER BY SUM(frequency) DESC
Si vous ajoutez d'autres tables ngram, vous devrez ajouter une autre clause UNION à la requête ci-dessus. Vous remarquerez peut-être que dans la première requête, j'ai utilisé word1 = @ word3. Et dans la deuxième requête, mot1 = @ mot2 ET mot2 = @ mot3. C'est parce que nous devons aligner les trois mots de la requête pour les données ngram. Si nous voulons le mot suivant le plus probable pour une séquence de trois mots, nous devons comparer le premier mot des données bigrammes avec le dernier mot des mots de la séquence.
Vous pouvez modifier les paramètres de poids comme vous le souhaitez. Dans cet exemple, j'ai supposé que des grammes "n" ordinaux supérieurs seraient plus fiables.
PS Je structurerais le code du programme pour gérer n'importe quel nombre de tables ngram_N via la configuration. Vous pouvez modifier le programme de manière déclarative pour utiliser la plage N-grammes N (1..6) après avoir créé les tables ngram_5 et ngram_6.