Sử dụng TextRCNN cho Nhận diện Ý định trong Hệ thống Hỏi Đáp

Ứng dụng TextRCNN trong phân loại văn bản để nhận diện ý định

Giải pháp triển khai mạng TextRCNN (Recurrent Convolutional Neural Network) cho bài toán phân loại văn bản nhằm xác định ý định trong hệ thống hỏi đáp. Mô hình kết hợp kiến trúc LSTM và CNN để trích xuất đặc trưng từ chuỗi ký tự đầu vào.

Mã nguồn triển khai

Cấu hình môi trường và tiền xử lý dữ liệu


import os
import torch
from torchtext import data
import pandas as pd
import pickle

DEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

# Đường dẫn dữ liệu
data_path = os.path.abspath('../../classification_data/classification_data.csv')
df = pd.read_csv(data_path)

# Hàm tách từ theo ký tự
tokenize = lambda x: x.split()

# Định nghĩa field dữ liệu
text_field = data.Field(
    sequential=True,
    tokenize=tokenize,
    lower=True,
    pad_token='<pad>',
    unk_token='<unk>',
    batch_first=True,
    fix_length=20
)

label_field = data.Field(sequential=False, use_vocab=False)

# Hàm tạo dataset
def create_dataset(df, text, label):
    fields = [('id', None), ('text', text), ('label', label)]
    examples = [data.Example.fromlist([None, t, l], fields) 
               for t, l in zip(df['text'], df['label'])]
    return data.Dataset(examples, fields)

# Tạo dataset và xây dựng từ điển
dataset = create_dataset(df, text_field, label_field)
pretrained_path = 'sgns.sogou.char'
text_field.build_vocab(dataset, min_freq=1, vectors=data.Vectors(name=pretrained_path))

# Lưu từ điển
with open('vocab.pkl', 'wb') as f:
    pickle.dump(text_field.vocab, f)

Triển khai mô hình TextRCNN


import torch.nn as nn

class TextRCNN(nn.Module):
    def __init__(self, vocab_size, embed_dim, hidden_size, layers, classes):
        super().__init__()
        self.embedding = nn.Embedding(vocab_size, embed_dim)
        self.lstm = nn.LSTM(embed_dim, hidden_size, layers, 
                          bidirectional=True, batch_first=True)
        self.classifier = nn.Sequential(
            nn.Dropout(0.5),
            nn.Linear(hidden_size*2 + embed_dim, classes)
        )
    
    def forward(self, x):
        embedded = self.embedding(x)
        out, _ = self.lstm(embedded)
        combined = torch.cat([embedded, out], dim=2)
        activated = torch.relu(combined)
        pooled = torch.max(activated.transpose(1,2), dim=2)[0]
        return self.classifier(pooled)

Quy trình huấn luyện


from torch.utils.tensorboard import SummaryWriter
import torch.optim as optim

# Khởi tạo mô hình
model = TextRCNN(
    len(text_field.vocab), 300, 128, 2, 16
).to(DEVICE)

# Sử dụng embedding tiền huấn luyện
model.embedding.weight.data.copy_(text_field.vocab.vectors)

# Cấu hình huấn luyện
optimizer = optim.SGD(model.parameters(), lr=0.1, momentum=0.95)
criterion = nn.CrossEntropyLoss()
writer = SummaryWriter('logs')

# Vòng lặp huấn luyện
for epoch in range(300):
    for batch in train_loader:
        inputs = batch.text.to(DEVICE)
        labels = batch.label.to(DEVICE)
        
        outputs = model(inputs)
        loss = criterion(outputs, labels)
        
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        
        writer.add_scalar('Loss/train', loss.item(), epoch)
        if (epoch+1) % 10 == 0:
            print(f'Epoch {epoch+1}, Loss: {loss.item():.4f}')

Kết quả huấn luyện


Epoch 10, Loss: 2.1661
Epoch 20, Loss: 1.3261
Epoch 30, Loss: 0.7458
Epoch 40, Loss: 0.4683
Epoch 50, Loss: 0.3658
...
Epoch 300, Loss: 0.0072

Thẻ: PyTorch torchtext lstm text-classification intent-detection

Đăng vào ngày 7 tháng 6 lúc 06:07