【忘備録】ツイートのネガポジ分析

# はじめに
機械学習超初心者が、自然言語処理に挑戦してみた。<br>

# 動作環境
* Google Colaboratory
* Python 3.7.13
* MeCab - 0.996
* Pandas - 1.3.5
* NumPy - 1.21.6

```python:colab
!apt install aptitude
!aptitude install mecab libmecab-dev mecab-ipadic-utf8 git make curl xz-utils file -y
!pip install mecab-python3==0.7

import MeCab
import pandas as pd
import numpy as np
```

# 自然言語とは
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518762/11d683e1-a9bc-f4a4-dcf8-1d9d37884286.png)

「**自然言語**」とは、わたしたち人間が日常的に話したり書いたりしている「自然発生的に生まれた言語(自然な言語)」のこと。例として、日常会話に使われるような言葉が挙げられる。
「自然言語」に対して、「**人工言語**」が存在する。例として、「プログラミング言語」が挙げられる。
「プログラミング言語」には一切の曖昧性がなく、すべてのコンピュータが同じ解釈をすることができる。

# 自然言語処理とは
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518762/66490041-6517-c0be-839b-c86bed71b594.png)

「**自然言語処理**」とは、「自然言語」を機械が処理し、その内容を抽出していく作業のこと。文章・言葉などのコミュニケーションで用いられる「話し言葉」や、論文に用いられるような「書き言葉」といった自然言語を対象に、言葉が持っている意味を解析する。
機械は「自然言語」をそのまま解析することはできないため、「自然言語」を数値化してから機械に渡す。単語の出現頻度や意味合いを数値の基準にしたする。

# 感情分析手法
1. 文章を形態素解析する
2. 極性辞書と比較し、単語を数値化する
3. 文章の感情を判定する


## 1. 文章を形態素解析する
### 形態素解析とは
**形態素解析**とは、文章を形態素に分解し、その形態素に品詞などの情報を付与すること。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518762/363ba8e0-91fe-b458-b4ff-531b5a55efdc.png)

:::note info
本記事では、形態素解析ツールとして**MeCab**を用いる
:::

:::note info
使用するツイートは、アカウントのアーカイブのダウンロードを申請することで取得した。
ダウンロードファイルを解凍して、data\tweet.jsがツイートの一覧である。
データの前処理として、jsonファイルに記載されているツイート箇所を抜き出し、csvに変換している。
:::

```python:colab
# tweetを読み込む
my_tweet_df = pd.read_csv(r"my_tweets.csv", header=0, index_col=0)

# Mecabで形態素解析する
mecab = MeCab.Tagger("-Ochasen")

word_list = []
for data in my_tweet_df['text']:
    temp = []
    if data is not np.nan:
        for v in mecab.parse(data).splitlines():
            if len(v.split()) >= 3:
                if v.split()[3][:2] in ['名詞','形容詞','動詞','副詞']:
                    temp.append(v.split()[2])
        word_list.append(temp)


word_stop_list = []
# 空の要素とストップワードを削除
stop_words = ['形態素解析に必要ない単語を記載する','例えばwとか']
for sentence in word_list:
    if sentence != None:
        temp = []
        for word in sentence:
            if word not in stop_words:
                temp.append(word)
        word_stop_list.append(temp)
```

## 2. 極性辞書と比較し、単語を数値化する
### 極性辞書とは
**極性**
ネガティブ、ポジティブのこと

**極性辞書**
単語ごとに極性を付けたもの
極性は数値や文字で表される


**お借りした極性辞書**
日本語評価極性辞書（名詞編）ver.1.0（2008年12月版）

http://www.cl.ecei.tohoku.ac.jp/resources/sent_lex/pn.csv.m3.120408.trim

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518762/e3550ef5-5d57-13b4-9613-4f82201873a5.png)

```python:colab
pd.set_option('display.unicode.east_asian_width', True)
pn_dic_df = pd.read_table(r"極性辞書のパス",names=["基本形","感情"],header=None,usecols=[0,1])
```

## 3. 文章の感情を判定する
**スコア計算方法**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518762/fdfcf173-3d2b-3e22-476d-7fd1621e0b88.png)

**極性辞書の感情を単語に置換する**
* p(ポジティブ) = 1
* n (ネガティブ) = -1
* e (ニュートラル) = 0

```python:colab
# 辞書をn, p, eの3種類に絞る
pn_dic_npe_df = pn_dic_df[(pn_dic_df['感情']=="p")|(pn_dic_df['感情']=="n")|(pn_dic_df['感情']=="e")]

# 感情を数値に変換する
pn_dic_npe_num_df = pn_dic_npe_df.copy()
pn_dic_npe_num_df.loc[:,"感情"] = pn_dic_npe_num_df.loc[:,"感情"].replace({"p":1, "e":0, "n":-1})

# dfをdictに変換する
keys = pn_dic_npe_num_df["基本形"].to_list()
values = pn_dic_npe_num_df["感情"].to_list()
pn_dic_npe_num_dic = dict(zip(keys, values))

# ツイートごとに、(単語,スコア)のリストを作る
result = []
for sentence in word_stop_list:
    temp = []
    for word in sentence:
        word_score = []
        score = pn_dic_npe_num_dic.get(word)
        word_score = (word, score)
        temp.append(word_score)
    result.append(temp)

# 文単位の平均値を計算する
mean_list = []
for i, score in enumerate(result):
    temp = []
    for j in score:
        if not j[1] == None:
            temp.append(float(j[1]))
    if temp:
        mean = (sum(temp) / len(temp))
    else:
        mean = float(0.0)
    mean_dic = [my_tweet_df.iloc[i,0],mean]
    mean_list.append(mean_dic)
```
:::note warn
mean_listの中身を見ると、ツイートから算出したスコアが間違っている。
時間が取れた時に上記コードを見直す予定である。
:::

# 結果
```python:colab
import seaborn
seaborn.displot(mean_list_df['score'],kde=False)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518762/b3b5eeb7-89ef-4fd6-cc65-708b156da646.png)

:::note warn
ツイートから算出したスコアが間違っているので、この結果も修正される予定である。
:::


# おわりに
初めてネガポジ分析をした。
やはり、ものができるのはとても嬉しいことである。
ある程度できるようになったら、モデルを作成しようと思っている。<br>
<br>



**お借りした素材**

https://loosedrawing.com/contact/