Python: Phát hiện loa trong HIMYM bằng cách gắn thẻ các phần của lời nói (POS)


Nguyễn Ðông Phong
4 năm trước
Hữu ích 8 Chia sẻ Viết bình luận 0
Đã xem 5552

Trong vài tuần qua, tôi đã thử nghiệm với các phân loại khác nhau để phát hiện các loa trong bảng điểm HIMYM và trong tất cả các nỗ lực của tôi cho đến nay, các tính năng duy nhất tôi đã sử dụng là từ.

Điều này dẫn đến các phân loại được cung cấp quá mức cho dữ liệu đào tạo, vì vậy tôi muốn khái quát chúng bằng cách giới thiệu các phần của lời nói trong các câu chung chung hơn.

Đầu tiên tôi đã thay đổi chức năng tạo ra các tính năng cho mỗi từ để chứa các phần của lời nói của các từ trước và tiếp theo cũng như chính từ đó:

def pos_features(sentence, sentence_pos, i):
    features = {}
 
    features["word"] = sentence[i]
    features["word-pos"] = sentence_pos[i][1]
 
    if i == 0:
        features["prev-word"] = "<START>"
        features["prev-word-pos"] = "<START>"
    else:
        features["prev-word"] = sentence[i-1]
        features["prev-word-pos"] = sentence_pos[i-1][1]
 
    if i == len(sentence) - 1:
        features["next-word"] = "<END>"
        features["next-word-pos"] = "<END>"
    else:
        features["next-word"] = sentence[i+1]
        features["next-word-pos"] = sentence_pos[i+1][1]
 
    return features

Tiếp theo, chúng ta cần điều chỉnh mã gọi để tính toán các phần của thẻ lời nói cho mỗi câu và chuyển nó vào:

featuresets = []
for tagged_sent in tagged_sents:
    untagged_sent = nltk.tag.untag(tagged_sent)
    sentence_pos = nltk.pos_tag(untagged_sent)
    for i, (word, tag) in enumerate(tagged_sent):
        featuresets.append((pos_features(untagged_sent, sentence_pos, i), tag) )

Tôi đang sử dụng nltk để làm điều này và mặc dù nó chậm hơn một số lựa chọn thay thế , bộ dữ liệu đủ nhỏ để nó không phải là vấn đề.

Bây giờ là lúc để đào tạo Cây quyết định với các tính năng mới. Tôi đã tạo ra ba biến thể - một biến thể có cả từ và POS; một chỉ có lời nói; một chỉ có POS.

Tôi đã lấy một bản sao sâu của các tập dữ liệu huấn luyện / kiểm tra và sau đó loại bỏ các khóa thích hợp:

def get_rid_of(entry, *keys):
    for key in keys:
        del entry[key]
 
import copy
 
# Word based classifier
tmp_train_data = copy.deepcopy(train_data)
for entry, tag in tmp_train_data:
    get_rid_of(entry, 'prev-word-pos', 'word-pos', 'next-word-pos')
 
tmp_test_data = copy.deepcopy(test_data)
for entry, tag in tmp_test_data:
    get_rid_of(entry, 'prev-word-pos', 'word-pos', 'next-word-pos')
 
c = nltk.DecisionTreeClassifier.train(tmp_train_data)
c.classify(tmp_test_data)
 
# POS based classifier
tmp_train_data = copy.deepcopy(train_data)
for entry, tag in tmp_train_data:
    get_rid_of(entry, 'prev-word', 'word', 'next-word')
 
tmp_test_data = copy.deepcopy(test_data)
for entry, tag in tmp_test_data:
    get_rid_of(entry, 'prev-word', 'word', 'next-word')
 
c = nltk.DecisionTreeClassifier.train(tmp_train_data)
c.classify(tmp_test_data)

Các mã đầy đủ là trên github của tôi nhưng đây là những kết quả tôi thấy:

$ time python scripts/detect_speaker.py
Classifier              speaker precision    speaker recall    non-speaker precision    non-speaker recall
--------------------  -------------------  ----------------  -----------------------  --------------------
Decision Tree All In             0.911765          0.939394                 0.997602              0.996407
Decision Tree Words              0.911765          0.939394                 0.997602              0.996407
Decision Tree POS                0.90099           0.919192                 0.996804              0.996008

Vẫn chưa có nhiều trong đó - POS một có nhiều điểm sai hơn và dương tính giả khi phân loại loa nhưng trên các hoạt động khác, nó hoạt động tốt hơn.

Nếu chúng ta nhìn vào cây quyết định được xây dựng cho POS, chúng ta có thể thấy rằng đó là tất cả về POS ngay bây giờ như bạn mong đợi:

>>> print(c.pseudocode(depth=2))
if next-word-pos == '

Tôi thích rằng nó đã xác định mẫu ':':

if next-word-pos == ':':
  ...
  if prev-word-pos == '<START>': return True

Tiếp theo tôi cần đi sâu vào các loại cấu trúc câu mà nó không thành công và tìm ra một số tính năng có thể xử lý chúng. Tôi vẫn cần phải xem một rừng cây quyết định tốt như thế nào.

Hữu ích 8 Chia sẻ Viết bình luận 0
Đã xem 5552