深度学习入门系列17项目实战:从电影评论预测情感

大家好,我技术人Howzit,这是深度学习入门系列第十七篇,欢迎大家一起交流!

深度学习入门系列1:多层感知器概述
深度学习入门系列2:用TensorFlow构建你的第一个神经网络
深度学习入门系列3:深度学习模型的性能评价方法
深度学习入门系列4:用scikit-learn找到最好的模型
深度学习入门系列5项目实战:用深度学习识别鸢尾花种类
深度学习入门系列6项目实战:声纳回声识别
深度学习入门系列7项目实战:波士顿房屋价格回归
深度学习入门系列8:用序列化保存模型便于继续训练
深度学习入门系列9:用检查点保存训练期间最好的模型
深度学习入门系列10:从绘制记录中理解训练期间的模型行为
深度学习入门系列11:用Dropout正则减少过拟合
深度学习入门系列12:使用学习规划来提升性能
深度学习入门系列13:卷积神经网络概述
深度学习入门系列14:项目实战:基于CNN的手写数字识别
深度学习入门系列15:用图像增强改善模型性能
深度学习入门系列16:项目实战:图像中目标识别
深度学习入门系列17:项目实战:从电影评论预测情感
深度学习入门系列18:递归神经网络概述
深度学习入门系列19:基于窗口(window)的多层感知器解决时序问题
深度学习入门系列20:LSTM循环神经网络解决国际航空乘客预测问题
深度学习入门系列21:项目:用LSTM+CNN对电影评论分类
深度学习入门系列22:从猜字母游戏中理解有状态的LSTM递归神经网络
深度学习入门系列23:项目:用爱丽丝梦游仙境生成文本

文章目录

    • 17.1 电影评论情感分类数据集
    • 17.2 用Keras加载IMDB数据集
    • 17.3 词嵌入
    • 17.4 简单多层感知器模型
    • 17.5 一维卷积神经网络
    • 17.6 总结


情感分析是自然处理的问题,它包括文本的理解和潜在意图的预测。在这节课中,你将学习如何在python中使用Keras深度学习库预测电影评论的情感-要么正向要么负向。一步步完成这节课之后,你讲学到:

  • 关于用于自然语言处理的IMDB情感分析问题以及如何在Keras中加载它。
  • 如何在Keras中用词表示解决自然语言处理问题。
  • 对于IMDB问题,如何开发和评估多层感知器模型。
  • 对于IMDB问题,如何开发出一维卷积神经网络模型。

让我开始吧。

17.1 电影评论情感分类数据集

这个项目使用的数据集是大规模电影评论数据集,通常指的是IMDB数据集。IMDB数据集包含了25000高极性电影评论(好或者坏)用于训练,同样数量也用于测试。这个问题决定了给定电影评论是否有个正向或者负向情感。

这个数据由斯坦福大学研究者所收集的,并在2011年论文中使用,并分割成50-50数据,用于训练和测试。获得88.89%精度。

17.2 用Keras加载IMDB数据集

Keras提供了访问内制的IMBD数据方法。imdb.load_data() 函数允许你以准备要是用的神经网络模型和深度学习模型的格式加载数据集。单词已被表示该单词在数据集中的绝对流行度的整数取代。每个评论的句子由整型序列组成。

首次调用 imdb.load_data() 将要下载IMDB数据集到你的电脑里并存在你的主目录 ~/.keras/datasets/imdb.pkl下的一个32Mb文件。imdb.load_data() 提供了附加参数包括前排单词加载的数量(在返回的数据中单词小点的整型标记为0),前排单词跳过的数量(为了避免the’s)以及最大评论长度的支持。让我们加载数据集并计算它的一些属性。我们将要通过加载一些库和加载完整的IMDB数据集作为训练集来开始。

import numpy from keras.datasets
import imdb from matplotlib
import pyplot

# load the dataset
(X_train, y_train), (X_test, y_test) = imdb.load_data()
X = numpy.concatenate((X_train, X_test), axis=0)
y = numpy.concatenate((y_train, y_test), axis=0)

接下来我们展示训练集大小

# summarize size
print("Training data: ")
print(X.shape)
int(y.shape)

运行这个片段,我们能看到有50000个记录。

Training data:
(50000,)
(50000,)

我们也能打印出总共的类值

# Summarize number of cl
print("Classes: ")
print(numpy.unique(y))

我们能看到这是一个二分类问题,评论中有好和坏。

Classes:
[0,1]

接下来,我们可以了解数据集中唯一单词的总数。

# Summarize number of words

print("Number of words: ")
print(len(numpy.unique(numpy.hstack(X))))

有趣的是,我们可以看到整个数据集中只有不到100,000个单词。

Number of words:
88585

最后,我们搞清楚评论平均长度。

# Summarize review length
print("Review length: ")
result = [len(x) for x in X]
print("Mean %.2f words (%f)" % (numpy.mean(result),numpy.std(result)))
# plot review length as a boxplot and histogram
pyplot.subplot(121)
pyplot.boxplot(result)
pyplot.subplot(122)
pyplot.hist(result)
pyplot.show()

我们能看到评论平均单词个数在300以下标准差在200单词。

Review length:
Mean 234.76 words (172.911495)

为了完整性提供了全部代码

import numpy  
from matplotlib import pyplot  
from tensorflow.keras.datasets import imdb  
  
# load the dataset  
(X_train, y_train), (X_test, y_test) = imdb.load_data()  
X = numpy.concatenate((X_train, X_test), axis=0)  
y = numpy.concatenate((y_train, y_test), axis=0)  
  
# summarize size  
print("Training data: ")  
print(X.shape)  
print(y.shape)  
  
# Summarize number of words  
print("Number of words: ")  
print(len(numpy.unique(numpy.hstack(X))))  
  
# Summarize review length  
print("Review length: ")  
result = [len(x) for x in X]  
  
print("Mean %.2f words (%f)" % (numpy.mean(result), numpy.std(result)))  
# plot review length as a boxplot and histogram  
pyplot.subplot(121)  
pyplot.boxplot(result)  
pyplot.subplot(122)  
pyplot.hist(result)  
pyplot.show()

查看方框图和晶须图以及以字为单位的评论长度的直方图,我们可能会看到一个指数分布,我们可能用400到500个单词的剪切长度覆盖了分布的质量。
深度学习入门系列17项目实战:从电影评论预测情感_第1张图片

17.3 词嵌入

最近一项在自然语言处理领域突破叫做词表示。这是一种在高维空间中将单词编码为实值向量的技术,在意义上,单词之间的相似度转换为向量空间中的紧密度。离散的单词被映射为连续数字向量。当我从事自然语言处理问题时,这是有用的,因为输入需要时数字。

Keras提供一个便捷的方法,通过Embedding层把词正整数词表示转成词嵌入。这个层的入参定义映射关系,包括期望单词最大个数,也称之为词汇大小(如,最大整数值将被看作输入端大小)。这个层也允许你指定每个单词向量的维度,称之为输出维度。

我们愿意对IMDB数据集使用词嵌入表示。让我们说我仅仅对数据集中前5000个常用的单词感兴趣。因而我们词汇大小为5000。我们能够选着32维度向量表示每个单词。最后,我们可以选择将最大评论长度上限为500个单词,将截断的评论长度大于截断长度,将用0填充的评论不足截断长度部分。我们按照如下加载IMDB数据:

imdb.load_data(nb_words=5000)

我们使用Keras工具对每个观察值使用sequence.pad_sequences() 函数进行截断或者填充到500长度。

X_train = sequence.pad_sequences(X_train, maxlen=500)
X_test = sequence.pad_sequences(X_test, maxlen=500)

最后,我们模型的第一层是一个词嵌入层,通过下面Embedding类创建。

Embedding(5000,32,input_length=500)

对于给定格式下电影评论训练或者测试模式,第一层输出层是一个32×500的矩阵。既然我们已经知道如何Keras中加载IMDB数据并如何为它使用词嵌入表示,那么就让我们开发和评估一些模型。

17.4 简单多层感知器模型

我们通过开发一个简单且只有一个神经元隐藏层的多层感知器模型开始。嵌入表示是真正的创新,我们将用一个相对简单的神经网络来演示2011年被认为是世界一流的结果。让我们从导入这个模型需要的类和函数开始并初始化随机数生成器的常数值确保我们能够轻而易举复制结果。

# MLP for the IMDB problem
import numpy
from tensorflow.keras.datasets import imdb
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.layers import Flatten
from tensorflow.keras.layers import Embedding
from tensorflow.keras.preprocessing import sequence

# fix random seed for reproducibility
seed = 7
numpy.random.seed(seed)

接下来,我们将开始加载IMDB数据集。正如词嵌入部分讨论那样,我们将简化数据。仅仅前5000个单词被加载。我们也将使用50%/50%划分方法,把数据集分为训练集和测试集。这是一个很好的标准划分方法。

top_words = 500
 (X_train, y_train), (X_test, y_test) = imdb.load_data(num_words=top_words)

我们将界定评论在500个单词,截断长的评论并用0填充段的评论。

max_words = 500
X_train = sequence.pad_sequences(X_train, maxlen=max_words)
X_test = sequence.pad_sequences(X_test, maxlen=max_words)

现在我们开始创建我们的模型。我们将使用一个Embedding 层作为输入层,设置词汇为5000个,单词向量大小为32维度并且输出长度为500。第一层的输出是上一个部分讨论的大小为32×500矩阵。我将Embedding层的输出扁平化为一维向量,然后使用了一个带有整流器激活函数的250个单元的dense隐藏层。输出层有个一个神经元并将使用sigmoid激活函数来输出一个0和1的值作为预测。这个模型使用对数损失并使用高效的ADAM优化程序进行优化。

# create the model
model = Sequential()
model.add(Embedding(top_words, 32, input_length=max_words))
model.add(Flatten())
model.add(Dense(250, activation="relu"))
model.add(Dense(1, activation="sigmoid"))
model.compile(loss="binary_crossentropy", optimizer="adam", metrics=["accuracy"])
print(model.summary())

我们能拟合模型并在训练时使用测试数据集进行验证。这个模型很容易过拟合,所以我们将使用非常时候训练周期,在这个例子中仅仅为2。有很多数据,因此我们将使用128批处理大小。这个模型被训练之后,我们在测试数据集上评估它的精度。

# Fit the model
model.fit(X_train, 
	y_train, 
	validation_data=(X_test, y_test), 
	epochs=2, 
	batch_size=128,
verbose=1)

# Final evaluation of the model
scores = model.evaluate(X_test, y_test, verbose=0)
print("Accuracy: %.2f%%" % (scores[1]*100))

为了完整性,下面提供所有的代码。

# MLP for the IMDB problem  
import numpy  
from tensorflow.keras.datasets import imdb  
from tensorflow.keras.layers import Dense  
from tensorflow.keras.layers import Embedding  
from tensorflow.keras.layers import Flatten  
from tensorflow.keras.models import Sequential  
from tensorflow.keras.preprocessing import sequence  
  
# fix random seed for reproducibility  
seed = 7  
numpy.random.seed(seed)  
  
# load the dataset but only keep the top n words, zero the rest  
top_words = 5000  
(X_train, y_train), (X_test, y_test) = imdb.load_data(num_words=top_words)  
  
max_words = 500  
X_train = sequence.pad_sequences(X_train, maxlen=max_words)  
X_test = sequence.pad_sequences(X_test, maxlen=max_words)  
  
# create the model  
model = Sequential()  
model.add(Embedding(top_words, 32, input_length=max_words))  
model.add(Flatten())  
model.add(Dense(250, activation="relu"))  
model.add(Dense(1, activation="sigmoid"))  
model.compile(loss="binary_crossentropy", optimizer="adam", metrics=["accuracy"])  
print(model.summary())  
  
# Fit the model  
model.fit(X_train,   
          y_train,   
          validation_data=(X_test, y_test),   
          epochs=2,   
          batch_size=128,   
          verbose=1)  
  
# Final evaluation of the model  
scores = model.evaluate(X_test, y_test, verbose=0)  
print("Accuracy: %.2f%%" % (scores[1] * 100))

运行此示例将拟合模型并总结了估计的性能。我们能看到这个非常简单模型花了很少代价却获得接近87.4%分数接近了原始论文。

Train on 25000 samples, validate on 25000 samples 
Epoch 1/2 
39s - loss: 0.5160 - acc: 0.7040 - val_loss: 0.2982 - val_acc: 0.8716 
Epoch 2/2
37s - loss: 0.1897 - acc: 0.9266 - val_loss: 0.3143 - val_acc: 0.8694 
Accuracy: 86.94%

我确定,如果我们使用更大embedding和增加更多的隐藏层来训练这个网络,我们能做的更好。让我们尝试不同的网络类型。

17.5 一维卷积神经网络

卷积神经网络被设计为尊重图像数据中的空间结构,同时对场景中学习对象的位置和方向具有鲁棒性。同样的规则被用于序列,如电影评论的一维单词序列。使CNN模型对于学习识别图像中的对象具有吸引力的相同属性可以帮助学习单词段落中的结构,即对特征的特定位置的技术不变性。

Keras分别通过Convolution1DMaxPooling1D支持一维卷积和池化。再一次,让我们导入这个例子需要的类和函数并初始化随机生成器为常数以至于我们能够轻易再现结果。

# CNN for the IMDB problem

import numpy
from tensorflow.keras.datasets import imdb
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.layers import Flatten
from tensorflow.keras.layers import Convolution1D
from tensorflow.keras.layers import MaxPooling1D
from tensorflow.keras.layers import Embedding
from tensorflow.keras.preprocessing import sequence

# fix random seed for reproducibility
seed = 7
numpy.random.seed(seed)

正如前面所做的,我们也能加载和准备我们IMDB数据集

# load the dataset but only keep the top n words, zero the rest
top_words = 5000
(X_train, y_train), (X_test, y_test) = imdb.load_data(nb_words=top_words)

# pad dataset to a maximum review length in words
max_words = 500
X_train = sequence.pad_sequences(X_train, maxlen=max_words)
X_test = sequence.pad_sequences(X_test, maxlen=max_words)

我们现在定义我们卷积神经网络模型。这时,在Embedding输入层之后,我们插入一个Convolution1D层。这个卷积层有32个特征图并一次读取嵌入单词表示,词嵌入的3个向量元素。卷积层后面是长度和步长为2的MaxPooling1D,它是来自卷积层的特征图的一半。剩余的网络和上面神经网络一样。

# create the model  
model = Sequential()  
model.add(Embedding(top_words, 32, input_length=max_words))  
model.add(Convolution1D(filters=32, kernel_size=3, padding="same", activation="relu"))  
model.add(MaxPooling1D(pool_size=2))  
model.add(Flatten())  
model.add(Dense(250, activation="relu"))  
model.add(Dense(1, activation="sigmoid"))  
model.compile(loss="binary_crossentropy", optimizer="adam", metrics=["accuracy"])  
print(model.summary())

我们也想之前一样拟合网络。

# Fit the model
model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=2, batch_size=128,verbose=1)

# Final evaluation of the model
scores = model.evaluate(X_test, y_test, verbose=0)
print("Accuracy: %.2f%%" % (scores[1] * 100)))

运行这个例子,我们首先用神经网络结构展示(不是在这)。我们能够看到我们的卷积层保留了最大500个单词的32维输入的词嵌入输入层的维数。池化层通过将表示减半来压缩它。运行这个例子,通过上面神经网络模型提供了一个小但好的改进精度-接近为88.3%。

为了完整性,下面提供了完整的代码。

# CNN for the IMDB problem  
import numpy  
from tensorflow.keras.datasets import imdb  
from tensorflow.keras.layers import Convolution1D  
from tensorflow.keras.layers import Dense  
from tensorflow.keras.layers import Embedding  
from tensorflow.keras.layers import Flatten  
from tensorflow.keras.layers import MaxPooling1D  
from tensorflow.keras.models import Sequential  
from tensorflow.keras.preprocessing import sequence  
  
# fix random seed for reproducibility  
seed = 7  
numpy.random.seed(seed)  
  
# load the dataset but only keep the top n words, zero the rest  
top_words = 5000  
(X_train, y_train), (X_test, y_test) = imdb.load_data(num_words=top_words)  
# pad dataset to a maximum review length in words  
max_words = 500  
X_train = sequence.pad_sequences(X_train, maxlen=max_words)  
X_test = sequence.pad_sequences(X_test, maxlen=max_words)  
  
# create the model  
model = Sequential()  
model.add(Embedding(top_words, 32, input_length=max_words))  
model.add(Convolution1D(filters=32, kernel_size=3, padding="same", activation="relu"))  
model.add(MaxPooling1D(pool_size=2))  
model.add(Flatten())  
model.add(Dense(250, activation="relu"))  
model.add(Dense(1, activation="sigmoid"))  
model.compile(loss="binary_crossentropy", optimizer="adam", metrics=["accuracy"])  
print(model.summary())  
  
# Fit the model  
model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=2, batch_size=128,  
          verbose=1)  
# Final evaluation of the model  
scores = model.evaluate(X_test, y_test, verbose=0)  
print("Accuracy: %.2f%%" % (scores[1] * 100))
Accuracy:88.28%

再一次,有许多机会进一步优化,比如使用更深的或者是更大的卷积层。一个有趣的想法是设置要使用的最大池化层为长度为500的输入。这会压缩每个特征图为一个32维长的向量并可能提高性能。

17.6 总结

在这节课,针对自然语言处理,你已经学习IMDB情感分析数据集。你已经学习如何为情感分析开发深度学习模型:

  • 如何在Keras中加载和审查IMDB数据集。
  • 如何为情感分析开发一个更大的神经网络模型。
  • 如何为情感分析开发一个一维卷积神经网络模型。

这个教程包括第五部分和Keras的卷积升级网络模型的介绍。接下来,第6部分,我们将学习不同类型的神经网络模型,目的是学习和预测序列,称之为递归神经网络(RNN)。

你可能感兴趣的:(深度学习入门,深度学习,tensorflow,人工智能)