深度学习实战案例:新闻文本分类(代码片段)

尤尔小屋的猫 尤尔小屋的猫     2022-12-11     564

关键词:

深度学习多分类案例:新闻文本分类

公众号:机器学习杂货店
作者:Peter
编辑:Peter

大家好,我是Peter~

这里是机器学习杂货店 Machine Learning Grocery~

之前介绍过一个单分类的问题。当每个数据点可以划分到多个类别、多个标签下,这就是属于多分类问题了。

本文介绍一个基于深度学习的多分类实战案例:新闻文本分类,最终是有46个不同的类别

数据集

路透社数据集

广泛使用的文本分类数据集:46个不同的主题,即输出有46个类别。某些样本的主题更多,但是训练集中的每个主题至少有10个样本

加载数据集

也是内置的数据集

In [1]:

from keras.datasets import reuters

In [2]:

# 限制前10000个最常见的单词

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

In [3]:

# 查看数据
len(train_data)

Out[3]:

8982

In [4]:

len(test_data)

Out[4]:

2246

In [5]:

train_data.shape

Out[5]:

(8982,)

In [6]:

type(train_data)

Out[6]:

numpy.ndarray

索引解码为单词

In [7]:

word_index = reuters.get_word_index()

reverse_word_index = dict([(value, key) for (key, value) in word_index.items()])

In [8]:

decoded_newswire = ' '.join([reverse_word_index.get(i - 3, '?') for i in train_data[0]])
decoded_newswire

Out[8]:

'? ? ? said as a result of its december acquisition of space co it expects earnings per share in 1987 of 1 15 to 1 30 dlrs per share up from 70 cts in 1986 the company said pretax net should rise to nine to 10 mln dlrs from six mln dlrs in 1986 and rental operation revenues to 19 to 22 mln dlrs from 12 5 mln dlrs it said cash flow per share this year should be 2 50 to three dlrs reuter 3'

索引减去3是因为:012分别是为“padding填充”,“start of sequence(序列开始)”,"unknown(未知)"分别保留的索引

样本标签对应的是0-45范围内的整数:

In [9]:

train_labels[10]

Out[9]:

3

数据向量化

In [10]:

import numpy as np

def vectorize_sequences(sequences, dimension=10000):
    results = np.zeros((len(sequences), dimension)) # 创建全0矩阵
    
    for i, sequence in enumerate(sequences):  
        results[i, sequence] = 1.  # 指定位置填充1
    return results

# 训练数据和测试数据向量化
x_train = vectorize_sequences(train_data)
x_test = vectorize_sequences(test_data)

标签向量化-onehot

主要是有两种方法:

  • 将标签列表转成整数张量
  • one-hot编码,分类编码的一种

In [11]:

import numpy as np

def to_one_hot(labels, dimension=46):
    results = np.zeros((len(labels), dimension)) # 创建全0矩阵
    for i, label in enumerate(labels):  
        results[i, label] = 1.  # 指定位置填充1
    return results

# 训练标签和测试标签向量化
one_hot_train_label = to_one_hot(train_labels)
one_hot_test_label = to_one_hot(test_labels)

In [12]:

np.zeros((4,5))

Out[12]:

array([[0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.]])

Keras内置方法实现one-hot

In [13]:

from keras.utils.np_utils import to_categorical

one_hot_train_labels = to_categorical(train_labels)
one_hot_test_labels = to_categorical(test_labels)

建模

模型定义(修改)

In [14]:

import tensorflow as tf  # add
from keras import models
from keras import layers 

model = models.Sequential()

# 原文model.add(layers.Dense(16, activation="relu", input_shape=(10000, )))
# 统一修改3处内容:layers.Dense 变成 tf.keras.layers.Dense
model.add(tf.keras.layers.Dense(64,
                       activation="relu",
                       input_shape=(10000,)
                      ))
model.add(tf.keras.layers.Dense(64,
                       activation="relu"
                      ))
model.add(tf.keras.layers.Dense(46,
                      activation="softmax"
                      ))

注意两点:

  1. 网络的最后一层是大小为46的Dense层。意味着,对于每个输入样本,网络都会输出一个46维的向量,这个向量的每个元素代表不同的输出类型
  2. 最后一个使用的是softmax激活:网络将输出在46个不同类别上的概率分布,output[i]是样本属于第i个类别的概率,46个概率的总和是1

模型编译

多分类问题最好使用categorical_crossentropy作为损失函数。它用于衡量两个概率分布之间的距离:网络输出的概率分布和标签的真实概率分布

目标:这两个概率分布的距离最小化

In [15]:

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

验证模型-提取验证集

In [16]:

# 取出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训练网络

In [17]:

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

绘图

损失

In [20]:

# 损失绘图
import matplotlib.pyplot as plt

history_dict = history.history
loss_values = history_dict["loss"]
val_loss_values = history_dict["val_loss"]

epochs = range(1,len(loss_values) + 1)  

# 训练
plt.plot(epochs,  #  横坐标
         loss_values,  # 纵坐标
         "r",  # 颜色和形状,默认是实线
         label="Training_Loss"  # 标签名
        )
# 验证
plt.plot(epochs,
         val_loss_values,
         "b",
         label="Validation_Loss"
        )

plt.title("Training and Validation Loss")
plt.xlabel("Epochs")
plt.ylabel("Loss")
plt.legend()

plt.show()

精度(修改)

多分类问题中得到的是acc的全拼,而不是缩写

In [19]:

# 精度绘图
import matplotlib.pyplot as plt

history_dict = history.history
acc_values = history_dict["accuracy"]  # 修改:原文是acc ---> accuracy
val_acc_values = history_dict["val_accuracy"]   # val_acc ---> val_accuracy

epochs = range(1,len(loss_values) + 1)


plt.plot(epochs,
         acc_values,
         "r",
         label="Training_ACC"
        )

plt.plot(epochs,
         val_acc_values,
         "b",
         label="Validation_ACC"
        )

plt.title("Training and Validation ACC")
plt.xlabel("Epochs")
plt.ylabel("acc")
plt.legend()

plt.show()

重新训练

网路在训练9轮后开始过拟合,重新训练一个新网络:共9个轮次

In [25]:

import tensorflow as tf  # add
from keras import models
from keras import layers 

model = models.Sequential()
model.add(tf.keras.layers.Dense(64,
                                activation="relu",
                                input_shape=(10000, )
                               ))

model.add(tf.keras.layers.Dense(64,
                               activation="relu"))

model.add(tf.keras.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) 
results

这个模型的精度到达了78.6%。如果是随机的基准是多少呢?

In [26]:

import copy 

test_labels_copy = copy.copy(test_labels)
np.random.shuffle(test_labels_copy)

In [28]:

hist_array = np.array(test_labels) == np.array(test_labels_copy)

In [29]:

hist_array  # T或者F的元素

Out[29]:

array([False, False, False, ..., False,  True, False])

In [30]:

float(np.sum(hist_array)) / len(test_labels)

Out[30]:

0.18744434550311664

测试集验证

使用的是predict函数

In [31]:

predictions = model.predict(x_test)
predictions

Out[31]:

array([[1.35964816e-04, 5.63261092e-05, 1.82070780e-05, ...,
        1.30567923e-06, 1.98109021e-07, 6.60357784e-07],
       [4.93899640e-03, 4.66015842e-03, 1.14109996e-03, ...,
        1.06564505e-04, 3.91121466e-05, 9.38424782e-04],
       [1.59738748e-03, 7.79436469e-01, 1.73478038e-03, ...,
        1.25069331e-04, 1.86533769e-04, 1.70501284e-04],
       ...,
       [6.38374695e-05, 1.36295348e-04, 4.94179221e-05, ...,
        2.28828794e-05, 2.12488590e-06, 5.73998386e-06],
       [3.28431278e-03, 6.02599606e-02, 3.11069656e-03, ...,
        6.78190409e-05, 8.90388037e-05, 2.43265240e-04],
       [1.19820972e-04, 6.49809241e-01, 1.08765960e-02, ...,
        7.17515213e-05, 3.85396503e-04, 3.51801835e-04]], dtype=float32)

1、predictions中每个元素都是46维的向量:

In [32]:

# 每个元素都是46维的向量

predictions[0].shape

Out[32]:

(46,)

In [33]:

predictions[1].shape

Out[33]:

(46,)

In [34]:

predictions[50].shape

Out[34]:

(46,)

2、所有元素的和为1:

In [35]:

# 所有元素的和为1
sum(predictions[0])

Out[35]:

1.0000001240543241

3、最大元素就是预测的类别,也就是概率最大的类别:

In [36]:

np.argmax(predictions[0])

Out[36]:

3

In [37]:

np.argmax(predictions[4])

Out[37]:

13

换种方式处理标签和损失

In [38]:

# 方式1:转换为整数张量

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

使用的损失函数categorical_crossentropy,标签遵循分类编码。

如果是整数标签,使用sparse_categorical_crossentropy:

In [39]:

model.compile(optimizer="rmsprop",
               loss="sparse_categorical_crossentropy",  # 损失函数
               metrics=["accuracy"]
              )

中间层维度足够大的重要性

最终输出是46维的,因此中间层的隐藏单个数不应该比46小太多。如果小太多,将会造成信息的丢失:

In [40]:

import tensorflow as tf  
from keras import models
from keras import layers 

model = models.Sequential()
model.add(tf.keras.layers.Dense(64,
                                activation="relu",
                                input_shape=(10000, )
                               ))

model.add(tf.keras.layers.Dense(4,  # 中间层从64---->4
                               activation="relu"))

model.add(tf.keras.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=512,
          validation_data=(x_val, y_val))

我们发现最终上升到了69.2%

进一步实验

  1. 尝试使用更多或者更少的隐藏单元,比如32或者128等
  2. 改变隐藏层个数,目前是2个;可以改成1个或者3个

小结

  1. 如果是对N个类别进行分类,最后一层应该是大小为N的Dense层
  2. 单标签多分类问题,网络的最后一层使用softmax激活,输出在N个输出类别上的概率分布
  3. 损失函数几乎都是分类交叉熵categorical_crossentropy。它将网络输出的概率分布和目标真实分布之间的距离最小化
  4. 避免使用太小的中间层,以免在网络中造成信息瓶颈。
  5. 处理多分类的标签方法:
    • 分类编码:one-hot编码,然后使用categorical_crossentropy
    • 将标签编码为整数,然后使用sparse_categorical_crossentropy

keras深度学习实战——新闻文本分类(代码片段)

Keras深度学习实战(9)——新闻文本分类0.前言1.新闻文本分类任务与神经网络模型分析1.1数据集1.2神经网络模型2.使用神经网络进行新闻文本分类小结系列链接0.前言在先前的应用实战中,我们分析了结构化的数据集&... 查看详情

深度学习100例|第43天:文本卷积神经网络(textcnn)新闻文本分类实战(代码片段)

...9;本文作者:微学AI、K同学啊🥇精选专栏:《深度学习100例》🔥推荐专栏:《新手入门深度学习》📚选自专栏:《Matplotlib教程》🧿优秀专栏:《Python入门100题》大家好,我是K同学啊!... 查看详情

深度学习实战案例:电影评论二分类(代码片段)

第一个深度学习实战案例:电影评论分类公众号:机器学习杂货店作者:Peter编辑:Peter大家好,我是Peter~这里是机器学习杂货店MachineLearningGrocery~本文的案例讲解的是机器学习中一个重要问题:分类问题。... 查看详情

nlp——天池新闻文本分类task4:fasttext深度学习(代码片段)

NLP——新闻文本分类:TASK3深度学习FasttextFasttext是一种深度学习词向量的表示方法,它是一种三层神经网络,包含输入层,隐含层和输出层。模型架构:fastText模型输入一个词的序列(一段文本或者一句话),输出这个词序列属于... 查看详情

datawhale-新闻文本分类-task4-基于深度学习的文本分类1-fasttext(代码片段)

1.fasttext参数含义-input#trainingfilepath(required)训练文件路径(必须)<br>-lr#learningrate[0.1]学习率default0.1<br>-dim#sizeofwordvectors[100]词向量维度default100<br>-ws#sizeofthecontextwindow[5]上下文窗口大小d 查看详情

毕业设计之---新闻分类系统(代码片段)

...自然语言分类,可以使用机器学习算法去处理,也可以使用深度学习算法去处理.基本步骤如下:文本数据采集-->选择训练算法(机器学习/深度学习)-->进行训练-->检效果.本文章博主将介绍:从头开始实践中文短文本分类运用多种... 查看详情

毕业设计之---新闻分类系统(代码片段)

...自然语言分类,可以使用机器学习算法去处理,也可以使用深度学习算法去处理.基本步骤如下:文本数据采集-->选择训练算法(机器学习/深度学习)-->进行训练-->检效果.本文章博主将介绍:从头开始实践中文短文本分类运用多种... 查看详情

深度学习100例|第33天:迁移学习-实战案例教程(必须掌握的一个点)(代码片段)

我的知乎我的微信公众号我的CSDN下载本文源码+数据需要帮助.Ctrl+D:收藏本页面在本教程中,你将学习如何使用迁移学习通过预训练网络对猫和狗的图像进行分类。预训练模型是一个之前基于大型数据集(通常... 查看详情

seaborn实战案例|绘制分类条形统计图(代码片段)

...1a;python3🚩作者:K同学啊🥇精选专栏:《深度学习100例》🔥推荐专栏:《新手入门深度学习》📚选自专栏:《Matplotlib教程》🧿优秀专栏:《Python入门100题》plt.figure(figsiz 查看详情

《自然语言处理实战入门》深度学习----预训练模型的使用(albert进行多标签文本分类与微调finetune)(代码片段)

文章大纲环境构建关键点数据预处理模型微调、评估、预测keras模型结构训练微调模型保存与再次载入模型预测参考文献如何使用预训练模型进行文本分类以及下游任务的微调呢?其实挺简单的,CPU+大内存(16G及以上)也能跑,... 查看详情

keras深度学习实战(30)——使用文本生成模型进行文学创作(代码片段)

Keras深度学习实战(30)——使用文本生成模型进行文学创作0.前言1.文本生成模型与数据集分析1.1数据集分析1.2模型分析2.构建文本生成模型2.1数据预处理2.2模型构建与训练小结系列链接0.前言在情感分类任务中,神经... 查看详情

keras深度学习实战(39)——音乐音频分类(代码片段)

Keras深度学习实战(39)——音乐音频分类0.前言1.数据集与模型分析1.1数据集分析1.2模型分析2.歌曲流派分类模型2.1数据加载与预处理2.2模型构建与训练3.聚类分析小结系列链接0.前言音乐音频分类技术能够基于音乐内容为... 查看详情

跟着chatgpt学深度学习chatgpt教我文本分类(代码片段)

...相关,读研读博相关......)👈【跟着ChatGPT学深度学习】ChatGPT教我文本分类ChatGPT既然无所不能,我为啥不干脆拜他为师,直接向他学习,岂不是妙哉。说干就干,我马上就让ChatGPT给我生成了一段文本... 查看详情

《自然语言处理实战入门》深度学习----预训练模型的使用(albert进行多标签文本分类与cpu下的微调finetune)(代码片段)

文章大纲环境构建关键点数据预处理模型微调、评估、预测keras模型结构训练微调模型保存与再次载入模型预测参考文献如何使用预训练模型进行文本分类以及下游任务的微调呢?其实挺简单的,CPU+大内存(16G及以上)也能跑,... 查看详情

keras深度学习实战——基于vgg19模型实现性别分类(代码片段)

Keras深度学习实战——基于VGG19模型实现性别分类0.前言1.VGG19架构简介2.使用预训练VGG19模型进行性别分类2.1构建输入与输出数据2.2模型构建与训练2.3模型错误分类示例相关链接0.前言在《迁移学习》中,我们了解了利用迁移学... 查看详情

keras深度学习实战——基于inceptionv3实现性别分类(代码片段)

Keras深度学习实战——基于Inceptionv3实现性别分类0.前言1.Inception结构1.1Inceptionv1损失函数1.2Inceptionv2和Inceptionv32.使用预训练的Inceptionv3模型实现性别分类2.1模型实现2.2错误分类的图片示例相关链接0.前言我们已经学习了基于VGG16和VG... 查看详情

机器学习实战教程:朴素贝叶斯实战篇之新浪新闻分类(代码片段)

.../cuijiahua.com/blog/2017/11/ml_5_bayes_2.html一、前言上篇文章机器学习实战教程(四):朴素贝叶斯基础篇之言论过滤器讲解了朴素贝叶斯的基础知识。本篇文章将在此基础上进行扩展,你将看到以下内容:拉普拉斯平滑垃圾邮件过滤(Py... 查看详情

keras深度学习实战——基于resnet模型实现性别分类(代码片段)

Keras深度学习实战——基于ResNet模型实现性别分类0.前言1.ResNet架构简介2.基于预训练的ResNet50模型实现性别分类2.1训练性别分类模型2.2错误分类图像示例相关链接0.前言从VGG16到VGG19,最显著的变化在于网络层数的增加,通... 查看详情