13
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

nlplotを使って自然言語データを可視化してみた

  • 製造業出身のデータサイエンティストがお送りする記事
  • 今回は自然言語データの可視化にnlplotというライブラリーが良さそうでしたので試してみました。

はじめに

今までずっと構造化データを扱っておりましたが、非構造化データも扱えるようになりたいと思い、まずは自然言語データを対象に可視化から勉強してみました。

nlplotとは

nlplotは基本的には、自然言語(NLP)において基本的な可視化を簡単にできるようにしたパッケージらしいです。
NLPにおいては、知識が無いので、詳しいことはnlplotのGithubを参考にご確認ください。
ブログの記事も見つけましたので、確認して頂けますと幸いです。

nlplotを使ってみる

今回、使用するデータはlivedoorニュースコーパスの「ldcc-20140209.tar.gz」を使います。

まず、データフレームを作成します。

import os
from glob import glob
import pandas as pd
import linecache
import nlplot
import plotly
from plotly.subplots import make_subplots

pd.set_option('display.max_columns', 300)
pd.set_option('display.max_rows', 300)
pd.options.display.float_format = '{:.3f}'.format
pd.set_option('display.max_colwidth', 5000)

# カテゴリを配列で取得
categories = [name for name in os.listdir("text") if os.path.isdir("text/" + name)]
print(categories)
#['dokujo-tsushin', 'it-life-hack', 'kaden-channel', 'livedoor-homme', 'movie-enter', 'peachy', 'smax', 'sports-watch', 'topic-news']

df = pd.DataFrame(columns=["title", "category"])
for cat in categories:
    path = "text/" + cat + "/*.txt"
    files = glob(path)
    for text_name in files:
        title = linecache.getline(text_name, 3)
        s = pd.Series([title, cat], index=df.columns)
        df = df.append(s, ignore_index=True)

# データフレームシャッフル
df = df.sample(frac=1).reset_index(drop=True)
df.head()

スクリーンショット 2021-03-26 20.09.19.png

次にデータを各々インスタンス化します。

# 全データ・livedoor-homme・#kaggleをそれぞれインスタンス化
npt = nlplot.NLPlot(df, target_col='title')
npt_livedoor = nlplot.NLPlot(df.query('category == "livedoor-homme"'), target_col='title')
npt_movie = nlplot.NLPlot(df.query('category == "movie-enter"'), target_col='title')

次にストップワードの計算をします。

# top_nで頻出上位単語, min_freqで頻出下位単語を指定できる
# 今回は上位5単語(livedoor-homme・movie-enter)をストップワードに指定
stopwords = npt.get_stopword(top_n=5, min_freq=0)
stopwords
#['ゆるっとcafe', '【Sports', 'by', 'PHONE', '-']

ここから可視化になります。
最初は「N-gram bar chart」です。

npt.bar_ngram(
    title='uni-gram',
    xaxis_label='word_count',
    yaxis_label='word',
    ngram=1,
    top_n=50,
    width=800,
    height=1100,
    color=None,
    horizon=True,
    stopwords=stopwords,
    verbose=True,
    save=False,
)

newplot.png

npt.bar_ngram(
    title='bi-gram',
    xaxis_label='word_count',
    yaxis_label='word',
    ngram=2,
    top_n=50,
    width=800,
    height=1100,
    color=None,
    horizon=True,
    stopwords=stopwords,
    verbose=True,
    save=False,
)

newplot (1).png

npt.bar_ngram(
    title='tri-gram',
    xaxis_label='word_count',
    yaxis_label='word',
    ngram=3,
    top_n=50,
    width=1000,
    height=1100,
    color=None,
    horizon=True,
    stopwords=stopwords,
    verbose=True,
    save=False,
)

newplot (2).png

次はラベル毎に比較します。

# livedoor-hommeのfigを取得
fig_unigram_livedoor = npt_livedoor.bar_ngram(
    stopwords=stopwords,
    title='uni-gram',
    xaxis_label='word_count',
    yaxis_label='word',
    ngram=1,
    top_n=50,
    width=600,
    height=1100,
    color=None,
    horizon=True,
    verbose=True,
    save=False,
)

# movie-enterのfigを取得
fig_unigram_movie = npt_movie.bar_ngram(
    stopwords=stopwords,
    title='uni-gram',
    xaxis_label='word_count',
    yaxis_label='word',
    ngram=1,
    top_n=50,
    width=600,
    height=1100,
    color=None,
    horizon=True,
    verbose=True,
    save=False,
)

# subplot
trace1 = fig_unigram_livedoor['data'][0]
trace2 = fig_unigram_movie['data'][0]

fig = make_subplots(rows=1, cols=2, subplot_titles=('livedoor-homme', 'movie-enter'), shared_xaxes=False)
fig.update_xaxes(title_text='word count', row=1, col=1)
fig.update_xaxes(title_text='word count', row=1, col=2)

fig.update_layout(height=1100, width=1900, title_text='unigram livedoor-homme vs. movie-enter')
fig.add_trace(trace1, row=1, col=1)
fig.add_trace(trace2, row=1, col=2)

plotly.offline.plot(fig, filename='unigram livedoor-homme_vs_movie-enter.html', auto_open=False)

fig.show()

newplot (3).png

次はN-gram tree Mapを可視化してみます。

npt.treemap(
    title='Tree of Most Common Words',
    ngram=1,
    top_n=30,
    stopwords=stopwords,
)

newplot (4).png

次は単語の出現頻度の分布を可視化します。

# 単語数の分布
npt.word_distribution(
    title='number of words distribution',
    xaxis_label='count',
    yaxis_label='',
    width=1000,
    height=500,
    color=None,
    template='plotly',
    bins=None,
    save=False,
)

newplot (5).png

ラベル毎に出現頻度の分布も可視化できます。

# livedoor-hommeのfigを取得
fig_wd_livedoor = npt_livedoor.word_distribution(
    title='number of words distribution',
    xaxis_label='length',
    yaxis_label='',
    width=1000,
    height=500,
    color=None,
    template='plotly',
    bins=None,
    save=False,
)

# movie-enterのfigを取得
fig_wd_movie = npt_movie.word_distribution(
    title='number of words distribution',
    xaxis_label='length',
    yaxis_label='',
    width=1000,
    height=500,
    color=None,
    template='plotly',
    bins=None,
    save=False,
)

trace1 = fig_wd_livedoor['data'][0]
trace2 = fig_wd_movie['data'][0]

fig = make_subplots(rows=2, cols=1, subplot_titles=('livedoor-homme', 'movie-enter'), shared_xaxes=True)

fig.update_layout(height=900, width=1200, title_text='words distribution livedoor-homme vs. movie-enter')
fig.add_trace(trace1, row=1, col=1)
fig.add_trace(trace2, row=2, col=1)

plotly.offline.plot(fig, filename='words distribution #データサイエンティストvs#kaggle.html', auto_open=False)

fig.show()

newplot (6).png

良く見るword cloudも簡単に使えます。

npt.wordcloud(
    stopwords=stopwords,
    width=1000,
    height=600,
    max_words=100,
    max_font_size=100,
    colormap='tab20_r',
    mask_file=None,
    save=True
)

image.png

次は共起ネットワークの可視化です。

# ビルド(データ件数によっては処理に時間を要します)※ノードの数のみ変更
npt.build_graph(stopwords=stopwords, min_edge_frequency=5)

display(
    npt.node_df.head(), npt.node_df.shape,
    npt.edge_df.head(), npt.edge_df.shape
)

npt.co_network(
    title='Co-occurrence network',
)

スクリーンショット 2021-03-26 20.20.16.png

newplot.png

次は、sunburst chartを可視化します。

npt.sunburst(
    title='All sentiment sunburst chart',
    colorscale=True,
    color_continuous_scale='Oryel',
    width=800,
    height=600,
    save=True
)

newplot (1).png

最後はpyLDAvisです。

npt.ldavis(num_topics=2, passes=5, save=True)

スクリーンショット 2021-03-26 20.23.51.png

さいごに

最後まで読んで頂き、ありがとうございました。
今回、初めて自然言語の可視化ライブラリーnlplotを使って自然言語データの可視化をしてみました。
シンプルに可視化できて凄い良いですね。今後、非構造化データについても扱っていけるように勉強しようと思います。

訂正要望がありましたら、ご連絡頂けますと幸いです。

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
13
Help us understand the problem. What are the problem?