在《XGBoost与神经网络谁更牛?》文章,基于相同数据,对XGBoost和神经网络(NN)两种方法进行横行比较。XGBoost是属于Tree Model,只把分类特征进行数字化。对神经网络(NN)先把分类特征数值化,然后转换为One-hot。结果两个算法的测试结果(损失值)如下:
表3-1两种不同算法测试结果

《XGBoost与神经网络谁更牛?》基于相同数据集用不同算法进行比较,本章将从纵向进行比较,即基于相同数据集,相同算法(都是神经网络NN),但特征处理方式不同。一种是《XGBoost与神经网络谁更牛?》的方法,另外一种对分类特征采用Embedding方法,把分类特征转换为向量,并且这些向量的值会随着模型的迭代而自动更新。这两种方法比较的结果如表3-2所示:
表3-2 同一算法不同特征处理方式的测试结果

训练及测试数据没有打乱,其中测试数据是最新原数据的10%。
从表3-2可以看出,使用EE处理分类特征的方法性能远好于不使用EE的神经网络,使用EE有利于充分发挥NN的潜能,提升NN在实现传统机器学习任务的性能。
EE处理方法为何能大大提升模型的性能?使用EE处理特征有哪些优势,Embedding方法是否还适合于处理其它特征?如连续特征、时许特征、图(graph)特征等。这些问题后续将陆续进行说明。接下来我们将用Keras或TensorFlow的Embeding层处理分类特征。

3.1 Embedding简介

神经网络、深度学习的应用越来越广泛,从计算机视觉到自然语言处理和时间序列预测。在这些领域都取得不错成绩,有很多落地项目性能已超过人的平均水平。不但有较好的性能,特征工程方面更是实现了特征工程的自动化。
特征工程是传统机器学习的核心任务,模型性能如何很大程度取决特征工程处理方法,由此,要得到理想的特征工程往往需要很多业务和技术方面的技巧,因此有“特征工程是一门艺术”的说法,这也从一个侧面说明特征工程的门槛比较高,不利于普及和推广。不过这种情况,近些年正在改变。为了解决这一大瓶颈,人们开始使用神经网络或深度学习方法处理传统机器学习任务,特征工程方法使用Embedding 方法,把离散变量转变为较低维的向量,通过这种方式,我们可以将神经网络,深度学习用于更广泛的领域。
目前Embedding已广泛使用在自然语言处理(NLP)、结构化数据、图形数据等处理方面。在NLP 中常用的 Word Embedding ,对结构化数据使用 Entity Embedding,对图形数据采用Graph Embedding。这些内容后续我们将陆续介绍。这里先介绍如何用keras或TensorFlow实现分类特征的Embedding。

3.1.1 Keras.Embedding格式

keras的Embedding层格式如下:

Keras提供了一个嵌入层(Embedding layer),可用于处理文本数据、分类数据等的神经网络。它要求输入数据进行整数编码,以便每个单词或类别由唯一的整数表示。嵌入层使用随机权重初始化,并将学习所有数据集中词或类别的表示。这层只能作为模型的第1层。
【参数说明】
 input_dim: int > 0。词汇表大小或类别总数, 即,最大整数索引(index) + 1。
 output_dim: int >= 0。词向量的维度。
 embeddings_initializer: embeddings 矩阵的初始化方法 (详见 https://keras.io/initializers/)。
 embeddings_regularizer: embeddings matrix 的正则化方法
(详见https://keras.io/regularizers/)。
 embeddings_constraint: embeddings matrix 的约束函数 (详见 https://keras.io/constraints/)。
 mask_zero: 是否把 0 看作为一个应该被遮蔽的特殊的 "padding" 值。这对于可变长的循环神经网络层十分有用。 如果设定为 True,那么接下来的所有层都必须支持 masking,否则就会抛出异常。 如果 mask_zero 为 True,作为结果,索引 0 就不能被用于词汇表中 (input_dim 应该与 vocabulary + 1 大小相同)。
 input_length: 输入序列的长度,当它是固定的时。 如果你需要连接 Flatten 和 Dense 层,则这个参数是必须的 (没有它,dense 层的输出尺寸就无法计算)。
 输入尺寸
尺寸为 (batch_size, sequence_length) 的 2D 张量。
 输出尺寸
尺寸为 (batch_size, sequence_length, output_dim) 的 3D 张量。
更多信息可参考官网:
https://keras.io/layers/embeddings/
https://keras.io/zh/layers/embeddings/(中文)
假设定义一个词汇量为200的嵌入层的整数编码单词,将词嵌入到32维的向量空间,每次输入50个单词的输入文档,那么对应的embedding可写成如下格式:

为更好理解Keras的Embedding层的使用,下面列举几个具体实例。
(1)简单实例代码:

(2)用Embedding学习文本表示实例
假设有10个文本文档,每个文档都有一个学生提交的工作评论。每个文本文档被分类为正的“1”或负的“0”。这是一个简单的情感分析问题。用Keras的Embedding学习这10个文本的表示,具体实现代码如下;
#导入需要的模块

运行结果如下:
把文本转换为整数
[[49, 28], [33, 36], [21, 41], [18, 36], [32], [29], [18, 41], [30, 33], [18, 36], [43, 17, 28, 34]]
填充向量
[[49 28 0 0]
[33 36 0 0]
[21 41 0 0]
[18 36 0 0]
[32 0 0 0]
[29 0 0 0]
[18 41 0 0]
[30 33 0 0]
[18 36 0 0]
[43 17 28 34]]
查看模型结构
Model: "sequential_5"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
embedding_5 (Embedding) (None, 4, 8) 400
_________________________________________________________________
flatten_4 (Flatten) (None, 32) 0
_________________________________________________________________
dense_4 (Dense) (None, 1) 33
=================================================================
Total params: 433
Trainable params: 433
Non-trainable params: 0
_________________________________________________________________
None
查看模型精度
Accuracy: 89.999998

查看通过50次迭代后的Embedding矩阵。

运行结果如下:
array([[ 0.03469506, 0.05556902, -0.06460979, 0.04944995, -0.04956526,
-0.01446372, -0.01657126, 0.04287368],
[ 0.04969586, -0.0284451 , -0.03200825, -0.00149088, 0.04212971,
-0.00741715, -0.02147427, -0.02345204],
[ 0.00152697, 0.04381416, 0.01856637, -0.00952369, 0.04007444,
0.00964203, -0.0313913 , -0.04820969]], dtype=float32)

3.1.2 Dense简介

Dense就是常用的的全连接层,它实现以下操作:

其中 activation 是按逐个元素计算的激活函数,kernel 是由网络层创建的权值矩阵,以及 bias 是其创建的偏置向量 (只在 use_bias 为 True 时才有用)。
注意: 如果该层的输入的秩大于2,那么它首先被展平然后 再计算与 kernel 的点乘。
【参数说明】
 units: 正整数,输出空间维度。
 activation: 激活函数 (详见 activations)。 若不指定,则不使用激活函数 (即,「线性」激活: a(x) = x)。
 use_bias: 布尔值,该层是否使用偏置向量。
 kernel_initializer: kernel 权值矩阵的初始化器 (详见https://keras.io/zh/initializers/)。
 bias_initializer: 偏置向量的初始化器 (详见https://keras.io/zh/initializers/).
 kernel_regularizer: 运用到 kernel 权值矩阵的正则化函数 (详见 https://keras.io/zh/regularizers/)。
 bias_regularizer: 运用到偏置向的的正则化函数 (详见 https://keras.io/zh/regularizers/)。
 activity_regularizer: 运用到层的输出的正则化函数 (它的 "activation")。 (详见 https://keras.io/zh/regularizers/)。
 kernel_constraint: 运用到 kernel 权值矩阵的约束函数 (详见https://keras.io/zh/constraints/)。
 bias_constraint: 运用到偏置向量的约束函数 (详见https://keras.io/zh/constraints/)。
 输入尺寸
nD张量,尺寸: (batch_size, ..., input_dim)。 最常见的情况是一个尺寸为 (batch_size, input_dim) 的2D输入。
 输出尺寸
nD张量,尺寸: (batch_size, ..., units)。 例如,对于尺寸为 (batch_size, input_dim)的2D输入, 输出的尺寸为 (batch_size, units)。

简单示例代码:

3.2 NN架构


图3-1 NN架构图
从图3-1可知,NN共处理7个特征,其中promo特征因只有2个值(0或1),无需转换为Embedding向量,其它6个特征,根据类别数,分别做了Embedding处理。处理后合并这7个特征,再通过3个全连接层。

3.3 分类特征处理

基于第2章(《XGBoost与NN谁更牛?》)处理保存的feature_train_data.pickle文件,做如下处理:

3.3.1 数据预处理

(1)定义对特征进行Embedding处理函数

(2)导入模块

(3)读取数据

(4)生成训练、测试数据

(5)定义采样函数

(6)采样生成训练数据

3.3.2 构建模型

(1)定义Model类

(2)构建模型

(3)训练模型

运行部分结果
Fitting NN_with_EntityEmbedding...
Train on 200000 samples, validate on 84434 samples
Epoch 1/10
200000/200000 [==============================] - 37s 185us/sample - loss: 0.0140 - val_loss: 0.0113
Epoch 2/10
200000/200000 [==============================] - 33s 165us/sample - loss: 0.0093 - val_loss: 0.0110
Epoch 3/10
200000/200000 [==============================] - 34s 168us/sample - loss: 0.0085 - val_loss: 0.0104
Epoch 4/10
200000/200000 [==============================] - 35s 173us/sample - loss: 0.0079 - val_loss: 0.0107
Epoch 5/10
200000/200000 [==============================] - 37s 184us/sample - loss: 0.0076 - val_loss: 0.0100
Epoch 6/10
200000/200000 [==============================] - 38s 191us/sample - loss: 0.0074 - val_loss: 0.0095
Epoch 7/10
200000/200000 [==============================] - 31s 154us/sample - loss: 0.0072 - val_loss: 0.0097
Epoch 8/10
200000/200000 [==============================] - 33s 167us/sample - loss: 0.0071 - val_loss: 0.0091
Epoch 9/10
200000/200000 [==============================] - 36s 181us/sample - loss: 0.0069 - val_loss: 0.0090
Epoch 10/10
200000/200000 [==============================] - 40s 201us/sample - loss: 0.0068 - val_loss: 0.0089
Result on validation data: 0.09481584162850512
Train on 200000 samples, validate on 84434 samples
Epoch 1/10
200000/200000 [==============================] - 38s 191us/sample - loss: 0.0143 - val_loss: 0.0125
Epoch 2/10
200000/200000 [==============================] - 41s 206us/sample - loss: 0.0096 - val_loss: 0.0107
Epoch 3/10
200000/200000 [==============================] - 46s 232us/sample - loss: 0.0089 - val_loss: 0.0105
Epoch 4/10
200000/200000 [==============================] - 39s 197us/sample - loss: 0.0082 - val_loss: 0.0099
Epoch 5/10
200000/200000 [==============================] - 39s 197us/sample - loss: 0.0077 - val_loss: 0.0095
Epoch 6/10
200000/200000 [==============================] - 41s 207us/sample - loss: 0.0075 - val_loss: 0.0111
Epoch 7/10
200000/200000 [==============================] - 39s 193us/sample - loss: 0.0073 - val_loss: 0.0092
Epoch 8/10
200000/200000 [==============================] - 50s 248us/sample - loss: 0.0071 - val_loss: 0.0092
Epoch 9/10
200000/200000 [==============================] - 46s 228us/sample - loss: 0.0070 - val_loss: 0.0094
Epoch 10/10
200000/200000 [==============================] - 44s 221us/sample - loss: 0.0069 - val_loss: 0.0091
Result on validation data: 0.09585602861091462

3.3.3 验证模型

运行结果如下:
Evaluate combined models...
Training error...
0.06760082089742254
Validation error...
0.09348419043167332

3.4 可视化Entity Embedding

把特征转换为Entity Embedding之后,可以利用t-SNE进行可视化,如对store特征的Embedding降维后进行可视化,从可视化结果揭示出一些重要信息,彼此相似的类别比较接近。

3.4.1 保存Embedding

3.4.2 可视化Embedding特征

(1)导入模块

(2)读取保存的embedding文件

(3)定义对应各州的名称

(4)可视化german_states_embedding

可视化结果如下:


图3-2 可视化german_states_embedding
从图3-2 可知,德国的原属于东德的几个州:萨克森州、萨克森安哈尔特州、图林根州彼此比较接近。其它各州也有类似属性,这就是Embedding通过多次迭代,从数据中学习到一些规则。