どのように肯定的なあなたのFacebookの投稿ですか?


PythonとRを用いたルールベース感情分析


概要


なぜ感情分析?


NLPは言語,計算機科学,人工知能の分野であるwiki ), そして、あなたはそれを勉強する何年も過ごすことができました.
しかし、私はNLPがどのように働くかについて直観を得るために速いダイビングを望みました、そして、我々は彼らの極性によってテキストを分類している感情分析を通してそれをします.
我々は、我々自身のソーシャルメディアポストについての洞察を見るために動機づけられる気がすることができません.

どのようにFacebookは私たちを知っていますか?


見つけるために、私はテキストと感情分析を適用するために、14年のポストをダウンロードしました.ウェイルユースPython 読むjson Facebookからのデータ.
Pythonの自然言語ツールキットによるトークン化や正規化などのタスクを実行します.NLTK . それから、我々はVader ルールベース(Lexicon)感情分析のためのモジュール(HuttoとGilbert,2014)
最後に、我々のワークフローをRtidyverse データ操作と可視化.

データ取得


まず、以下の設定で自分のFacebookのデータをダウンロードする必要があります:設定&プライバシー設定は、あなたのFacebookの情報をダウンロードしてください.
以下、ファイル名を指定しましたyour_posts_1.json , しかし、あなたはこれを変えることができます.
私たちはPythonのjson モジュールデータを読み込みます.我々は、データのための感じを得ることができますtype and len .
import json

# load json into python, assign to 'data'
with open('your_posts_1.json') as file:
    data = json.load(file)

type(data)     # a list
type(data[0])  # first object in the list: a dictionary
len(data)      # my list contains 2166 dictionaries
このポストで使用するPythonライブラリは以下の通りです.
import pandas as pd
from nltk.sentiment.vader import SentimentIntensityAnalyzer
from nltk.stem import LancasterStemmer, WordNetLemmatizer      # OPTIONAL (more relevant for individual words)
from nltk.corpus import stopwords
from nltk.probability import FreqDist
import re
import unicodedata
import nltk
import json
import inflect
import matplotlib.pyplot as plt
Natural Language Tookkit 人間の言語データで働くための人気のあるPythonプラットフォームです.それは50以上の語彙的なリソースを持っているが、我々はVader Sentiment Lexicon , それは特に社会的メディアで表現された感情に同調している.
Regex (正規表現)句読点を取り除くために使われます.
Unicode Database 非ASCII文字を削除するために使用されます.
JSON モジュールは、我々がFacebookからJSONで読むのを助けます.
Inflect 私たちは単語に番号を変換するのに役立ちます.
Pandas データフレームにデータを保存し、CSVに書き込むときの強力なデータ操作とデータ解析ツールです.
我々のデータを持っている後、我々は実際のテキストデータを取得します.
これをリストに保存します.
注意:data キーは時には空の配列を返します、そして、我々はチェックすることによってそれらをスキップしたいですif len(v) > 0 .
# create empty list
empty_lst = []

# multiple nested loops to store all post in empty list
for dct in data:
    for k, v in dct.items():
        if k == 'data':
            if len(v) > 0:
                for k_i, v_i in vee[0].items():  
                    if k_i == 'post':
                        empty_lst.append(v_i)

print("This is the empty list: ", empty_lst)
print("\nLength of list: ", len(empty_lst))
現在、文字列のリストがあります.

時分化


私たちは、各文をトークン化するためにnltk.sent_tokenize() . テキストを個々の文章に分割したい.

これによりリストのリストが得られます.
# - list of list, len: 1762 (each list contain sentences)
nested_sent_token = [nltk.sent_tokenize(lst) for lst in empty_lst]

# flatten list, len: 3241
flat_sent_token = [item for sublist in nested_sent_token for item in sublist]
print("Flatten sentence token: ", len(flat_sent_token))

正規化文


このセクションで使用される機能のコンテキストについては、Matthew Mayoによるこの記事をチェックしてくださいText Data Preprocessing .
まず、非ASCII文字を削除します.remove_non_ascii(words) ) を含む# , - , ' and ? , 他の多くの間で.それから、小文字を返しますto_lowercase(words) ), 句読点を削除するremove_punctuation(words) ), 置換するreplace_numbers(words) ), を削除します.remove_stopwords(words) ).
例のストップワードは:あなた、あなた自身、あなた自身、彼、彼、彼自身、等.
これは、それぞれの文を平等なプレーフィールドにすることができます.
# Remove Non-ASCII
def remove_non_ascii(words):
    """Remove non-ASCII character from List of tokenized words"""
    new_words = []
    for word in words:
        new_word = unicodedata.normalize('NFKD', word).encode(
            'ascii', 'ignore').decode('utf-8', 'ignore')
        new_words.append(new_word)
    return new_words


# To LowerCase
def to_lowercase(words):
    """Convert all characters to lowercase from List of tokenized words"""
    new_words = []
    for word in words:
        new_word = word.lower()
        new_words.append(new_word)
    return new_words


# Remove Punctuation , then Re-Plot Frequency Graph
def remove_punctuation(words):
    """Remove punctuation from list of tokenized words"""
    new_words = []
    for word in words:
        new_word = re.sub(r'[^\w\s]', '', word)
        if new_word != '':
            new_words.append(new_word)
    return new_words


# Replace Numbers with Textual Representations
def replace_numbers(words):
    """Replace all interger occurrences in list of tokenized words with textual representation"""
    p = inflect.engine()
    new_words = []
    for word in words:
        if word.isdigit():
            new_word = p.number_to_words(word)
            new_words.append(new_word)
        else:
            new_words.append(word)
    return new_words

# Remove Stopwords
def remove_stopwords(words):
    """Remove stop words from list of tokenized words"""
    new_words = []
    for word in words:
        if word not in stopwords.words('english'):
            new_words.append(word)
    return new_words

# Combine all functions into Normalize() function
def normalize(words):
    words = remove_non_ascii(words)
    words = to_lowercase(words)
    words = remove_punctuation(words)
    words = replace_numbers(words)
    words = remove_stopwords(words)
    return words
以下のスクリーンキャップは、文正規化対非正規化の違いについての考えを与えます.

sents = normalize(flat_sent_token)
print("Length of sentences list: ", len(sents))   # 3194
注:ステミングとレメディゼーションのプロセスは、個人の単語(文章上)のためのより多くの意味を作るので、我々はここでそれらを使用しません.

頻度


あなたはFreqDist() 関数は、最も一般的な文章を取得します.次に、最も頻繁な文章の視覚的な比較のための行のグラフをプロットすることができます.
単純な、カウント周波数はいくつかをもたらすことができます.
from nltk.probability import FreqDist

# Find frequency of sentence
fdist_sent = FreqDist(sents)
fdist_sent.most_common(10)   

# Plot
fdist_sent.plot(10)

感情分析


私たちはVader モジュールNLTK . Vaderは次のようになります.

Valence, Aware, Dictionary and sEntiment Reasoner.


我々は、かなりのデータセットを持っているが、堅牢なトレーニングセットを構築するためにラベル付きデータが不足しているので、感情分析に規則ベース/語彙アイコンアプローチを取っている.したがって、機械学習はこのタスクには理想的ではない.
直観するVader モジュールの作品は、我々はビューにgithubレポを訪問することができますvader_lexicon.txt ( source ). これは経験的に検証された辞書です.センチメントの評価は、10の独立した人間のララー(事前スクリーニング、訓練され、interRater信頼性をチェック)によって提供されています.
スコアは-(4)から非常に負(4)非常に肯定的な、(0)中立として.例えば、“ダイ”は定格2.9ですが、“dignified”は2.2の評価をしています.詳しくはrepo ).
私たちは、2つの空リストを作成して、文章と極性スコアを別々に格納します.sentiment キャプチャ各文章とsent_scores , を初期化するnltk.sentiment.vader.SentimentIntensityAnalyzer 各々の文(すなわち、否定的な、中立的な、肯定的な)のPolyityScoreスコアを計算すること.sentiment2 タプルのリスト内の各極性と値をキャプチャします.
スクリーンキャップの下には、私たちが持っているものの感覚があります.

後に、それぞれの文を追加しましたsentiment ) とそれらの極性スコアsentiment2 , これらの値を格納するためにデータフレームを作成します.
次に、データフレームをCSVに移行してR . CSVの保存時にインデックスをfalseに設定します.Pythonは0でカウントを開始しますR 1でスタートしますので、インデックスを作成するにはR .
注:私がここで何をしているかより効率的な方法があります.私のソリューションは2つのCSVファイルを保存してR 更なるデータ操作と可視化のために.これは主にデータフレームと視覚化を扱うための個人的な好みですR , しかし、私はこれを行うことができます指摘する必要がありますpandas and matplotlib .
# nltk.download('vader_lexicon')

sid = SentimentIntensityAnalyzer()

sentiment = []
sentiment2 = []

for sent in sents:
    sent1 = sent
    sent_scores = sid.polarity_scores(sent1)
    for x, y in sent_scores.items():
        sentiment2.append((x, y))
    sentiment.append((sent1, sent_scores))
    # print(sentiment)

# sentiment
cols = ['sentence', 'numbers']
result = pd.DataFrame(sentiment, columns=cols)
print("First five rows of results: ", result.head())

# sentiment2
cols2 = ['label', 'values']
result2 = pd.DataFrame(sentiment2, columns=cols2)
print("First five rows of results2: ", result2.head())

# save to CSV
result.to_csv('sent_sentiment.csv', index=False)
result2.to_csv('sent_sentiment_2.csv', index=False)

データ変換


この点から、我々は利用していますRtidyverse データ操作と可視化.RStudio IDEはここで選択します.私たちはR Script すべてのデータの変換と可視化プロセスを格納します.私たちは、上記のCSVファイルが作成された同じディレクトリになければなりませんpandas .
我々は保存した2つのCSVファイルをロードしますtidyverse ライブラリ
library(tidyverse)

# load data
df <- read_csv("sent_sentiment.csv")       
df2 <- read_csv('sent_sentiment_2.csv')    
最初のデータフレームのインデックスに一致する別の列を作成します.保存するdf1 , しかし、あなたはオリジナルを上書きすることができましたdf あなたが望むならば.
# create a unique identifier for each sentence
df1 <- df %>%
    mutate(row = row_number())
次に、2番目のデータフレーム(SenCount SentimentCage 2 . csv)については、インデックスに一致する別の列を作成しますpivot_wider からtidyr パッケージ.注:あなたはgroup_by 最初にラベルを使用しmutate 一意の識別子を作成します.
それから、我々は使用しますpivot_wider すべての極性値(負、中立、正)が自分の列を持つことを保証します.
を使用して一意の識別子を作成するmutate and row_number() , 参加することができますleft_join ) 並んで.
最後に、私はdf3 これは、私が可視化のための新鮮な新しいデータフレームをオフに動作することができます.
# long-to-wide for df2
# note: first, group by label; then, create a unique identifier for each label then use pivot_wider

df3 <- df2 %>%
    group_by(label) %>%
    mutate(row = row_number()) %>%
    pivot_wider(names_from = label, values_from = values) %>%
    left_join(df1, by = 'row') %>%
    select(row, sentence, neg:compound, numbers) 

可視化


まず、すべての3194文の間で、正と負の極性のスコアを個別に可視化されます(あなたの番号が異なります).
ここにポジショニングスコアです

ここに負のスコアがあります

私が比を得るために正と負の点数を合計するとき、それはおよそ588 : 97または5.8 xVader (valance - aware辞書と感情reasoner).
The Vader モジュールは、すべての文を取り、1(最も否定的な)から1(最も肯定的な)の価電子スコアを割り当てる.文章を分類することができますpos (前向き)neu (中立)neg (負)または複合体としてcompound ) スコア(すなわち、正規化、重み付き合成スコア).詳細はvader-sentiment documentation .
ここでは、両方の正と負のスコアを一緒に参照するためのグラフです.

最後に、我々も使用することができますhistograms 文章の中の否定的で肯定的な感情の分配を見ること

非正規化データ


それはVader モジュールは完全に句読点、単語の形状(強調のための資本化)、俗語、さらにはUTF - 8エンコードemojisで文章を分析することができます.
したがって、正規化なしで感情分析を実装した場合、どのような違いがあるのかを確認するために、上記のすべての分析を再実行しました.
ここでは比較のためのデータの2つのバージョンです.正規化のためのトップと非正規化のための底.

わずかな違いが予想されるが、彼らはわずかです.

概要


私はルールベースのセンチメント分析を実行し、結果を可視化するFacebookのポストの14年の価値をダウンロードして、組み合わせを使用してPython and R .
私はこのプロジェクトの両方を使用して楽しんで、その強さに再生しようとしました.私はすぐにPythonでパーソンJSONを見つけました、しかし、一旦我々がデータフレームに移行するならば、私はr .
我々はラベルデータを欠いたので、感情分析にルールベース/語彙のアプローチを使用して意味をなした.原子価スコアのラベルがある今、将来のポストの原子価を予測するための機械学習アプローチを取ることが可能かもしれません.

参考文献

  • Hutto , C . J .& Gilbert , E . E .( 2014 )Vader:ソーシャルメディアテキストの感情分析のための倹約ルールベースモデル第8回ウェブログとソーシャルメディアに関する国際会議( ICWSM - 14 )アンArbor、MI、2014年6月.
  • データサイエンス、機械学習、R、パイソン、SQLとより多くのより多くの内容のために.