概要
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 |
# 以下<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参照。