ichou1のブログ

主に音声認識、時々、データ分析のことを書く

Kerasメモ(Embeddingレイヤ) その2

既に学習済みの単語埋め込みベクトルを使ってみる。
Using pre-trained word embeddings in a Keras model

今回はGloVe word embeddingsを選択。

Specifically, we will use the 100-dimensional GloVe embeddings of 400k words computed on a 2014 dump of English Wikipedia.

2014年英語版Wikipediaをもとに、40万語の単語(またはドットやカンマといったトークン)を100次元で表現したものになる。

ダウンロードサイズは1GB近い。

/% du -h glove.6B.zip         
823M	glove.6B.zip

100次元だけでなく、50次元や200次元で表現したバージョンも入っている。

% zipinfo glove.6B.zip
Archive:  glove.6B.zip
Zip file size: 862182613 bytes, number of entries: 4
-rw-rw-r--  3.0 unx 171350079 tx defN 14-Aug-05 05:15 glove.6B.50d.txt
-rw-rw-r--  3.0 unx 347116733 tx defN 14-Aug-05 05:14 glove.6B.100d.txt
-rw-rw-r--  3.0 unx 693432828 tx defN 14-Aug-05 05:14 glove.6B.200d.txt
-rw-rw-r--  3.0 unx 1037962819 tx defN 14-Aug-28 04:19 glove.6B.300d.txt
4 files, 2249862459 bytes uncompressed, 862181945 bytes compressed:  61.7%

% du -h glove.6B.100d.txt 
332M	glove.6B.100d.txt

ファイルの中身

The -0.038194 -0.24487 0.72812 -0.39961 0.083172 ...
, -0.10767 0.11053 0.59812 -0.54361 0.67396 ...
. -0.33979 0.20941 0.46348 -0.64792 -0.38377 ...
of -0.1529 -0.24279 0.89837 0.16996 0.53516 ...
to -0.1897 0.050024 0.19084 -0.049184 -0.089737 ... 
and -0.071953 0.23127 0.023731 -0.50638 0.33923 ...
in 0.085703 -0.22201 0.16569 0.13373 0.38239 ...
a -0.27086 0.044006 -0.02026 -0.17395 0.6444 ...
" -0.30457 -0.23645 0.17576 -0.72854 -0.28343 ...
's 0.58854 -0.2025 0.73479 -0.68338 -0.19675 ...
...

ファイル読み込み(pythonでの記述、冒頭のThe Keras Blogより抜粋)

embeddings_index = {}
f = open(os.path.join(GLOVE_DIR, 'glove.6B.100d.txt'))
for line in f:
    values = line.split()
    word = values[0]
    coefs = np.asarray(values[1:], dtype='float32')
    embeddings_index[word] = coefs
f.close()

環境はpython2.7

>>> type(embeddings_index)
<type 'dict'>

>>> len(embeddings_index)
400000

>>> sys.getsizeof(embeddings_index)
12583048

# from pympler import asizeof
>>> asizeof.asizeof(embeddings_index)
204712744L

# 大文字は小文字に変換される
>>> embeddings_index['The']
*** KeyError: 'The'

>>> embeddings_index['the'].shape
(100,)

>>> embeddings_index['the']
array([-0.038194, -0.24487 ,  0.72812 , -0.39961 ,  0.083172,  0.043953,
       ...
       -0.52028 , -0.1459  ,  0.8278  ,  0.27062 ], dtype=float32)

メモリ上の読み込みサイズは、ざっと195MB。
読み込んだ辞書(embeddings_index)をもとに、単語埋め込みベクトルを作成する。

EMBEDDING_DIM = 100
# tokenizer.word_index : type 'dict'
# tokenizer.word_index : 298
embedding_matrix = np.zeros((len(word_index) + 1, EMBEDDING_DIM))
for word, i in word_index.items():
    embedding_vector = embeddings_index.get(word)
    if embedding_vector is not None:
        # words not found in embedding index will be all-zeros.
        embedding_matrix[i] = embedding_vector

Tokenizerクラスで作った辞書(word_index)のindexは1始まりなので、行方向のサイズはプラス1とする(index=0は使わない)

トークン'the'(index=1)の例
>>> tokenizer.word_index['the']
1

>>> embeddings_index['the'][:5]
array([-0.038194, -0.24487 ,  0.72812 , -0.39961 ,  0.083172],
      dtype=float32)

>>> embedding_matrix[1][:5]
array([-0.038194  , -0.24487001,  0.72812003, -0.39961001,  0.083172  ])

単語埋め込みベクトルのサイズ。

>>> embedding_matrix.shape
(299, 100)

>>> type(embedding_matrix[0][0])
<type 'numpy.float64'>

>>> sys.getsizeof(embedding_matrix)
239256L

>>> asizeof.asizeof(embedding_matrix)
239256L

>>> print asizeof.asized(embedding_matrix, detail=1).format()
array([[ 0.        ,  0.        ,  0. ....9,
         0.61399001, -0.052185  ]]) size=239256 flat=239256

これをEmbeddingレイヤに読み込む。
学習しないので、trainable=Falseを設定する。

embedding_layer = Embedding(len(word_index) + 1,
                            EMBEDDING_DIM,
                            weights=[embedding_matrix],
                            trainable=False)