所用环境为Colab.
定义任务目标
拿到一些新闻报道, 这些新闻报道都只属于某一个主题, 而不会同时属于多个主题. 把这些新闻报道归类到对应的主题下. 这是一个单标签多分类问题.
数据收集
使用 路透社 数据集.
|
|
数据可视化
建立对数据形状的感受.
|
|
看一下数据集里的数据到底长什么样子, 数据对应的标签是什么.
|
|
数据集里的评论被编码为了数字, 解码成正常文本看看.
|
|
解码出来的文本:
? ? ? 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
数据标注
已标注好
数据清理
无需清理
选择模型评估方法
评估方法选择
这里选择精度(accuracy)作为模型评估的指标. 精度, 即正确分类的新闻条数所占比例.
怎样用? 构建好模型后, 在模型编译阶段, 将model.compile()
的metrics
参数值设定为["accuracy"]
确定简单基准(模型应能超越这个基准)
如果为一条新闻随机指定分类, 能分类正确的概率理论上为$\frac{1}{46} \approx 2.17%$, 因此建立的模型的分类正确率应该超过该值.
对一批数据进行随机分类, 分类正确的比例是多少? 计算一下:
|
|
把标签随机打乱, 和原来的标签进行比较, 得到分类正确的比率为17.32%, 因此, 建立的模型的正确率应超过该值.
数据预处理
数据向量化和规范化
数据向量化
对文本列表进行multi-hot编码, 将其转换为由0和1组成的向量. 把每条新闻都转换为一个10000维向量, 如果一个单词在该评论里出现, 就把该单词的索引(单词对应的那个整数)对应位置的元素设为1.
|
|
标签向量化和规范化
使用one-hot编码(也叫 分类编码 categorical encoding)将标签向量化, 即将每个标签表示为维数为标签总类别数(标签一共有46个类别, 则向量的维数就是46)的向量. 该向量的值的特点: 标签索引对应的元素为1, 其余元素均设为0.
|
|
处理后
|
|
处理缺失值
不需要处理缺失值.
数据划分: 训练集, 验证集, 测试集
从训练集中分出一部分作为验证集.
|
|
构建第一个模型
特征选择(过滤没有信息量的特征; 开发新特征)
在本例中特征就是新闻里编码后的单词了.
选择架构
两个中间层, 每层64个单元. 第三层输出预测值.
层1: Dense层, “表示空间"的维数units
为64
, 激活函数activation
为relu
.
层2: Dense层, “表示空间"的维数units
为64
, 激活函数activation
为relu
.
层3: Dense层, “表示空间"的维数units
为46
, 激活函数activation
为softmax
. 输出是一个数组, 数组元素为46个概率值(总和为1), 表示样本目标值等于各类别的可能性.
训练配置(损失函数, 批量大小, 学习率)
优化器 optimizer
这里选rmsprop
损失函数 loss function
这里选分类交叉熵损失函数categorical_crossentropy
训练轮数
这里训练20轮.
数据批量大小
批量大小设为512.
模型构建代码
|
|
拟合模型
|
|
输出:
Epoch 1/20
16/16 [==============================] - 3s 94ms/step - loss: 2.7054 - accuracy: 0.5150 - val_loss: 1.8234 - val_accuracy: 0.6300
Epoch 2/20
16/16 [==============================] - 1s 58ms/step - loss: 1.5491 - accuracy: 0.6840 - val_loss: 1.4136 - val_accuracy: 0.7010
Epoch 3/20
16/16 [==============================] - 1s 59ms/step - loss: 1.2007 - accuracy: 0.7417 - val_loss: 1.2068 - val_accuracy: 0.7470
Epoch 4/20
16/16 [==============================] - 1s 58ms/step - loss: 0.9851 - accuracy: 0.7928 - val_loss: 1.1092 - val_accuracy: 0.7520
Epoch 5/20
16/16 [==============================] - 1s 58ms/step - loss: 0.8261 - accuracy: 0.8235 - val_loss: 1.0294 - val_accuracy: 0.7940
Epoch 6/20
16/16 [==============================] - 1s 59ms/step - loss: 0.6971 - accuracy: 0.8502 - val_loss: 0.9827 - val_accuracy: 0.7970
Epoch 7/20
16/16 [==============================] - 1s 59ms/step - loss: 0.5887 - accuracy: 0.8711 - val_loss: 0.9479 - val_accuracy: 0.8000
Epoch 8/20
16/16 [==============================] - 1s 79ms/step - loss: 0.4959 - accuracy: 0.8925 - val_loss: 0.9140 - val_accuracy: 0.8050
Epoch 9/20
16/16 [==============================] - 2s 100ms/step - loss: 0.4289 - accuracy: 0.9053 - val_loss: 0.8881 - val_accuracy: 0.8160
Epoch 10/20
16/16 [==============================] - 1s 77ms/step - loss: 0.3663 - accuracy: 0.9182 - val_loss: 0.8877 - val_accuracy: 0.8250
Epoch 11/20
16/16 [==============================] - 1s 55ms/step - loss: 0.3154 - accuracy: 0.9305 - val_loss: 0.8755 - val_accuracy: 0.8110
Epoch 12/20
16/16 [==============================] - 1s 56ms/step - loss: 0.2739 - accuracy: 0.9361 - val_loss: 0.8825 - val_accuracy: 0.8140
Epoch 13/20
16/16 [==============================] - 1s 60ms/step - loss: 0.2457 - accuracy: 0.9430 - val_loss: 0.9108 - val_accuracy: 0.8180
Epoch 14/20
16/16 [==============================] - 1s 58ms/step - loss: 0.2229 - accuracy: 0.9469 - val_loss: 0.8906 - val_accuracy: 0.8170
Epoch 15/20
16/16 [==============================] - 1s 54ms/step - loss: 0.1983 - accuracy: 0.9499 - val_loss: 0.9395 - val_accuracy: 0.8050
Epoch 16/20
16/16 [==============================] - 1s 54ms/step - loss: 0.1820 - accuracy: 0.9534 - val_loss: 0.9114 - val_accuracy: 0.8170
Epoch 17/20
16/16 [==============================] - 1s 55ms/step - loss: 0.1712 - accuracy: 0.9531 - val_loss: 0.9610 - val_accuracy: 0.8070
Epoch 18/20
16/16 [==============================] - 1s 53ms/step - loss: 0.1546 - accuracy: 0.9550 - val_loss: 0.9263 - val_accuracy: 0.8180
Epoch 19/20
16/16 [==============================] - 1s 65ms/step - loss: 0.1473 - accuracy: 0.9557 - val_loss: 0.9865 - val_accuracy: 0.7990
Epoch 20/20
16/16 [==============================] - 1s 52ms/step - loss: 0.1391 - accuracy: 0.9562 - val_loss: 0.9480 - val_accuracy: 0.8160
可以看到, 训练了20轮后, 虽然在训练集上的精度达到了0.9480
, 但在验证集上, 精度却只有0.8160
.
|
|
可视化拟合结果
绘制训练损失和验证损失
|
|
绘制训练精度和验证精度
|
|
从图中看出, 模型在训练到第9轮后, 开始出现过拟合的现象.
改进模型
让模型在训练9轮后停止
因为模型在训练到第9轮后就开始过拟合, 因此让模型训练9轮, 之后再次评估模型.
|
|
评价模型
前面选择精度(accuracy)作为模型评估的指标, 因此在对模型效果进行评价时, 使用模型在整个测试集上的平均精度.
|
|
可以看到, 模型在测试集上的精度为0.7916, 相比于基准精度而言, 表明建立的模型确实是有效果的.
利用模型进行预测
拿到一条评论, 对它像在上面那样把它编码为一个由0和1组成的向量, 然后用model.predict()
进行预测.
|
|
部署模型
不部署.