Dato che non conoscerai l'intervallo ottimale di N, vorrai sicuramente essere in grado di cambiarlo. Ad esempio, se la tua applicazione prevede la probabilità che un determinato testo sia inglese, probabilmente vorrai usare il carattere N-grammi per N 3..5. (Questo è quello che abbiamo trovato sperimentalmente.)
Non hai condiviso i dettagli sulla tua applicazione, ma il problema è abbastanza chiaro. Si desidera rappresentare i dati N-gram in un database relazionale (o soluzione basata su documenti NoSQL). Prima di suggerire una mia soluzione, potresti voler dare un'occhiata ai seguenti approcci:
- Come archiviare al meglio gli ngram di Google in un database?
- Memorizzare n-grammi nel database in <n numero di tabelle
- Gestione di Google Web 1T da 5 grammi con Database relazionale
Ora, non avendo letto nessuno dei link sopra, suggerisco un approccio di database relazionale semplice usando più tabelle, una per ogni dimensione di N-grammo. Potresti mettere tutti i dati in una singola tabella con le colonne massime necessarie (ad es. Memorizzare i bigrammi e i trigrammi in ngram_4, lasciando nulle le colonne finali), ma ti consiglio di partizionare i dati. A seconda del motore del database, una singola tabella con un numero elevato di righe può influire negativamente sulle prestazioni.
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));
Successivamente, ti darò una query che restituirà la parola successiva più probabile date tutte le tue tabelle ngram. Ma prima, ecco alcuni dati di esempio che dovresti inserire nelle tabelle sopra:
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)
Per eseguire una query sulla parola successiva più probabile, utilizzare una query come questa.
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
Se si aggiungono più tabelle ngram, sarà necessario aggiungere un'altra clausola UNION alla query sopra. Potresti notare che nella prima query ho usato word1 = @ word3. E nella seconda query, word1 = @ word2 AND word2 = @ word3. Questo perché dobbiamo allineare le tre parole nella query per i dati ngram. Se vogliamo la parola successiva più probabile per una sequenza di tre parole, dovremo controllare la prima parola nei dati bigram rispetto all'ultima parola delle parole nella sequenza.
Puoi modificare i parametri del peso come desideri. In questo esempio, ho assunto che "n" grammi ordinali più alti saranno più affidabili.
PS Strutturerei il codice del programma per gestire qualsiasi numero di tabelle ngram_N tramite la configurazione. È possibile modificare in modo dichiarativo il programma per utilizzare l'intervallo N-grammo N (1..6) dopo aver creato le tabelle ngram_5 e ngram_6.