自然言語ツールキット-テキスト分類

テキスト分類とは何ですか?

テキスト分類は、その名前が示すように、テキストまたはドキュメントの断片を分類する方法です。しかし、ここで、なぜテキスト分類子を使用する必要があるのか​​という疑問が生じます。ドキュメントまたはテキスト内の単語の使用法を調べると、分類子はそれに割り当てるクラスラベルを決定できます。

二項分類器

名前が示すように、バイナリ分類器は2つのラベルのどちらかを決定します。たとえば、正または負。この場合、テキストまたはドキュメントはいずれかのラベルにすることができますが、両方にすることはできません。

マルチラベル分類子

バイナリ分類器とは反対に、マルチラベル分類器は1つ以上のラベルをテキストまたはドキュメントに割り当てることができます。

ラベル付きとラベルなしの機能セット

機能名から機能値へのKey-Valueマッピングは、機能セットと呼ばれます。ラベル付き機能セットまたはトレーニングデータは、後でラベルなし機能セットを分類できるように、分類トレーニングにとって非常に重要です。

ラベル付き機能セット ラベルのない機能セット
(feat、label)のようなタプルです。 それ自体が偉業です。
これは、既知のクラスラベルを持つインスタンスです。 ラベルが関連付けられていない場合は、インスタンスと呼ぶことができます。
分類アルゴリズムのトレーニングに使用されます。 トレーニングが完了すると、分類アルゴリズムはラベルのない機能セットを分類できます。

テキスト特徴抽出

テキスト特徴抽出は、その名前が示すように、単語のリストを分類器で使用できる特徴セットに変換するプロセスです。テキストをに変換する必要があります‘dict’ Natural Language Tool Kit(NLTK)が期待するため、スタイル機能セット ‘dict’ スタイルの機能セット。

Bag of Words(BoW)モデル

NLPで最も単純なモデルの1つであるBoWは、テキストまたはドキュメントから特徴を抽出するために使用され、MLアルゴリズムなどのモデリングで使用できるようにします。基本的に、インスタンスのすべての単語から単語プレゼンス機能セットを構築します。この方法の背後にある概念は、単語が出現する回数や単語の順序を気にせず、単語が単語のリストに存在するかどうかだけを気にするというものです。

この例では、bow()−という名前の関数を定義します。

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

さて、電話しましょう bow()言葉で機能します。この関数をbagwords.pyという名前のファイルに保存しました。

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

出力

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

分類器のトレーニング

前のセクションでは、テキストから特徴を抽出する方法を学びました。これで、分類器をトレーニングできます。最初で最も簡単な分類子はNaiveBayesClassifier クラス。

単純ベイズ分類器

特定の機能セットが特定のラベルに属する確率を予測するために、ベイズの定理を使用します。ベイズの定理の公式は次のとおりです。

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

ここに、

P(A|B) −事後確率、つまり2番目のイベント(B)が発生した場合に最初のイベント(A)が発生する確率とも呼ばれます。

P(B|A) −最初のイベント(A)の後に2番目のイベント(B)が発生する確率です。

P(A), P(B) −事前確率、つまり最初のイベント、つまりAまたは2番目のイベント、つまりBが発生する確率とも呼ばれます。

単純ベイズ分類器をトレーニングするために、 movie_reviewsNLTKのコーパス。このコーパスには、次の2つのカテゴリのテキストがあります。pos そして neg。これらのカテゴリは、それらでトレーニングされた分類器をバイナリ分類器にします。コーパス内のすべてのファイルは2つで構成され、1つは肯定的な映画レビューで、もう1つは否定的な映画レビューです。この例では、分類器のトレーニングとテストの両方で、各ファイルを単一のインスタンスとして使用します。

分類器をトレーニングするには、ラベル付きの機能セットのリストが必要です。これは[(featureset, label)]。ここにfeatureset 変数は dict labelは、の既知のクラスラベルです。 featureset。という名前の関数を作成しますlabel_corpus() 名前の付いたコーパスを取ります movie_reviewsまた、という名前の関数 feature_detector、デフォルトは bag of words。{label:[featureset]}という形式のマッピングを作成して返します。その後、このマッピングを使用して、ラベル付けされたトレーニングインスタンスとテストインスタンスのリストを作成します。

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

上記の関数の助けを借りて、マッピングを取得します {label:fetaureset}。次に、という名前の関数をもう1つ定義します。split それはから返されたマッピングを取ります label_corpus() 機能し、機能セットの各リストをラベル付きのトレーニングとテストインスタンスに分割します。

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

では、これらの関数をコーパスで使用しましょう。つまり、movie_reviews −

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

出力

['neg', 'pos']

lfeats = label_feats_from_corpus(movie_reviews)
lfeats.keys()

出力

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

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

出力

1500

len(test_feats)

出力

500

私たちはそれを見てきました movie_reviewsコーパスには、1000個のposファイルと1000個のnegファイルがあります。また、1500個のラベル付きトレーニングインスタンスと500個のラベル付きテストインスタンスが作成されます。

さあ、訓練しましょう NaïveBayesClassifier そのを使用して train() クラスメソッド-

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

出力

['neg', 'pos']

デシジョンツリー分類子

もう1つの重要な分類子は、決定木分類子です。ここでそれを訓練するDecisionTreeClassifierクラスはツリー構造を作成します。このツリー構造では、各ノードは機能名に対応し、ブランチは機能値に対応します。そして枝を下って、木の葉、つまり分類ラベルにたどり着きます。

デシジョンツリー分類器をトレーニングするには、同じトレーニングおよびテスト機能を使用します。 train_feats そして test_feats、から作成した変数 movie_reviews コーパス。

この分類器をトレーニングするために、 DecisionTreeClassifier.train() 次のようなクラスメソッド-

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)

出力

0.725

最大エントロピー分類器

もう1つの重要な分類子は MaxentClassifier これは、 conditional exponential classifier または logistic regression classifier。ここでそれを訓練するために、MaxentClassifier クラスは、エンコーディングを使用して、ラベル付けされたフィーチャセットをベクトルに変換します。

デシジョンツリー分類器をトレーニングするには、同じトレーニングおよびテスト機能を使用します。 train_featsそして test_feats、から作成した変数 movie_reviews コーパス。

この分類器をトレーニングするために、 MaxentClassifier.train() 次のようなクラスメソッド-

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)

出力

0.786

Scikit-learn分類子

最高の機械学習(ML)ライブラリの1つは、Scikit-learnです。実際には、さまざまな目的のためにあらゆる種類のMLアルゴリズムが含まれていますが、それらはすべて、次のように同じフィット設計パターンを持っています。

  • モデルをデータに適合させる
  • そして、そのモデルを使用して予測を行います

ここでは、scikit-learnモデルに直接アクセスするのではなく、NLTKを使用します。 SklearnClassifierクラス。このクラスは、NLTKのClassifierインターフェイスに準拠させるためのscikit-learnモデルのラッパークラスです。

次の手順に従って、 SklearnClassifier クラス-

Step 1 −最初に、以前のレシピで行ったようにトレーニング機能を作成します。

Step 2 −ここで、Scikit-learnアルゴリズムを選択してインポートします。

Step 3 −次に、構築する必要があります SklearnClassifier 選択したアルゴリズムのクラス。

Step 4 −最後にトレーニングします SklearnClassifier トレーニング機能を備えたクラス。

以下のPythonレシピでこれらのステップを実装しましょう-

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)

出力

0.885

適合率と再現率の測定

さまざまな分類器をトレーニングしながら、それらの精度も測定しました。しかし、精度とは別に、分類子を評価するために使用される他の多くのメトリックがあります。これらのメトリックの2つはprecision そして recall

この例では、以前にトレーニングしたNaiveBayesClassifierクラスの適合率と再現率を計算します。これを実現するために、2つの引数をとるmetrics_PR()という名前の関数を作成します。1つはトレーニング済みの分類子で、もう1つはラベル付きのテスト機能です。両方の引数は、分類子の精度を計算するときに渡したものと同じです。

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

この関数を呼び出して適合率を求め、再現率を求めましょう。

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

出力

0.6713532466435213

nb_precisions['neg']

出力

0.9676271186440678

nb_recalls['pos']

出力

0.96

nb_recalls['neg']

出力

0.478

分類子と投票の組み合わせ

分類器を組み合わせることは、分類のパフォーマンスを向上させるための最良の方法の1つです。また、投票は、複数の分類子を組み合わせるための最良の方法の1つです。投票するには、奇数の分類子が必要です。次のPythonレシピでは、NaiveBayesClassifierクラス、DecisionTreeClassifierクラス、MaxentClassifierクラスの3つの分類器を組み合わせます。

これを実現するために、voting_classifiers()という名前の関数を次のように定義します。

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()

この関数を呼び出して、3つの分類子を組み合わせ、精度を見つけましょう。

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

出力

['neg', 'pos']

accuracy(combined_classifier, test_feats)

出力

0.948

上記の出力から、結合された分類器が個々の分類器よりも最高の精度を獲得したことがわかります。