当前位置:   article > 正文

Keras---嵌入层学习_什么是神经网络嵌入层

什么是神经网络嵌入层

1 词嵌入

词嵌入提供了词的密集表示及其相对含义。最简单的理解就是:将词进行向量化表示,实体的抽象成了数学描述,就可以进行建模了。它们是对较简单的单词模型表示中使用的稀疏表示的改进。
词嵌入可以从文本数据中学习,并在项目之间重用。它们也可以作为在文本数据上拟合神经网络的一部分。用于学习词嵌入的两种最常见的技术分别是全局向量单词表示(Glove)和单词到向量表示(Word2vec)

2 Keras嵌入层

Keras提供了一个嵌入层,可用于处理文本数据的神经网络。它要求输入数据进行整数编码,以便每个单词都由唯一的整数表示。该数据准备步骤可以使用提供有Keras的Tokenizer API来执行。
在没有预训练词嵌入的Keras API中,嵌入层会使用随机权重进行初始化。它是一个灵活的层,可以以各种方式使用。
1.它可以单独使用来学习一个字嵌入,以后可以在另一个模型中使用。

2.它可以用作深度学习模型的一部分,其中嵌入与模型本身一起被学习。

3.它可以用于加载预训练的词嵌入模型,一种迁移学习。

嵌入层被定义为网络的第一个隐藏层。它必须指定3个参数:

它必须指定3个参数:

1.input_dim:这是文本数据中词汇的大小。如果你的数据是整数编码为0-10之间的值,则词表的大小将为11个字。

2.output_dim:这是嵌入单词的向量空间的大小。它为每个单词定义了该层的输出向量的大小。它可以是32或100甚至更大,根据你的问题来定。

3.input_length:这是输入序列的长度,正如你为Keras模型的任何输入层定义的那样。如果你的所有输入文档包含1000个单词,则为1000。

3 不使用预训练的词嵌入

我们定义一个小问题,我们有10个文本文档,每个文本文档都有一个关于学生作品的评论。这是一个简单的情绪分析问题,每个文本分类为正面“1”或负面“0”。
首先,我们将定义文档及其类标签。

# without embeddings
import numpy as np 
from keras.preprocessing.text import one_hot
from keras.preprocessing.sequence import pad_sequences
from keras.models import Sequential
from keras.layers import Dense,Flatten
from keras.layers.embeddings import Embedding

# define documents
documents = [
        'Well done!',
		'Good work',
		'Great effort',
		'nice work',
		'Excellent!',
		'Weak',
		'Poor effort!',
		'not good',
		'poor work',
		'Could have done better.']

# define class labels
labels = np.array([1,1,1,1,1,0,0,0,0,0])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

使用Keras文本处理API对每个文档进行one_hot编码,通常将文档表示为整数值序列,文档中的每个单词都表示为单个整数。

vocab_size = 50
encodeDocuments = [one_hot(doc,vocab_size) for doc in documents]
  • 1
  • 2

序列具有不同的长度,我们可以通过Keras库中的pad_sequences()来进行填充,我们将所有输入序列的长度设为4。

# 将文本填充到最大长度
max_length = 4
paddedDocuments = pad_sequences(encodeDocuments,maxlen=max_length,padding='post')
paddedDocuments
  • 1
  • 2
  • 3
  • 4

现在将我们的嵌入层定义为神经网络模型的一部分。嵌入词汇的大小为50,输入长度为4,选择8维的嵌入空间。这里的模型是二元分类器,而且嵌入层的输出为4个向量,每个向量8个维度,一个维度一个单词。
输出层的大小,计算方式很简单。假如输入尺寸为(batch_size, sequence_length)的2D张量,输出尺寸就为(batch_size, sequence_length, output_dim)3D张量。这里,batch_size为样本大小,所以输出尺寸中等于输入尺寸。而在嵌入层中我们会定义output_dim,词向量的维度。其实就一个矩阵乘法: s e q u e n c e _ l e n g t h × M = o u t p u t _ d i m sequence\_length \times M =output\_dim sequence_length×M=output_dim,M大小为(sequence_length, output_dim),所以输出尺寸为(batch_size, sequence_length, output_dim)

model = Sequential(name="without embeddings")
model.add(Embedding(vocab_size, 8, input_length=max_length,name="Embedding"))
model.add(Flatten(name='Flatten'))
model.add(Dense(1,activation='sigmoid',name='output'))
model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['acc'])
print(model.summary())

model.fit(paddedDocuments, labels, epochs=50, verbose=1)
model.save('./data/without_embeddings.h5')
model.save_weights('./data/without_embeddings_weights.h5')

loss, accuracy = model.evaluate(paddedDocuments, labels, verbose=0)
print('Accuracy: %f' % (accuracy*100))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

模型结构:
模型结构_1

4 使用预训练的词嵌入

现在使用Keras的预训练的词嵌入,代码大致与上文相同。我们将整个Glove词嵌入文件作为词嵌入数组的字典加载到内存中。在这里,我们使用60亿词和100维的数据训练的Glove,即glove.6B.100d.txt。

  • Glove下载
  • 下载Glove解压后,glove.6B.100d.txt 内容如图
    glove.6B.100d.txt如上文所述,第一步是定义,将其编码为整数,然后将序列设置为相同的长度。在这种情况下,我们需要能够将单词映射到整数以及整数到单词。
    Keras提供了一个标记生成器类,可以配合训练数据,可以将文本转换为序列,通过调用texts_to_sequences()的方法标记生成器的类,并提供访问字的字典映射到整数在word_index属性。
import numpy as np 
from keras.preprocessing.text import one_hot,Tokenizer
from keras.preprocessing.sequence import pad_sequences
from keras.models import Sequential
from keras.layers.embeddings import Embedding
from keras.layers import Dense,Flatten

# define documents
documents = [
        'Well done!',
		'Good work',
		'Great effort',
		'nice work',
		'Excellent!',
		'Weak',
		'Poor effort!',
		'not good',
		'poor work',
		'Could have done better.']

# define class labels
labels = np.array([1,1,1,1,1,0,0,0,0,0])

# use tokenizer and pad
tokenizer = Tokenizer()
tokenizer.fit_on_texts(documents)
vocab_size = len(tokenizer.word_index)+1
# print(tokenizer.word_counts)
encodeDocuments = tokenizer.texts_to_sequences(documents)
# print("encodeDocuments:\n",encodeDocuments)

max_length = 4
paddedDocuments = pad_sequences(encodeDocuments, maxlen=max_length, padding='post')
# print("paddedDocuments:\n",paddedDocuments)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

接下来,我们将整个GloVe字嵌入文件作为字嵌入数组的字典加载到内存中。并且为训练数据集中的每个单词创建一个嵌入矩阵。我们可以通过枚举Tokenizer.word_index中的所有唯一的字,并从加载的GloVe嵌入中定位嵌入权重向量。

# load glove model
inMemoryGlove = dict()
with open('/mnt/f/py/数据集/词向量/glove.6B/glove.6B.100d.txt') as fp:
    for  line in fp:
        values  = line.split()
        word = values[0]
        cofficients = np.asarray(values[1:],dtype='float32')
        inMemoryGlove[word] = cofficients
# print(len(inMemoryGlove))

# create coefficient matrix for training data
trainingToEmbeddings = np.zeros((vocab_size,100))
for word, i in tokenizer.word_index.items():
    gloveVector = inMemoryGlove.get(word)
    if gloveVector is not None:
        trainingToEmbeddings[i] = gloveVector
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

定义模型,训练与评估

model = Sequential()
model.add(Embedding(vocab_size,100,weights=[trainingToEmbeddings],input_length=max_length,trainable=False))
model.add(Flatten())
model.add(Dense(1,activation='sigmoid'))
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['acc'])
print(model.summary())
model.fit(paddedDocuments,labels,epochs=50,verbose=0)

loss, accuracy = model.evaluate(paddedDocuments, labels, verbose=0)
print('Accuracy: %f' % (accuracy * 100))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

模型结构图:
模型结构图_2

5 情感分析

情感分析基本上是用于识别并分类一段文本或语料库中所表达的情感的一种方法,为了确定他人对特定主题、产品等的态度是积极的、消极的还是中立的,使用NLP对应地文档分类为正面、中性或负面。
数据来自Crowdflower’s data for everyone数据库

import re
import numpy as np 
import pandas as pd
from keras.preprocessing.text import one_hot, Tokenizer
from keras.preprocessing.sequence import pad_sequences
from keras.models import Sequential
from keras.layers import Dense, Flatten
from keras.layers.embeddings import Embedding
from sklearn.model_selection import train_test_split

# 读取数据
X = pd.read_csv(r'./data/Sentiment.csv')
X = X[['text', 'sentiment']]
X = X[X.sentiment != 'Neutral'] # 放弃中性情感

# 对推文过滤,只保留有效的文本和单词
X['text'] = X['text'].apply(lambda x: x.lower())
X['text'] = X['text'].apply((lambda x: re.sub('[^a-zA-z0-9\s]', '', x)))
# X = X['text'].apply((lambda x:x.replace('rt',' ')))
# print(X)

for idx, row in X.iterrows():
    row[0] = row[0].replace('rt', ' ')
    
print(type(X))

# use tokenizer and pad
maxFeatures = 2000
tokenizer = Tokenizer(num_words=maxFeatures, split=' ')
tokenizer.fit_on_texts(X['text'].values) # 生成token词典
encodeDocuments = tokenizer.texts_to_sequences(X['text'].values)
# print(encodeDocuments)
# print(max([len(row) for row in encodeDocuments]))

max_length = 29
paddedDocuments = pad_sequences(encodeDocuments,
                                maxlen=max_length,
                                padding='post')

# load glove model
inMemoryGlove = dict()
with open('/mnt/f/py/数据集/词向量/glove.6B/glove.6B.100d.txt') as fp:
    for  line in fp:
        values  = line.split()
        word = values[0]
        cofficients = np.asarray(values[1:],dtype='float32')
        inMemoryGlove[word] = cofficients
print(len(inMemoryGlove))

# split data
labels = []
for i in X['sentiment']:
    if i == 'Positive':
        labels.append(1)
    else:
        labels.append(0)

labels = array(labels)
# print(len(labels))

X_train, X_test, Y_train, Y_test = train_test_split(paddedDocuments,labels, test_size = 0.33, random_state = 42)
print(X_train.shape, Y_train.shape)
print(X_test.shape, Y_test.shape)

# create coefficient matrix for training data
trainingToEmbeddings = np.zeros((maxFeatures, 100))
for word, i in tokenizer.word_index.items(): # i从1开始增加
    if i <= maxFeatures:
        gloveVector = inMemoryGlove.get(word)
        if gloveVector is not None:
            trainingToEmbeddings[i] = gloveVector
# print(trainingToEmbeddings)

model = Sequential(name='情感分析')
model.add(Embedding(maxFeatures,100,weights=[trainingToEmbeddings],input_length=max_length,trainable=False,name='Embedding'))
model.add(Flatten(name='Flatten'))
model.add(Dense(1,activation='sigmoid',name='output'))
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['acc'])
print(model.summary())

batch_size = 32
model.fit(X_train, Y_train, epochs=50, batch_size=batch_size, verbose=0)

loss, accuracy = model.evaluate(X_test, Y_test, verbose=0)
print('Accuracy: %f' % (accuracy * 100))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85

结果图:
结果图

参考资料:
Keras深度学习实战
Keras嵌入层API
在Keras模型中使用预训练的词嵌入
GloVe
词向量与Embedding究竟是怎么回事?

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/366369
推荐阅读
相关标签
  

闽ICP备14008679号