• [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))
    

    训练集和验证集的损失值变化
    image
    训练集和验证集的准确率变化
    image
    模型在第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作为损失函数;
    • 如果分类数目过大,应该避免网络中间层数目过小(比分类数目小--信息压缩),产生信息瓶颈。
  • 相关阅读:
    9.5 dubbo事件通知机制
    9.4 dubbo异步调用原理
    13.1 dubbo服务降级源码解析
    第十八章 dubbo-monitor计数监控
    12.4 客户端响应解码
    12.3 服务端响应编码
    12.2 服务端请求解码
    12.1 客户端请求编码
    git生成并添加SSH key
    Java并发之原子操作类汇总
  • 原文地址:https://www.cnblogs.com/ysugyl/p/9312578.html
Copyright © 2020-2023  润新知