在之前的章节中,我们学习了有关离散数据、图片信息的回归和分类方法。本节课,我们想利用深度学习模型,对电影评论这样的文本信息进行分类,判断观影者是喜欢还是不喜欢该电影。 image.png 让计算机处理、理解文本信息,其中涉及到自然语言处理(NLP)技术,什么是自然语言处理呢,它又有什么样的应用场景?

# 1.自然语言处理(Natural Langunge Processing, NLP )

简单的描述,NLP是用计算机来处理、理解以及运用人类语言(如中文、英文等),它属于人工智能的一个分支,是计算机科学与语言学的交叉学科,又常被称为计算语言学,同时也是现在关注度较高的领域。 image.png 接下来,我们看一个文本处理的例子,我们有一批影视评论文本数据,通过我们的努力,希望得到一个可以自动判断影视评论情感的分类器(只区分正面和负面评价)。在正式开始之前,我们先了解一下文本信息的预处理,毕竟计算机没有我们“聪明”,若是直接把文本给它,它会很懵~所以要预先进行数字化处理。

# 2.用数字表示文本

机器学习模型将向量(数字数组)作为输入。在处理文本时,我们必须先想出一种策略,将字符串转换为数字(或将文本“向量化”),然后再把它输入模型。我们来看一下几种处理方式:One-hot、唯一数字编码、Word Embedding、Word2vec 、Elmo、BERT等,我们介绍前三种基础的编码方式。

# 2.1独热编码(One-hot encodings)

我们可以对词汇表中的每个单词进行“独热”编码。考虑这样一句话:“The cat sat on the mat”。这句话中的词汇(或唯一单词)是(cat、mat、on、sat、the)。为了表示每个单词,我们将创建一个长度等于词汇量的零向量,然后在与该单词对应的索引中放置一个 1。下图显示了这种方法。 image.png 为了创建一个包含句子编码的向量,我们可以将每个单词的独热向量连接起来。 然而,这种方法效率低下。一个独热编码向量十分稀疏(这意味着大多数索引为零)。假设我们的词汇表中有 10,000 个单词。为了对每个单词进行独热编码,我们将创建一个其中 99.99% 的元素都为零的向量。

# 2.2用一个唯一的数字编码每个单词

image.png 我们可以尝试的第二种方法是使用唯一的数字来编码每个单词。继续上面的示例,我们可以将 1 分配给“cat”,将 2 分配给“mat”,依此类推。然后,我们可以将句子“The cat sat on the mat”编码为一个密集向量,例如 [5, 1, 4, 3, 5, 2]。这种方法是高效的。现在,我们有了一个密集向量(所有元素均已满),而不是稀疏向量。 但是,这种方法有两个缺点: 1、整数编码不能够体现单词之间的联系 2、对于要解释的模型而言,整数编码颇具挑战。例如,线性分类器针对每个特征学习一个权重。由于任何两个单词的相似性与其编码的相似性之间都没有关系,因此这种特征权重组合没有意义。

# 2.3单词嵌入向量(Word Embedding)

单词嵌入(Word Embedding)或者分布式向量(Distributional Vectors)是将自然语言表示的单词转换为计算机能够理解的向量或矩阵形式的技术。由于要考虑多种因素比如词的语义(同义词近义词)、语料中词之间的关系(上下文)和向量的维度(处理复杂度)等等,我们希望近义词或者表示同类事物的单词之间的距离可以理想地近,只有拿到很理想的单词表示形式,我们才更容易地去做翻译、问答、信息抽取等进一步的工作。 image.png 接下来,我们用代码实操阶段,从单词编码到把文本的情感进行分类。

# 3.代码讲解

导入相关库:

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers

import tensorflow_datasets as tfds
tfds.disable_progress_bar()
1
2
3
4
5
6

使用嵌入向量层,可以将嵌入向量层理解为一个从整数索引(代表特定单词)映射到密集向量(其嵌入向量)的查找表。嵌入向量的维数(或宽度)是一个参数,可以试验它的数值,以了解多少维度适合我们的问题,这与试验密集层中神经元数量的方式非常相似。

embedding_layer = layers.Embedding(1000, 5)
1

创建嵌入向量层时,嵌入向量的权重会随机初始化(就像其他任何层一样)。在训练过程中,通过反向传播来逐渐调整这些权重。训练后,学习到的单词嵌入向量将粗略地编码单词之间的相似性(因为它们是针对训练模型的特定问题而学习的)。如果将整数传递给嵌入向量层,结果会将每个整数替换为嵌入向量表中的向量:

result = embedding_layer(tf.constant([1,2,3]))
result.numpy()
1
2

对于文本或序列问题,嵌入向量层采用整数组成的 2D 张量,其形状为 (samples, sequence_length),其中每个条目都是一个整数序列。它可以嵌入可变长度的序列。您可以在形状为 (32, 10)(32 个长度为 10 的序列组成的批次)或 (64, 15)(64 个长度为 15 的序列组成的批次)的批次上方馈入嵌入向量层。返回的张量比输入多一个轴,嵌入向量沿新的最后一个轴对齐。向其传递 (2, 3) 输入批次,输出为 (2, 3, N)

result = embedding_layer(tf.constant([[0,1,2],[3,4,5]]))
result.shape
1
2

当给定一个序列批次作为输入时,嵌入向量层将返回形状为 (samples, sequence_length, embedding_dimensionality) 的 3D 浮点张量,本样例使用池化,因为它最简单。我们将基于 IMDB 电影评论来训练情感分类器。在此过程中,模型将从头开始学习嵌入向量。我们将使用经过预处理的数据集。

(train_data, test_data), info = tfds.load(
    'imdb_reviews/subwords8k', 
    split = (tfds.Split.TRAIN, tfds.Split.TEST), 
    with_info=True, as_supervised=True)
1
2
3
4

获取编码器 (tfds.features.text.SubwordTextEncoder),并快速浏览词汇表:

encoder = info.features['text'].encoder
encoder.subwords[:20]
1
2

电影评论的长度可以不同。我们将使用 padded_batch 方法来标准化评论的长度。

train_batches = train_data.shuffle(1000).padded_batch(10)
test_batches = test_data.shuffle(1000).padded_batch(10)
1
2

导入时,评论的文本是整数编码的(每个整数代表词汇表中的特定单词或单词部分)。请注意尾随零,因为批次会填充为最长的示例。

train_batch, train_labels = next(iter(train_batches))
train_batch.numpy()
1
2

创建一个“连续词袋”样式的模型,嵌入向量层将采用整数编码的词汇表,并查找每个单词索引的嵌入向量。在模型训练时会学习这些向量。向量会向输出数组添加维度。得到的维度为:(batch, sequence, embedding)。接下来,通过对序列维度求平均值,GlobalAveragePooling1D 层会返回每个样本的固定长度输出向量。这让模型能够以最简单的方式处理可变长度的输入。此固定长度输出向量通过一个包含 16 个隐藏单元的完全连接(密集)层进行流水线传输。最后一层与单个输出节点密集连接。利用 Sigmoid 激活函数,得出此值是 0 到 1 之间的浮点数,表示评论为正面的概率(或置信度)。

embedding_dim=16

model = keras.Sequential([
  layers.Embedding(encoder.vocab_size, embedding_dim),
  layers.GlobalAveragePooling1D(),
  layers.Dense(16, activation='relu'),
  layers.Dense(1)
])

model.summary()
1
2
3
4
5
6
7
8
9
10

编译和训练模型

model.compile(optimizer='adam',
              loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
              metrics=['accuracy'])

history = model.fit(
    train_batches,
    epochs=10,
    validation_data=test_batches, validation_steps=20)
1
2
3
4
5
6
7
8

绘制学习曲线:

import matplotlib.pyplot as plt

history_dict = history.history

acc = history_dict['accuracy']
val_acc = history_dict['val_accuracy']
loss=history_dict['loss']
val_loss=history_dict['val_loss']

epochs = range(1, len(acc) + 1)

plt.figure(figsize=(12,9))
plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.show()

plt.figure(figsize=(12,9))
plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend(loc='lower right')
plt.ylim((0.5,1))
plt.show()
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

image.png 至此,我们体验了文本情感分类模型的训练流程。有关文本分析它是一个比较庞大的学科分支,限于篇幅,文中的代码示例没有向读者一一解释参数含义,若读者希望进一步进修人工智能的课程,鼓励大家自己查阅相关资料(官方文档是一个非常好的学习途径)。也欢迎读者在我们的交流群内分享学习进度与困惑。

# 3.1完整代码

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers

import tensorflow_datasets as tfds
tfds.disable_progress_bar()

embedding_layer = layers.Embedding(1000, 5)
(train_data, test_data), info = tfds.load(
    'imdb_reviews/subwords8k', 
    split = (tfds.Split.TRAIN, tfds.Split.TEST), 
    with_info=True, as_supervised=True)
encoder = info.features['text'].encoder
encoder.subwords[:20]
train_batches = train_data.shuffle(1000).padded_batch(10)
test_batches = test_data.shuffle(1000).padded_batch(10)
train_batch, train_labels = next(iter(train_batches))
train_batch.numpy()
embedding_dim=16

model = keras.Sequential([
  layers.Embedding(encoder.vocab_size, embedding_dim),
  layers.GlobalAveragePooling1D(),
  layers.Dense(16, activation='relu'),
  layers.Dense(1)
])
model.compile(optimizer='adam',
              loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
              metrics=['accuracy'])

history = model.fit(
    train_batches,
    epochs=10,
    validation_data=test_batches, validation_steps=20)
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

# 4.练习题

以下属于NLP任务的有?(多选):

A. 词性标注

B. 文本分类

C. 问答对话系统

D. 机器翻译

更新于: 12/30/2021, 2:39:56 AM