Bộ công cụ ngôn ngữ tự nhiên - Phân loại văn bản

Phân loại văn bản là gì?

Phân loại văn bản, như tên của nó, là cách để phân loại các phần văn bản hoặc tài liệu. Nhưng ở đây câu hỏi đặt ra là tại sao chúng ta cần sử dụng bộ phân loại văn bản? Sau khi kiểm tra việc sử dụng từ trong một tài liệu hoặc đoạn văn bản, bộ phân loại sẽ có thể quyết định nhãn lớp nào nên được gán cho nó.

Bộ phân loại nhị phân

Như tên của nó, bộ phân loại nhị phân sẽ quyết định giữa hai nhãn. Ví dụ, tích cực hoặc tiêu cực. Trong trường hợp này, đoạn văn bản hoặc tài liệu có thể là nhãn này hoặc nhãn khác, nhưng không phải cả hai.

Bộ phân loại nhiều nhãn

Ngược lại với trình phân loại nhị phân, trình phân loại nhiều nhãn có thể gán một hoặc nhiều nhãn cho một đoạn văn bản hoặc tài liệu.

Bộ tính năng không gắn nhãn Vs được gắn nhãn

Ánh xạ khóa-giá trị của tên đối tượng với giá trị đối tượng được gọi là tập hợp đối tượng. Tập hợp tính năng được gắn nhãn hoặc dữ liệu huấn luyện rất quan trọng đối với việc huấn luyện phân loại để sau này nó có thể phân loại tập tính năng không được gắn nhãn.

Bộ tính năng được gắn nhãn Bộ tính năng không được gắn nhãn
Nó là một bộ tuple trông giống như (kỳ công, nhãn). Bản thân nó đã là một kỳ công.
Nó là một thể hiện có nhãn lớp đã biết. Nếu không có nhãn liên kết, chúng ta có thể gọi nó là một phiên bản.
Được sử dụng để đào tạo một thuật toán phân loại. Sau khi được đào tạo, thuật toán phân loại có thể phân loại một tập hợp tính năng không được gắn nhãn.

Trích xuất tính năng văn bản

Trích xuất tính năng văn bản, như tên của nó, là quá trình chuyển đổi danh sách các từ thành một tập hợp tính năng có thể sử dụng được bởi bộ phân loại. Chúng ta phải chuyển đổi văn bản của mình thành‘dict’ bộ tính năng kiểu do Bộ công cụ ngôn ngữ tự nhiên (NLTK) mong đợi ‘dict’ bộ đặc điểm phong cách.

Mô hình Bag of Words (BoW)

BoW, một trong những mô hình đơn giản nhất trong NLP, được sử dụng để trích xuất các tính năng từ đoạn văn bản hoặc tài liệu để nó có thể được sử dụng trong mô hình hóa như vậy trong các thuật toán ML. Về cơ bản, nó xây dựng bộ tính năng hiện diện từ từ tất cả các từ của một thể hiện. Khái niệm đằng sau phương pháp này là nó không quan tâm đến việc một từ xuất hiện bao nhiêu lần hoặc về thứ tự của các từ, nó chỉ quan tâm thời tiết từ đó có trong danh sách các từ hay không.

Thí dụ

Đối với ví dụ này, chúng ta sẽ định nghĩa một hàm có tên là bow () -

def bow(words):
   return dict([(word, True) for word in words])

Bây giờ, hãy để chúng tôi gọi bow()chức năng trên từ. Chúng tôi đã lưu các chức năng này trong một tệp có tên bagwords.py.

from bagwords import bow
bow(['we', 'are', 'using', 'tutorialspoint'])

Đầu ra

{'we': True, 'are': True, 'using': True, 'tutorialspoint': True}

Đào tạo phân loại

Trong các phần trước, chúng ta đã học cách trích xuất các đối tượng địa lý từ văn bản. Vì vậy, bây giờ chúng ta có thể đào tạo một bộ phân loại. Bộ phân loại đầu tiên và dễ nhất làNaiveBayesClassifier lớp học.

Naïve Bayes Classifier

Để dự đoán xác suất mà một tập đặc trưng nhất định thuộc về một nhãn cụ thể, nó sử dụng định lý Bayes. Công thức của định lý Bayes như sau.

$$ P (A | B) = \ frac {P (B | A) P (A)} {P (B)} $$

Đây,

P(A|B) - Nó còn được gọi là xác suất hậu kỳ tức là xác suất của sự kiện thứ nhất tức là A xảy ra cho sự kiện thứ hai tức là B xảy ra.

P(B|A) - Là xác suất của sự kiện thứ hai tức là B xảy ra sau sự kiện thứ nhất tức là A xảy ra.

P(A), P(B) - Nó còn được gọi là xác suất trước tức là xác suất của sự kiện thứ nhất tức là A hoặc sự kiện thứ hai tức là B xảy ra.

Để đào tạo bộ phân loại Naïve Bayes, chúng tôi sẽ sử dụng movie_reviewskho ngữ liệu từ NLTK. Kho tài liệu này có hai loại văn bản, đó là:posneg. Các danh mục này làm cho một bộ phân loại được đào tạo trên chúng trở thành một bộ phân loại nhị phân. Mỗi tệp trong kho tài liệu bao gồm hai, một là đánh giá phim tích cực và một là đánh giá phim tiêu cực. Trong ví dụ của chúng tôi, chúng tôi sẽ sử dụng mỗi tệp như một phiên bản duy nhất cho cả việc đào tạo và kiểm tra trình phân loại.

Thí dụ

Đối với trình phân loại huấn luyện, chúng ta cần một danh sách các tập hợp tính năng được gắn nhãn, sẽ có dạng [(featureset, label)]. Đâyfeatureset biến là một dict và nhãn là nhãn lớp đã biết cho featureset. Chúng ta sẽ tạo một hàm có tênlabel_corpus() sẽ lấy một kho ngữ liệu có tên movie_reviewsvà cũng là một hàm có tên feature_detector, mặc định là bag of words. Nó sẽ xây dựng và trả về một ánh xạ của biểu mẫu, {label: [featureset]}. Sau đó, chúng tôi sẽ sử dụng ánh xạ này để tạo danh sách các trường hợp đào tạo được gắn nhãn và các trường hợp thử nghiệm.

import collections

def label_corpus(corp, feature_detector=bow):
   label_feats = collections.defaultdict(list)
   for label in corp.categories():
      for fileid in corp.fileids(categories=[label]):
         feats = feature_detector(corp.words(fileids=[fileid]))
         label_feats[label].append(feats)
   return label_feats

Với sự trợ giúp của hàm trên, chúng ta sẽ nhận được một ánh xạ {label:fetaureset}. Bây giờ chúng ta sẽ định nghĩa một hàm nữa có tênsplit điều đó sẽ lấy một ánh xạ trả về từ label_corpus() chức năng và chia từng danh sách các tập hợp tính năng thành các phiên bản huấn luyện có nhãn cũng như thử nghiệm.

def split(lfeats, split=0.75):
   train_feats = []
   test_feats = []
   for label, feats in lfeats.items():
      cutoff = int(len(feats) * split)
      train_feats.extend([(feat, label) for feat in feats[:cutoff]])
      test_feats.extend([(feat, label) for feat in feats[cutoff:]])
   return train_feats, test_feats

Bây giờ, chúng ta hãy sử dụng các hàm này trên kho tài liệu của chúng ta, tức là movie_reviews -

from nltk.corpus import movie_reviews
from featx import label_feats_from_corpus, split_label_feats
movie_reviews.categories()

Đầu ra

['neg', 'pos']

Thí dụ

lfeats = label_feats_from_corpus(movie_reviews)
lfeats.keys()

Đầu ra

dict_keys(['neg', 'pos'])

Thí dụ

train_feats, test_feats = split_label_feats(lfeats, split = 0.75)
len(train_feats)

Đầu ra

1500

Thí dụ

len(test_feats)

Đầu ra

500

Chúng tôi đã thấy điều đó trong movie_reviewskho văn bản, có 1000 tệp pos và 1000 tệp neg. Chúng tôi cũng kết thúc với 1500 phiên bản đào tạo được gắn nhãn và 500 phiên bản thử nghiệm được gắn nhãn.

Bây giờ hãy để chúng tôi đào tạo NaïveBayesClassifier sử dụng nó train() phương pháp lớp -

from nltk.classify import NaiveBayesClassifier
NBC = NaiveBayesClassifier.train(train_feats)
NBC.labels()

Đầu ra

['neg', 'pos']

Bộ phân loại cây quyết định

Một bộ phân loại quan trọng khác là bộ phân loại cây quyết định. Ở đây để đào tạo nóDecisionTreeClassifierlớp sẽ tạo ra một cấu trúc cây. Trong cấu trúc cây này, mỗi nút tương ứng với một tên đối tượng và các nhánh tương ứng với các giá trị đối tượng. Và xuống các cành, chúng ta sẽ đến lá của cây tức là các nhãn phân loại.

Để đào tạo bộ phân loại cây quyết định, chúng tôi sẽ sử dụng các tính năng đào tạo và kiểm tra tương tự, tức là train_featstest_feats, các biến chúng tôi đã tạo từ movie_reviews ngữ liệu.

Thí dụ

Để đào tạo bộ phân loại này, chúng tôi sẽ gọi DecisionTreeClassifier.train() phương thức lớp như sau:

from nltk.classify import DecisionTreeClassifier
decisiont_classifier = DecisionTreeClassifier.train(
   train_feats, binary = True, entropy_cutoff = 0.8, 
   depth_cutoff = 5, support_cutoff = 30
)
accuracy(decisiont_classifier, test_feats)

Đầu ra

0.725

Bộ phân loại Entropy tối đa

Một bộ phân loại quan trọng khác là MaxentClassifier mà còn được gọi là conditional exponential classifier hoặc là logistic regression classifier. Ở đây để đào tạo nó,MaxentClassifier lớp sẽ chuyển đổi các tập đặc trưng có nhãn thành vectơ bằng cách sử dụng mã hóa.

Để đào tạo bộ phân loại cây quyết định, chúng tôi sẽ sử dụng các tính năng đào tạo và kiểm tra tương tự, tức là train_featstest_feats, các biến chúng tôi đã tạo từ movie_reviews ngữ liệu.

Thí dụ

Để đào tạo bộ phân loại này, chúng tôi sẽ gọi MaxentClassifier.train() phương thức lớp như sau:

from nltk.classify import MaxentClassifier
maxent_classifier = MaxentClassifier
.train(train_feats,algorithm = 'gis', trace = 0, max_iter = 10, min_lldelta = 0.5)
accuracy(maxent_classifier, test_feats)

Đầu ra

0.786

Bộ phân loại Scikit-learning

Một trong những thư viện máy học (ML) tốt nhất là Scikit-learning. Nó thực sự chứa tất cả các loại thuật toán ML cho các mục đích khác nhau, nhưng chúng đều có cùng một mẫu thiết kế phù hợp như sau:

  • Phù hợp với mô hình với dữ liệu
  • Và sử dụng mô hình đó để đưa ra dự đoán

Thay vì truy cập trực tiếp vào các mô hình scikit-learning, ở đây chúng tôi sẽ sử dụng NLTK's SklearnClassifierlớp học. Lớp này là một lớp bao bọc xung quanh một mô hình scikit-learning để làm cho nó phù hợp với giao diện Bộ phân loại của NLTK.

Chúng tôi sẽ làm theo các bước sau để đào tạo một SklearnClassifier lớp học -

Step 1 - Đầu tiên chúng ta sẽ tạo các tính năng luyện tập như đã làm ở các công thức trước.

Step 2 - Bây giờ, chọn và nhập một thuật toán Scikit-learning.

Step 3 - Tiếp theo, chúng ta cần xây dựng một SklearnClassifier lớp với thuật toán đã chọn.

Step 4 - Cuối cùng, chúng tôi sẽ đào tạo SklearnClassifier lớp với các tính năng đào tạo của chúng tôi.

Hãy để chúng tôi thực hiện các bước này trong công thức Python bên dưới -

from nltk.classify.scikitlearn import SklearnClassifier
from sklearn.naive_bayes import MultinomialNB
sklearn_classifier = SklearnClassifier(MultinomialNB())
sklearn_classifier.train(train_feats)
<SklearnClassifier(MultinomialNB(alpha = 1.0,class_prior = None,fit_prior = True))>
accuracy(sk_classifier, test_feats)

Đầu ra

0.885

Đo độ chính xác và thu hồi

Trong khi đào tạo các bộ phân loại khác nhau, chúng tôi cũng đã đo độ chính xác của chúng. Nhưng ngoài độ chính xác, còn có một số chỉ số khác được sử dụng để đánh giá các bộ phân loại. Hai trong số các chỉ số này làprecisionrecall.

Thí dụ

Trong ví dụ này, chúng ta sẽ tính toán độ chính xác và nhớ lại lớp NaiveBayesClassifier mà chúng ta đã đào tạo trước đó. Để đạt được điều này, chúng tôi sẽ tạo một hàm có tên metrics_PR () sẽ nhận hai đối số, một là bộ phân loại được đào tạo và một là các tính năng kiểm tra được gắn nhãn. Cả hai đối số đều giống như chúng ta đã truyền trong khi tính toán độ chính xác của bộ phân loại -

import collections
from nltk import metrics
def metrics_PR(classifier, testfeats):
   refsets = collections.defaultdict(set)
   testsets = collections.defaultdict(set)
   for i, (feats, label) in enumerate(testfeats):
      refsets[label].add(i)
      observed = classifier.classify(feats)
         testsets[observed].add(i)
   precisions = {}
   recalls = {}
   for label in classifier.labels():
   precisions[label] = metrics.precision(refsets[label],testsets[label])
   recalls[label] = metrics.recall(refsets[label], testsets[label])
   return precisions, recalls

Hãy để chúng tôi gọi hàm này để tìm độ chính xác và nhớ lại -

from metrics_classification import metrics_PR
nb_precisions, nb_recalls = metrics_PR(nb_classifier,test_feats)
nb_precisions['pos']

Đầu ra

0.6713532466435213

Thí dụ

nb_precisions['neg']

Đầu ra

0.9676271186440678

Thí dụ

nb_recalls['pos']

Đầu ra

0.96

Thí dụ

nb_recalls['neg']

Đầu ra

0.478

Sự kết hợp của trình phân loại và biểu quyết

Kết hợp các bộ phân loại là một trong những cách tốt nhất để cải thiện hiệu suất phân loại. Và bỏ phiếu là một trong những cách tốt nhất để kết hợp nhiều bộ phân loại. Để bỏ phiếu, chúng ta cần có số phân loại lẻ. Trong công thức Python sau đây, chúng ta sẽ kết hợp ba bộ phân loại là lớp NaiveBayesClassifier, lớp DecisionTreeClassifier và lớp MaxentClassifier.

Để đạt được điều này, chúng ta sẽ định nghĩa một hàm có tên là vote_classifiers () như sau.

import itertools
from nltk.classify import ClassifierI
from nltk.probability import FreqDist
class Voting_classifiers(ClassifierI):
   def __init__(self, *classifiers):
      self._classifiers = classifiers
      self._labels = sorted(set(itertools.chain(*[c.labels() for c in classifiers])))
   def labels(self):
      return self._labels
   def classify(self, feats):
      counts = FreqDist()
      for classifier in self._classifiers:
         counts[classifier.classify(feats)] += 1
      return counts.max()

Chúng ta hãy gọi hàm này để kết hợp ba bộ phân loại và tìm độ chính xác -

from vote_classification import Voting_classifiers
combined_classifier = Voting_classifiers(NBC, decisiont_classifier, maxent_classifier)
combined_classifier.labels()

Đầu ra

['neg', 'pos']

Thí dụ

accuracy(combined_classifier, test_feats)

Đầu ra

0.948

Từ kết quả trên, chúng ta có thể thấy rằng các bộ phân loại kết hợp có độ chính xác cao hơn các bộ phân loại riêng lẻ.