1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

テキストデータをNLPのコーパスとして活用するための事前処理

Posted at

概要

web上から引っ張ってきたWikipediaのデータを元に、データ解析を行うための事前処理を行う。
具体的には以下の2点を導出する。

  • 単語の出現頻度(TF)

データ解析に使用する単語の選別時に使用。 TF に応じて、トレーニングデータに含めるか否か決める。

テキスト内にある単語すべてを解析対象とすると、解析時間のコストが増大する。
そこで TF が低い単語を解析対象から外すことで、時間コストの問題を低減する。

以下、単語の出現頻度 (TF) の一部サンプル。

単語ID 単語 テキスト内の出現頻度
30 使用 51
31 世紀 102
32 滞る 6

- **テキストのインデックス化**

TF 割り出し時に各単語に付けた インデックスによるテキスト管理を行うことで、one-hot encodingを使ったデータ解析を行いやすくする。

単語ID変換 【前】 のテキストサンプル
日本語は、主に日本国内や日本人同士の間で使用されている言語である。

単語ID変換 【後】
315, 8, 117, 26, 324, 484, 135, 1079, 797, 16, 235, 19, 30, 11, 22, 58, 59, 69, 13, 14

(単語ID 315: 日本語、単語ID 8: は)

手順

1. 準備

githubのコードをダウンロードし、 requirements.txtに記載の python ライブラリをインストール。

使用環境
python3.7.2
ライブラリのインストール
pip install -r requirements.txt

2. 単語の出現頻度(TF)を求め、DBに格納

2-1. 形態素解析を用い、テキストデータを単語に分割。分割した単語の出現頻度(TF)を求める

コーパス(ex.wikipedia)のデータを文単位に分割。
MeCabの形態素解析にかけて、さらに単語単位に分割。
単語の出現頻度は Counter クラスを用いて導出。

以下は、サンプル文に対しての処理の流れを記載

sample_sentence = '日本語は、主に日本国内や日本人同士の間で使用されている言語である。'

# 日本語の表層形でなく、基本形を使用するために、パーサーとしてOchasenを使用
tagger = MeCab.Tagger('-Ochasen')
# サンプル文を形態素解析した単語群にパース
node = tagger.parseToNode(sample_sentence)
words = []
while node:
    #  node.featureで、該当単語に対して以下の特徴抽出ができる
    # [品詞,品詞細分類1,品詞細分類2,品詞細分類3,活用型,活用形,原形,読み,発音]
    # 表層形でなく、基本形(原形)を採用
    word = node.feature.split(",")[6]
    # 日本語の表現だけを抽出
    if re.search(r'[ぁ-んァ-ヶ一-龥]+', word):
        words.append(word)
    node = node.next

words_frequency = Counter(words_list)

コーパスデータ内の全文に同様の処理を行い、 Counterクラス同士の加算演算をすることで、データ全体の単語出現頻度(TF)を算出。

2-2. DB(sqlite)の準備。単語の出現頻度(TF)をDBに格納

今後の処理を行いやすくするために、算出したデータをDBに格納。
以下、格納する wordsテープルの定義一覧

物理名 論理名 主キー AUTO INCREMENT
id インデックス INTEGER
word 単語 STRING
frequency 出現回数 STRING
wordsテーブルへの格納
# 以下<db_file_path>はsqliteのdbファイル格納場所
conn = sqlite3.connect('<db_file_path>')
cur = self.conn.cursor()

insert_word_sql = 'INSERT INTO words (word, frequency) values (?,?)'
inserted_info = []
# words テーブルに格納するデータを配列に格納し、一括でinsert
for word, frequency in dict(words_frequency).items():
    inserted_info.append((word, frequency))
cur.executemany(insert_word_sql, inserted_info)

3. テキスト内にある各単語をインデックス番号に変換し、DBに格納

3-1. テキスト内の各単語をインデックスに変換できるよう、dictionaryを作成

手順2で格納したテーブルデータから、 全単語のリストを抽出。
それを元に key:単語value:単語インデックスのdictionaryを作成。

# words テーブルから全データを抽出
cur.execute('SELECT * FROM words')
words_info = cur.fetchall()

word_stoi = {}
for word_info in words_info:
    word_stoi[word_info[1]] = word_info[0]

上で求めたdictionaryを使って、テキストデータを単語インデックスの配列に整形

words_indices = []
while node:
    word = node.feature.split(",")[6]
    # 日本語の表現だけを抽出
    if re.search(r'[ぁ-んァ-ヶ一-龥]+', word):
        words_indices.append(word_stoi[word])
    node = node.next
3-2. DBへの格納

元のテキストデータと単語をインデックス変換した配列のデータをDBに格納する
以下、格納する sentencesテープルの定義一覧

物理名 論理名 主キー AUTO INCREMENT
id インデックス INTEGER
word_sentence テキストデータ STRING
index_sentence 構成単語のID配列 STRING
insert_sentence_sql = '''
    INSERT INTO sentences (
        word_sentence, index_sentence
    ) values (?,?)
'''
inserted_info = [sample_sentence, str(words_indices)]
cur.execute(insert_sentence_sql, inserted_info)

結論

NLP処理を行うための前準備として、テキストデータの処理を行った。
またDBに格納することで、今後の処理を行いやすくした。

ここでは、サンプル文に対するデータ処理を掲載したが、wikipedia全データに対する処理の流れは、jupyter notebookに掲載。
全コードは、github参照。

参考

1
2
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
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?