前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[Deep-Learning-with-Python]基于Kears的Reuters新闻分类

[Deep-Learning-with-Python]基于Kears的Reuters新闻分类

作者头像
用户1631856
发布2018-08-01 11:52:08
1.1K0
发布2018-08-01 11:52:08
举报
文章被收录于专栏:老秦求学老秦求学

Reuters数据集下载速度慢,可以在我的repo库中找到下载,下载后放到~/.keras/datasets/目录下,即可正常运行。

构建神经网络将路透社新闻分类,一共有46个类别。因为有多个类别,属于多分类问题,而每条数据只属于一个类别,所以是单标签多分类问题;如果每条数据可以被分到多个类别中,那问题则属于多标签多分类问题。 完整代码 欢迎Fork、Star

路透社数据集

Reuters数据集发布在1986年,一系列短新闻及对应话题的数据集;是文本分类问题最常用的小数据集。和IMDB、MNIST数据集类似,Reuters数据集也可以通过Keras直接下载。

加载数据集

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

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

有8982条训练集,2246条测试集。 每个样本表示成整数列表。

代码语言:javascript
复制
>>> train_data[10]
[1, 245, 273, 207, 156, 53, 74, 160, 26, 14, 46, 296, 26, 39, 74, 2979,
3554, 14, 46, 4689, 4329, 86, 61, 3499, 4795, 14, 61, 451, 4329, 17, 12]

也可以将整数列表转换成原始数据[英文句子]

代码语言:javascript
复制
word_index = reuters.get_word_index()# 单词--下标 对应字典
reverse_word_index = dict([(value, key) for (key, value) in word_index.items()])# 下标-单词对应字典

decoded_newswire = ' '.join([reverse_word_index.get(i - 3, '?') for i in
train_data[0]]) #偏移3个:0,1,2保留下标,分别表示:“padding,” “start of sequence,” and “unknown.”

准备数据

整数数据向量化,与IMDB数据集处理方法相同。

代码语言:javascript
复制
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)

标签的向量化有两种方法:将标签列表转换成整数张量;使用one-hot编码。One-hot编码方式是类别数据常用的一种数据格式,也称为categorical encoding。

代码语言:javascript
复制
def to_one_hot(labels, dimension=46):# 46个类别
    results = np.zeros((len(labels), dimension))
    for i, label in enumerate(labels):
        results[i, label] = 1.
    return results

one_hot_train_labels = to_one_hot(train_labels)
one_hot_test_labels = to_one_hot(test_labels)

Keras中有一个内置的One-hot编码转换函数:

代码语言:javascript
复制
from keras.utils.np_utils import to_categorical

one_hot_train_labels = to_categorical(train_labels)
one_hot_test_labels = to_categorical(test_labels)

模型搭建

使用Dense线性连接堆栈结构,每层网络只能处理上层网络的输出结果。如果网络层丢失了一些关于分类问题的信息,那么下一层网络并不能恢复这些信息:每个网络层潜在地成为一个信息处理瓶颈。

网络定义

代码语言:javascript
复制
from keras import models
from keras import layers

model = models.Sequential()
model.add(layers.Dense(64, activation='relu', input_shape=(10000,)))
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(46, activation='softmax'))

关于这个网络架构有两点需要注意:

  • 最后一层网络神经元数目为46.意味着每个输入样本最终变成46维的向量。输出向量的每个数表示不同的类别;
  • 最后一层网络使用softmax激活函数--网络会输出一个46类的概率分布。每个输入最终都会产生一个46维的向量,每个数表示属于该类别的概率,46个数加起来等于1.

最好的损失函数为categorical_crossentropy---衡量两个概率分布之间的距离:网络的输出向量和标签的真实分布向量。通过最小化两个分布之间的距离,训练网络模型,使得输出向量尽可能与真实分布相似。

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

模型验证

在训练数据中分出1000条样本做为验证集。

代码语言:javascript
复制
x_val = x_train[:1000]
partial_x_train = x_train[1000:]

y_val = one_hot_train_labels[:1000]
partial_y_train = one_hot_train_labels[1000:]

训练20个epochs

代码语言:javascript
复制
history = model.fit(partial_x_train,partial_y_train,epochs=20,batch_size=512,validation_data=(x_val, y_val))

训练集和验证集的损失值变化

image
image

训练集和验证集的准确率变化

image
image

模型在第9次epochs之后开始过拟合。我们将epochs设置为5重新训练,同时在测试集上测试。

代码语言:javascript
复制
model = models.Sequential()

model.add(layers.Dense(64, activation='relu', input_shape=(10000,)))
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(46, activation='softmax'))

model.compile(optimizer='rmsprop',loss='categorical_crossentropy',
metrics=['accuracy'])

model.fit(partial_x_train,partial_y_train,epochs=9,batch_size=512,
validation_data=(x_val, y_val))

results = model.evaluate(x_test, one_hot_test_labels)
# [0.9565213431445807, 0.79697239536954589] 损失值,准确率

准确率达到80%.比随机猜测好。

预测新数据

使用predict函数,产生一个46维的概率分布。在测试数据上进行预测:

代码语言:javascript
复制
predictions = model.predict(x_test)

在预测结果中概率最大的类别就是预测类:

代码语言:javascript
复制
np.argmax(predictions[0])#第一条新闻的预测类 4

另一种标签、损失函数处理方式

直接将列表转换成numpy数组

代码语言:javascript
复制
y_train = np.array(train_labels)
y_test = np.array(test_labels)

需要改变的是损失函数的选择。categorical_crossentropy损失函数期望标签数据使用categorical encoding编码方式。整数标签,应该使用sparse_categorical_crossentropy损失函数:

代码语言:javascript
复制
model.compile(optimizer='rmsprop',loss='sparse_categorical_crossentropy',metrics=['acc'])

新的损失函数在数学表示上与categorical_crossentropy损失函数相同,只是接口不同。

有充分大规模中间层的重要性

因为最终分为46类,中间层的神经元数目不应该小于46个。如果中间层数目小于46,有4个,将会产生信息瓶颈。

代码语言:javascript
复制
model = models.Sequential()

model.add(layers.Dense(64, activation='relu', input_shape=(10000,)))
model.add(layers.Dense(4, activation='relu'))
model.add(layers.Dense(46, activation='softmax'))
model.compile(optimizer='rmsprop',loss='categorical_crossentropy',metrics=['accuracy'])
model.fit(partial_x_train,partial_y_train,epochs=20,batch_size=128,validation_data=(x_val, y_val))

最终训练结果最高为71%,降低了8个百分点。主要原始是模型试图将大量的信息压缩到低纬度空间中表示,丢失了大量重要的信息。

小结

  • N分类问题,网络最后Dense层神经元数目为N;
  • 单标签多分类问题中,最后一层的激活函数为softmax,产生一个包含N类的概率分布;
  • categorical crossentropy是处理单标签多分类问题最常用的损失函数;
  • 在多分类问题中有两种标签处理方式:
    1. 使用categorical encoding(one-hot)编码,将标签one-hot化,同时使用categorical_crossentropy作为损失函数;
    2. 编码成整数向量,使用sparse_categorical_crossentropy作为损失函数;
  • 如果分类数目过大,应该避免网络中间层数目过小(比分类数目小--信息压缩),产生信息瓶颈。
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-07-15 ,如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 路透社数据集
  • 准备数据
    • 模型搭建
      • 模型验证
        • 预测新数据
          • 另一种标签、损失函数处理方式
            • 有充分大规模中间层的重要性
              • 小结
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档