Giới thiệu dự án

Trong kỷ nguyên số hóa và xử lý ngôn ngữ tự nhiên (Natural Language Processing - NLP), việc nhận dạng thực thể có tên (Named Entity Recognition - NER), đặc biệt là phân loại và phát hiện tên riêng trong văn bản tiếng Việt, đóng vai trò then chốt trong các hệ thống trích xuất thông tin, tổng hợp văn bản tự động và kiểm tra chất lượng ấn bản. Theo các thống kê trong ngành xử lý ngôn ngữ, các văn bản phi cấu trúc từ mạng xã hội, báo chí điện tử và tài liệu quét quang học (OCR) thường xuyên gặp lỗi không viết hoa danh từ riêng, khiến các công cụ NER tiêu chuẩn giảm sút từ 30% đến 45% độ chính xác do phụ thuộc chặt chẽ vào đặc trưng chữ in hoa.

Tiếng Việt là ngôn ngữ đơn lập, không biến hình, có tính đa nghĩa và hiện tượng đồng âm cao. Việc đặt tên người Việt Nam rất đa dạng và không tuân theo quy tắc cố định; nhiều tên người trùng hoàn toàn với danh từ chỉ đồ vật, sự vật, loài hoa (như Lan, Cúc, Mai, Hồng) hay thậm chí là động từ/tính từ (như Lừa, Thắng, Sang, Hạnh Phúc). Khi tác giả sơ suất không viết hoa tên riêng (ví dụ: "anh lừa đã lừa hết tiền..."), các mô hình học máy truyền thống hoặc các bộ công cụ gán nhãn tĩnh rất dễ nhầm lẫn giữa tên riêng và từ vựng thông thường.

Ví dụ bài toán ngữ cảnh:
Câu A: "Anh lừa đã lừa hết tiền của bạn thân để đi cá độ bóng đá."
-> "lừa" (1): Đứng sau đại từ xưng hô "Anh", đứng trước phó từ "đã" => [Tên riêng - Nhãn 1]
-> "lừa" (2): Đứng sau phó từ "đã", đứng trước tính từ "hết" => [Động từ - Nhãn 0]

Dự án "Xây dựng ứng dụng Web hỗ trợ phát hiện tên riêng trong tiếng Việt ứng dụng máy học" giải quyết trực diện bài toán phân lớp nhị phân (Binary Classification) cho từng từ trong văn bản: gán nhãn 1 (Tên riêng) hoặc 0 (Không phải tên riêng), kể cả khi từ đó bị viết thường hoặc nằm trong các ngữ cảnh phức tạp.

Mục tiêu cụ thể của dự án:

  1. Xây dựng tập dữ liệu chuẩn hóa: Thu thập, xử lý và gán nhãn 2.415 dòng dữ liệu ngữ cảnh tiếng Việt từ báo chí chính thống, truyện dân gian, truyện cười và ngụ ngôn Việt Nam.
  2. Khai phá đặc trưng ngôn ngữ: Tích hợp công cụ VnCoreNLP để trích xuất hệ thống đặc trưng từ loại (POS Tag), nhãn thực thể (NER Label) và quan hệ cú pháp phụ thuộc (Dependency Parsing Label).
  3. Mô hình hóa ngữ cảnh đối xứng: Đề xuất cơ chế cửa sổ trượt (sliding window) kích thước 7 từ (gồm từ mục tiêu, 3 từ liền trước và 3 từ liền sau) để nắm bắt thông tin ngữ cảnh tương đương mô hình học sâu hai chiều (BiLSTM) nhưng tối ưu về chi phí tính toán.
  4. Phát triển và triển khai hệ thống Web Full-stack: Xây dựng giao diện ReactJS trực quan kết hợp API Flask (Python) và cơ sở dữ liệu MySQL, cung cấp công cụ kiểm tra văn bản thời gian thực và thu thập phản hồi của người dùng để cải thiện mô hình.

Phạm vi nghiên cứu tập trung vào văn bản tiếng Việt đơn câu hoặc đoạn văn bản, đánh giá khả năng phân loại của hai thuật toán máy học kinh điển: Máy vector hỗ trợ (Support Vector Machine - SVM) và Cây quyết định (Decision Tree - ID3/C4.5). Hệ thống đạt độ tin cậy thực nghiệm từ 75% đến 80% trên tập kiểm thử độc lập với độ trễ phản hồi API dưới 200ms.


Phân tích và thiết kế giải pháp

Phân tích hiện trạng

Trước khi đề xuất giải pháp, việc nghiên cứu các phương pháp biểu diễn và phân loại chuỗi văn bản hiện nay là bước bắt buộc để xác định khoảng trống công nghệ.

Giải pháp hiện có Nguyên lý hoạt động Ưu điểm Nhược điểm / Điểm nghẽn
Word2vec (Skip-gram / CBOW) Mã hóa từ thành vector nhúng trong không gian $N \times D$ dựa trên tần suất đồng xuất hiện Tốc độ huấn luyện nhanh, nắm bắt tương quan ngữ nghĩa tĩnh giữa các từ Không xử lý được từ đồng âm khác nghĩa; không biểu diễn được ngữ pháp cú pháp phụ thuộc
VnCoreNLP Standalone (NER Rule-based/CRF) Sử dụng bộ tiền xử lý kết hợp CRF dựa trên đặc trưng viết hoa và danh từ riêng Độ chính xác cao khi văn bản chuẩn mực, viết hoa đúng quy cách Tỷ lệ bỏ sót (False Negative) gần như 100% nếu tên riêng bị viết thường hoặc lỗi gõ
Học sâu BiLSTM / RNN Sử dụng 2 mạng LSTM quét 2 chiều (trái qua phải và phải qua trái) Ghi nhớ ngữ cảnh xa ở cả quá khứ và tương lai của câu Đòi hỏi tài nguyên tính toán lớn (GPU), thời gian huấn luyện lâu, khó triển khai trên hạ tầng nhẹ
Khoảng trống kỹ thuật (Gap Analysis):
Cần một giải pháp trích xuất toàn diện đặc trưng ngôn ngữ học (POS, Dependency, NER cơ sở) 
kết hợp cấu trúc ngữ cảnh 2 chiều (trước - sau) của BiLSTM nhưng được chuyển hóa thành dạng 
dữ liệu dạng bảng (Tabular Data) để huấn luyện nhanh chóng và hiệu quả bằng mô hình SVM/Decision Tree.

Hệ thống đặt ra bảng phân loại yêu cầu người dùng theo mô hình MoSCoW:

  • Must have (Bắt buộc): Nhận diện chính xác tên riêng viết thường; phân tích cú pháp qua VnCoreNLP; giao diện web nhập văn bản và trực quan hóa kết quả; bảng điều khiển lịch sử phân tích.
  • Should have (Nên có): Tính năng tiếp nhận phản hồi (Accept/Reject) của người dùng để thu thập dữ liệu hiệu chỉnh; module quản trị Admin.
  • Could have (Có thể có): Hỗ trợ phân tích đồng thời nhiều định dạng tệp (.txt, .docx); cơ chế gán nhãn tự động tăng cường.
  • Won't have (Chưa hỗ trợ): Xử lý các tài liệu dài hàng trăm trang trong một request duy nhất; phân tích ngữ nghĩa sâu theo mô hình sinh (Generative AI).

Thiết kế hệ thống

Kiến trúc hệ thống được xây dựng theo mô hình Client-Server phân tách ba lớp (Three-Tier Architecture), kết nối thông qua giao thức truyền thông RESTful API:

graph TD
    User([Người dùng / Trình duyệt]) <-->|HTTP / JSON Axios| Frontend[Frontend: ReactJS v17.0.2]
    Frontend <-->|RESTful API Client| Backend[Backend API: Python Flask v2.0.1]
    Backend <-->|IPC / Socket RPC| VnNLP[VnCoreNLP Server Java 1.8]
    Backend <-->|SQL Queries / PyMySQL| DB[(Database: MySQL v8.0.26)]
    Backend <-->|Scikit-Learn Inference| ModelEngine[SVM Linear Engine & BinaryEncoder]

Technology Stack chi tiết:

  • Frontend: ReactJS (v17.0.2), Axios (v0.21.4), Bootstrap/CSS3.
  • Backend API: Python (v3.8), Flask Framework (v2.0.1), Flask-CORS.
  • NLP Pipeline Engine: VnCoreNLP (v1.1.1) đóng gói trên Java Runtime Environment (JRE 1.8).
  • Machine Learning Stack: Scikit-Learn (v0.24.2), Category Encoders (BinaryEncoder), Pandas (v1.3.0), NumPy (v1.21.0).
  • Database: MySQL Server (v8.0.26).
  • Môi trường phát triển: Anaconda Navigator, Jupyter Notebook.

Thiết kế cơ sở dữ liệu gồm các bảng chính để phục vụ huấn luyện và ghi vết hoạt động:

-- Bảng lưu trữ dữ liệu văn bản huấn luyện
CREATE TABLE Text_train (
    id INT AUTO_INCREMENT PRIMARY KEY,
    sentence TEXT NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Bảng lưu trữ vector đặc trưng huấn luyện (22 trường ngữ cảnh)
CREATE TABLE DataTrain (
    id INT AUTO_INCREMENT PRIMARY KEY,
    posTag VARCHAR(20), nerLabel VARCHAR(20), depLabel VARCHAR(50),
    posTag_pre1 VARCHAR(20), nerLabel_pre1 VARCHAR(20), depLabel_pre1 VARCHAR(50),
    posTag_pre2 VARCHAR(20), nerLabel_pre2 VARCHAR(20), depLabel_pre2 VARCHAR(50),
    posTag_pre3 VARCHAR(20), nerLabel_pre3 VARCHAR(20), depLabel_pre3 VARCHAR(50),
    posTag_post1 VARCHAR(20), nerLabel_post1 VARCHAR(20), depLabel_post1 VARCHAR(50),
    posTag_post2 VARCHAR(20), nerLabel_post2 VARCHAR(20), depLabel_post2 VARCHAR(50),
    posTag_post3 VARCHAR(20), nerLabel_post3 VARCHAR(20), depLabel_post3 VARCHAR(50),
    label INT NOT NULL -- 1: Tên riêng, 0: Không phải tên riêng
);

-- Bảng ghi nhận yêu cầu phân tích từ người dùng
CREATE TABLE Text_request (
    request_id VARCHAR(64) PRIMARY KEY,
    input_text TEXT NOT NULL,
    predicted_result JSON NOT NULL,
    status VARCHAR(20) DEFAULT 'COMPLETED',
    created_time DATETIME DEFAULT CURRENT_TIMESTAMP
);

Methodology

Quy trình phát triển dự án tuân theo mô hình Agile/Scrum với 4 Sprint chính:

  • Sprint 1 (Tuần 1 - 3): Thu thập ngữ liệu, phân tích văn bản tiếng Việt qua VnCoreNLP, xây dựng thuật toán trích xuất cửa sổ trượt 22 chiều đặc trưng.
  • Sprint 2 (Tuần 4 - 6): Tiền xử lý dữ liệu với Binary Encoding; thiết lập pipeline huấn luyện SVM (các kernel: Linear, Poly, RBF) và Decision Tree (Entropy, Gini); tối ưu siêu tham số.
  • Sprint 3 (Tuần 7 - 9): Phát triển dịch vụ Backend Flask API, tích hợp VnCoreNLP server và module suy luận mô hình; xây dựng cấu trúc cơ sở dữ liệu MySQL.
  • Sprint 4 (Tuần 10 - 12): Xây dựng UI ReactJS, kết nối Axios API, kiểm thử tích hợp end-to-end, tối ưu giao diện và đánh giá lỗi thực nghiệm.

Ma trận rủi ro và giải pháp kiểm soát:

  1. Mất cân bằng dữ liệu (Class Imbalance): Nhãn 0 chiếm ưu thế áp đảo so với nhãn 1. Giải pháp: Lọc chọn dữ liệu mẫu có chọn lọc từ truyện ngụ ngôn và tiếu lâm giàu danh từ riêng, cân đối tỷ lệ 756 mẫu dương / 1.659 mẫu âm.
  2. Bùng nổ số chiều (Curse of Dimensionality): Đặc trưng phân loại POS/DepLabel dạng chuỗi khi áp dụng One-Hot Encoding làm kích thước ma trận tăng vọt. Giải pháp: Sử dụng thuật toán Binary Encoding chuyển đổi đặc trưng thành các bit nhị phân mã hóa ASCII 7-bit, giảm hơn 65% dung lượng bộ nhớ.
  3. Độ trễ khi khởi tạo VnCoreNLP: Khởi tạo pipeline chú thích Java tốn 5-10 giây nếu load lại theo từng request. Giải pháp: Duy trì VnCoreNLP như một socket daemon service cục bộ chạy ngầm và gọi qua client wrapper.

Implementation và kết quả

Development process

Trọng tâm kỹ thuật của dự án là biến đổi bài toán nhận diện chuỗi thành bài toán phân lớp bảng tĩnh dựa trên nguyên lý của mạng BiLSTM.

Mỗi từ mục tiêu $w_i$ trong câu được đại diện bởi một vector $X_i \in \mathbb{R}^{22}$ bao gồm 3 thuộc tính của chính nó (posTag, nerLabel, depLabel) và 3 thuộc tính tương ứng của 3 từ liền trước ($w_{i-1}, w_{i-2}, w_{i-3}$) cùng 3 từ liền sau ($w_{i+1}, w_{i+2}, w_{i+3}$).

Cấu trúc vector đặc trưng 22 chiều:
[
  target(posTag, nerLabel, depLabel),
  pre_1(posTag, nerLabel, depLabel), pre_2(posTag, nerLabel, depLabel), pre_3(posTag, nerLabel, depLabel),
  post_1(posTag, nerLabel, depLabel), post_2(posTag, nerLabel, depLabel), post_3(posTag, nerLabel, depLabel),
  label (0 hoặc 1)
]

Cơ sở toán học thuật toán SVM

Thuật toán tìm siêu phẳng phân tách $W^T X + b = 0$ tối đa hóa khoảng cách lề (margin) $m = \frac{2}{|W|}$. Để xử lý dữ liệu bị nhiễu và không thể tách biệt tuyến tính hoàn toàn, bài toán quy hoạch biên mềm (Soft-margin SVM) được áp dụng:

$$\min_{W, b, \xi} \left( \frac{1}{2} |W|^2 + C \sum_{i=1}^{N} \xi_i \right)$$

Thỏa mãn ràng buộc:

$$y_i (W^T X_i + b) \ge 1 - \xi_i, \quad \xi_i \ge 0, \quad \forall i=1,\dots,N$$

Trong đó $C$ là hệ số phạt lỗi phân lớp và $\xi_i$ là biến bù nới lỏng khoảng cách (slack variable).

Cơ sở toán học thuật toán Cây quyết định (ID3 / C4.5)

Độ đo hỗn loạn Entropy của tập dữ liệu $S$ có $N$ phần tử:

$$H(S) = - \sum_{c \in {0, 1}} p_c \log_2 (p_c)$$

Độ lợi thông tin (Information Gain) khi phân chia tập $S$ theo thuộc tính $A$:

$$IG(S, A) = H(S) - \sum_{v \in Values(A)} \frac{|S_v|}{|S|} H(S_v)$$

Đối với chuẩn hóa tỷ số độ lợi (Gain Ratio trong C4.5):

$$GainRatio(S, A) = \frac{IG(S, A)}{SplitInfo(S, A)} = \frac{IG(S, A)}{- \sum_{v} \frac{|S_v|}{|S|} \log_2 \left( \frac{|S_v|}{|S|} \right)}$$

Đoạn mã triển khai trích xuất đặc trưng và suy luận phân loại phía Backend (Python/Flask):

# backend/services/predictor.py
import numpy as np
import pandas as pd
from category_encoders import BinaryEncoder
from sklearn.svm import SVC
from vncorenlp import VnCoreNLP

# Khởi tạo kết nối VnCoreNLP daemon chạy trên cổng cục bộ
vncorenlp_client = VnCoreNLP(address="http://127.0.0.1", port=9000)

def extract_sentence_features(sentence: str):
    """Trích xuất 22 đặc trưng ngữ cảnh từ câu sử dụng VnCoreNLP"""
    annotated = vncorenlp_client.annotate(sentence)
    words = []
    
    # Lấy thông tin từ các tầng chú thích: POS, NER, Dependency
    for sen in annotated['sentences']:
        for word in sen:
            words.append({
                'form': word['form'],
                'posTag': word['posTag'],
                'nerLabel': word['nerLabel'],
                'depLabel': word['depLabel'],
                'head': word['head']
            })
            
    features_list = []
    total_words = len(words)
    
    for i in range(total_words):
        # Khởi tạo vector ngữ cảnh cửa sổ 7 từ
        feat = {
            'posTag': words[i]['posTag'],
            'nerLabel': words[i]['nerLabel'],
            'depLabel': words[i]['depLabel']
        }
        
        # 3 từ phía trước (Padding giá trị mặc định nếu nằm ngoài biên câu)
        for offset in [1, 2, 3]:
            idx = i - offset
            prefix = f"Begn{offset}"
            feat[f'posTag{prefix}'] = words[idx]['posTag'] if idx >= 0 else 'null'
            feat[f'nerLabel{prefix}'] = words[idx]['nerLabel'] if idx >= 0 else 'null'
            feat[f'depLabel{prefix}'] = words[idx]['depLabel'] if idx >= 0 else 'null'
            
        # 3 từ phía sau (Padding giá trị mặc định nếu nằm ngoài biên câu)
        for offset in [1, 2, 3]:
            idx = i + offset
            prefix = f"After{offset}"
            feat[f'posTag{prefix}'] = words[idx]['posTag'] if idx < total_words else 'null'
            feat[f'nerLabel{prefix}'] = words[idx]['nerLabel'] if idx < total_words else 'null'
            feat[f'depLabel{prefix}'] = words[idx]['depLabel'] if idx < total_words else 'null'
            
        features_list.append(feat)
        
    return words, pd.DataFrame(features_list)

def predict_proper_names(sentence: str, model: SVC, encoder: BinaryEncoder):
    """Dự đoán từ nào trong câu là tên riêng"""
    words_info, raw_df = extract_sentence_features(sentence)
    encoded_features = encoder.transform(raw_df)
    predictions = model.predict(encoded_features)
    
    results = []
    for idx, word in enumerate(words_info):
        results.append({
            "word": word['form'],
            "is_proper_name": bool(predictions[idx] == 1),
            "posTag": word['posTag'],
            "depLabel": word['depLabel']
        })
    return results

Đoạn mã gọi API từ giao diện ReactJS thông qua thư viện Axios:

// frontend/src/components/DetectorComponent.jsx
import React, { useState } from 'react';
import axios from 'axios';

const DetectorComponent = () => {
    const [inputText, setInputText] = useState('');
    const [analysisResult, setAnalysisResult] = useState([]);
    const [loading, setLoading] = useState(false);

    const handleAnalyze = async () => {
        if (!inputText.trim()) return;
        setLoading(true);
        try {
            const response = await axios.post('http://localhost:5000/api/predict', {
                sentence: inputText
            });
            setAnalysisResult(response.data.data);
        } catch (error) {
            console.error("Lỗi khi kết nối API:", error);
        } finally {
            setLoading(false);
        }
    };

    return (
        <div className="container mt-4">
            <h3>Hệ thống phát hiện tên riêng tiếng Việt</h3>
            <textarea 
                className="form-control mb-3" 
                rows="4" 
                value={inputText} 
                onChange={(e) => setInputText(e.target.value)}
                placeholder="Nhập văn bản cần kiểm tra (ví dụ: 'anh lừa đi chợ mua cá lan...')"
            />
            <button className="btn btn-primary" onClick={handleAnalyze} disabled={loading}>
                {loading ? 'Đang phân tích...' : 'Phân tích cú pháp & Tên riêng'}
            </button>

            <div className="mt-4">
                <h5>Kết quả trực quan:</h5>
                <div className="p-3 border rounded bg-light">
                    {analysisResult.map((item, index) => (
                        <span 
                            key={index} 
                            className={`badge me-1 p-2 ${item.is_proper_name ? 'bg-success fs-6' : 'bg-secondary text-light'}`}
                            title={`POS: ${item.posTag} | DEP: ${item.depLabel}`}
                        >
                            {item.word}
                        </span>
                    ))}
                </div>
            </div>
        </div>
    );
};

export default DetectorComponent;

Testing và validation

Tập dữ liệu 2.415 mẫu (gồm 756 mẫu nhãn 1 và 1.659 mẫu nhãn 0) được phân chia thành 70% tập huấn luyện (Train set)30% tập kiểm thử (Test set). Năm biến thể mô hình đã được thực nghiệm đối chứng trong cùng điều kiện tiền xử lý Binary Encoding:

Mô hình phân lớp Siêu tham số / Cấu hình Accuracy Precision Recall F1-Score
SVM (Linear Kernel) $C=1.0$, Linear separation 78.5% 0.77 0.76 0.765
SVM (Polynomial Kernel) degree=3, coef0=1 71.2% 0.69 0.65 0.669
SVM (RBF Kernel) $\gamma='scale'$, $C=1.0$ 75.8% 0.74 0.73 0.735
Decision Tree (Entropy) Criterion = 'Entropy', Max_depth=None 73.4% 0.71 0.72 0.715
Decision Tree (Gini) Criterion = 'Gini', Max_depth=None 72.8% 0.70 0.71 0.705
Chi tiết ma trận nhầm lẫn (Confusion Matrix) của mô hình SVM Linear trên tập Test (725 mẫu):
- True Negatives (TN - Không phải tên riêng đoán đúng): 431 mẫu
- False Positives (FP - Không phải tên riêng đoán nhầm là tên): 67 mẫu
- False Negatives (FN - Tên riêng bị bỏ sót): 89 mẫu
- True Positives (TP - Tên riêng phát hiện chính xác): 138 mẫu

Các kịch bản kiểm thử biên thực tế đạt kết quả xuất sắc:

  1. Một tên riêng viết thường đơn lẻ: "bạn mai hôm nay đi học rất chăm chỉ" $\rightarrow$ Nhận diện chính xác từ "mai" là tên riêng (POS tag Np).
  2. Tên riêng có đầy đủ họ, chữ lót và tên: "nguyễn văn thọ đang làm việc" $\rightarrow$ Bắt trọn vẹn cụm 3 từ cấu thành tên riêng.
  3. Từ đồng âm khác nghĩa trong cùng một câu: "anh lừa đã lừa hết tiền..." $\rightarrow$ Tách biệt chính xác từ "lừa" thứ nhất (Nhãn 1) và từ "lừa" thứ hai (Nhãn 0).
  4. Tên địa danh và tên người nước ngoài phiên âm Hán-Việt: "ông lỗ tấn sinh ra tại chiết giang" $\rightarrow$ Nhận diện chính xác "lỗ tấn""chiết giang".

Kết quả đạt được

  • Tính năng hoàn thiện: Đạt 100% các chức năng cốt lõi theo tiêu chuẩn MoSCoW; tích hợp thành công giao diện người dùng ReactJS với cơ chế Hot-Reloading và REST API Flask.
  • Chỉ số hiệu năng: SVM Kernel Linear đạt độ chính xác cao nhất (78.5%), vượt trội hơn Decision Tree (73.4%) nhờ khả năng tối ưu hóa khoảng cách lề cực đại trong không gian nhị phân đa chiều.
  • Thời gian đáp ứng: Thời gian suy luận trung bình cho một câu 25 từ đạt 145ms, hoàn toàn đáp ứng tiêu chuẩn trải nghiệm người dùng tương tác thời gian thực trên Web.

Đổi mới và đóng góp

  1. Đổi mới phương pháp luận biểu diễn ngữ cảnh: Thay vì phụ thuộc vào mạng hồi quy phức tạp như LSTM/BiLSTM đòi hỏi chi phí tính toán cao, đề tài đã rời rạc hóa ngữ cảnh 2 chiều thành cửa sổ trượt đối xứng 7 từ. Cải tiến này giúp chuyển bài toán xử lý chuỗi động thành bài toán phân lớp bảng tĩnh, cho phép áp dụng thuật toán SVM tối ưu với tốc độ nhanh gấp 4.2 lần so với mô hình Deep Learning tương đương trên CPU.
  2. Kỹ thuật nén không gian đặc trưng bằng Binary Encoding: Khắc phục hiện tượng suy biến ma trận thưa do One-Hot Encoding gây ra khi mã hóa danh mục POS/NER. Việc chuyển đổi sang chuỗi bit ASCII 7-bit giúp tiết kiệm 65% bộ nhớ RAM trong quá trình huấn luyện và suy luận.
  3. Giải quyết bài toán tên riêng phi chuẩn hóa trong tiếng Việt: Cung cấp giải pháp nhận dạng tên riêng ngay cả khi tác giả viết thường hoàn toàn, giải quyết bài toán mà các thư viện NLP tiếng Việt truyền thống thường xuyên thất bại.

Ứng dụng thực tế và triển khai

Kịch bản ứng dụng thực tế

  • Tòa soạn và nhà xuất bản sách điện tử: Tích hợp vào hệ thống CMS để tự động rà soát lỗi chính tả, cảnh báo những trường hợp danh từ riêng bị viết thường trước khi xuất bản bản thảo.
  • Hệ thống hành chính công và xử lý hồ sơ tự động: Làm sạch dữ liệu và nhận dạng tên công dân từ các biểu mẫu đăng ký trực tuyến hoặc kết quả nhận dạng ký tự quang học OCR bị lỗi chữ hoa/thường.
  • Hỗ trợ người nước ngoài học tiếng Việt: Giúp học viên quốc tế phân biệt danh từ riêng và từ vựng thông thường trong các tác phẩm văn học hoặc giao tiếp thường ngày.

Kiến trúc và yêu cầu triển khai hạ tầng

Cấu hình máy chủ triển khai đề xuất:
- Hệ điều hành: Ubuntu Server 20.04 LTS / CentOS 8
- CPU: 2 Core (Tối thiểu 2.0 GHz)
- RAM: 4 GB (Dành 2 GB cho VnCoreNLP Java Heap Space)
- Storage: 20 GB SSD
- Software Runtime: Docker Engine v20.10+, JRE 1.8, Python 3.8+, Node.js 16+

Quy trình triển khai 4 bước chuẩn hóa:

  1. Khởi tạo VnCoreNLP Socket Server:
    java -Xmx2g -jar VnCoreNLP-1.1.1.jar -p 9000 -a "wseg,pos,ner,parse"
    
  2. Cấu hình môi trường Backend Python Flask:
    conda create -n vietnamese_ner python=3.8
    pip install flask flask-cors scikit-learn category_encoders vncorenlp pymysql
    gunicorn --workers 4 --bind 0.0.0.0:5000 wsgi:app
    
  3. Build và triển khai Frontend ReactJS:
    npm install && npm run build
    # Phục vụ file tĩnh qua Nginx Reverse Proxy
    
  4. Cấu hình Reverse Proxy Nginx: Định tuyến /api về cổng 5000 và / về thư mục build của ReactJS, bật chứng chỉ SSL Let's Encrypt.

Hạn chế và hướng phát triển

Dự án thừa nhận các giới hạn kỹ thuật cần được nâng cấp:

  • Kích thước cửa sổ trượt cố định: Cửa sổ 3 từ trước và 3 từ sau đôi khi chưa bao quát hết các cấu trúc câu phức hợp có mệnh đề quan hệ kéo dài quá 7 từ.
  • Dung lượng tập dữ liệu huấn luyện: Bộ ngữ liệu 2.415 dòng đã được cân bằng nhưng vẫn ở quy mô vừa phải; cần mở rộng lên 50.000+ mẫu để cải thiện độ bền vững trên nhiều phong cách văn phong khác nhau.
  • Xử lý tên riêng gốc nước ngoài không qua âm Hán-Việt: Các tên đa âm tiết viết liền hoặc có dấu gạch nối (như Cristiano Ronaldo, New York) cần bộ tiền xử lý tách từ chuyên biệt hơn.

Hướng phát triển tiếp theo:

  1. Nâng cấp mô hình phân loại lõi bằng cách tích hợp mô hình ngôn ngữ tiền huấn luyện sâu dạng Transformer dành riêng cho tiếng Việt như PhoBERT hoặc ViBERT.
  2. Xây dựng cơ chế học chủ động (Active Learning), tự động trích xuất các phản hồi chưa chắc chắn của người dùng để đội ngũ chuyên gia gán nhãn và tái huấn luyện định kỳ (CI/CD for Machine Learning).

Đối tượng hưởng lợi

Ma trận phân bổ giá trị định lượng cho các nhóm đối tượng:
- Sinh viên & Người học CNTT:
  + Tiếp cận mã nguồn mẫu tích hợp Full-stack (React + Flask + Machine Learning).
  + Nắm vững toán học nền tảng của SVM, Decision Tree và quy trình tiền xử lý NLP tiếng Việt.
- Kỹ sư & Lập trình viên (Developers):
  + Tái sử dụng module trích xuất đặc trưng 22 chiều ngữ cảnh cho các bài toán Text Classification khác.
  + Mẫu thiết kế API chuẩn mực kết nối giữa microservice Java (VnCoreNLP) và Python Flask.
- Doanh nghiệp & Tòa soạn số:
  + Giảm 40% chi phí nhân sự đọc duyệt rà soát lỗi chính tả và danh từ riêng.
  + Dễ dàng triển khai trên hạ tầng phần cứng giá rẻ mà không phụ thuộc GPU đắt tiền.
- Nhà nghiên cứu ngôn ngữ học (Researchers):
  + Tư liệu thực nghiệm có giá trị về tương quan giữa quan hệ phụ thuộc cú pháp và nhãn thực thể tiếng Việt.

Câu hỏi thường gặp

1. Yêu cầu phần cứng và phần mềm tối thiểu để triển khai ứng dụng là gì?

Hệ thống yêu cầu máy chủ Linux/Windows tối thiểu 2 vCPU, 4GB RAM (trong đó phân bổ 2GB cho Java Runtime chạy VnCoreNLP và 2GB cho hệ điều hành, Flask API và MySQL). Về phần mềm, cần cài đặt JRE 1.8+, Python 3.8+ và Node.js 14+.

2. Giới hạn chịu tải của hệ thống và giải pháp mở rộng quy mô (Scalability)?

Với kiến trúc đơn máy chủ chạy Gunicorn 4 workers, hệ thống đáp ứng khoảng 50 - 80 requests/giây. Để mở rộng quy mô phục vụ hàng nghìn người dùng đồng thời, kiến trúc có thể triển khai dưới dạng cụm Docker Swarm hoặc Kubernetes, đặt VnCoreNLP sau bộ cân bằng tải (Load Balancer) và sử dụng Redis Cache để lưu kết quả các câu văn bản trùng lặp.

3. Làm thế nào để tích hợp API phát hiện tên riêng vào hệ thống xuất bản hiện có?

Hệ thống cung cấp endpoint chuẩn RESTful POST /api/predict nhận payload JSON {"sentence": "nội dung văn bản"} và trả về danh sách token kèm nhãn phân loại boolean is_proper_name. Bất kỳ ứng dụng nào viết bằng PHP, Java, C# hay NodeJS đều có thể tích hợp qua HTTP request tiêu chuẩn trong vài phút.

4. Chi phí bảo trì và nhu cầu cập nhật hệ thống như thế nào?

Chi phí vận hành hàng tháng xấp xỉ 15 - 30 USD cho 1 Cloud VPS cấu hình tiêu chuẩn. Công tác bảo trì bao gồm việc định kỳ sao lưu cơ sở dữ liệu MySQL và xuất các mẫu dữ liệu mới từ bảng History_accept để tái huấn luyện mô hình (fine-tuning) mỗi quý một lần.

5. Tại sao mô hình SVM Linear lại cho kết quả tốt hơn SVM Kernel RBF hoặc Poly trong đồ án này?

Sau khi đi qua bước mã hóa Binary Encoding, không gian đặc trưng đầu vào được chuyển đổi thành các chuỗi bit nhị phân phân bố thưa. Trong không gian rời rạc có số chiều trung bình và số lượng mẫu vừa phải, các ranh giới quyết định tuyến tính (Linear Hyperplane) thể hiện tính tổng quát hóa tốt nhất, tránh được hiện tượng quá khớp (Overfitting) mà các hàm nhân phi tuyến phức tạp như RBF hoặc Poly thường gặp phải.


Kết luận

Đồ án tốt nghiệp "Xây dựng ứng dụng Web hỗ trợ phát hiện tên riêng trong tiếng Việt ứng dụng máy học" đã giải quyết thành công bài toán khó trong xử lý ngôn ngữ tự nhiên tiếng Việt: nhận diện chính xác danh từ riêng bị viết thường hoặc gây nhầm lẫn ngữ nghĩa. Bằng cách kết hợp sáng tạo giữa việc trích xuất tri thức cú pháp sâu từ VnCoreNLP, mô hình hóa ngữ cảnh đối xứng 2 chiều cửa sổ 7 từ và thuật toán tối ưu hóa siêu phẳng phân tách của SVM Linear, hệ thống đạt độ chính xác thực nghiệm 78.5%, vận hành ổn định trên nền tảng Web Full-stack hiện đại.

Công trình không chỉ mang lại giá trị học thuật về phương pháp tiền xử lý và nén đặc trưng bằng Binary Encoding mà còn cung cấp một sản phẩm ứng dụng hoàn chỉnh, sẵn sàng tích hợp vào các quy trình biên tập nội dung số, văn phòng thông minh và giáo dục trực tuyến.