2023年4月18日火曜日

iDS演習第2回のソースコード

データの導入

import pandas as pd
df0 = pd.read_excel('ethical_tweets_original.xlsx')
df0 = df0.drop(df0['Unnamed: 0'], axis=1)
df0

リツイートと広告ツイートの排除

df1 = df0.drop(df0[df0['retweet']].index)
df2 = df1.drop(df1[df1['advertise']].index)
df2

キーワードとツイート内容の列だけのデータフレームにする

df3 = df2[['keyword', 'tweet']]
df3

{ キーワード,ツイート内容 } の dict に変換する

tweets = df3.to_dict(orient='records')
tweets

センチメント分析の下準備(1)

!pip install transformers
!pip install transformers['ja']
!pip install sentencepiece
!pip install ipadic

センチメント分析の下準備(2)

from transformers import pipeline, AutoModelForSequenceClassification
from transformers import BertJapaneseTokenizer, BertTokenizer, BertForSequenceClassification

# パイプラインの準備
model = AutoModelForSequenceClassification.from_pretrained('koheiduck/bert-japanese-finetuned-sentiment')
tokenizer = BertJapaneseTokenizer.from_pretrained('cl-tohoku/bert-base-japanese-whole-word-masking')
classifier = pipeline("sentiment-analysis",model=model,tokenizer=tokenizer)

センチメント分析をして極性とスコアを返す関数を定義し,取得したツイートに適用する

def classify(tw):
result = classifier(tw)[0]
return (result['label'], round(result['score'], 4))

col_names = ['label','score','keyword','tweet']
df = pd.DataFrame(columns=col_names)

for tw in tweets:
(label, score) = classify(tw['tweet'])
new_row = pd.DataFrame([[label,score,tw['keyword'],tw['tweet']]],
columns=col_names)
df = pd.concat([df,new_row],axis=0)

df

インデクスが全部0でおかしいので,それを修正

df = df.reset_index().drop('index', axis=1)
df

簡単なテキストマイニングをしてみる.その準備(1)

#GiNZAのインストール
!pip install ginza
!pip install ja_ginza

#Matplotlib日本語化のインストール
!pip install japanize-matplotlib

#GraphViz関連のインストール
!apt install libgraphviz-dev
!pip install pygraphviz

#日本語フォントのインストール
!apt-get -y install fonts-ipafont-gothic
!rm ~/.cache/matplotlib/fontlist-v310.json

簡単なテキストマイニングをしてみる.その準備(2)

import pandas as pd
import spacy
import ginza
import math
import matplotlib.pyplot as plt
from itertools import combinations, dropwhile
from collections import Counter, OrderedDict
import numpy as np
from networkx.drawing import nx_agraph
import networkx as nx
import japanize_matplotlib

STOPWORDS = ['\n', 'o', '\u3000', '\n\u3000','\u3000\n',
'お','す','り','ご','いる','ある','ない','こと',
'なる','ござる','する','いう','言う','思う']

nlp = spacy.load('ja_ginza')
ginza.set_split_mode(nlp, 'C')

@によるメンションを削除する関数を定義

def remove_at_mention(text):
words = text.split()
return ' '.join([ x for x in words if x[0] != '@' ])

単語を抽出する関数の定義

def extract(s):
text = list(s)[0]
text = remove_at_mention(text) # @xxx... を取り除く
doc = nlp(text)
retvar = []
for sent in doc.sents:
noun = ''
for token in sent:
if token.lemma_ in STOPWORDS: continue
if token.pos_ in ['NOUN', 'PROPN', 'NUM']:
noun = noun + token.lemma_
elif noun != '':
retvar.append(noun)
noun = ''
if token.pos_ in ['ADJ', 'INTJ', 'ADV', 'VERB']:
retvar.append(token.lemma_)
if len(noun) > 0: retvar.append(noun)
return retvar

単語に分割した結果を新たな列として追加されたデータフレームを作成

df['words'] = df[['tweet']].apply(extract, axis=1)
df

共起ネットワーク図を書くコードの定義

def conet(df, outfile, min_count=3, edge_th=0.12):
# jaccard係数を計算する(回答の単語登場数:3以上、jaccard係数:0.12以上)
jaccard_coef = []
pair_all = []

words_array = [ set(x) for x in list(df['words']) ]
for chunk in words_array:
tmp_pair = list(combinations(chunk, 2))
for i, pair in enumerate(tmp_pair): tmp_pair[i] = tuple(sorted(pair))
pair_all += tmp_pair
pair_count = {x: count for x, count in Counter(pair_all).items() if count >= min_count}

word_count = Counter()
for chunk in words_array: word_count += Counter(chunk)
for pair, count in pair_count.items():
jaccard_coef.append(count / (word_count[pair[0]] + word_count[pair[1]] - count))
jaccard_dict = OrderedDict()
for (pair, count), coef in zip(pair_count.items(), jaccard_coef):
if coef >= edge_th: jaccard_dict[pair] = coef

# グラフの描画
G = nx.Graph()
G.add_nodes_from(sorted(set([j for pair in jaccard_dict.keys() for j in pair])))
for pair, coef in jaccard_dict.items(): G.add_edge(pair[0], pair[1], weight=coef)

plt.figure(figsize=(15, 15))
seed = 0
np.random.seed(seed)
pos = nx_agraph.graphviz_layout(G, prog='neato',
args='-Goverlap="scalexy" -Gsep="+6" -Gnodesep=0.8 -Gsplines="polyline" -GpackMode="graph" -Gstart={}'.format(seed))

values = nx.pagerank(G).values()
nx.draw_networkx_nodes(G, pos, node_color=list(values), cmap=plt.cm.terrain, alpha=1.0, node_size=[100000*v for v in values],
edgecolors='black')
nx.draw_networkx_labels(G, pos, font_family='IPAexGothic', font_size=24)
nx.draw_networkx_edges(G, pos, alpha=0.7, edge_color='black', width=[d['weight'] * 8 for (u, v, d) in G.edges(data=True)])

plt.axis('off')
plt.tight_layout()
plt.savefig(outfile, bbox_inches='tight')

クラス分けする

df_nega = df[df['label'] == 'NEGATIVE']
df_posi = df[df['label'] == 'POSITIVE']
df_neut = df[df['label'] == 'NEUTRAL']

共起ネットワーク図を描く(ネガティブ群)

conet(df_nega, 'nega.png')

共起ネットワーク図を描く(ポジティブ群)

conet(df_posi, 'posi.png')

ワードクラウドを作ってみる

import wordcloud

path_to_font='/usr/share/fonts/truetype/fonts-japanese-gothic.ttf'

def mk_wc(word_array):
wc = wordcloud.WordCloud(width=1000, height=600,
background_color='white', font_path=path_to_font)
wc.generate(' '.join(word_array))
plt.imshow(wc)
plt.axis('off')

import itertools

def mk_wc_from_df(df):
mk_wc(list(itertools.chain.from_iterable(df['words'])))

ワードクラウドを描く(ネガティブ群)

mk_wc_from_df(df_nega)

ワードクラウドを描く(ポジティブ群)

mk_wc_from_df(df_posi)

0 件のコメント:

コメントを投稿