Biorąc pod uwagę, że nie poznasz optymalnego zakresu N, zdecydowanie chcesz móc go zmienić. Na przykład, jeśli twoja aplikacja przewiduje prawdopodobieństwo, że określony tekst jest angielski, prawdopodobnie będziesz chciał użyć N-gramów znaków dla N 3..5. (Właśnie to znaleźliśmy eksperymentalnie.)
Nie udostępniłeś szczegółowych informacji o swojej aplikacji, ale problem jest wystarczająco jasny. Chcesz reprezentować dane w gramach w relacyjnej bazie danych (lub rozwiązaniu opartym na dokumentach NoSQL). Zanim zaproponuję własne rozwiązanie, możesz rzucić okiem na następujące podejścia:
- Jak najlepiej przechowywać ngramy Google w bazie danych?
- Przechowywanie n-gramów w bazie danych w <n liczbie tabel
- Zarządzanie Google Web 1T 5-gram za pomocą relacyjnej bazy danych
Teraz, nie czytając żadnego z powyższych łączy, sugeruję proste, relacyjne podejście do bazy danych przy użyciu wielu tabel, po jednej dla każdego rozmiaru N-gramów. Możesz umieścić wszystkie dane w jednej tabeli z maksymalną niezbędną liczbą kolumn (tj. Przechowywać bigramy i trygramy w ngram_4, pozostawiając końcowe kolumny puste), ale zalecam partycjonowanie danych. W zależności od silnika bazy danych pojedyncza tabela z dużą liczbą wierszy może mieć negatywny wpływ na wydajność.
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));
Następnie dam ci zapytanie, które zwróci najbardziej prawdopodobne następne słowo, biorąc pod uwagę wszystkie tabele ngram. Ale po pierwsze, oto kilka przykładowych danych, które powinieneś wstawić do powyższych tabel:
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)
Aby wyszukać najbardziej prawdopodobne następne słowo, użyj takiego zapytania.
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
Jeśli dodasz więcej tabel ngram, będziesz musiał dodać kolejną klauzulę UNION do powyższego zapytania. Możesz zauważyć, że w pierwszym zapytaniu użyłem słowa1 = @ słowo3. A w drugim zapytaniu słowo1 = @ słowo2 ORAZ słowo2 = @ słowo3. Jest tak, ponieważ musimy wyrównać trzy słowa w zapytaniu dotyczącym danych ngram. Jeśli chcemy najbardziej prawdopodobnego następnego słowa dla ciągu trzech słów, będziemy musieli sprawdzić pierwsze słowo w danych bigram z ostatnim słowem słów w sekwencji.
Możesz dostosować parametry wagi, jak chcesz. W tym przykładzie założyłem, że wyższe porządkowe „n” gramy będą bardziej niezawodne.
PS Skonfiguruję kod programu, aby obsługiwał dowolną liczbę tabel ngram_N poprzez konfigurację. Można deklaratywnie zmienić program, aby używał zakresu N-gramów N (1..6) po utworzeniu tabel ngram_5 i ngram_6.