Dato che non conoscerai la gamma ottimale di N, vorresti sicuramente essere in grado di cambiarlo. Ad esempio, se la tua applicazione prevede la probabilità che un determinato testo sia in inglese, probabilmente vorrai usare il carattere N-gram 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 dare un'occhiata ai seguenti approcci:
- Come archiviare meglio Google ngram in un database ?
- Memorizzazione di n-grammi nel database in < n numero di tabelle
- Gestione di Google Web 1T 5 grammi con database relazionale
Ora, non avendo letto nessuno dei link sopra, suggerisco un semplice approccio al database relazionale che usa più tabelle, una per ogni dimensione di N-grammo. Puoi inserire tutti i dati in una singola tabella con le colonne massime necessarie (ad esempio, memorizzare i bigram e i trigram in ngram_4, lasciando le colonne finali nulle), ma ti consiglio di partizionare i dati. A seconda del tuo motore di database, una singola tabella con un numero elevato di righe può avere un impatto negativo 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 a tutte le tue tabelle ngram. Ma prima, ecco alcuni dati di esempio che dovresti inserire nelle tabelle precedenti:
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 interrogare la prossima parola più probabile, dovresti usare 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 aggiungi altre tabelle ngram, dovrai aggiungere un'altra clausola UNION alla query sopra. Si potrebbe notare che nella prima query ho usato word1 = @ word3. E nella seconda query, word1 = @ word2 AND word2 = @ word3. Questo perché abbiamo bisogno di allineare le tre parole nella query per i dati di ngram. Se vogliamo la prossima parola più probabile per una sequenza di tre parole, dovremo controllare la prima parola nei dati del bigram contro la ultima parola delle parole nella sequenza.
Puoi modificare i parametri di peso come desideri. In questo esempio, ho assunto che i grammi ordinali più alti "n" saranno più affidabili.
P.S. Vorrei strutturare il codice del programma per gestire un numero qualsiasi di tabelle ngram_N tramite la configurazione. Potresti cambiare dichiaratamente il programma per usare l'intervallo N-grammi N (1..6) dopo aver creato le tabelle ngram_5 e ngram_6.