_著者はhttps://www.brightfunds.org/funds/open-internet-free-speech[Open Internet / Free Speech]基金を選択して、https://do.co/w4do-ctaの一部として寄付を受け取りました[寄付のために書く]プログラム。

前書き

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

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

この記事は、https://www.python.org/ [Python](https://www.digitalocean.com/community/tutorial_series/how-to-code-in-pythonを参照)の基本に精通していることを前提としています。 -3 [Python 3シリーズのコーディング方法])、主にデータ構造、クラス、およびメソッドの使用。 このチュートリアルでは、NLPと `+ nltk +`の背景知識がないことを前提としていますが、NLPに関するある程度の知識は追加の利点です。

前提条件

  • このチュートリアルは、Pythonバージョン3.6.5に基づいています。 Python 3がインストールされていない場合は、https://www.digitalocean.com/community/tutorial_series/how-to-install-and-set-up-a-local-programming-environment-for-のガイドをご覧くださいpython-3 [Python 3のローカルプログラミング環境のインストールとセットアップ]。

  • 言語データの操作に精通していることをお勧めします。 NLTKを初めて使用する場合は、https://www.digitalocean.com/community/tutorials/how-to-work-with-language-data-in-python-3-using-the-natural-をご覧ください。 language-toolkit-nltk [Natural Language Toolkit(NLTK)を使用してPython 3で言語データを操作する方法]ガイド。

手順1-NLTKのインストールとデータのダウンロード

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

まず、 `+ pip +`パッケージマネージャーでhttps://www.nltk.org/install.html[NLTKパッケージをインストール]:

pip install nltk==3.3

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

python3

次に、Pythonインタープリターで `+ nltk +`モジュールをインポートします。

import nltk

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

nltk.download('twitter_samples')

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

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

独自のデータセットを使用する場合は、https://developer.twitter.com/en/docs.html [Twitter API]を使用して、特定の期間、ユーザー、またはハッシュタグからツイートを収集できます。

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

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

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

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

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

nano nlp_test.py

このファイルでは、最初に `+ twitter_samples +`をインポートして、そのデータを操作できるようにします。

nlp_test.py

from nltk.corpus import twitter_samples

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

  • + negativetweets.json:否定的な感情を持つ5000件のツイート

  • + positivetweets.json:肯定的な感情を持つ5000のツイート

  • + tweets.20150430-223406.json +:感情のない20000件のツイート

次に、 + positive_tweets ++ negative_tweets +、および `+ text +`の変数を作成します。

nlp_test.py

from nltk.corpus import twitter_samples

`+ twitter_samples `の ` strings()+`メソッドは、データセット内のすべてのツイートを文字列として出力します。 さまざまなツイートコレクションを変数として設定すると、処理とテストが容易になります。

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

python3

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

import nltk
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')

スクリプトをテストして、実行中の `+ .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')

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

python3 nlp_test.py

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

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

ここで、 `+ .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')

#print(tweet_tokens[0])

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

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

単語にはさまざまな形式があります。たとえば、「ran」、「runs」、「running」は、同じ動詞「run」のさまざまな形式です。 分析の要件に応じて、これらすべてのバージョンを同じ形式の「​​実行」に変換する必要がある場合があります。 NLPのhttps://en.wikipedia.org/wiki/Text_normalization[Normalization]は、単語を正規の形式に変換するプロセスです。

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

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

このチュートリアルでは、語彙とhttps://en.wikipedia.org/wiki/Morphology_(linguistics)[形態素解析]のコンテキストで単語を正規化する、見出し語化のプロセスを使用します。 補題アルゴリズムは、単語の構造とそのコンテキストを分析して、正規化された形式に変換します。 したがって、速度が犠牲になります。 ステミングと補題の比較は、最終的には速度と精度のトレードオフに帰着します。

見出し語化の使用に進む前に、Pythonインタラクティブセッションに次を入力して必要なリソースをダウンロードします。

python3

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

import nltk
nltk.download('wordnet')
nltk.download('averaged_perceptron_tagger')

http://www.nltk.org/howto/wordnet.html [+ wordnet +]は、スクリプトがベースワードを決定するのに役立つ英語の字句データベースです。 文の単語のコンテキストを決定するには、 `+ averaged_perceptron_tagger +`リソースが必要です。

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

from nltk.tag import pos_tag
from nltk.corpus import twitter_samples

tweet_tokens = twitter_samples.tokenized('positive_tweets.json')
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 +:動詞、過去分詞

https://www.ling.upenn.edu/courses/Fall_2003/ling001/penn_treebank_pos.html [データセットの全リスト]はこちらです。

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

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

文を見出し語化する次の関数を使用して、 `+ 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 +」で始まる場合、トークンは動詞として割り当てられます。

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

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-データからノイズを除去する

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

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

このチュートリアルでは、https://docs.python.org/3.6/howto/regex.html [Pythonで正規表現を使用]でこれらのアイテムを検索して削除します。

  • ハイパーリンク-Twitterのすべてのハイパーリンクは、URL短縮サービスhttps://developer.twitter.com/en/docs/basics/tco.html[t.co]に変換されます。 したがって、それらをテキスト処理に保持しても、分析に値が追加されることはありません。

  • * Twitterは返信を処理します*-これらのTwitterユーザー名の前には、意味を伝えない「+ @ +」記号が付いています。

  • 句読点と特殊文字-これらはテキストデータのコンテキストを提供することが多いですが、このコンテキストはしばしば処理が困難です。 簡単にするために、すべての句読点と特殊文字をツイートから削除します。

ハイパーリンクを削除するには、最初に `+ http:// `または ` https:// `で始まり、その後に文字、数字、または特殊文字が続くURLに一致する部分文字列を検索する必要があります。 パターンが一致すると、 ` .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]|[[email protected]&+#]|[!*\(\),]|'\
                      '(?:%[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つの引数を取ります。

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

同様に、「+ @ 」の言及を削除するために、コードは正規表現を使用してテキストの関連部分を置き換えます。 このコードは、 ` re `ライブラリを使用して ` @ `シンボルを検索し、その後に数字、文字、または ` _ +`を検索し、それらを空の文字列に置き換えます。

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

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

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

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

サンプルのツイートをクリーンアップするコードを追加したので、元のトークンをサンプルのツイートのクリーンアップされたトークンと比較することができます。 これをテストする場合は、ファイルに次のコードを追加して、リスト内の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-単語密度の決定

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

次のスニペットは、https://realpython.com/introduction-to-python-generators/ [ジェネレータ関数]を定義します。これは、すべての単語のリストを提供する引数としてツイートのリストを取得します。ツイートトークンが参加しました。 次のコードを「+ 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)

ツイートのサンプルに含まれるすべての単語をまとめたので、http://www.nltk.org/api/nltk.html?highlight = freqdist [+ FreqDist +]を使用して最も一般的な単語を見つけることができます。 NLTKのクラス。 次のコードを `+ nlp_test.py +`ファイルに追加します:

nlp_test.py

from nltk import FreqDist

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

`+ .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のhttps://www.nltk.org/_modules/nltk/classify/naivebayes.html[Naive Bayes classifier]を使用します。 モデルには、ツイート内の単語のリストだけでなく、単語をキーとして、値が `+ True +`であるPython辞書が必要であることに注意してください。 次の関数は、生成されたデータの形式を変更するジェネレーター関数を作成します。

次のコードを追加して、クリーンアップされたトークンのリストからツイートを、キーをトークンとして、 `+ True `を値として使用する辞書に変換します。 対応する辞書は、 ` positive_tokens_for_model `および ` negative_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 +」を作成します。

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

最後に、コードはシャッフルされたデータをそれぞれトレーニングとテストのために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))

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

OutputAccuracy 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.6」対「1」であることを示しています。 興味深いことに、ポジティブなデータセットには `:(`を持つトークンが1つあったようです。 テキストの上の2つの識別項目が顔文字であることがわかります。 さらに、「+ sad 」などの単語は否定的な感情につながり、「 welcome 」と「 glad +」は肯定的な感情に関連付けられます。

次に、モデルが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 = ''

これが出力です:

Output'Positive'

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

nlp_test.py

...
custom_tweet = ''

これが出力です:

Output'Positive'

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

このステップでは、モデルを構築してテストしました。 また、特定の例で皮肉を検出しないなど、その制限のいくつかを検討しました。 完成したコードには、引き続きチュートリアルの成果物が残っているため、次のステップでは、コードをPythonのベストプラクティスに合わせる手順を説明します。

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

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

  • すべてのインポートはファイルの先頭にある必要があります。 同じライブラリからのインポートは、1つのステートメントにグループ化する必要があります。

  • すべての関数は、インポート後に定義する必要があります。

  • ファイル内のすべてのステートメントは、 `+ if name ==” main “:+`条件の下に格納する必要があります。 これにより、ファイルの機能を別のファイルにインポートしている場合にステートメントが実行されないことが保証されます。

また、新しい「+ remove_noise 」関数によって補題化が完了するため、「 lemmatize_sentence +」関数とともにチュートリアルに従ってコメントアウトされたコードも削除します。

これは、 `+ 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]|[[email protected]&+#]|[!*\(\),]|'\
                      '(?:%[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)))

結論

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

教師あり学習モデルは、トレーニングデータと同じくらい優れています。 モデルをさらに強化するには、興奮や怒りなどのカテゴリを追加することを検討できます。 このチュートリアルでは、初歩的なモデルを作成することで表面をスクラッチしただけです。 これはhttps://monkeylearn.com/sentiment-analysis/ [さまざまな考慮事項に関する詳細なガイド]で、センチメント分析の実行中に注意する必要があります。