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

深度学习的广泛运用之一就是对文本按照其内容进行分类。例如对新闻报道根据其性质进行划分是常见的应用领域。在本节,我们要把路透社自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框架提供的接口一次性方便简单的完成:

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个,代码如下:

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

像上一节一样,在网络训练时我们要设置校验数据集,因为网络并不是训练得次数越多越好,有了校验数据集,我们就知道网络在训练几次的情况下能够达到最优状态,准备校验数据集的代码如下:

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个神经元的中间层看看准确率有没有提升。

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

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

更详细的讲解和代码调试演示过程,请点击链接

更多技术信息,包括操作系统,编译器,面试算法,机器学习,人工智能,请关照我的公众号:


这里写图片描述
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容

  • 来到石磨村不久,我就近在北京成府小学二分校入学。 可能是老师看错了,把二多加了一横,我一下子从1年...
    王驰1960阅读 465评论 1 4
  • 文/艺莫 亲爱的我就是要这样宠着你 亲爱的让我亲亲你的眼 亲爱的外面冷,和我一起回家吧! 亲爱的不生气了,来我让我...
    艺莫阅读 279评论 0 2
  • 文/辛夏禾yuan 其实要真的说起来,我不算是一个特别能言善辩的姑娘,尤其是对父亲,有的时候便是连语言都显得有些格...
    辛夏禾yuan阅读 676评论 17 29