在TensorFlow学习笔记(8):CNN实现中我们以图像处理为场景对卷积神经网络进行了介绍,包括了卷积操作和pooling操作的实现,其中卷积和pooling都采用了二维的操作,输入数据是四维的,shape = [batch, in_height, in_width, in_channels],例如图像像素为28 * 28, RGB三色道表示,batch取100,那么shape = [100, 28, 28, 3]
在处理文本的时候,通常卷积操作的kernel的高度是固定的,与文本中每个字符的向量的长度相同,因此我们通常采用一维卷积来进行操作,例如下面的模型
在本文中,我们介绍如何对文本向量进行卷积和pooling,
1. 一维卷积操作
在tf.layers.conv1d中提供了一维卷积操作,参数如下所示
tf.layers.conv1d(
inputs,
filters,
kernel_size,
strides=1,
padding='valid',
data_format='channels_last',
dilation_rate=1,
activation=None,
use_bias=True,
kernel_initializer=None,
bias_initializer=tf.zeros_initializer(),
kernel_regularizer=None,
bias_regularizer=None,
activity_regularizer=None,
kernel_constraint=None,
bias_constraint=None,
trainable=True,
name=None,
reuse=None
)
其中几个重要的参数如下所示:
- inputs:3维的输入Tensor,每个维度分别表示(batch size, max sentence length, vector dimension)
- filters: 表示filters的数量
- kernel_size:表示卷积核的大小,卷积核其实应该是一个二维的,这里只需要指定一维,是因为卷积核的第二维与输入的词向量维度是一致的,因为对于句子而言,卷积的移动方向只能是沿着词的方向,即只能在列维度移动
- strides: 表示步长,因为只能在词的方向移动,因此是一个整数,通常取1
- activation: 表示激活函数,如果是None的话,就表示线性激活函数
- padding:表示是否进行填充
2. 一维pooling
同样tensorflow中提供了一维的pooling操作,包括tf.layers.MaxPooling1D和tf.layers.AveragePooling1D,我们以MaxPooling操作来进行说明
__init__(
pool_size,
strides,
padding='valid',
data_format='channels_last',
name=None,
**kwargs
)
其中
- strides是整数,表示步长
- pool_size是pooling窗口的大小
- padding:表示是否进行填充
例如下面的代码实现了采用CNN进行文本分类的功能
# 首先对句子进行卷积
with tf.variable_scope('cnn'):
# shape (batch size, max sentence length, kernel nums)
feature_maps = tf.layers.conv1d(
inputs = self.char_embeddings,
kernel_size = self.hp.cnn_kernel_size,
filters = self.hp.cnn_kernel_nums,
padding = 'same',
use_bias = True,
activation = tf.nn.tanh,
name = 'convolution'
)
# 进行pooling
with tf.variable_scope('poolinig'):
# shape = (batch size, 1, kernel nums)
pooled_output = tf.layers.max_pooling1d(
inputs = feature_maps,
pool_size = self.hp.max_length_sentence,
strides = 1,
padding = 'valid',
name = 'max_pooling'
)
# 进行变换
# 然后用全联接网络计算概率
with tf.variable_scope('proj'):
W = tf.get_variable(
name = 'w',
dtype = tf.float32,
shape = [self.hp.cnn_kernel_nums, len(self.argument_role_vocab)]
)
b = tf.get_variable(
name = 'b',
dtype = tf.float32,
shape = [len(self.argument_role_vocab)],
initializer = tf.zeros_initializer()
)
# shape = (batch size, kernel nums)
output = tf.reshape(pooled_output, [-1, self.hp.cnn_kernel_nums])
# shape = (batch size, vocab_tags_nums)
self.logits = tf.matmul(output, W) + b
其中pooling是对每个feature map进行处理,因此我们选择了pool_size为feature map的长度,也就是句子的最大长度,这样得到的结果就是每个feature map中的最大值;然后进行维度变换,得到的结果就是图示模型中的样子