序章

今日生成される大量のデータは非構造化であり、洞察を生成するための処理が必要です。 非構造化データの例としては、ニュース記事、ソーシャルメディアへの投稿、検索履歴などがあります。 自然言語を分析してそれを理解するプロセスは、自然言語処理(NLP)の分野に分類されます。 感情分析は一般的なNLPタスクであり、テキストまたはテキストの一部を事前定義された感情に分類する必要があります。 Natural Language Toolkit(NLTK)は、Pythonで一般的に使用されるNLPライブラリであり、テキストデータを分析します。

このチュートリアルでは、さまざまなデータクリーニング方法を使用して、NLP用のNLTKパッケージからサンプルツイートのデータセットを準備します。 データセットを処理する準備ができたら、事前に分類されたツイートでモデルをトレーニングし、そのモデルを使用してサンプルのツイートを否定的な感情と肯定的な感情に分類します。

この記事は、 Python Python 3シリーズのコーディング方法を参照)の基本、主にデータ構造、クラス、およびメソッドの使用に精通していることを前提としています。 このチュートリアルでは、NLPのバックグラウンドがなく、 nltk、それに関するいくつかの知識は追加の利点ですが。

前提条件

  • このチュートリアルは、Pythonバージョン3.6.5に基づいています。 Python 3をインストールしていない場合は、Python3のローカルプログラミング環境をインストールしてセットアップするためのガイドを以下に示します。
  • 言語データの操作に精通していることをお勧めします。 NLTKを初めて使用する場合は、 Natural Language Toolkit(NLTK)ガイドを使用してPython3で言語データを操作する方法を確認してください。

ステップ1—NLTKのインストールとデータのダウンロード

このチュートリアルでは、すべてのNLPタスクにPythonのNLTKパッケージを使用します。 このステップでは、NLTKをインストールし、モデルのトレーニングとテストに使用するサンプルツイートをダウンロードします。

まず、NLTKパッケージをインストールします。 pip パッケージマネージャー:

  1. pip install nltk==3.3

このチュートリアルでは、NLTKパッケージの一部であるサンプルツイートを使用します。 まず、次のコマンドを実行してPythonインタラクティブセッションを開始します。

  1. python3

次に、 nltk Pythonインタープリターのモジュール。

  1. import nltk

NLTKパッケージからサンプルツイートをダウンロードします。

  1. nltk.download('twitter_samples')

Pythonインタープリターからこのコマンドを実行すると、ツイートがダウンロードされてローカルに保存されます。 サンプルがダウンロードされると、使用できるようになります。

チュートリアルの後半で、ネガティブツイートとポジティブツイートを使用して、感情分析に関するモデルをトレーニングします。 感情のないツイートは、モデルのテストに使用されます。

独自のデータセットを使用する場合は、 Twitter API を使用して、特定の期間、ユーザー、またはハッシュタグからツイートを収集できます。

NLTKをインポートし、サンプルツイートをダウンロードしたので、次のように入力してインタラクティブセッションを終了します。 exit(). これで、ツイートをインポートしてデータの処理を開始する準備が整いました。

ステップ2—データのトークン化

元の形式の言語は機械で正確に処理できないため、機械が理解しやすいように言語を処理する必要があります。 データを理解するための最初の部分は、トークン化と呼ばれるプロセス、またはトークンと呼ばれる小さな部分に文字列を分割することです。

トークンは、ユニットとして機能するテキスト内の文字のシーケンスです。 トークンの作成方法に基づいて、トークンは単語、絵文字、ハッシュタグ、リンク、または個々の文字で構成されている場合があります。 言語をトークンに分割する基本的な方法は、空白と句読点に基づいてテキストを分割することです。

開始するには、新しいを作成します .py スクリプトを保持するファイル。 このチュートリアルでは、 nlp_test.py:

  1. nano nlp_test.py

このファイルでは、最初にインポートします twitter_samples そのため、そのデータを操作できます。

nlp_test.py
from nltk.corpus import twitter_samples

これにより、モデルをトレーニングおよびテストするためのさまざまなツイートを含む3つのデータセットがNLTKからインポートされます。

  • negative_tweets.json:否定的な感情を持つ5000ツイート
  • positive_tweets.json:肯定的な感情を持つ5000ツイート
  • tweets.20150430-223406.json:感情のない20000ツイート

次に、の変数を作成します positive_tweets, negative_tweets、 と text:

nlp_test.py
from nltk.corpus import twitter_samples

positive_tweets = twitter_samples.strings('positive_tweets.json')
negative_tweets = twitter_samples.strings('negative_tweets.json')
text = twitter_samples.strings('tweets.20150430-223406.json')

The strings() の方法 twitter_samples データセット内のすべてのツイートを文字列として出力します。 さまざまなツイートコレクションを変数として設定すると、処理とテストが簡単になります。

NLTKでトークナイザーを使用する前に、追加のリソースをダウンロードする必要があります。 punkt. The punkt モジュールは、単語や文をトークン化するのに役立つ事前トレーニング済みのモデルです。 たとえば、このモデルは、名前にピリオドが含まれている可能性があることを認識しています(「S. Daityari」)と文のこの期間の存在は必ずしもそれを終わらせるわけではありません。 まず、Pythonインタラクティブセッションを開始します。

  1. python3

セッションで次のコマンドを実行して、 punkt 資源:

  1. import nltk
  2. nltk.download('punkt')

ダウンロードが完了すると、NLTKのトークナイザーを使用できるようになります。 NLTKは、ツイートのデフォルトのトークナイザーを提供します。 .tokenized() 方法。 行を追加して、トークン化するオブジェクトを作成します positive_tweets.json データセット:

nlp_test.py
from nltk.corpus import twitter_samples

positive_tweets = twitter_samples.strings('positive_tweets.json')
negative_tweets = twitter_samples.strings('negative_tweets.json')
text = twitter_samples.strings('tweets.20150430-223406.json')
tweet_tokens = twitter_samples.tokenized('positive_tweets.json')

スクリプトをテストして、 .tokenized 実行中のメソッドで、強調表示されたコンテンツを nlp_test.py 脚本。 これは、からの単一のツイートをトークン化します positive_tweets.json データセット:

nlp_test.py
from nltk.corpus import twitter_samples

positive_tweets = twitter_samples.strings('positive_tweets.json')
negative_tweets = twitter_samples.strings('negative_tweets.json')
text = twitter_samples.strings('tweets.20150430-223406.json')
tweet_tokens = twitter_samples.tokenized('positive_tweets.json')[0]

print(tweet_tokens[0])

ファイルを保存して閉じ、スクリプトを実行します。

  1. python3 nlp_test.py

トークン化のプロセスは、空白での単純な分割ではないため、時間がかかります。 しばらく処理すると、次のように表示されます。

Output
['#FollowFriday', '@France_Inte', '@PKuchly57', '@Milipol_Paris', 'for', 'being', 'top', 'engaged', 'members', 'in', 'my', 'community', 'this', 'week', ':)']

ここでは、 .tokenized() メソッドは、次のような特殊文字を返します @_. これらの文字は、このチュートリアルの後半で正規表現によって削除されます。

これで、 .tokenized() メソッドは機能します。コメントアウトするか、最後の行を削除して、トークン化されたツイートをスクリプトから追加して、 # 行の先頭まで:

nlp_test.py
from nltk.corpus import twitter_samples

positive_tweets = twitter_samples.strings('positive_tweets.json')
negative_tweets = twitter_samples.strings('negative_tweets.json')
text = twitter_samples.strings('tweets.20150430-223406.json')
tweet_tokens = twitter_samples.tokenized('positive_tweets.json')[0]

#print(tweet_tokens[0])

これで、データをトークン化するようにスクリプトが構成されました。 次のステップでは、スクリプトを更新してデータを正規化します。

ステップ3—データの正規化

単語にはさまざまな形式があります。たとえば、「ran」、「runs」、「running」は、同じ動詞「run」のさまざまな形式です。 分析の要件によっては、これらすべてのバージョンを同じ形式の「実行」に変換する必要がある場合があります。 NLPの正規化は、単語を標準形に変換するプロセスです。

正規化は、同じ意味で異なる形式の単語をグループ化するのに役立ちます。 正規化しないと、「run」、「runs」、および「running」は、同じ単語として扱われるようにしたい場合でも、異なる単語として扱われます。 このセクションでは、正規化の2つの一般的な手法であるステミングレンマ化について説明します。

ステミングは、単語から接辞を削除するプロセスです。 単純な動詞形式のみを処理するステミングは、単語の終わりを削除するヒューリスティックなプロセスです。

このチュートリアルでは、語彙のコンテキストとテキスト内の単語の形態素解析で単語を正規化するレンマ化のプロセスを使用します。 レンマ化アルゴリズムは、単語の構造とそのコンテキストを分析して、正規化された形式に変換します。 したがって、速度が犠牲になります。 ステミングとレンマ化の比較は、最終的には速度と精度の間のトレードオフになります。

lemmatizationの使用に進む前に、Pythonインタラクティブセッションに次のように入力して、必要なリソースをダウンロードしてください。

  1. python3

セッションで次のコマンドを実行して、リソースをダウンロードします。

  1. import nltk
  2. nltk.download('wordnet')
  3. nltk.download('averaged_perceptron_tagger')

wordnet は、スクリプトがベースワードを決定するのに役立つ英語の字句データベースです。 あなたは averaged_perceptron_tagger 文中の単語の文脈を決定するためのリソース。

ダウンロードすると、レンマタイザーを使用する準備がほぼ整います。 レンマタイザーを実行する前に、テキスト内の各単語のコンテキストを決定する必要があります。 これは、文中の単語の相対的な位置を評価するタグ付けアルゴリズムによって実現されます。 Pythonセッションで、 pos_tag 関数、およびタグを取得するための引数としてトークンのリストを提供します。 Pythonでこれを試してみましょう:

  1. from nltk.tag import pos_tag
  2. from nltk.corpus import twitter_samples
  3. tweet_tokens = twitter_samples.tokenized('positive_tweets.json')
  4. print(pos_tag(tweet_tokens[0]))

これがの出力です pos_tag 関数。

Output
[('#FollowFriday', 'JJ'), ('@France_Inte', 'NNP'), ('@PKuchly57', 'NNP'), ('@Milipol_Paris', 'NNP'), ('for', 'IN'), ('being', 'VBG'), ('top', 'JJ'), ('engaged', 'VBN'), ('members', 'NNS'), ('in', 'IN'), ('my', 'PRP$'), ('community', 'NN'), ('this', 'DT'), ('week', 'NN'), (':)', 'NN')]

タグのリストから、最も一般的なアイテムとその意味のリストを次に示します。

  • NNP:名詞、適切、単数
  • NN:名詞、一般、単数または質量
  • IN:前置詞または接続詞、従属
  • VBG:動詞、動名詞または現在分詞
  • VBN:動詞、過去分詞

これがデータセットの完全なリストです。

一般に、タグがで始まる場合 NN、単語は名詞であり、 VB、単語は動詞です。 タグを確認したら、次のように入力してPythonセッションを終了します exit().

これを文を正規化する関数に組み込むには、最初にテキスト内の各トークンのタグを生成してから、タグを使用して各単語を語彙化する必要があります。

を更新します nlp_test.py 文をレンマ化する次の関数を含むファイル:

nlp_test.py
...

from nltk.tag import pos_tag
from nltk.stem.wordnet import WordNetLemmatizer

def lemmatize_sentence(tokens):
    lemmatizer = WordNetLemmatizer()
    lemmatized_sentence = []
    for word, tag in pos_tag(tokens):
        if tag.startswith('NN'):
            pos = 'n'
        elif tag.startswith('VB'):
            pos = 'v'
        else:
            pos = 'a'
        lemmatized_sentence.append(lemmatizer.lemmatize(word, pos))
    return lemmatized_sentence

print(lemmatize_sentence(tweet_tokens[0]))

このコードは WordNetLemmatizer クラスを作成し、それを変数に初期化します。 lemmatizer.

関数 lemmatize_sentence まず、ツイートの各トークンの位置タグを取得します。 以内 if ステートメント、タグがで始まる場合 NN、トークンは名詞として割り当てられます。 同様に、タグがで始まる場合 VB、トークンは動詞として割り当てられます。

ファイルを保存して閉じ、スクリプトを実行します。

  1. python3 nlp_test.py

出力は次のとおりです。

Output
['#FollowFriday', '@France_Inte', '@PKuchly57', '@Milipol_Paris', 'for', 'be', 'top', 'engage', 'member', 'in', 'my', 'community', 'this', 'week', ':)']

動詞に気付くでしょう being ルートフォームへの変更、 be、および名詞 members に変更 member. 先に進む前に、スクリプトからのサンプルツイートを出力する最後の行をコメントアウトしてください。

単語を正規化する関数を正常に作成したので、ノイズを除去する準備が整いました。

ステップ4—データからノイズを取り除く

このステップでは、データセットからノイズを除去します。 Noise は、データに意味や情報を追加しないテキストの一部です。

ノイズはプロジェクトごとに固有であるため、あるプロジェクトでノイズを構成するものが別のプロジェクトにない場合があります。 たとえば、ある言語で最も一般的な単語は、ストップワードと呼ばれます。 ストップワードの例としては、「is」、「the」、「a」などがあります。 特定のユースケースでそれらを含めることが保証されない限り、言語を処理する際には一般的に無関係です。

このチュートリアルでは、 Python の正規表現を使用して、次のアイテムを検索および削除します。

  • ハイパーリンク-Twitterのすべてのハイパーリンクは、URL短縮サービスt.coに変換されます。 したがって、それらをテキスト処理に保持しても、分析に価値はありません。
  • 返信でのTwitterハンドル-これらのTwitterユーザー名の前には @ 意味を伝えない記号。
  • 句読点と特殊文字-これらはテキストデータにコンテキストを提供することがよくありますが、このコンテキストは処理が難しいことがよくあります。 簡単にするために、ツイートからすべての句読点と特殊文字を削除します。

ハイパーリンクを削除するには、最初に、で始まるURLに一致する部分文字列を検索する必要があります http:// また https://、その後に文字、数字、または特殊文字が続きます。 パターンが一致すると、 .sub() メソッドはそれを空の文字列に置き換えます。

内の単語形式を正規化するので remove_noise() 関数、あなたはコメントアウトすることができます lemmatize_sentence() スクリプトからの機能。

次のコードをに追加します nlp_test.py データセットからノイズを除去するファイル:

nlp_test.py
...

import re, string

def remove_noise(tweet_tokens, stop_words = ()):

    cleaned_tokens = []

    for token, tag in pos_tag(tweet_tokens):
        token = re.sub('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+#]|[!*\(\),]|'\
                       '(?:%[0-9a-fA-F][0-9a-fA-F]))+','', token)
        token = re.sub("(@[A-Za-z0-9_]+)","", token)

        if tag.startswith("NN"):
            pos = 'n'
        elif tag.startswith('VB'):
            pos = 'v'
        else:
            pos = 'a'

        lemmatizer = WordNetLemmatizer()
        token = lemmatizer.lemmatize(token, pos)

        if len(token) > 0 and token not in string.punctuation and token.lower() not in stop_words:
            cleaned_tokens.append(token.lower())
    return cleaned_tokens

このコードは remove_noise() ノイズを除去し、前のセクションで説明した正規化とレンマ化を組み込んだ関数。 このコードは、ツイートトークンとストップワードのタプルの2つの引数を取ります。

次に、コードはループを使用してデータセットからノイズを除去します。 ハイパーリンクを削除するには、コードは最初に、で始まるURLに一致する部分文字列を検索します http:// また https://、その後に文字、数字、または特殊文字が続きます。 パターンが一致すると、 .sub() メソッドはそれを空の文字列に置き換えます、または ''.

同様に、削除するには @ 言及すると、コードは正規表現を使用してテキストの関連部分を置き換えます。 コードは re 検索するライブラリ @ 記号の後に数字、文字、または _、およびそれらを空の文字列に置き換えます。

最後に、ライブラリを使用して句読点を削除できます string.

これに加えて、NLTKに組み込まれているストップワードのセットを使用してストップワードを削除することもできます。これは、別途ダウンロードする必要があります。

Pythonインタラクティブセッションから次のコマンドを実行して、このリソースをダウンロードします。

  1. nltk.download('stopwords')

リソースがダウンロードされたら、インタラクティブセッションを終了します。

あなたは使用することができます .words() 英語のストップワードのリストを取得するメソッド。 関数をテストするために、サンプルツイートで実行してみましょう。 次の行をの末尾に追加します nlp_test.py ファイル:

nlp_test.py
...
from nltk.corpus import stopwords
stop_words = stopwords.words('english')

print(remove_noise(tweet_tokens[0], stop_words))

ファイルを保存して閉じた後、スクリプトを再度実行して、次のような出力を受け取ります。

Output
['#followfriday', 'top', 'engage', 'member', 'community', 'week', ':)']

関数がすべてを削除することに注意してください @ 言及し、単語を止め、単語を小文字に変換します。

次のステップのモデリング演習に進む前に、 remove_noise() ポジティブツイートとネガティブツイートをクリーンアップする機能。 行をコメントアウトして、の出力を出力します。 remove_noise() サンプルツイートに以下を追加します nlp_test.py 脚本:

nlp_test.py
...
from nltk.corpus import stopwords
stop_words = stopwords.words('english')

#print(remove_noise(tweet_tokens[0], stop_words))

positive_tweet_tokens = twitter_samples.tokenized('positive_tweets.json')
negative_tweet_tokens = twitter_samples.tokenized('negative_tweets.json')

positive_cleaned_tokens_list = []
negative_cleaned_tokens_list = []

for tokens in positive_tweet_tokens:
    positive_cleaned_tokens_list.append(remove_noise(tokens, stop_words))

for tokens in negative_tweet_tokens:
    negative_cleaned_tokens_list.append(remove_noise(tokens, stop_words))

サンプルツイートをクリーンアップするコードを追加したので、元のトークンをサンプルツイートのクリーンアップされたトークンと比較することをお勧めします。 これをテストする場合は、次のコードをファイルに追加して、リスト内の500番目のツイートの両方のバージョンを比較します。

nlp_test.py
...
print(positive_tweet_tokens[500])
print(positive_cleaned_tokens_list[500])

ファイルを保存して閉じ、スクリプトを実行します。 出力から、句読点とリンクが削除され、単語が小文字に変換されていることがわかります。

Output
['Dang', 'that', 'is', 'some', 'rad', '@AbzuGame', '#fanart', '!', ':D', 'https://t.co/bI8k8tb9ht'] ['dang', 'rad', '#fanart', ':d']

テキストの前処理中に発生する可能性のある特定の問題があります。 たとえば、スペースのない単語(“ iLoveYou”)は1つとして扱われ、そのような単語を区切るのは難しい場合があります。 さらに、「Hi」、「Hii」、および「Hiiiii」は、問題に取り組むために特定の何かを記述しない限り、スクリプトによって異なる方法で処理されます。 特定のデータのノイズ除去プロセスを微調整するのが一般的です。

今、あなたは見ました remove_noise() 関数が動作している場合は、スクリプトにコメントアウトするか、スクリプトから最後の2行を削除して、スクリプトにさらに追加できるようにしてください。

nlp_test.py
...
#print(positive_tweet_tokens[500])
#print(positive_cleaned_tokens_list[500])

このステップでは、分析をより効果的にするために、データからノイズを除去しました。 次のステップでは、データを分析して、サンプルデータセットで最も一般的な単語を見つけます。

ステップ5—単語密度の決定

テキストデータの分析の最も基本的な形式は、単語の頻度を取り出すことです。 単一のツイートは、単語の分布を見つけるにはエンティティとしては小さすぎるため、単語の頻度の分析は、すべての肯定的なツイートに対して行われます。

次のスニペットは、ジェネレーター関数を定義します。 get_all_words、これは、ツイートのリストを引数として取り、結合されたすべてのツイートトークン内の単語のリストを提供します。 次のコードをに追加します nlp_test.py ファイル:

nlp_test.py
...

def get_all_words(cleaned_tokens_list):
    for tokens in cleaned_tokens_list:
        for token in tokens:
            yield token

all_pos_words = get_all_words(positive_cleaned_tokens_list)

ツイートのサンプルにあるすべての単語をまとめたので、NLTKのFreqDistクラスを使用して最も一般的な単語を見つけることができます。 次のコードをに追加します nlp_test.py ファイル:

nlp_test.py
from nltk import FreqDist

freq_dist_pos = FreqDist(all_pos_words)
print(freq_dist_pos.most_common(10))

The .most_common() メソッドは、データで最も頻繁に出現する単語をリストします。 これらの変更を行った後、ファイルを保存して閉じます。

ここでファイルを実行すると、データに最も一般的な用語が含まれています。

Output
[(':)', 3691), (':-)', 701), (':d', 658), ('thanks', 388), ('follow', 357), ('love', 333), ('...', 290), ('good', 283), ('get', 263), ('thank', 253)]

このデータから、絵文字エンティティがポジティブツイートの最も一般的な部分のいくつかを形成していることがわかります。 次のステップに進む前に、上位10個のトークンを出力するスクリプトの最後の行を必ずコメントアウトしてください。

要約すると、あなたはからツイートを抽出しました nltk、トークン化、正規化、およびモデルで使用するためのツイートのクリーンアップ。 最後に、データ内のトークンの頻度も調べ、上位10個のトークンの頻度を確認しました。

次のステップでは、感情分析用のデータを準備します。

ステップ6—モデルのデータを準備する

感情分析は、書かれているトピックに対する著者の態度を特定するプロセスです。 モデルをトレーニングするためのトレーニングデータセットを作成します。 これは教師あり学習機械学習プロセスであり、各データセットをトレーニングの「感情」に関連付ける必要があります。 このチュートリアルでは、モデルは「ポジティブ」および「ネガティブ」な感情を使用します。

感情分析を使用して、テキストをさまざまな感情に分類できます。 トレーニングデータセットを簡素化して利用できるようにするために、このチュートリアルでは、ポジティブとネガティブの2つのカテゴリのみでモデルをトレーニングするのに役立ちます。

モデルは、ルールと方程式を使用したシステムの記述です。 身長を考えると、人の体重を予測する方程式のように単純な場合があります。 構築する感情分析モデルは、ツイートをポジティブまたはネガティブな感情に関連付けます。 データセットを2つの部分に分割する必要があります。 最初の部分の目的はモデルを構築することですが、次の部分はモデルのパフォーマンスをテストします。

データ準備ステップでは、トークンを辞書形式に変換して感情分析用のデータを準備し、トレーニングとテストの目的でデータを分割します。

トークンを辞書に変換する

まず、モデルに入力するデータを準備します。 NLTKの単純ベイズ分類器を使用して、モデリングの演習を行います。 モデルには、ツイート内の単語のリストだけでなく、単語をキーとして使用するPython辞書が必要であることに注意してください。 True 値として。 次の関数は、クリーンアップされたデータの形式を変更するジェネレーター関数を作成します。

次のコードを追加して、ツイートをクリーンアップされたトークンのリストから、キーをトークンとして持つ辞書に変換します。 True 値として。 対応する辞書はに保存されます positive_tokens_for_modelnegative_tokens_for_model.

nlp_test.py
...
def get_tweets_for_model(cleaned_tokens_list):
    for tweet_tokens in cleaned_tokens_list:
        yield dict([token, True] for token in tweet_tokens)

positive_tokens_for_model = get_tweets_for_model(positive_cleaned_tokens_list)
negative_tokens_for_model = get_tweets_for_model(negative_cleaned_tokens_list)

モデルのトレーニングとテストのためのデータセットの分割

次に、トレーニング用のデータを準備する必要があります NaiveBayesClassifier クラス。 次のコードをファイルに追加して、データを準備します。

nlp_test.py
...
import random

positive_dataset = [(tweet_dict, "Positive")
                     for tweet_dict in positive_tokens_for_model]

negative_dataset = [(tweet_dict, "Negative")
                     for tweet_dict in negative_tokens_for_model]

dataset = positive_dataset + negative_dataset

random.shuffle(dataset)

train_data = dataset[:7000]
test_data = dataset[7000:]

このコードは Positive また Negative 各ツイートにラベルを付けます。 次に、 dataset ポジティブとネガティブなツイートに参加することによって。

デフォルトでは、データにはすべての肯定的なツイートとそれに続くすべての否定的なツイートが順番に含まれます。 モデルをトレーニングするときは、バイアスを含まないデータのサンプルを提供する必要があります。 バイアスを回避するために、を使用してデータをランダムに配置するコードを追加しました .shuffle() の方法 random.

最後に、コードはシャッフルされたデータをトレーニングとテストのためにそれぞれ70:30の比率に分割します。 ツイートの数は10000であるため、シャッフルされたデータセットの最初の7000ツイートをモデルのトレーニングに使用し、最後の3000ツイートをモデルのテストに使用できます。

このステップでは、クリーンアップされたトークンを辞書形式に変換し、データセットをランダムにシャッフルして、トレーニングデータとテストデータに分割しました。

ステップ7—モデルの構築とテスト

最後に、あなたは使用することができます NaiveBayesClassifier モデルを構築するためのクラス。 使用 .train() モデルをトレーニングする方法と .accuracy() テストデータでモデルをテストする方法。

nlp_test.py
...
from nltk import classify
from nltk import NaiveBayesClassifier
classifier = NaiveBayesClassifier.train(train_data)

print("Accuracy is:", classify.accuracy(classifier, test_data))

print(classifier.show_most_informative_features(10))

コードを追加したら、ファイルを保存して閉じ、実行します。 コードの出力は次のようになります。

Output
Accuracy is: 0.9956666666666667 Most Informative Features :( = True Negati : Positi = 2085.6 : 1.0 :) = True Positi : Negati = 986.0 : 1.0 welcome = True Positi : Negati = 37.2 : 1.0 arrive = True Positi : Negati = 31.3 : 1.0 sad = True Negati : Positi = 25.9 : 1.0 follower = True Positi : Negati = 21.1 : 1.0 bam = True Positi : Negati = 20.7 : 1.0 glad = True Positi : Negati = 18.1 : 1.0 x15 = True Negati : Positi = 15.9 : 1.0 community = True Positi : Negati = 14.1 : 1.0

精度は、モデルが感情を正しく予測できたテストデータセット内のツイートの割合として定義されます。 テストセットの99.5%の精度はかなり良いです。

最も有益な機能を示す表では、出力のすべての行に、トレーニングデータセットのポジティブタグとネガティブタグのツイートでのトークンの発生率が示されています。 データの最初の行は、トークンを含むすべてのツイートで :(、ポジティブツイートに対するネガティブツイートの比率は 2085.61. 興味深いことに、トークンが1つあったようです :( ポジティブデータセットで。 テキストの上位2つの識別項目が絵文字であることがわかります。 さらに、 sad 否定的な感情につながるのに対し、 welcomeglad ポジティブな感情に関連付けられています。

次に、Twitterからのランダムなツイートでモデルがどのように機能するかを確認できます。 次のコードをファイルに追加します。

nlp_test.py
...
from nltk.tokenize import word_tokenize

custom_tweet = "I ordered just once from TerribleCo, they screwed up, never used the app again."

custom_tokens = remove_noise(word_tokenize(custom_tweet))

print(classifier.classify(dict([token, True] for token in custom_tokens)))

このコードを使用すると、に関連付けられた文字列を更新してカスタムツイートをテストできます。 custom_tweet 変数。 これらの変更を行った後、ファイルを保存して閉じます。

スクリプトを実行して、カスタムテキストを分析します。 例のカスタムテキストの出力は次のとおりです。

Output
'Negative'

また、肯定的なツイートを正しく特徴付けているかどうかを確認することもできます。

nlp_test.py
...
custom_tweet = 'Congrats #SportStar on your 7th best goal from last season winning goal of the year :) #Baller #Topbin #oneofmanyworldies'

出力は次のとおりです。

Output
'Positive'

ポジティブな感情とネガティブな感情の両方をテストしたので、変数を更新して、皮肉のようなより複雑な感情をテストします。

nlp_test.py
...
custom_tweet = 'Thank you for sending my baggage to CityX and flying me to CityY at the same time. Brilliant service. #thanksGenericAirline'

出力は次のとおりです。

Output
'Positive'

モデルは、この例をポジティブとして分類しました。 これは、トレーニングデータが、皮肉なツイートをネガティブとして分類するのに十分なほど包括的ではなかったためです。 モデルで皮肉を予測する場合は、それに応じてモデルをトレーニングするために十分な量のトレーニングデータを提供する必要があります。

このステップでは、モデルを作成してテストしました。 また、特定の例で皮肉を検出しないなど、その制限のいくつかについても調査しました。 完成したコードには、チュートリアルに従うことでアーティファクトが残っているため、次のステップでは、コードをPythonのベストプラクティスに合わせる方法を説明します。

ステップ8—コードのクリーンアップ(オプション)

チュートリアルを完了しましたが、コードを再編成することをお勧めします。 nlp_test.py プログラミングのベストプラクティスに従うためのファイル。 ベストプラクティスに従って、コードは次の基準を満たす必要があります。

  • すべてのインポートはファイルの先頭にある必要があります。 同じライブラリからのインポートは、1つのステートメントにグループ化する必要があります。
  • すべての関数は、インポート後に定義する必要があります。
  • ファイル内のすべてのステートメントは、 if __name__ == "__main__": 調子。 これにより、ファイルの機能を別のファイルにインポートする場合にステートメントが実行されなくなります。

また、チュートリアルに従ってコメントアウトされたコードを削除します。 lemmatize_sentence レンマ化が新しいによって完了するので、機能 remove_noise 関数。

これがクリーンバージョンです nlp_test.py:

from nltk.stem.wordnet import WordNetLemmatizer
from nltk.corpus import twitter_samples, stopwords
from nltk.tag import pos_tag
from nltk.tokenize import word_tokenize
from nltk import FreqDist, classify, NaiveBayesClassifier

import re, string, random

def remove_noise(tweet_tokens, stop_words = ()):

    cleaned_tokens = []

    for token, tag in pos_tag(tweet_tokens):
        token = re.sub('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+#]|[!*\(\),]|'\
                       '(?:%[0-9a-fA-F][0-9a-fA-F]))+','', token)
        token = re.sub("(@[A-Za-z0-9_]+)","", token)

        if tag.startswith("NN"):
            pos = 'n'
        elif tag.startswith('VB'):
            pos = 'v'
        else:
            pos = 'a'

        lemmatizer = WordNetLemmatizer()
        token = lemmatizer.lemmatize(token, pos)

        if len(token) > 0 and token not in string.punctuation and token.lower() not in stop_words:
            cleaned_tokens.append(token.lower())
    return cleaned_tokens

def get_all_words(cleaned_tokens_list):
    for tokens in cleaned_tokens_list:
        for token in tokens:
            yield token

def get_tweets_for_model(cleaned_tokens_list):
    for tweet_tokens in cleaned_tokens_list:
        yield dict([token, True] for token in tweet_tokens)

if __name__ == "__main__":

    positive_tweets = twitter_samples.strings('positive_tweets.json')
    negative_tweets = twitter_samples.strings('negative_tweets.json')
    text = twitter_samples.strings('tweets.20150430-223406.json')
    tweet_tokens = twitter_samples.tokenized('positive_tweets.json')[0]

    stop_words = stopwords.words('english')

    positive_tweet_tokens = twitter_samples.tokenized('positive_tweets.json')
    negative_tweet_tokens = twitter_samples.tokenized('negative_tweets.json')

    positive_cleaned_tokens_list = []
    negative_cleaned_tokens_list = []

    for tokens in positive_tweet_tokens:
        positive_cleaned_tokens_list.append(remove_noise(tokens, stop_words))

    for tokens in negative_tweet_tokens:
        negative_cleaned_tokens_list.append(remove_noise(tokens, stop_words))

    all_pos_words = get_all_words(positive_cleaned_tokens_list)

    freq_dist_pos = FreqDist(all_pos_words)
    print(freq_dist_pos.most_common(10))

    positive_tokens_for_model = get_tweets_for_model(positive_cleaned_tokens_list)
    negative_tokens_for_model = get_tweets_for_model(negative_cleaned_tokens_list)

    positive_dataset = [(tweet_dict, "Positive")
                         for tweet_dict in positive_tokens_for_model]

    negative_dataset = [(tweet_dict, "Negative")
                         for tweet_dict in negative_tokens_for_model]

    dataset = positive_dataset + negative_dataset

    random.shuffle(dataset)

    train_data = dataset[:7000]
    test_data = dataset[7000:]

    classifier = NaiveBayesClassifier.train(train_data)

    print("Accuracy is:", classify.accuracy(classifier, test_data))

    print(classifier.show_most_informative_features(10))

    custom_tweet = "I ordered just once from TerribleCo, they screwed up, never used the app again."

    custom_tokens = remove_noise(word_tokenize(custom_tweet))

    print(custom_tweet, classifier.classify(dict([token, True] for token in custom_tokens)))

結論

このチュートリアルでは、を使用した基本的な感情分析モデルを紹介しました。 nltk Python3のライブラリ。 まず、ツイートをトークン化し、単語を正規化し、ノイズを除去することにより、ツイートの前処理を実行しました。 次に、データ内で頻繁に発生するアイテムを視覚化しました。 最後に、ツイートを特定の感情に関連付けるモデルを作成しました。

教師あり学習モデルは、そのトレーニングデータと同じくらい優れています。 モデルをさらに強化するために、興奮や怒りなどのカテゴリをさらに追加することを検討できます。 このチュートリアルでは、基本的なモデルを作成することによって表面を引っかいただけです。 ここに感情分析を実行する際に注意しなければならないさまざまな考慮事項の詳細なガイドがあります。