前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >深度学习之二分类问题

深度学习之二分类问题

作者头像
李小白是一只喵
发布2020-04-23 15:27:08
1.4K0
发布2020-04-23 15:27:08
举报
文章被收录于专栏:算法微时光算法微时光

目录

IMDB 数据集

IMDB 数据集包含来自互联网电影数据库(IMDB)的 50 000 条严重两极分化的评论。

数据集被分为用于训练的 25 000 条评论与用于测试的 25 000 条评论,训练集和测试集都包含 50% 的正面评论和 50% 的负面评论。

为什么区分训练集和测试集

不应该将训练机器学习模型的同一批数据再用于测试模型!

模型在训练数据上的表现很好,并不意味着它在前所未见的数据上也会表现得很好,而且我们真正关心的是模型在新数据上的性能(因为已经知道了训练数据对应的标签,显然不再需要模型来进行预测)。

例如,模型最终可能只是记住了训练样本和目标值之间的映射关 系,但这对在前所未见的数据上进行预测毫无用处。

与 MNIST 数据集一样, IMDB 数据集也内置于 Keras 库。

Python enumerate() 函数

enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。

使用例子:

代码语言:javascript
复制
>>> seasons = ['Spring', 'Summer', 'Fall', 'Winter']
>>> list(enumerate(seasons))
[(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
>>> list(enumerate(seasons, start=1))       # 下标从 1 开始
[(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]

下载数据

使用一下代码下载数据:

代码语言:javascript
复制
from keras.datasets import imdb
(train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000)

参数 num_words=10000 的意思是仅保留训练数据中前 10 000 个最常出现的单词。低频单词将被舍弃。这

样得到的向量数据不会太大,便于处理。

得到的数据被分为train_data和test_data.

看一下数据内容:

代码语言:javascript
复制
train_data[0]
train_labels[0]

执行结果:

image.png

由于限定为前 10 000 个最常见的单词,单词索引都不会超过 10 000。

构建数据

将我们得到的数据构建成可以被神经网络处理的数据,也就是张量数据.需要通过一些方法:

  1. 填充列表,使其具有相同的长度,再将列表转换成形状为 (samples, word_indices)的整数张量,然后网络第一层使用能处理这种整数张量的层(即 Embedding )。
  2. 对列表进行 one-hot 编码,将其转换为 0 和 1 组成的向量。举个例子,序列 [3, 5] 将会被转换为 10 000 维向量,只有索引为 3 和 5 的元素是 1,其余元素都是 0。然后网络第一层可以用 Dense 层,它能够处理浮点数向量数据。

本次采用第二种方式实现张量化.

这里涉及到一个二维列表的使用方式,下面简单说明.

二维列表使用方法
代码语言:javascript
复制
res = np.zeros((2, 10))
mm = [3,4,5,6]
res[1, mm ] = 1
res

创建一个二维矩阵,然后再创建个一维列表,通过列表来设定举证里的值. 运行结果:

根据这个特性来构建输入数据.

填充数据为张量

使用如下代码:

代码语言:javascript
复制
from keras.datasets import imdb

(train_data, train_labels), (test_data, test_labels) = imdb.load_data(
num_words=10000)

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)

然后再将标签向量化:

代码语言:javascript
复制
y_train = np.asarray(train_labels).astype('float32')
y_test = np.asarray(test_labels).astype('float32')

构建网络

有了输入数据,接下来就是构建网络了.

这里使用激活函数为relu的全连接层.比 如 Dense(16, activation='relu') 。

全连接网络的介绍参考文章深度学习之神经网络(反向传播算法)(三)

传入 Dense 层的参数(16)是该层隐藏单元的个数。一个隐藏单元(hidden unit)是该层表示空间的一个维度。

16 个隐藏单元对应的权重矩阵 W 的形状为(input_dimension, 16) ,与 W 做点积相当于将输入数据投影到 16 维表示空间中(然后再加上偏置向量 b 并应用 relu 运算)。

网络可以描述为;

本次使用顺序模型进行编程.

Keras构建网络

在 Keras 中有两类主要的模型:Sequential 顺序模型使用函数式 API 的 Model 类模型

Sequential 顺序模型

顺序模型是函数式模型的简略版,为最简单的线性、从头到尾的结构顺序,不分叉,是多个网络层的线性堆叠。

方法一 使用以下代码可以简单创建个Sequential模型:

代码语言:javascript
复制
from keras.models import Sequential
from keras.layers import Dense, Activation
 
model = Sequential([
    Dense(32, input_shape=(784,)),
    Activation('relu'),
    Dense(10),
    Activation('softmax'),
])

Activation是激活函数. 方法二 也可以使用.add()方法将各层添加到模型中:

代码语言:javascript
复制
model = Sequential()
model.add(Dense(32, input_dim=784))
model.add(Activation('relu'))

在完成了模型的构建后, 可以使用 .compile() 来配置学习过程:选择损失函数和优化器。

由于面对的是一个二分类问题,网络输出是一个概率值(网络最后一层使用 sigmoid 激活函数,仅包含一个单元),那么最好使用 binary_crossentropy (二元交叉熵)损失。

当然这不是唯一可行的选择,比如还可以使用 mean_squared_error (均方误差)。但对于输出概率值的模型,交叉熵(crossentropy)往往是最好的选择。

详细说明参考文章<<深度学习之二元交叉熵损失函数>>

代码语言:javascript
复制
model.compile(loss='categorical_crossentropy',
              optimizer='sgd',
              metrics=['accuracy'])

这样就可以在训练数据上训练模型了:

代码语言:javascript
复制
# x_train 和 y_train 是 Numpy 数组 -- 就像在 Scikit-Learn API 中一样。
model.fit(x_train, y_train, epochs=5, batch_size=32)

实战

代码语言:javascript
复制
#!/usr/bin/python
# -*- coding: UTF-8 -*-

from keras.datasets import imdb
import numpy as np
from keras import models
from keras import layers
import matplotlib.pyplot as plt


## 构建数据
(train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000)


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)

y_train = np.asarray(train_labels).astype('float32')
y_test = np.asarray(test_labels).astype('float32')

## 构建网络
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'])


x_val = x_train[:10000]
partial_x_train = x_train[10000:]
y_val = y_train[:10000]
partial_y_train = y_train[10000:]

## 训练模型
history = model.fit(partial_x_train,partial_y_train,epochs=20,
                    batch_size=512,
                    validation_data=(x_val, y_val))

## 显示训练数据
history_dict = history.history
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()

运行结果:

参考

Python enumerate() 函数 Keras 中文文档 深入学习Keras中Sequential模型及方法

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 目录
  • IMDB 数据集
    • 为什么区分训练集和测试集
    • Python enumerate() 函数
    • 下载数据
    • 构建数据
      • 二维列表使用方法
        • 填充数据为张量
        • 构建网络
        • Keras构建网络
          • Sequential 顺序模型
          • 实战
          • 参考
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档