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

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

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

路透社数据集

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

加载数据集

from keras.datasets import reuters

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

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

>>> 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]

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

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数据集处理方法相同。

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。

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编码转换函数:

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

网络定义

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---衡量两个概率分布之间的距离:网络的输出向量和标签的真实分布向量。通过最小化两个分布之间的距离,训练网络模型,使得输出向量尽可能与真实分布相似。

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

模型验证

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

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

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

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

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

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

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维的概率分布。在测试数据上进行预测:

predictions = model.predict(x_test)

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

np.argmax(predictions[0])#第一条新闻的预测类 4

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

直接将列表转换成numpy数组

y_train = np.array(train_labels)
y_test = np.array(test_labels)

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

model.compile(optimizer='rmsprop',loss='sparse_categorical_crossentropy',metrics=['acc'])

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

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

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

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作为损失函数;
  • 如果分类数目过大,应该避免网络中间层数目过小(比分类数目小--信息压缩),产生信息瓶颈。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏瓜大三哥

matlab神经网络1

神经网络的通用函数 一、神经网络仿真函数 [Y,Pf,Af,E,Perf]=sim(net,P,Pi,Ai,T) 其中,参数Y为网络的输出;Pf表示最终的输入延...

25880
来自专栏null的专栏

机器学习算法实践——K-Means算法与图像分割

一、理论准备 1.1、图像分割 图像分割是图像处理中的一种方法,图像分割是指将一幅图像分解成若干互不相交区域的集合,其实质可以看成是一种像素的聚类过程。通常使用...

77660
来自专栏智能算法

KNN最近邻算法及其Python实现

k-NN是一种基本的分类和回归方法,用于分类时,算法思路较简单:通过计算不同特征之间的距离方法来得到最近的k个训练实例,根据k个实例的类别采用多数表决等方式进...

1K70
来自专栏Small Code

【TensorFlow】学习率、迭代次数和初始化方式对准确率的影响

想必学过机器学习的人都知道,学习率、训练迭代次数和模型参数的初始化方式都对模型最后的准确率有一定的影响,那么影响到底有多大呢? 我初步做了个实验,在 Tenso...

51180

Keras中神经网络模型的5阶段生命周期

使用Python的Keras库可以很容易创建和评测深度学习神经网络,但是您必须遵循严格的模型生命周期。

35190
来自专栏机器学习从入门到成神

机器学习之深入理解K-means、与KNN算法区别及其代码实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sinat_35512245/articl...

1K10
来自专栏企鹅号快讯

matlab神经网络1

神经网络的通用函数一、神经网络仿真函数 [Y,Pf,Af,E,Perf]=sim(net,P,Pi,Ai,T) 其中,参数Y为网络的输出;Pf表示最终的输入延时...

36950
来自专栏机器学习算法工程师

SSD源码解析

- SSD理论总结(SSD: Single Shot MultiBox Detector)

71340
来自专栏Petrichor的专栏

深度学习: greedy layer-wise pre-training (逐层贪婪预训练)

每次只训练网络中的一层,即我们首先训练一个只含一个隐藏层的网络,仅当这层网络训练结束之后才开始训练一个有两个隐藏层的网络,以此类推。

37030
来自专栏LhWorld哥陪你聊算法

【TensorFlow篇】--DNN初始和应用

正向传播:在开始的每一层上都有一个参数值w,初始的时候是随机的,前向带入的是每一个样本值。

15920

扫码关注云+社区

领取腾讯云代金券