埋め込みとRNNを使用して翻訳ネットワークを構築しようとしています。私はGensimWord2Vecモデルをトレーニングしましたが、Wordの関連付けをかなりよく学習しています。ただし、Kerasモデルにレイヤーを適切に追加する方法について頭を悩ませることはできませんでした。 (そして、出力に対して「逆埋め込み」を行う方法。しかし、それは答えられた別の質問です。デフォルトではできません。)
Word2Vecでは、文字列を入力すると、たとえば_model.wv[‘hello’]
_、Wordのベクトル表現を取得します。ただし、Word2Vecの get_keras_embedding() によって返される_keras.layers.Embedding
_レイヤーは、文字列入力ではなく、ワンホット/トークン化された入力を受け取ると思います。しかし、ドキュメントには、適切な入力が何であるかについての説明はありません。 埋め込みレイヤーの入力と1対1で対応するボキャブラリーのワンホット/トークン化されたベクトルを取得する方法がわかりません。
以下の詳細:
現在の私の回避策は、ネットワークにフィードする前に、Kerasの外部に埋め込みを適用することです。これを行うことに何か不利益はありますか?とにかく、埋め込みを訓練不可能に設定します。これまでのところ、メモリの使用は非常に非効率的であり(64ワードの長さの文のコレクションに対してKerasモデルを宣言する前でも50GBのように)、モデルの外部にパディングされた入力と重みをロードする必要があることに気付きました。多分ジェネレータが役立つことができます。
以下は私のコードです。入力は64ワードの長さに埋め込まれます。 Word2Vecの埋め込みには300の次元があります。埋め込みを機能させるために繰り返し実験を行ったため、ここにはおそらく多くの間違いがあります。提案は大歓迎です。
_import gensim
Word2vec_model = gensim.models.Word2Vec.load(“Word2vec.model")
_
_from keras.models import Sequential
from keras.layers import Embedding, GRU, Input, Flatten, Dense, TimeDistributed, Activation, PReLU, RepeatVector, Bidirectional, Dropout
from keras.optimizers import Adam, Adadelta
from keras.callbacks import ModelCheckpoint
from keras.losses import sparse_categorical_crossentropy, mean_squared_error, cosine_proximity
keras_model = Sequential()
keras_model.add(Word2vec_model.wv.get_keras_embedding(train_embeddings=False))
keras_model.add(Bidirectional(GRU(300, return_sequences=True, dropout=0.1, recurrent_dropout=0.1, activation='tanh')))
keras_model.add(TimeDistributed(Dense(600, activation='tanh')))
# keras_model.add(PReLU())
# ^ For some reason I get error when I add Activation ‘outside’:
# int() argument must be a string, a bytes-like object or a number, not 'NoneType'
# But keras_model.add(Activation('relu')) works.
keras_model.add(Dense(source_arr.shape[1] * source_arr.shape[2]))
# size = max-output-sentence-length * embedding-dimensions to learn the embedding vector and find the nearest Word in Word2vec_model.wv.similar_by_vector() afterwards.
# Alternatively one can use Dense(vocab_size) and train the network to output one-hot categorical words instead.
# Remember to change Keras loss to sparse_categorical_crossentropy.
# But this won’t benefit from Word2Vec.
keras_model.compile(loss=mean_squared_error,
optimizer=Adadelta(),
metrics=['mean_absolute_error'])
keras_model.summary()
_
__________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
embedding_19 (Embedding) (None, None, 300) 8219700
_________________________________________________________________
bidirectional_17 (Bidirectio (None, None, 600) 1081800
_________________________________________________________________
activation_4 (Activation) (None, None, 600) 0
_________________________________________________________________
time_distributed_17 (TimeDis (None, None, 600) 360600
_________________________________________________________________
dense_24 (Dense) (None, None, 19200) 11539200
=================================================================
Total params: 21,201,300
Trainable params: 12,981,600
Non-trainable params: 8,219,700
_________________________________________________________________
_
_filepath="best-weights.hdf5"
checkpoint = ModelCheckpoint(filepath, monitor='val_mean_absolute_error', verbose=1, save_best_only=True, mode='auto')
callbacks_list = [checkpoint]
keras_model.fit(array_of_Word_lists, array_of_Word_lists_AFTER_being_transformed_by_Word2vec, epochs=100, batch_size=2000, shuffle=True, callbacks=callbacks_list, validation_split=0.2)
_
モデルをテキストに合わせようとすると、エラーがスローされます。
_Train on 8000 samples, validate on 2000 samples Epoch 1/100
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-32-865f8b75fbc3> in <module>()
2 checkpoint = ModelCheckpoint(filepath, monitor='val_mean_absolute_error', verbose=1, save_best_only=True, mode='auto')
3 callbacks_list = [checkpoint]
----> 4 keras_model.fit(array_of_Word_lists, array_of_Word_lists_AFTER_being_transformed_by_Word2vec, epochs=100, batch_size=2000, shuffle=True, callbacks=callbacks_list, validation_split=0.2)
~/virtualenv/lib/python3.6/site-packages/keras/engine/training.py in fit(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_Epoch, steps_per_Epoch, validation_steps, **kwargs)
1040 initial_Epoch=initial_Epoch,
1041 steps_per_Epoch=steps_per_Epoch,
-> 1042 validation_steps=validation_steps)
1043
1044 def evaluate(self, x=None, y=None,
~/virtualenv/lib/python3.6/site-packages/keras/engine/training_arrays.py in fit_loop(model, f, ins, out_labels, batch_size, epochs, verbose, callbacks, val_f, val_ins, shuffle, callback_metrics, initial_Epoch, steps_per_Epoch, validation_steps)
197 ins_batch[i] = ins_batch[i].toarray()
198
--> 199 outs = f(ins_batch)
200 if not isinstance(outs, list):
201 outs = [outs]
~/virtualenv/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py in __call__(self, inputs)
2659 return self._legacy_call(inputs)
2660
-> 2661 return self._call(inputs)
2662 else:
2663 if py_any(is_tensor(x) for x in inputs):
~/virtualenv/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py in _call(self, inputs)
2612 array_vals.append(
2613 np.asarray(value,
-> 2614 dtype=tensor.dtype.base_dtype.name))
2615 if self.feed_dict:
2616 for key in sorted(self.feed_dict.keys()):
~/virtualenv/lib/python3.6/site-packages/numpy/core/numeric.py in asarray(a, dtype, order)
490
491 """
--> 492 return array(a, dtype, copy=False, order=order)
493
494
ValueError: could not convert string to float: 'hello'
_
以下は Rajmakからの抜粋 トークナイザーを使用して単語をKerasEmbeddingの入力に変換する方法を示しています。
_tokenizer = Tokenizer(num_words=MAX_NB_WORDS)
tokenizer.fit_on_texts(all_texts)
sequences = tokenizer.texts_to_sequences(texts)
Word_index = tokenizer.Word_index
……
indices = np.arange(data.shape[0]) # get sequence of row index
np.random.shuffle(indices) # shuffle the row indexes
data = data[indices] # shuffle data/product-titles/x-axis
……
nb_validation_samples = int(VALIDATION_SPLIT * data.shape[0])
x_train = data[:-nb_validation_samples]
……
Word2vec = KeyedVectors.load_Word2vec_format(EMBEDDING_FILE, binary=True)
_
Keras埋め込みレイヤーは、Gensim Word2VecのWord2vec.get_keras_embedding(train_embeddings = False)メソッドで取得するか、次のように構築できます。 nullの単語の埋め込みは、事前にトレーニングされたベクトル(この場合はGoogleニュース)に見つからない単語の数を示します。これは、この文脈におけるブランドのユニークな言葉である可能性があります。
_from keras.layers import Embedding
Word_index = tokenizer.Word_index
nb_words = min(MAX_NB_WORDS, len(Word_index))+1
embedding_matrix = np.zeros((nb_words, EMBEDDING_DIM))
for Word, i in Word_index.items():
if Word in Word2vec.vocab:
embedding_matrix[i] = Word2vec.Word_vec(Word)
print('Null Word embeddings: %d' % np.sum(np.sum(embedding_matrix, axis=1) == 0))
embedding_layer = Embedding(embedding_matrix.shape[0], # or len(Word_index) + 1
embedding_matrix.shape[1], # or EMBEDDING_DIM,
weights=[embedding_matrix],
input_length=MAX_SEQUENCE_LENGTH,
trainable=False)
from keras.models import Sequential
from keras.layers import Conv1D, GlobalMaxPooling1D, Flatten
from keras.layers import Dense, Input, LSTM, Embedding, Dropout, Activation
model = Sequential()
model.add(embedding_layer)
model.add(Dropout(0.2))
model.add(Conv1D(300, 3, padding='valid',activation='relu',strides=2))
model.add(Conv1D(150, 3, padding='valid',activation='relu',strides=2))
model.add(Conv1D(75, 3, padding='valid',activation='relu',strides=2))
model.add(Flatten())
model.add(Dropout(0.2))
model.add(Dense(150,activation='sigmoid'))
model.add(Dropout(0.2))
model.add(Dense(3,activation='sigmoid'))
model.compile(loss='categorical_crossentropy',optimizer='rmsprop',metrics=['acc'])
model.summary()
model.fit(x_train, y_train, validation_data=(x_val, y_val), epochs=2, batch_size=128)
score = model.evaluate(x_val, y_val, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])
_
ここで、_embedding_layer
_は、以下を使用して明示的に作成されます。
_for Word, i in Word_index.items():
if Word in Word2vec.vocab:
embedding_matrix[i] = Word2vec.Word_vec(Word)
_
ただし、get_keras_embedding()
を使用すると、埋め込み行列はすでに作成されて修正されています。 Tokenizerの各Word_indexをget_keras_embedding()
のKeras埋め込み入力。
では、KerasでWord2Vecのget_keras_embedding()を使用する適切な方法は何ですか?
だから私は解決策を見つけました。トークン化されたWordのインデックスは_Word2vec_model.wv.vocab[Word].index
_にあり、その逆は_Word2vec_model.wv.index2Word[word_index]
_によって取得できます。 get_keras_embedding()
は前者を入力として受け取ります。
私は次のように変換を行います:
_source_Word_indices = []
for i in range(len(array_of_Word_lists)):
source_Word_indices.append([])
for j in range(len(array_of_Word_lists[i])):
Word = array_of_Word_lists[i][j]
if Word in Word2vec_model.wv.vocab:
Word_index = Word2vec_model.wv.vocab[Word].index
source_Word_indices[i].append(Word_index)
else:
# Do something. For example, leave it blank or replace with padding character's index.
source_Word_indices[i].append(padding_index)
source = numpy.array(source_Word_indices)
_
そして最後に_keras_model.fit(source, ...
_