深度学习:将新闻报道按照不一样话题性质进行分类

深度学习的普遍运用之一就是对文本按照其内容进行分类。例如对新闻报道根据其性质进行划分是常见的应用领域。在本节,咱们要把路透社自1986年以来的新闻数据按照46个不一样话题进行划分。网络通过训练后,它可以分析一篇新闻稿,而后按照其报道内容,将其纳入到设定好的46个话题之一。深度学习在这方面的应用属于典型的“单标签,多类别划分”的文本分类应用。微信

咱们这里采用的数据集来自于路透社1986年以来的报道,数据中每一篇新闻稿附带一个话题标签,以用于网络训练,每个话题至少含有10篇文章,某些报道它内容很明显属于给定话题,有些报道会模棱两可,很差肯定它到底属于哪种类的话题,咱们先把数据加载到机器里,代码以下:网络

from keras.datasets import reuters
(train_data, train_label), (test_data, test_labels) = reuters.load_data(num_words=10000)

keras框架直接附带了相关数据集,经过执行上面代码就能够将数据下载下来。上面代码运行后结果以下:

从上面运行结果看,它总共有8982条训练数据和2246条测试数据。跟咱们上节数据类型同样,数据里面对应的是每一个单词的频率编号,咱们能够经过上一节相似的代码,将编号对应的单词从字典中抽取出来结合成一篇文章,代码以下:框架

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]])
print(decoded_newswire)

上面代码运行后结果以下:
函数

如同上一节,咱们必需要把训练数据转换成数据向量才能提供给网络进行训练,所以咱们像上一节同样,对每条新闻建立一个长度为一万的向量,先把元素都初始为0,而后若是某个对应频率的词在文本中出现,那么咱们就在向量中相应下标设置为1,代码以下:学习

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)

print(x_train[0])

上面代码运行后,咱们就把训练数据变成含有1或0的向量了:测试

其实咱们能够直接调用keras框架提供的接口一次性方便简单的完成:lua

from keras.utils.np_utils import to_categorical

one_hot_train_labels = to_categorical(train_label)
one_hot_test_labels = to_categorical(test_labels)

接下来咱们能够着手构建分析网络,网络的结构与上节很像,由于要解决的问题性质差很少,都是对文本进行分析。然而有一个重大不一样在于,上一节咱们只让网络将文本划分红两种类别,而此次咱们须要将文本划分为46个类别!上一节咱们构造网络时,中间层网络咱们设置了16个神经元,因为如今咱们须要在最外层输出46个结果,所以中间层若是只设置16个神经元那就不够用,因为输出的信息太多,若是中间层神经元数量不足,那么他就会成为信息过滤的瓶颈,所以此次咱们搭建网络时,中间层网络节点扩大为6个,代码以下:spa

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'))
#当结果是输出多个分类的几率时,用softmax激活函数,它将为46个分类提供不一样的可能性几率值
model.add(layers.Dense(46, activation='softmax'))

#对于输出多个分类结果,最好的损失函数是categorical_crossentropy
model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])

像上一节同样,在网络训练时咱们要设置校验数据集,由于网络并非训练得次数越多越好,有了校验数据集,咱们就知道网络在训练几回的状况下可以达到最优状态,准备校验数据集的代码以下:.net

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

有了数据,就至关于有米入锅,咱们能够把数据输入网络进行训练:

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

代码进行了20个周期的循环训练,因为数据量比上一节小,所以速度快不少,与上一节同样,网络的训练并非越多越好,它会有一个拐点,训练次数超出后,效果会愈来愈差,咱们把训练数据图形化,以便观察拐点从哪里开始:

import matplotlib.pyplot as plt
loss = 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.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()

plt.show()

上面代码运行后结果以下:

经过上图观察咱们看到,以蓝点表示的是网络对训练数据的判断准确率,该准确率一直在不断降低,可是蓝线表示的是网络对校验数据判断的准确率,仔细观察发现,它一开始是迅速降低的,过了某个点,达到最低点后就开始上升,这个点大概是在epochs=9那里,因此咱们把前面对网络训练的循环次数减小到9:

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'))
#当结果是输出多个分类的几率时,用softmax激活函数,它将为46个分类提供不一样的可能性几率值
model.add(layers.Dense(46, activation='softmax'))

#对于输出多个分类结果,最好的损失函数是categorical_crossentropy
model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])

history = 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)
print(results)

上面两句代码运行结果为:

右边0.78表示,咱们网络对新闻进行话题分类的准确率达到78%,差一点到80%。咱们从测试数据集中拿出一条数据,让网络进行分类,获得结果再与其对应的正确结果比较看看是否一致:

predictions = model.predict(x_test)
print(predictions[0])
print(np.sum(predictions[0]))
print(np.argmax(predictions[0]))
print(one_hot_test_labels[0])

咱们让网络对每一条测试数据一一进行判断,并把它对第一条数据的判断结果显示出来,最后咱们打印出第一条测试数据对应的分类,最后看看网络给出去的结果与正确结果是否一致,上面代码运行后结果以下:

从上面运行结果看到,网络对第一条数据给出了属于46个分类的几率,其中下标为3的几率值最大,也就是第一条数据属于分类4的几率最大,最后打印出来的测试数据对应的正确结果来看,它也是下标为3的元素值为1,也就是说数据对应的正确分类是4,由此咱们网络获得的结果是正确的。

前面提到过,因为网络最终输出结果包含46个元素,所以中间节点的神经元数目不能小于46,由于小于46,那么有关46个元素的信息就会遭到挤压,因而在层层运算后会致使信息丢失,最后导致最终结果的准确率降低,咱们试试看是否是这样:

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(4, activation='relu'))
#当结果是输出多个分类的几率时,用softmax激活函数,它将为46个分类提供不一样的可能性几率值
model.add(layers.Dense(46, activation='softmax'))

#对于输出多个分类结果,最好的损失函数是categorical_crossentropy
model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])

history = 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)
print(results)

上面代码运行后,输出的results结果以下:
[1.4625472680649796, 0.6705253784505788]

从上面结果看到,咱们代码几乎没变,导致把第二层中间层神经元数量改为4,最终结果的准确率就降低10个点,因此中间层神经元的减小致使信息压缩后,最后计算的准确度缺失。反过来你也能够试试用128个神经元的中间层看看准确率有没有提高。

到这里不知道你发现没有,神经网络在实际项目中的运用有点相似于乐高积木,你根据实际须要,经过选定参数,用几行代码配置好基本的网络结构,把训练数据改形成合适的数字向量,而后就能够输入到网络中进行训练,训练过程当中记得用校验数据监测最优训练次数,防止过分拟合。

在网络的设计过程当中,其背后的数学原理咱们几乎无需了解,只须要凭借经验,根据项目的性质,设定网络的各项参数,最关键的其实在根据项目数据性质对网络进行调优,例如网络设置几层好,每层几个神经元,用什么样的激活函数和损失函数等等,这些操做与技术无关,取决以我的经验,属于“艺术”的范畴。

更详细的讲解,请点击‘阅读原文’。



本文分享自微信公众号 - Coding迪斯尼(gh_c9f933e7765d)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。

相关文章
相关标签/搜索