wake-up-neo.com

Verhindern Sie eine Überanpassung der Textklassifizierung durch die Word-Einbettung mit LSTM

Zielsetzung :

  • Identifizieren des Klassenetiketts anhand der vom Benutzer eingegebenen Frage (wie Question Antwortsystem). 
  • Daten, die aus der Datei Big PDF extrahiert wurden, und müssen anhand der Benutzereingaben vorhergesagt werden.
  • Wird hauptsächlich im Richtliniendokument verwendet, wobei Benutzer __. eine Frage zu den Richtlinien haben und bestimmte Seitennummern anzeigen müssen.

Vorherige Implementierung: Angewendete elastische Suche, jedoch sehr ungenau, da der Benutzer einen beliebigen Text wie "Ich brauche" == "möchte" eingeben möchte. 


Datensatzinformationen: Datensatz enthält jede Zeile als Text (oder Absatz) und Label (als Seitennummer). Hier ist die Dateigröße klein, ich habe nur 500 Zeilen.

Aktuelle Implementierung:

  • Angewandte Word-Einbettung (Handschuh) mit LSTM in Keras und Back-End ist Tensor-Fluss 
  • Applied Droupout 
  • Angewandte AktivitätRegularisierung 
  • Applied L2 W_regularizer (von 0,1 bis 0,001) 
  • Angewendet verschiedene nb_Epoch von 10 bis 600 
  • EMBEDDING_DIM von 100 auf 300 von Glove Data geändert

Angewendetes NLP für,

  • Konvertieren Sie in Kleinschreibung 
  • Entfernen Sie Stop Word of English 
  • Stemming 
  • Zahlen entfernen 
  • URL und IP-Adresse entfernen

Ergebnis: Die Genauigkeit der Testdaten (oder Validierungsdaten) beträgt 23%, die Zugdaten jedoch 91%.


Code:

import time
from time import strftime

import numpy as np
from keras.callbacks import CSVLogger, ModelCheckpoint
from keras.layers import Dense, Input, LSTM, ActivityRegularization
from keras.layers import Embedding, Dropout,Bidirectional
from keras.models import Model
from keras.preprocessing.sequence import pad_sequences
from keras.preprocessing.text import Tokenizer
from keras.regularizers import l2
from keras.utils import to_categorical

import pickle
from DataGenerator import *

BASE_DIR = ''
GLOVE_DIR = 'D:/Dataset/glove.6B'  # BASE_DIR + '/glove.6B/'

MAX_SEQUENCE_LENGTH = 50
MAX_NB_WORDS = 20000
EMBEDDING_DIM = 300
VALIDATION_SPLIT = 0.2

# first, build index mapping words in the embeddings set
# to their embedding vector
np.random.seed(1337)  # for reproducibility

print('Indexing Word vectors.')

t_start = time.time()

embeddings_index = {}

if os.path.exists('pickle/glove.pickle'):
    print('Pickle found..')
    with open('pickle/glove.pickle', 'rb') as handle:
        embeddings_index = pickle.load(handle)
else:
    print('Pickle not found...')
    f = open(os.path.join(GLOVE_DIR, 'glove.6B.300d.txt'), encoding='utf8')
    for line in f:
        values = line.split()
        Word = values[0]
        coefs = np.asarray(values[1:], dtype='float32')
        embeddings_index[Word] = coefs
    f.close()
    with open('pickle/glove.pickle', 'wb') as handle:
        pickle.dump(embeddings_index, handle, protocol=pickle.HIGHEST_PROTOCOL)

print('Found %s Word vectors.' % len(embeddings_index))

# second, prepare text samples and their labels
print('Processing text dataset')

texts = []  # list of text samples
labels = []  # list of label ids
labels_index = {}  # dictionary mapping label name to numeric id

(texts, labels, labels_index) = get_data('D:/PolicyDocument/')

print('Found %s texts.' % len(texts))

# finally, vectorize the text samples into a 2D integer tensor
tokenizer = Tokenizer(nb_words=MAX_NB_WORDS)
tokenizer.fit_on_texts(texts)
sequences = tokenizer.texts_to_sequences(texts)

Word_index = tokenizer.Word_index
print('Found %s unique tokens.' % len(Word_index))
data = pad_sequences(sequences, maxlen=MAX_SEQUENCE_LENGTH)

labels = to_categorical(np.asarray(labels))
print('Shape of data tensor:', data.shape)
print('Shape of label tensor:', labels.shape)

# split the data into a training set and a validation set
indices = np.arange(data.shape[0])
np.random.shuffle(indices)
data = data[indices]
labels = labels[indices]
num_validation_samples = int(VALIDATION_SPLIT * data.shape[0])

x_train = data[:-num_validation_samples]
y_train = labels[:-num_validation_samples]
x_val = data[-num_validation_samples:]
y_val = labels[-num_validation_samples:]

# prepare embedding matrix
num_words = min(MAX_NB_WORDS, len(Word_index))
embedding_matrix = np.zeros((num_words + 1, EMBEDDING_DIM))
print('Preparing embedding matrix. :', embedding_matrix.shape)
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

# load pre-trained Word embeddings into an Embedding layer
# note that we set trainable = False so as to keep the embeddings fixed
embedding_layer = Embedding(embedding_matrix.shape[0],
                            embedding_matrix.shape[1],
                            weights=[embedding_matrix],
                            input_length=MAX_SEQUENCE_LENGTH,
                            mask_zero=True,
                            trainable=False)

print('Training model.')

csv_file = "logs/training_log_" + strftime("%Y-%m-%d %H-%M", time.localtime()) + ".csv"
model_file = "models/Model_" + strftime("%Y-%m-%d %H-%M", time.localtime()) + ".mdl"
print("Model file:" + model_file)
csv_logger = CSVLogger(csv_file)

# train a 1D convnet with global maxpooling
sequence_input = Input(shape=(MAX_SEQUENCE_LENGTH,), dtype='int32')
embedded_sequences = embedding_layer(sequence_input)

rate_drop_lstm = 0.15 + np.random.Rand() * 0.25
num_lstm = np.random.randint(175, 275)
rate_drop_dense = 0.15 + np.random.Rand() * 0.25

x = LSTM(num_lstm, return_sequences=True, W_regularizer=l2(0.001))(embedded_sequences)
x = Dropout(0.5)(x)
x = LSTM(64)(x)
x = Dropout(0.25)(x)
x = ActivityRegularization(l1=0.01, l2=0.001)(x)
preds = Dense(len(labels_index), activation='softmax')(x)

model = Model(sequence_input, preds)
model.compile(loss='categorical_crossentropy',
              optimizer='adam',
              metrics=['acc'])

model_checkpoint = ModelCheckpoint(model_file, monitor='val_loss', verbose=0, save_best_only=True,
                                   save_weights_only=False, mode='auto')

model.fit(x_train, y_train,
          batch_size=1,
          nb_Epoch=600,
          validation_data=(x_val, y_val), callbacks=[csv_logger, model_checkpoint])

score = model.evaluate(x_val, y_val, verbose=0)
print('Test score:', score[0])
print('Test accuracy:', score[1])

t_end = time.time()
total = t_end - t_start
ret_str = "Time needed(s): " + str(total)
print(ret_str)
10
Somnath Kadam

Dropout und BN sind sehr effektiv bei Vorwärtskopplungs-NNs. Sie können jedoch Probleme mit RNNs verursachen (zu diesem Thema gibt es viele Veröffentlichungen)

Die beste Möglichkeit, Ihr RNN-Modell besser zu generalisieren, besteht darin, die Größe der Datenmenge zu erhöhen. In Ihrem Fall (LSTM mit etwa 200 Zellen) möchten Sie wahrscheinlich in der Größenordnung von 100.000 oder mehr markierte Proben zum Trainieren haben.

8
MaxB

Neben der Reduzierung der Parameter wie Einbettungsgröße und Anzahl der Einheiten in einigen Schichten besteht auch die Möglichkeit, den wiederkehrenden Ausfall in LSTMs anzupassen.

LSTMs scheinen ziemlich leicht zu überanpassen (so habe ich gelesen).

Dann können Sie in der Keras-Dokumentation die Verwendung von dropout und recurrent_dropout als Parameter für jede LSTM-Ebene sehen. 

Beispiel mit beliebigen Zahlen:

x = LSTM(num_lstm, return_sequences=True, W_regularizer=l2(0.001), recurrent_dropout=0.4)(embedded_sequences)
x = Dropout(0.5)(x)
x = LSTM(64,dropout=0,5, recurrent_dropout=0,3)(x)

Andere Ursachen können falsche oder unzureichende Daten sein:

  • Haben Sie versucht, den Test und die Validierungsdaten zusammen zu mischen und neue Zug- und Validierungssätze zu erstellen?

  • Wie viele Sätze haben Sie in den Trainingsdaten? Versuchen Sie es mit kleinen Sets? Verwenden Sie das gesamte Set oder versuchen Sie die Dada-Erweiterung (Erstellen neuer Sätze und ihrer Klassifizierungen - dies kann jedoch bei Text sehr schwierig sein). 

6
Daniel Möller

Was Sie beschreiben, klingt sehr nach Überanpassung . Ohne weitere Informationen zu den Daten ist es am besten, dass Sie stärkere Regularisierungsmethoden ausprobieren. dropout und recurrent_dropout. Sie können auch versuchen, das Verhältnis für Dropout-Layer zu erhöhen. Verwenden Sie eine stärkere Regularisierung mit dem Parameter W_regularizer.

Andere Optionen könnten mit weiteren Informationen geöffnet werden, z. B. ob Sie Daniels Vorschlag ausprobiert haben und welche Ergebnisse erzielt wurden.

3
ginge

Widersprüchliche Trainingsmethoden (als Mittel zur Regularisierung) können einen Blick wert sein. Adversarial Training Methods für Semi-Supervised Text Classification

0
MARK