1.介绍
textcnn是一种利用卷积神经网络来进行文本分类的计算机算法,如果采用多种词向量组合的方式,可以获得很高的分类准确率。我们团队在2018年暑期的DC文本竞赛时使用了textcnn,如果不做开始的词向量融合,textcnn甚至超越不了传统的支持向量机方法。但是由于和支持向量机的工作方式不一样,在模型融合时可以提一些分数。
2. 模型代码
比赛中我们发现,textcnn的全连接层的神经元数量不易过多,过多反而导致分数不高,我们最后选择的神经元数量只有16或者32. 接下来是textcnn的代码,关于完整代码可以查看我的github:https://github.com/jianfeng123/NLP
class TextCNN(object):
"""文本分类,CNN模型"""
def __init__(self, saving_loading = False):
# 三个待输入的数据
## 重新导入计算图防止卡顿
tf.reset_default_graph()
self.input_x = tf.placeholder(tf.int32, [None, Config.seq_length], name='input_x')
self.input_y = tf.placeholder(tf.float32, [None, Config.num_classes], name='input_y')
self.keep_prob = tf.placeholder(tf.float32, name='keep_prob')
self.cnn()
self.session = tf.Session()
self.session.run(tf.global_variables_initializer())
## 是否导入模型
if saving_loading == True:
self.save_dir = 'checkpoints/textcnn'
self.save_path = os.path.join(self.save_dir, 'best_validation')
self.saver = load_model(self.session, self.save_dir)
self.saving_or_loading = saving_loading
## textcnn网路
def cnn(self):
"""CNN模型"""
# 词向量映射
with tf.name_scope('embedding'):
embedding = tf.get_variable('embedding', [Config.vocab_size, Config.embedding_dim]) ### embedding 映射,原始的向量模型,可以用词向量进行替代
embedding_outputs = tf.nn.embedding_lookup(embedding, self.input_x)
pooled_outputs = []
for filter_size in Config.kernel_size: ## 并行处理的卷积层个数,由于可能存在2、3、4个字组成的词,所以卷积核的大小也会不一样
with tf.name_scope('conv_filter{0}'.format(filter_size)):
conv1 = tf.layers.conv1d(embedding_outputs, 128,kernel_size=filter_size,strides=1, padding='VALID') ## 单核卷积的输入是二维张量,双核卷积输入是三维
conv_re_output = tf.nn.relu(conv1)
with tf.name_scope("pool_filter{0}".format(filter_size)):
pooled0 = tf.reduce_max(conv_re_output, reduction_indices=[1]) ## 最大池化
pooled1 = tf.reduce_mean(conv_re_output, reduction_indices=[1]) ## 平均池化
pooled_combine = tf.concat([pooled0, pooled1], axis=-1)
pooled_outputs.append(pooled_combine)
h_pool = tf.concat(pooled_outputs, axis=1) ## 将输出的特征重组
with tf.name_scope("score"):
# 分类器
self.logits = tf.layers.dense(h_pool, Config.num_classes, name='fc3')
self.soft = tf.nn.softmax(self.logits)
self.y_pred_cls = tf.argmax(self.soft, 1) # 预测类别 ## 分类结果
with tf.name_scope("optimize"):
cross_entropy = tf.nn.softmax_cross_entropy_with_logits(logits=self.logits, labels=self.input_y) ## 交叉熵最小化
self.loss = tf.reduce_mean(cross_entropy)
# 优化器
self.optim = tf.train.AdamOptimizer(learning_rate=Config.learning_rate).minimize(self.loss) ## 优化函数
with tf.name_scope("accuracy"): ## 准确率计算
# 准确率
correct_pred = tf.equal(tf.argmax(self.input_y, 1), self.y_pred_cls)
self.acc = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
self.label = tf.argmax(self.input_y, 1)