Wikipedia日本語版ダンプからgensimコーパスを作成する

概要

Wikipedia日本語版のダンプファイルから,gensimのbag-of-wordsおよびTF-IDFコーパスを作成する.日本語の分かち書きには,形態素解析器SudachiPyを用いる.

目次

ダンプファイルのダウンロード

Wikipedia日本語版の全記事データは,Wikimedia Dumpsから取得する.

jawiki-latest-pages-articles.xml.bz2

ダウンロードURL: https://dumps.wikimedia.org/jawiki/latest/jawiki-latest-pages-articles.xml.bz2

bz2圧縮されたXML形式であり,ファイルサイズは約4.5GBである.

gensim付属スクリプトによる変換

gensimには,Wikipediaダンプをbag-of-wordsおよびTF-IDF形式に変換するスクリプトが付属している.

ソースコード: https://github.com/piskvorky/gensim/blob/develop/gensim/scripts/make_wikicorpus.py

python -m gensim.scripts.make_wikicorpus /path/to/jawiki-latest-pages-articles.xml.bz2 jawiki

生成されるファイルは以下のとおりである.

jawiki_wordids.txt.bz2           # 単語-ID対応表
jawiki_bow.mm                    # bag-of-words(Matrix Market形式)
jawiki_bow.mm.index              # インデックス
jawiki_bow.mm.metadata.cpickle   # 記事タイトル
jawiki_tfidf.mm                  # TF-IDF(Matrix Market形式)
jawiki_tfidf.mm.index            # インデックス
jawiki.tfidf_model               # TF-IDFモデル

ただし,このスクリプトのデフォルトtokenizerはアルファベット圏の言語向けであり,日本語には対応していない.日本語を処理するには,カスタムtokenizerが必要である.

日本語対応のPythonコード

WikiCorpusのコンストラクタは,tokenizer_func引数でtokenizerを差し替えられる.以下は,SudachiPyを使用した例である.SudachiPyは,日本語形態素解析器Sudachiのバインディングであり,pip install sudachipy sudachidict_coreで辞書を含めてインストールできる.単位表現(例:「国家公務員」のような複合語)に強く,新語辞書の更新も継続して行われている.

# jawiki_corpus.py
# Wikipedia日本語版ダンプからbag-of-wordsおよびTF-IDFコーパスを生成する
#
# pip install gensim sudachipy sudachidict_core

from sudachipy import Dictionary, SplitMode
from gensim.corpora import Dictionary as GensimDictionary, MmCorpus, WikiCorpus
from gensim.models import TfidfModel

# --- 設定 ---
DUMP_PATH = "/path/to/jawiki-latest-pages-articles.xml.bz2"
OUTPUT_PREFIX = "jawiki"
DICT_SIZE = 100000

# --- 日本語tokenizer ---
_sudachi_tokenizer = Dictionary().create()

def tokenize_ja(text, token_min_len, token_max_len, lower):
    """名詞・動詞・形容詞の終止形を抽出する"""
    tokens = []
    for m in _sudachi_tokenizer.tokenize(text, SplitMode.C):
        pos = m.part_of_speech()[0]
        if pos in ("名詞", "動詞", "形容詞"):
            word = m.dictionary_form()
            if lower:
                word = word.lower()
            if token_min_len <= len(word) <= token_max_len:
                tokens.append(word)
    return tokens

# --- コーパス構築 ---
wiki = WikiCorpus(DUMP_PATH, tokenizer_func=tokenize_ja)
wiki.dictionary.filter_extremes(no_below=20, no_above=0.1, keep_n=DICT_SIZE)

# bag-of-words形式で保存
MmCorpus.serialize(OUTPUT_PREFIX + "_bow.mm", wiki, progress_cnt=10000, metadata=True)
wiki.dictionary.save_as_text(OUTPUT_PREFIX + "_wordids.txt.bz2")

# TF-IDFモデルの構築と保存
dictionary = GensimDictionary.load_from_text(OUTPUT_PREFIX + "_wordids.txt.bz2")
mm = MmCorpus(OUTPUT_PREFIX + "_bow.mm")
tfidf = TfidfModel(mm, id2word=dictionary, normalize=True)
tfidf.save(OUTPUT_PREFIX + ".tfidf_model")
MmCorpus.serialize(OUTPUT_PREFIX + "_tfidf.mm", tfidf[mm], progress_cnt=10000)

WikiCorpusは,辞書の構築にダンプ全体を走査するため,数時間を要する場合がある.MmCorpus.serializeは,コーパスをMatrix Market形式で保存し,metadata=Trueを指定すると,記事タイトルが.metadata.cpickleファイルに出力される.