Cho rằng bạn sẽ không biết phạm vi tối ưu của N, bạn chắc chắn muốn có thể thay đổi nó. Ví dụ: nếu ứng dụng của bạn dự đoán khả năng một văn bản nhất định là tiếng Anh, có lẽ bạn sẽ muốn sử dụng ký tự N-gram cho N 3..5. (Đó là những gì chúng tôi tìm thấy bằng thực nghiệm.)
Bạn chưa chia sẻ chi tiết về ứng dụng của mình, nhưng vấn đề đã đủ rõ ràng. Bạn muốn biểu diễn dữ liệu N-gram trong cơ sở dữ liệu quan hệ (hoặc giải pháp dựa trên tài liệu NoQuery). Trước khi đề xuất một giải pháp của riêng tôi, bạn có thể muốn xem qua các phương pháp sau:
- Làm cách nào để lưu trữ Google ngrams tốt nhất trong cơ sở dữ liệu?
- Lưu trữ n-gram trong cơ sở dữ liệu trong <n số bảng
- Quản lý Google Web 1T 5 gram với Cơ sở dữ liệu quan hệ
Bây giờ, khi chưa đọc bất kỳ liên kết nào ở trên, tôi đề xuất một cách tiếp cận cơ sở dữ liệu quan hệ đơn giản bằng nhiều bảng, mỗi bảng cho mỗi kích thước của N-gram. Bạn có thể đặt tất cả dữ liệu vào một bảng với các cột cần thiết tối đa (nghĩa là lưu trữ bigram và trigram trong ngram_4, để các cột cuối cùng là null), nhưng tôi khuyên bạn nên phân vùng dữ liệu. Tùy thuộc vào công cụ cơ sở dữ liệu của bạn, một bảng có số lượng hàng lớn có thể ảnh hưởng tiêu cực đến hiệu suất.
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));
Tiếp theo, tôi sẽ cung cấp cho bạn một truy vấn sẽ trả về từ tiếp theo có thể xảy ra nhất với tất cả các bảng ngram của bạn. Nhưng trước tiên, đây là một số dữ liệu mẫu mà bạn nên chèn vào các bảng trên:
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)
Để truy vấn từ tiếp theo có thể xảy ra nhất, bạn sẽ sử dụng truy vấn như thế này.
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
Nếu bạn thêm nhiều bảng ngram, bạn sẽ cần thêm một mệnh đề UNION khác cho truy vấn trên. Bạn có thể nhận thấy rằng trong truy vấn đầu tiên tôi đã sử dụng word1 = @ word3. Và trong truy vấn thứ hai, word1 = @ word2 AND word2 = @ word3. Đó là bởi vì chúng ta cần căn chỉnh ba từ trong truy vấn cho dữ liệu ngram. Nếu chúng ta muốn từ tiếp theo có khả năng nhất cho một chuỗi gồm ba từ, chúng ta sẽ cần kiểm tra từ đầu tiên trong dữ liệu bigram so với từ cuối cùng của các từ trong chuỗi.
Bạn có thể điều chỉnh các thông số trọng lượng như bạn muốn. Trong ví dụ này, tôi giả định rằng gram "n" gram cao hơn sẽ đáng tin cậy hơn.
PS Tôi sẽ cấu trúc mã chương trình để xử lý bất kỳ số lượng bảng ngram_N nào thông qua cấu hình. Bạn có thể thay đổi khai báo chương trình để sử dụng phạm vi N-gram N (1..6) sau khi tạo các bảng ngram_5 và ngram_6.