LoginSignup
4
7

More than 3 years have passed since last update.

LDA (Latent Dirichlet Allocation) を使って英文記事をクラスタリングする(前処理編)

Last updated at Posted at 2019-10-08

自然言語処理の研究を始めるにあたって LDA に触れておこうと思ったので,ついでに簡単にまとめてみます.
この分野はまだ学び始めたばかりなので,もし間違いがあれば指摘していただけると嬉しいです.
実行環境には Google Colaboratory を使用しました.

LDA について

トピックモデルは,テキストデータの集合から得られる抽象的なトピックを見つけ出すための,確率モデルの一種です.LDA (Latent Dirichlet Allocation) はそのようなトピックモデルの一つで,あるドキュメントを適当なトピックに分類するために使われます.ドキュメント毎のトピックが占める割合,及びトピック毎の単語が占める割合をそれぞれ算出します.

LDA でできることを簡単に述べると,

  • 文書の集合はどんなトピックに分類できるのか
  • ある文書にはどんなトピックがどの程度含まれているか
  • あるトピックはどの単語がどの程度構成しているのか

のようなことがわかります.

LDA についてはこのあたりの記事で紹介されています.

トピックモデル(LDA)で初学者に分かりづらいポイントについての解説

【Python】トピックモデル(LDA)

LDA の入力データについて

テキストデータを LDA で使用するためのデータの加工方法として,BOW (Bag of Words) や tf-idf があります.これらは以下の記事で紹介されています.

Bag of Wordsについて書いてみる

tf-idfについてざっくりまとめ_理論編

実際に使ってみる

ここでは以下の記事を参考にしながら,英語のニュース見出しのクラスタリングをやっていこうと思います.
https://towardsdatascience.com/topic-modeling-and-latent-dirichlet-allocation-in-python-9bf156893c24

データの準備

今回使用するデータはここからダウンロードします(要:kaggle へのサインイン)
https://www.kaggle.com/therohk/million-headlines/data

データを Python で利用できるように読み込みます.

import pandas as pd

data = pd.read_csv('abcnews-date-text.csv', error_bad_lines=False);
data_text = data[['headline_text']]
data_text['index'] = data_text.index
documents = data_text

データの中身がどうなっているのか少し見てみると,およそ110万件のドキュメント(ニュース見出し)があって,そのうち上から5件が上の表のようになっていることがわかります.

print(len(documents))
print(documents[:5])

1103663

headline_text index
0 aba decides against community broadcasting lic... 0
1 act fire witnesses must be aware of defamation 1
2 a g calls for infrastructure protection summit 2
3 air nz staff in aust strike for pay rise 3
4 air nz strike to affect australian travellers 4

前処理

次の手順でデータを処理します.

  • ドキュメントのトークン化:具体的には,テキストを文単位に,文を単語単位にそれぞれ分割します.大文字の単語を小文字に修正し,句読点を取り除きます.
  • 3文字未満の単語の除去
  • ストップワードの除去:ストップワードとは,頻出あるいは一般的すぎて,利用価値が低いと考えられる単語のことをいいます.ex. the, a, for
  • 単語を見出し語化 (lemmatize) :具体的には,三人称の単語は一人称に,過去時制及び未来時制の動詞は現在時制に変更されます.
  • 単語の語幹抽出 (stemming)

処理には gensim と nltk を使います.

import gensim
from gensim.utils import simple_preprocess
from gensim.parsing.preprocessing import STOPWORDS
from nltk.stem import WordNetLemmatizer, SnowballStemmer
from nltk.stem.porter import *
import numpy as np
np.random.seed(2018)

import nltk
nltk.download('wordnet')

lemmatize の例を確認してみます.

print(WordNetLemmatizer().lemmatize('went', pos='v'))

go

stemming の例を確認してみます(結果は省略).

stemmer = SnowballStemmer('english')
original_words = ['caresses', 'flies', 'dies', 'mules', 'denied','died', 'agreed', 'owned', 
           'humbled', 'sized','meeting', 'stating', 'siezing', 'itemization','sensational', 
           'traditional', 'reference', 'colonizer','plotted']
singles = [stemmer.stem(plural) for plural in original_words]
pd.DataFrame(data = {'original word': original_words, 'stemmed': singles})

lemmatizeとstemming をする関数を定義し,前に述べた手順で前処理をするための関数を作成します.

def lemmatize_stemming(text):
  return stemmer.stem(WordNetLemmatizer().lemmatize(text, pos='v'))

def preprocess(text):
  result = []
  for token in gensim.utils.simple_preprocess(text):
    if token not in gensim.parsing.preprocessing.STOPWORDS and len(token) > 3:
      result.append(lemmatize_stemming(token))
  return result

ドキュメントを一つ選択して前処理の前後比較をしてみましょう.

doc_sample = documents[documents['index'] == 4310].values[0][0]

print('original document: ')
words = []
for word in doc_sample.split(' '):
  words.append(word)
print(words)
print('\n\ntokenized and lemmatized document: ')
print(preprocess(doc_sample))

original document:
['rain', 'helps', 'dampen', 'bushfires']

tokenized and lemmatized document:
['rain', 'help', 'dampen', 'bushfir']

きちんと動作していることが確認できたので,全ドキュメントの前処理をします.完了には少し時間がかかると思います.

processed_docs = documents['headline_text'].map(preprocess)

長くなってしまうので,今回はここまでとします.
次回は,LDA の入力データ (BOW, TF-IDF) の作成と,LDA モデルの作成について書こうと思います.

次回 -> LDA (Latent Dirichlet Allocation) を使って英文記事をクラスタリングする(分類編)

4
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
7