路透社数据集——新闻主题多分类

编程入门 行业动态 更新时间:2024-10-27 23:17:21

<a href=https://www.elefans.com/category/jswz/34/1696273.html style=路透社数据集——新闻主题多分类"/>

路透社数据集——新闻主题多分类

文章目录

      • 1.数据集及问题简介
      • 2.加载数据集并探索数据
      • 3.准备输入的数据
      • 4.构建网络
      • 5.编译网络
      • 6.从训练集中留出验证集
      • 7.训练模型
      • 8.画出训练数据
      • 9.根据训练数据,重新训练模型并测试
      • 10.使用训练好的网络在新数据上生成预测结果
      • 总结

1.数据集及问题简介

路透社数据集(Reuter),它包含许多短新闻及其对应的主题,由路透社在1986 年发布。它是一个简单的、广泛使用的文本分类数据集。它包括46 个不同的主题:某些主题的样本更多,但训练集中每个主题都有至少10 个样本。与IMDB 和MNIST 类似,路透社数据集也内置为Keras 的一部分。

我们需要将路透社新闻划分为46 个互斥的主题。因为有多个类别,所以这是多分类(multiclass classification)问题的一个例子。因为每个数据点只能划分到一个类别,所以更具体地说,这是单标签、多分类(single-label, multiclass classification)问题的一个例子。如果每个数据点可以划分到多个类别(主题),那它就是一个多标签、多分类(multilabel,multiclass classification)问题。

2.加载数据集并探索数据

from keras.datasets import reuters(train_data, train_labels), (test_data, test_labels) = reuters.load_data(num_words=10000)print(len(train_data)) #8982
print(len(test_data)) #2246
print(train_data[10])
print(train_labels[10]) # 3

与IMDB 数据集一样,参数num_words=10000 将数据限定为前10 000 个最常出现的单词。我们有8982 个训练样本和2246 个测试样本。与IMDB 评论一样,每个样本都是一个整数列表(表示单词索引)。样本对应的标签是一个0~45 范围内的整数,即话题索引编号。

我们可以用下列代码将索引解码为单词。

word_index = reuters.get_word_index()
reverse_word_index = dict([(value, key) for (key, value) in word_index.items()])
# Note that our indices were offset by 3
# because 0, 1 and 2 are reserved indices for "padding", "start of sequence", and "unknown".
decoded_newswire = ' '.join([reverse_word_index.get(i - 3, '?') for i in train_data[0]])

3.准备输入的数据

import numpy as npdef to_one_hot(labels, dimension=46):results = np.zeros((len(labels), dimension))for i, label in enumerate(labels):results[i, label] = 1.return results# Our vectorized training labels
one_hot_train_labels = to_one_hot(train_labels)
# Our vectorized test labels
one_hot_test_labels = to_one_hot(test_labels)

Keras 内置方法也可以实现这个操作。

from keras.utils.np_utils import to_categoricalone_hot_train_labels = to_categorical(train_labels)
one_hot_test_labels = to_categorical(test_labels)

4.构建网络

这个主题分类问题与前面的电影评论分类问题类似,两个例子都是试图对简短的文本片段进行分类。但这个问题有一个新的约束条件:输出类别的数量从2 个变为46 个。输出空间的维度要大得多。对于前面用过的Dense 层的堆叠,每层只能访问上一层输出的信息。如果某一层丢失了与分类问题相关的一些信息,那么这些信息无法被后面的层找回,也就是说,每一层都可能成为信息瓶颈。上一个例子使用了16 维的中间层,但对这个例子来说16 维空间可能太小了,无法学会区分46 个不同的类别。这种维度较小的层可能成为信息瓶颈,永久地丢失相关信息。出于这个原因,下面将使用维度更大的层,包含64 个单元。

from keras import models
from keras import layersmodel = 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 的 Dense 层。这意味着,对于每个输入样本,网络都会输出一个46 维向量。这个向量的每个元素(即每个维度)代表不同的输出类别。
  • 最后一层使用了 softmax 激活,网络将输出在 46个不同输出类别上的概率分布——对于每一个输入样本,网络都会输出一个46 维向量,其中output[i] 是样本属于第i 个类别的概率。46 个概率的总和为1。对于这个例子,最好的损失函数是categorical_crossentropy(分类交叉熵)。它用于衡量两个概率分布之间的距离,这里两个概率分布分别是网络输出的概率分布和标签的真实分布。通过将这两个分布的距离最小化,训练网络可使输出结果尽可能接近真实标签。

5.编译网络

modelpile(optimizer='rmsprop',loss='categorical_crossentropy',metrics=['accuracy'])

6.从训练集中留出验证集

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

7.训练模型

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

8.画出训练数据

import matplotlib.pyplot as plt
%matplotlib inlineloss = history.history['loss']
val_loss = history.history['val_loss']epochs = range(1, len(loss) + 1)plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()plt.show()

plt.clf()   # clear figureacc = history.history['accuracy']
val_acc = history.history['val_accuracy']plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()plt.show()

9.根据训练数据,重新训练模型并测试

网络在训练9 轮后开始过拟合。我们从头开始训练一个新网络,共9 个轮次,然后在测试集上评估模型。

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'))
modelpile(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)results 

[1.006295904344676, 0.7849510312080383]

这种方法可以得到约80% 的精度。对于平衡的二分类问题,完全随机的分类器能够得到50% 的精度。但在这个例子中,完全随机的精度约为19%,所以上述结果相当不错,至少和随机的基准比起来还不错。

import copy
#【完全随机】
test_labels_copy = copy.copy(test_labels)
np.random.shuffle(test_labels_copy)
float(np.sum(np.array(test_labels) == np.array(test_labels_copy))) / len(test_labels)

0.18432769367764915

10.使用训练好的网络在新数据上生成预测结果

predictions = model.predict(x_test)
print(predictions[0].shape) #(46,)
print(np.sum(predictions[0])) #0.99999994
print(np.argmax(predictions[0])) #3

总结

  • 如果要对 N个类别的数据点进行分类,网络的最后一层应该是大小为N的Dense层。
  • 对于单标签、多分类问题,网络的最后一层应该使用softmax 激活,这样可以输出在N个输出类别上的概率分布。
  • 这种问题的损失函数几乎总是应该使用分类交叉熵。它将网络输出的概率分布与目标的真实分布之间的距离最小化。
  • 处理多分类问题的标签有两种方法。
  • 通过分类编码(也叫 one-hot 编码)对标签进行编码,然后使用 categorical_crossentropy作为损失函数。
  • 将标签编码为整数,然后使用 sparse_categorical_crossentropy损失函数。
  • 如果你需要将数据划分到许多类别中,应该避免使用太小的中间层,以免在网络中造成信息瓶颈。

更多推荐

路透社数据集——新闻主题多分类

本文发布于:2024-02-17 14:13:24,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1694278.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:路透社   数据   主题   新闻

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!