python深度学习——深度学习用于文本和序列1

**

文本处理

**
深度学习模型不会接收原始文本作为输入,它只能处理数值张量。文本向量化(vectorize)是指将文本转换为数值张量的过程。它有多种实现方法。
将文本分解而成的单元(单词、字符或 n-gram)叫作标记(token),将文本分解成标记的过程叫作分(tokenization)。所有文本向量化过程都是应用某种分词方案,然后将数值向量与生成的标记相关联。将向量与标记相关联的方法有很多种。本节将介绍两种主要方法:对标记做 one-hot 编码(one-hot
encoding)与标记嵌入[token embedding,通常只用于单词,叫作词嵌入(word embedding)]。
one-hot 编码得到的向量是二进制的、稀疏的(绝大部分元素都是 0)、维度很高的(维度大小等于词表中的单词个数),而词嵌入是低维的浮点数向量(即密集向量,与稀疏向量相对),参见图 6-2。与 one-hot 编码得到的词向量不同,词嵌入是从数据中学习得到的。常见的词向量维度是 256、512 或 1024(处理非常大的词表时)。与此相对,onehot 编码的词向量维度通常为 20 000 或更高(对应包含 20 000 个标记的词表)。因此,词向量可以将更多的信息塞入更低的维度中。
在这里插入图片描述
词袋往往被用于浅层的语言处理模型,而不是深度学习模型,在使用轻量级的浅层文本处理模型时(比
如 logistic 回归和随机森林),n-gram 是一种功能强大、不可或缺的特征工程工具。
**

  1. one-hot编码

**
keras实现:

from keras.preprocessing.text import Tokenizer
samples = ['The cat sat on the mat.', 'The dog ate my homework.']
# 创建一个分词器(tokenizer),设置为只考虑前 1000 个最常见的单词
tokenizer = Tokenizer(num_words=1000)
# 构建单词索引
tokenizer.fit_on_texts(samples)
#将字符串转换为整数索引组成的列表
sequences = tokenizer.texts_to_sequences(samples)
# 也可以直接得到 one-hot 二进制表示。这个分词器也支持除 one-hot 编码外的其他向量化模式
one_hot_results = tokenizer.texts_to_matrix(samples, mode='binary')
# 找回单词索引
word_index = tokenizer.word_index
print('word_index = ',  word_index)
print('Found %s unique tokens.' % len(word_index))

在这里插入图片描述
one-hot 编码的一种变体是所谓的 one-hot 散列技巧(one-hot hashing trick),如果词表中唯一标记的数量太大而无法直接处理,就可以使用这种技巧。这种方法没有为每个单词显式分配一个索引并将这些索引保存在一个字典中,而是将单词散列编码为固定长度的向量,通常用一个非常简单的散列函数来实现。这种方法的主要优点在于,它避免了维护一个显式的单词索引,从而节省内存并允许数据的在线编码(在读取完所有数据之前,你就可以立刻生成标记向量)。这种方法有一个缺点,就是可能会出现散列冲突(hash collision),即两个不同的单词可能具有相同的散列值,随后任何机器学习模型观察这些散列值,都无法区分它们所对应的单词。如果散列空间的维度远大于需要散列的唯一标记的个数,散列冲突的可能性会减小。

import numpy as np
samples = ['The cat sat on the mat.', 'The dog ate my homework.']
# 将单词保存为长度为 1000 的向量。如果单词数量接近 1000 个(或更多),那么会遇到很多散列冲突,这会降低这种编码方法的准确性
dimensionality = 1000
max_length = 10
results = np.zeros((len(samples), max_length, dimensionality))
for i, sample in enumerate(samples):
 for j, word in list(enumerate(sample.split()))[:max_length]:
 	# 将单词散列为 0~1000 范围内的一个随机整数索引
     index = abs(hash(word)) % dimensionality
     results[i, j, index] = 1.
print(results.shape) # (2, 10, 1000)

results结果
在这里插入图片描述
在这里插入图片描述
**

2. 词嵌入

**
获取词嵌入有两种方法。

  • 在完成主任务(比如文档分类或情感预测)的同时学习词嵌入。在这种情况下,一开始是随机的词向量,然后对这些词向量进行学习,其学习方式与学习神经网络的权重相同。
  • 在不同于待解决问题的机器学习任务上预计算好词嵌入,然后将其加载到模型中。这些词嵌入叫作预训练词嵌入(pretrained word embedding)。

利用 Embedding 层学习词嵌入
实例化embedding层

from keras.layers import Embedding
embedding_layer = Embedding(1000, 64)
# Embedding 层至少需要两个参数:标记的个数(这里是 1000,即最大单词索引 +1)和嵌入的维度(这里是 64)

IMDB 电影评论情感预测任务

from keras.datasets import imdb
from keras.layers import preprocessing
from keras.models import Sequential
from keras.layers import Flatten, Dense, Embedding

max_features = 10000
maxlen = 20
(x_train, y_train), (x_test, y_test) = imdb.load_data(
 num_words=max_features)
# 将整数列表转换成形状为(samples, maxlen) 的二维整数张量
x_train = preprocessing.sequence.pad_sequences(x_train, maxlen=maxlen)
x_test = preprocessing.sequence.pad_sequences(x_test, maxlen=maxlen)

model = Sequential()
# 指定 Embedding 层的最大输入长度,以便后面将嵌入输入展平。Embedding 层激活的形状为 (samples, maxlen, 8)
model.add(Embedding(10000, 8, input_length=maxlen))
# 将三维的嵌入张量展平成形状为 (samples, maxlen * 8) 的二维张量
model.add(Flatten())
model.add(Dense(1, activation='sigmoid'))
model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['acc'])
model.summary()
history = model.fit(x_train, y_train,
 epochs=10,
 batch_size=32,
 validation_split=0.2)

得到的验证精度约为 76%,考虑到仅查看每条评论的前 20 个单词,这个结果还是相当不错的。但请注意,仅仅将嵌入序列展开并在上面训练一个 Dense 层,会导致模型对输入序列中的每个单词单独处理,而没有考虑单词之间的关系和句子结构(举个例子,这个模型可能会将 this movie is a bomb 和 this movie is the bomb 两条都归为负面评论 a)。更好的做法是在嵌入序列上添加循环层或一维卷积层,将每个序列作为整体来学习特征。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值