基于Keras的IMDB数据集的损失率和准确率对比

Keras 简介 

本文的代码示例全都使用Keras 实现。Keras 是一个Python 深度学习框架,可以方便地定 义和训练几乎所有类型的深度学习模型。Keras 最开始是为研究人员开发的,其目的在于快速 实验。

Keras 具有以下重要特性:

  •  相同的代码可以在 CPU 或 GPU 上无缝切换运行。
  •  具有用户友好的 API,便于快速开发深度学习模型的原型。
  •  内置支持卷积网络(用于计算机视觉)、循环网络(用于序列处理)以及二者的任意 组合。
  • 支持任意网络架构:多输入或多输出模型、层共享、模型共享等。这也就是说,Keras 能够构建任意深度学习模型,无论是生成式对抗网络还是神经图灵机。 Keras 基于宽松的MIT 许可证发布,这意味着可以在商业项目中免费使用它。它与所有版 本的 Python 都兼容(截至 2017 年年中,从 Python 2.7 到 Python 3.6 都兼容)。 Keras 已有200 000 多个用户,既包括创业公司和大公司的学术研究人员和工程师,也包括 研究生和业余爱好者。Google、Netflix、Uber、CERN、Yelp、Square 以及上百家创业公司都在 用 Keras 解决各种各样的问题。Keras 还是机器学习竞赛网站Kaggle 上的热门框架,最新的深 度学习竞赛中,几乎所有的优胜者用的都是 Keras 模型,如图 3-2 所示。

 Keras、TensorFlow、Theano 和 CNTK

Keras 是一个模型级(model-level)的库,为开发深度学习模型提供了高层次的构建模块。 它不处理张量操作、求微分等低层次的运算。相反,它依赖于一个专门的、高度优化的张量库 来完成这些运算,这个张量库就是Keras 的后端引擎(backend engine)。 Keras 没有选择单个张 量库并将Keras 实现与这个库绑定,而是以模块化的方式处理这个问题(见图3-3)。因此,几 个不同的后端引擎都可以无缝嵌入到 Keras 中。目前,Keras 有三个后端实现:TensorFlow 后端、 Theano 后端和微软认知工具包(CNTK,Microsoft cognitive toolkit)后端。未来 Keras 可能会扩 展到支持更多的深度学习引擎。

TensorFlow、CNTK 和 Theano 是当今深度学习的几个主要平台。Theano 由蒙特利尔大学的 MILA 实验室开发,TensorFlow 由 Google 开发,CNTK 由微软开发。你用Keras 写的每一段代 码都可以在这三个后端上运行,无须任何修改。也就是说,你在开发过程中可以在两个后端之 间无缝切换,这通常是很有用的。例如,对于特定任务,某个后端的速度更快,那么我们就可以无缝切换过去。我们推荐使用TensorFlow 后端作为大部分深度学习任务的默认后端,因为它 的应用最广泛,可扩展,而且可用于生产环境。 通过 TensorFlow(或 Theano、CNTK), Keras 可以在 CPU 和GPU 上无缝运行。在 CPU 上运行 时,TensorFlow 本身封装了一个低层次的张量运算库,叫作Eigen;在GPU 上运行时,TensorFlow 封装了一个高度优化的深度学习运算库,叫作 NVIDIA CUDA 深度神经网络库(cuDNN)。


使用 Keras 开发:概述 


 你已经见过一个Keras 模型的示例,就是MNIST 的例子。典型的Keras 工作流程就和那个 例子类似。 (1) 定义训练数据:输入张量和目标张量。 (2) 定义层组成的网络(或模型),将输入映射到目标。 (3) 配置学习过程:选择损失函数、优化器和需要监控的指标。 (4) 调用模型的 fit 方法在训练数据上进行迭代。 定义模型有两种方法:一种是使用 Sequential 类(仅用于层的线性堆叠,这是目前最常 见的网络架构),另一种是函数式 API(functional API,用于层组成的有向无环图,让你可以构 建任意形式的架构)。 前面讲过,这是一个利用 Sequential 类定义的两层模型(注意,我们向第一层传入了输 入数据的预期形状)。
 

from keras import models 
from keras import layers 
 
model = models.Sequential() 
model.add(layers.Dense(32, activation='relu', input_shape=(784,)))
model.add(layers.Dense(10, activation='softmax')) 下面是用函数式 API 定义的相同模型。
input_tensor = layers.Input(shape=(784,)) x = layers.Dense(32, activation='relu')(input_tensor) output_tensor = layers.Dense(10, activation='softmax')(x) 
 
model = models.Model(inputs=input_tensor, outputs=output_tensor) 

利用函数式API,你可以操纵模型处理的数据张量,并将层应用于这个张量,就好像这些 层是函数一样。

一旦定义好了模型架构,使用 Sequential 模型还是函数式API 就不重要了。接下来的步 骤都是相同的。 配置学习过程是在编译这一步,你需要指定模型使用的优化器和损失函数,以及训练过程 中想要监控的指标。下面是单一损失函数的例子,这也是目前最常见的。

from keras import optimizers 
 
model.compile(optimizer=optimizers.RMSprop(lr=0.001),          
                loss='mse',               
                metrics=['accuracy']) 

最后,学习过程就是通过 fit() 方法将输入数据的Numpy 数组(和对应的目标数据)传 入模型,这一做法与 Scikit-Learn 及其他机器学习库类似。

model.fit(input_tensor, target_tensor, batch_size=128, epochs=10)

准备数据
 

 你不能将整数序列直接输入神经网络。你需要将列表转换为张量。转换方法有以下两种。 

  • 填充列表,使其具有相同的长度,再将列表转换成形状为 (samples, word_indices) 的整数张量,然后网络第一层使用能处理这种整数张量的层。

  • 对列表进行 one-hot 编码,将其转换为 0 和 1 组成的向量。举个例子,序列 [3, 5] 将会 被转换为10 000 维向量,只有索引为3 和 5 的元素是1,其余元素都是0。然后网络第 一层可以用 Dense 层,它能够处理浮点数向量数据。 

 将整数序列编码为二进制矩阵

import numpy as np 
 
def vectorize_sequences(sequences, dimension=10000):     
    results = np.zeros((len(sequences), dimension))      
    for i, sequence in enumerate(sequences):         
        results[i, sequence] = 1.      
    return results 
 
x_train = vectorize_sequences(train_data)   
x_test = vectorize_sequences(test_data)  
样本现在变成了这样: >>> x_train[0] array([ 0.,  1.,  1., ...,  0.,  0.,  0.])
你还应该将标签向量化,这很简单。 
y_train = np.asarray(train_labels).astype('float32') 
y_test = np.asarray(test_labels).astype('float32')

 构建网络

 输入数据是向量,而标签是标量(1 和 0),这是你会遇到的最简单的情况。有一类网络在这种问题上表现很好,就是带有relu 激活的全连接层(Dense)的简单堆叠,比如 Dense(16, activation='relu')。 传入 Dense 层的参数(16)是该层隐藏单元的个数。一个隐藏单元(hidden unit)是该层 表示空间的一个维度。我们在第2 章讲过,每个带有 relu 激活的 Dense 层都实现了下列张量 运算:
 

output = relu(dot(W, input) + b) 

16 个隐藏单元对应的权重矩阵 W 的形状为 (input_dimension, 16),与 W 做点积相当于 将输入数据投影到16 维表示空间中(然后再加上偏置向量 b 并应用 relu 运算)。你可以将表 示空间的维度直观地理解为“网络学习内部表示时所拥有的自由度”。隐藏单元越多(即更高维 的表示空间),网络越能够学到更加复杂的表示,但网络的计算代价也变得更大,而且可能会导 致学到不好的模式(这种模式会提高训练数据上的性能,但不会提高测试数据上的性能)。

对于这种 Dense 层的堆叠,你需要确定以下两个关键架构:

  • 网络有多少层;
  •  每层有多少个隐藏单元。
  • 现在你只需要相信我选择的下列架构: 两个中间层,每层都有 16 个隐藏单元;
  • 第三层输出一个标量,预测当前评论的情感。 中间层使用 relu 作为激活函数,最后一层使用 sigmoid 激活以输出一个 0~1 范围内的概率 值(表示样本的目标值等于1 的可能性,即评论为正面的可能性)。relu(rectified linear unit, 整流线性单元)函数将所有负值归零(见图3-4),而 sigmoid 函数则将任意值“压缩”到 [0, 1] 区间内(见图 3-5),其输出值可以看作概率值。

 

下图显示了网络的结构。


 模型定义

 

from keras import models 
from keras import layers 
 
model = models.Sequential() 
model.add(layers.Dense(16, activation='relu', input_shape=(10000,))) model.add(layers.Dense(16, activation='relu')) 
model.add(layers.Dense(1, activation='sigmoid'))

什么是激活函数?为什么要使用激活函数?
如果没有 relu 等激活函数(也叫非线性), Dense 层将只包含两个线性运算——点积 和加法:
output = dot(W, input) + b
这样 Dense 层就只能学习输入数据的线性变换(仿射变换):该层的假设空间是从输 入数据到16 位空间所有可能的线性变换集合。这种假设空间非常有限,无法利用多个表示 层的优势,因为多个线性层堆叠实现的仍是线性运算,添加层数并不会扩展假设空间。 为了得到更丰富的假设空间,从而充分利用多层表示的优势,你需要添加非线性或激 活函数。relu 是深度学习中最常用的激活函数,但还有许多其他函数可选,它们都有类似 的奇怪名称,比如 prelu、elu 等。

 最后,你需要选择损失函数和优化器。由于你面对的是一个二分类问题,网络输出是一 个概率值(网络最后一层使用sigmoid 激活函数,仅包含一个单元),那么最好使用 binary_ crossentropy(二元交叉熵)损失。这并不是唯一可行的选择,比如你还可以使用mean_ squared_error(均方误差)。但对于输出概率值的模型,交叉熵(crossentropy)往往是最好 的选择。交叉熵是来自于信息论领域的概念,用于衡量概率分布之间的距离,在这个例子中就 是真实分布与预测值之间的距离。 

 

编译模型

from keras import optimizers 
 
model.compile(optimizer=optimizers.RMSprop(lr=0.001),                           
              loss='binary_crossentropy',               
              metrics=['accuracy'])

实战: 

将数据集划分成训练集和测试集,训练之后选用测试集验证损失率和分类准确率

from keras.datasets import imdb
import numpy as np
from keras import models
from keras import layers
import matplotlib.pyplot as plt
def main():
    (train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000)
    word_index = imdb.get_word_index()
    # print(word_index)
    reverse_word_index = dict(
        [(value,key) for (key,value) in word_index.items()]
    )
    decoded_review = ' '.join(
        [reverse_word_index.get(i-3,'?') for i in train_data[0]]
    )
    print(decoded_review)

def vectorize_sequences(sequences,dimension = 10000):
    results = np.zeros((len(sequences),dimension))
    for i,sequences in enumerate(sequences):
        results[i,sequences] = 1.
    return results

def train():
    (train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000)
    x_train = vectorize_sequences(train_data)
    x_test  = vectorize_sequences(test_data)
    y_train = np.asarray(train_labels).astype('float32')
    y_test  = np.asarray(test_labels).astype('float32')

    x_val = x_train[:10000]
    partial_train_data = x_train[10000:]
    y_val = y_train[:10000]
    partial_train_labels = y_train[10000:]


    model = models.Sequential()
    model.add(layers.Dense(16,activation='relu',input_shape=(10000,)))
    model.add(layers.Dense(16,activation='relu'))
    model.add(layers.Dense(1,activation='sigmoid'))

    model.compile(optimizer='rmsprop',
                  loss='binary_crossentropy',
                  metrics=['accuracy'])
    history = model.fit(partial_train_data,
                        partial_train_labels,
                        epochs=20,
                        batch_size=512,
                        validation_data=(x_val, y_val))

    history_dict = history.history
    print(history_dict)
    print(history_dict.keys())

    loss_values = history_dict['loss']
    val_loss_values = history_dict['val_loss']

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

    plt.plot(epochs,loss_values,'bo',label = 'Training loss')
    plt.plot(epochs,val_loss_values,'b',label ='Validation loss')
    plt.title('Training and validation loss')
    plt.xlabel('Epochs')
    plt.ylabel('Loss')
    plt.legend()

    plt.show()


if __name__ == '__main__':

    # main()
    train()

    # print(train_data[0])

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是使用Keras框架生成深度学习IMDB数据集上的文本分类实验代码: ```python from keras.datasets import imdb from keras.preprocessing import sequence from keras.models import Sequential from keras.layers import Dense, Embedding, LSTM # 加载数据集 max_features = 20000 maxlen = 80 batch_size = 32 print('Loading data...') (x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=max_features) print(len(x_train), 'train sequences') print(len(x_test), 'test sequences') # 填充序列,使其长度一致 print('Pad sequences (samples x time)') x_train = sequence.pad_sequences(x_train, maxlen=maxlen) x_test = sequence.pad_sequences(x_test, maxlen=maxlen) print('x_train shape:', x_train.shape) print('x_test shape:', x_test.shape) # 构建模型 model = Sequential() model.add(Embedding(max_features, 128, input_length=maxlen)) model.add(LSTM(128, dropout=0.2, recurrent_dropout=0.2)) model.add(Dense(1, activation='sigmoid')) model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) # 训练模型 print('Train...') model.fit(x_train, y_train, batch_size=batch_size, epochs=15, validation_data=(x_test, y_test)) # 评估模型 score, acc = model.evaluate(x_test, y_test, batch_size=batch_size) print('Test score:', score) print('Test accuracy:', acc) ``` 这段代码中,我们使用了IMDB数据集中的前20000个最常见的单词作为特征,并设置了每条评论的最大长度为80。然后我们使用Embedding层将每个单词映射为128维的向量,再使用LSTM层进行序列分类,最后使用Sigmoid激活函数输出二分类结果。我们使用binary_crossentropy作为损失函数,Adam作为优化器,并在训练过程中记录了模型的准确率。最终,我们在测试集上评估了模型的性能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值