15.1. Tác vụ Phân tích Cảm xúc và Bộ Dữ liệu

Phân loại văn bản là một tác vụ phổ biến trong xử lý ngôn ngữ tự nhiên, ánh xạ chuỗi văn bản có độ dài không cố định tới một hạng mục tương ứng. Tác vụ này khá giống với phân loại ảnh, vốn là ứng dụng phổ biến nhất được giới thiệu trong cuốn sách này, ví dụ, Section 18.9. Điểm khác biệt duy nhất đó là, mẫu đầu vào của tác vụ phân loại là một câu văn bản thay vì một bức ảnh.

Phần này sẽ tập trung vào việc nạp dữ liệu cho một trong số những câu hỏi của bài toán này: sử dụng tác vụ phân loại cảm xúc văn bản để phân tích cảm xúc của người viết. Bài toán này cũng có thể gọi là phân tích cảm xúc (sắc thái) và có rất nhiều ứng dụng. Ví dụ, ta có thể phân tích đánh giá của khách hàng về sản phẩm để thu được thống kê độ hài lòng, hoặc phân tích cảm xúc của khách hàng về điều kiện thị trường và sử dụng kết quả này để dự đoán xu hướng tương lai.

from d2l import mxnet as d2l
from mxnet import gluon, np, npx
import os
npx.set_np()

15.1.1. Bộ Dữ liệu Phân tích Cảm xúc

Ta sử dụng tập dữ liệu lớn về đánh giá phim ảnh (Large Movie Review Dataset) của Stanford làm dữ liệu cho tác vụ phân tích cảm xúc. Tập dữ liệu này được chia thành hai tập huấn luyện và kiểm tra, mỗi tập chứa 25,000 đánh giá phim tải về từ IMDb. Trong mỗi tập dữ liệu, số lượng đánh giá có nhãn “tích cực” (positive) và “tiêu cực” (negative) là bằng nhau.

15.1.1.1. Đọc Dữ liệu

Đầu tiên, ta tải dữ liệu về thư mục “../data” và giải nén dữ liệu vào thư mục “../data/aclImdb”.

#@save
d2l.DATA_HUB['aclImdb'] = (
    'http://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz',
    '01ada507287d82875905620988597833ad4e0903')

data_dir = d2l.download_extract('aclImdb', 'aclImdb')
Downloading ../data/aclImdb_v1.tar.gz from http://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz...

Tiếp theo, ta đọc dữ liệu huấn luyện và dữ liệu kiểm tra. Mỗi mẫu là một bình luận đánh giá cùng với nhãn tương ứng: 1 cho “tích cực”, và 0 cho “tiêu cực”.

#@save
def read_imdb(data_dir, is_train):
    data, labels = [], []
    for label in ('pos', 'neg'):
        folder_name = os.path.join(data_dir, 'train' if is_train else 'test',
                                   label)
        for file in os.listdir(folder_name):
            with open(os.path.join(folder_name, file), 'rb') as f:
                review = f.read().decode('utf-8').replace('\n', '')
                data.append(review)
                labels.append(1 if label == 'pos' else 0)
    return data, labels

train_data = read_imdb(data_dir, is_train=True)
print('# trainings:', len(train_data[0]))
for x, y in zip(train_data[0][:3], train_data[1][:3]):
    print('label:', y, 'review:', x[0:60])
# trainings: 25000
label: 1 review: There's something compelling and strangely believable about
label: 1 review: I had heard some not too good things about this movie and ha
label: 1 review: Such energy and vitality. You just can't go wrong with Busby

15.1.1.2. Token hoá và Bộ từ vựng

Ta coi mỗi từ là một token, và tạo một từ điển dựa trên tập dữ liệu huấn luyện.

train_tokens = d2l.tokenize(train_data[0], token='word')
vocab = d2l.Vocab(train_tokens, min_freq=5, reserved_tokens=['<pad>'])

d2l.set_figsize()
d2l.plt.hist([len(line) for line in train_tokens], bins=range(0, 1000, 50));
../_images/output_sentiment-analysis-and-dataset_vn_7c80d0_7_0.svg

15.1.1.3. Đệm để cùng Độ dài

Vì mỗi câu đánh giá có độ dài khác nhau, nên chúng không thể được tổng hợp trực tiếp thành minibatch được. Ta có thể cố định độ dài mỗi câu bình luận là 500 bằng cách cắt xén hoặc thêm vào các chỉ mục “<unk>”.

num_steps = 500  # sequence length
train_features = np.array([d2l.truncate_pad(
    vocab[line], num_steps, vocab['<pad>']) for line in train_tokens])
train_features.shape
(25000, 500)

15.1.1.4. Tạo Iterator cho Dữ liệu

Bây giờ, ta sẽ tạo một iterator cho dữ liệu. Mỗi vòng lặp sẽ trả về một minibatch dữ liệu.

train_iter = d2l.load_array((train_features, train_data[1]), 64)

for X, y in train_iter:
    print('X', X.shape, 'y', y.shape)
    break
'# batches:', len(train_iter)
X (64, 500) y (64,)
('# batches:', 391)

15.1.2. Kết hợp Tất cả Lại

Cuối cùng, ta lưu hàm load_data_imdb vào d2l, hàm này trả về bộ từ vựng và các iterator của dữ liệu.

#@save
def load_data_imdb(batch_size, num_steps=500):
    data_dir = d2l.download_extract('aclImdb', 'aclImdb')
    train_data = read_imdb(data_dir, True)
    test_data = read_imdb(data_dir, False)
    train_tokens = d2l.tokenize(train_data[0], token='word')
    test_tokens = d2l.tokenize(test_data[0], token='word')
    vocab = d2l.Vocab(train_tokens, min_freq=5)
    train_features = np.array([d2l.truncate_pad(
        vocab[line], num_steps, vocab.unk) for line in train_tokens])
    test_features = np.array([d2l.truncate_pad(
        vocab[line], num_steps, vocab.unk) for line in test_tokens])
    train_iter = d2l.load_array((train_features, train_data[1]), batch_size)
    test_iter = d2l.load_array((test_features, test_data[1]), batch_size,
                               is_train=False)
    return train_iter, test_iter, vocab

15.1.3. Tóm tắt

  • Tác vụ phân loại văn bản có thể phân loại chuỗi văn bản theo hạng mục.
  • Để phân loại cảm xúc văn bản, ta nạp bộ dữ liệu IMDb và token hóa các từ trong đó. Sau đó, ta đệm thêm vào chuỗi văn bản của các câu đánh giá ngắn và tạo một iterator dữ liệu.

15.1.4. Bài tập

Hãy khám phá một tập dữ liệu ngôn ngữ tự nhiên khác (ví dụ tập dữ liệu Đánh giá Amazon) và xây dựng một hàm data_loader tương tự như load_data_imdb.

15.1.5. Thảo luận

15.1.6. Những người thực hiện

Bản dịch trong trang này được thực hiện bởi:

  • Đoàn Võ Duy Thanh
  • Nguyễn Văn Quang
  • Nguyễn Lê Quang Nhật
  • Lê Khắc Hồng Phúc
  • Phạm Hồng Vinh
  • Nguyễn Văn Cường

Lần cập nhật gần nhất: 26/09/2020. (Cập nhật lần cuối từ nội dung gốc: 30/06/2020)