【问题标题】:NLP Sentiment Analysis net is not learningNLP情感分析网不学习
【发布时间】:2020-05-29 12:32:13
【问题描述】:

我想训练一个用于情绪分析的神经网络。我已按照 keras 网页上的教程进行操作,但我必须将代码调整为我的用例,以便之后能够使用网络。

为此,我将来自 keras 的 imdb 数据集的文本从数字解码回文本,然后我对文本进行词干化,因为我需要使用词干化的文本。在那之后,因为我想控制我做词嵌入的方式,而不是使用 text_to_sequences 和 pad_sequences 我正在训练一个 doc2vec 嵌入,并在训练集上使用它,这样我就可以从我想要的文本中获取嵌入进行分类。

问题是,网络没有学到任何东西,准确率没有提高,我不能减少损失函数。我尝试了很多东西,比如网络的架构、所有的超参数以及将最后一层从 2 个网络更改为 1 个,从 sparse_categorical_entropy 更改为 binary_crossentropy。让我们看看是否有人可以提供帮助并对我的问题有所了解。我在这里插入代码并提前致谢。

from keras.datasets import imdb
max_features = 40000
(training_data, training_targets), (testing_data, testing_targets) = imdb.load_data(num_words=max_features)

import numpy as np
data = np.concatenate((training_data, testing_data), axis=0)
targets = np.concatenate((training_targets, testing_targets), axis=0)


index = imdb.get_word_index()
reverse_index = dict([(value, key) for (key, value) in index.items()])
decoded = " ".join([reverse_index.get(i - 3, "") for i in data[0]])

import nltk
from nltk .stem import LancasterStemmer

toke_corpus = list()
lan = LancasterStemmer()

from tqdm import tqdm
lista_reviews = list()

for review in tqdm(data):
  lista_reviews.append(np.array([lan.stem(reverse_index.get(i - 3, '')) for i in review][1:]))

train_x, test_x = lista_reviews[10000:], lista_reviews[:10000]
train_y, test_y = targets[10000:], targets[:10000]

 from gensim.models.callbacks import CallbackAny2Vec

 class EpochLogger(CallbackAny2Vec):
     '''Callback to log information about training'''
     def __init__(self):
         self.epoch = 0
     def on_epoch_begin(self, model):
         print("Epoch #{} start".format(self.epoch))
     def on_epoch_end(self, model):
         print("Epoch #{} end".format(self.epoch))
         self.epoch += 1


from gensim.models.doc2vec import Doc2Vec, TaggedDocument

documents = [TaggedDocument(doc, [i]) for i, doc in enumerate(lista_reviews)]
print("DOcuments already built")
epoch_logger = EpochLogger()
model = Doc2Vec(documents, vector_size=512, window=5, min_count=3, workers=8, epochs = 7, callbacks=[epoch_logger])


encoded_x_train, encoded_x_test = list(), list()
from tqdm import tqdm
for i in tqdm(train_x):
    encoded_x_train.append(model.infer_vector(i))
for k in tqdm(test_x):
    encoded_x_test.append(model.infer_vector(k))

import keras

reduce_lr = keras.callbacks.callbacks.ReduceLROnPlateau(monitor='val_loss', factor=0.50, patience=2, verbose=1, mode='auto', cooldown=0, min_lr=0.00001)

early = keras.callbacks.EarlyStopping(monitor='val_loss', min_delta=0, patience=4, verbose=1, mode='auto')

from keras import models
from keras.models import Sequential
from keras import layers
from keras.layers import Embedding, Bidirectional, Dense, LSTM, Conv1D, MaxPooling1D, Flatten

model1 = Sequential()
model1.add(Embedding(input_dim = max_features, input_length=512, output_dim=128, trainable=False))

model1.add(Conv1D(filters=64,
                 kernel_size=5,
                 padding='valid',
                 activation='linear',
                 strides=1))
model1.add(MaxPooling1D(pool_size=4))
model1.add(Dense(64, activation='linear'))
model1.add(LSTM(32, activation='tanh'))
# model1.add(Dense(32, activation='relu'))
# model1.add(Flatten())
# model1.add(Dense(1, activation='sigmoid'))
model1.add(Dense(2, activation='softmax'))
model1.summary()


from keras import optimizers
# sgd = optimizers.SGD(lr=0.001, decay=1e-6, momentum=0.9, nesterov=True)
adam = optimizers.Adam(learning_rate=0.01, beta_1=0.9, beta_2=0.999, amsgrad=False)


model1.compile(loss='sparse_categorical_crossentropy',
              optimizer=adam,
              metrics=['accuracy'])

history  = model1.fit( np.array(encoded_x_train), np.array(train_y),
 epochs= 20,
 batch_size = 500,
 validation_data = (np.array(encoded_x_test), np.array(test_y)), callbacks = [reduce_lr, early]
)

【问题讨论】:

  • np.array(encoded_x_test) 是浮点值的二维数组?为我们数据集中的每个样本提取的嵌入矩阵是否正确?
  • 正确。这是那个 (10000, 512) 的形状

标签: python tensorflow keras nlp


【解决方案1】:

您使用 Doc2Vec 创建样本嵌入。因此,我认为 Embedding、Conv1D 和 MaxPooling1D 层在您的网络中没有用处。它们对于 word2vec 很有用,您可以在其中提取每个标记的嵌入并在网络中使用它们。

尝试以这种方式直接使用嵌入来馈送您的网络

model1 = Sequential()
model1.add(Dense(128, activation='relu', input_shape=(512,)))
# ....
model1.add(Dense(2, activation='softmax'))

adam = optimizers.Adam(learning_rate=0.01, beta_1=0.9, beta_2=0.999, amsgrad=False)

model1.compile(loss='sparse_categorical_crossentropy',
              optimizer=adam,
              metrics=['accuracy'])

history  = model1.fit( np.array(encoded_x_train), np.array(train_y),
 epochs= 20,
 batch_size = 500,
 validation_data = (np.array(encoded_x_test), np.array(test_y)), callbacks = [reduce_lr, early]
)

【讨论】:

  • 您好,现在确实可以上网了。但我不明白你为什么说我应该删除 conv1D 和 MaxPooling 层。你认为我的方法是解决这个问题的好方法吗?非常感谢您的帮助
  • 我认为 Doc2Vec 加上一个密集的网络是一个很好的方法。 emb、maxpool 和 conv1d 在您的情况下没有用,因为您已经在句子/文档嵌入之前创建了它们,因此您不需要在网络中单独创建它们。您直接在 2d 空间中工作,而 maxpool 和 conv1d 强制您在 3d 中工作,这在您的情况下是无用的
  • 你好@Marco Cerliani,非常感谢。但是由于我需要向神经网络提供数字,您认为什么时候可以使用嵌入层和更难的架构?
  • 您可以使用 D2V、W2V + 嵌入或 keras 可训练嵌入...最好的方法是最适合您的测试集的方法
  • 是的,但如果我只有原始文本。你的意思是要么使用 DOC2vec 来提供嵌入,要么在 W2V 嵌入模型之前进行训练,然后通过每个单词的嵌入的平均值来制作嵌入,然后使用具有可训练 True 的嵌入层?或者这最后两个步骤对您来说是不同的方法?非常感谢您的意见
猜你喜欢
  • 2011-11-30
  • 1970-01-01
  • 1970-01-01
  • 2014-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-29
  • 1970-01-01
相关资源
最近更新 更多