cnn文本模型分类影视情感数据IMDB(CNN模型)

1. cnn语言模型

先大概了解一下cnn语言模型的基本原理。

cnn语言模型的基本原理和cnn图像模型类似,也是先通过卷积层提取特征,然后通过池化层减少神经元数量,最后通过类似softmax层输出类别可能性。

不同点在于数据结构不一样,图像数据是3维度的,长、宽和通道数;而语言模型是2维的,是句子的长度和每个词的词向量长度。图像卷积一般用tf.nn.conv2d;而文本卷积一般用conv1d

词向量卷积的时候通常利用多个长度不一的卷积核来提取特征。我们如果分别以3个连续单词、4个连续单词、5个连续单词为卷积核大小来提取特征,那么我们往往可以认为这种特征提取已经非常接近句子的意思了。语言模型的cnn原理大概就是这个样子了。

Cnn语言模型将多个不同大小的卷积核连起来作为特征提取,如345作为卷积核大小来提取特征,最后展开成总的特征向量。

我们以IMDB数据集来训练cnn文本模型,IMDB数据集是影戏评论的情绪数据,它的标签是2分类的,正面情绪和负面情绪。

2. 常量定义

首先我们定义一些常量。

vocab_size=10000  #词总数大小
max_seq_num = 256 #一个句子的最多单词数量
num_dimensions = 50  #词向量空间维度
batch_size = 64 # batch的尺寸
filter_sizes = [3,4,5] #conv1d的3种卷积核尺寸
num_filters = 32  # 卷积核数目
num_classes = 2  # 输出的类别数
iterations = 10000 # 迭代的次数 
dropout_keep_prob = 0.5  # dropout保留比例
learning_rate = 1e-3

3. 下载数据集

下载训练数据集。tensorflow提供了现成的代码做这事(集成了keras)。

import warnings
warnings.filterwarnings('ignore')
import tensorflow as tf
import numpy as np
import os
import random
from tensorflow import keras
from tensorflow.python.ops.rnn import static_rnn
from tensorflow.python.ops.rnn_cell_impl import BasicLSTMCell

#1. download imdb data and show data examples
imdb = keras.datasets.imdb
# 参数num_words = 10000 表示数据集将会保留出现频率在前10000的单词
(train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=vocab_size)
print('imdb data lens:%d,%d'%(len(train_data[0]), len(train_data[1])))
print("Training entries: {}, labels: {}".format(len(train_data), len(train_labels)))

下载后数据会放到~/.keras/datasets/目录,也可以直接将imdb.npz文件直接放到该目录下,节省下载时间。这里的数据集是不定长的句子,比如有的句子是40个单词,而有的句子是200个单词,长度不等。一般对原始句子还要经过Embedding层和填充层进行预处理,将句子装换成固定长度的词向量,才能进行神经网络的训练。

4. 预处理

文本预处理主要是填充成固定长度的向量,填充的单词序号通常是表示为0PAD字符。

#扩展整数数组让他们拥有相同的长度,这样每一个sequence会有共同的max_length(256),总计会占用 max_length*num_ dimensions大小,在sequence后面扩充0
train_data = keras.preprocessing.sequence.pad_sequences(train_data,maxlen=max_seq_num) 
test_data = keras.preprocessing.sequence.pad_sequences(test_data,maxlen=max_seq_num)

5. 定义网络结构

首先定义输入图片数据和label的占位符:

tf.reset_default_graph()
X_holder = tf.placeholder(tf.int32, [None, max_seq_num])
Y_holder = tf.placeholder(tf.int32, [None])

然后定义Embedding层。Embedding是指将总数vocab_size的词空间(one-hot形式)映射到num_dimensions维度中去。

embedding = tf.get_variable('embedding', [vocab_size, num_dimensions])
embedding_inputs = tf.nn.embedding_lookup(embedding, X_holder)

接着就是卷积池化层,用[3,4,5]的卷积核来提取文本特征。

# conv1d方式卷积
pooled_outputs = []
for i, filter_size in enumerate(filter_sizes):
    with tf.name_scope("conv_{0}".format(filter_size)):
        # CNN layer
        conv = tf.layers.conv1d(embedding_inputs, num_filters, filter_size, name='conv-%s' % filter_size)
        # global max pooling layer
        pooled = tf.reduce_max(conv, reduction_indices=[1], name='gmp')
        pooled_outputs.append(pooled)
 

最后将多种卷积核提取的特征向量展开并连接在一起,最后加全连接层输出类别。

# 将每种尺寸的卷积核得到的特征向量进行拼接
num_filters_total = num_filters * len(filter_sizes)
h_pool = tf.concat(pooled_outputs, 1)
h_pool_flat = tf.reshape(h_pool, [-1, num_filters_total])
 
# 对最终得到的句子向量进行dropout
with tf.name_scope("dropout"):
    h_drop = tf.nn.dropout(h_pool_flat, dropout_keep_prob)
 
# 全连接层
with tf.name_scope("output"):
    W = tf.get_variable("W",shape=[num_filters_total, num_classes],
                                initializer=tf.contrib.layers.xavier_initializer())
    b = tf.Variable(tf.constant(0.1, shape=[num_classes]), name="b")
    l2_loss += tf.nn.l2_loss(W)+tf.nn.l2_loss(b)    
    logits = tf.nn.xw_plus_b(h_drop, W, b, name="scores")
    pred = tf.argmax(logits, 1, name="predictions")
 
print("shape:%s  ,%s"%(h_pool_flat.shape,logits.shape))

6. 损失函数

接着我们要定义损失函数了。

损失函数就是训练数据的标签Y_holder和神经网络输出的最大可能性的标签的交叉熵。损失函数定义如下。

# 损失函数
l2_lambda=0.3
with tf.name_scope("loss"):
     losses = tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=tf.one_hot(Y_holder, num_classes),) + l2_lambda*l2_loss
     mean_loss = tf.reduce_mean(losses) 

7.优化函数训练

最后一步就是选择合适的优化函数进行训练了,这部分代码按照常见的套路来做就行了,没有什么特别之处。

# 优化函数
optimizer = tf.train.AdamOptimizer(learning_rate).minimize(mean_loss)
 
# 准确率
predict_Y = tf.argmax(logits, axis=1)
isCorrect = tf.equal(Y_holder, tf.cast(predict_Y, dtype=tf.int32))
accuracy = tf.reduce_mean(tf.cast(isCorrect, tf.float32))

init = tf.global_variables_initializer()
session = tf.Session()
session.run(init)

steps = np.zeros(iterations)
LOSS = np.zeros_like(steps)

with tf.Session() as sess:
	sess.run(tf.global_variables_initializer())		
	print ("begin training")
	for step in range(iterations):
		selected_index = np.random.choice(len(train_data),size=batch_size)
		batch_X = train_data[selected_index]
		batch_Y = train_labels[selected_index]
		feed_dict = {
			X_holder: batch_X,
			Y_holder: batch_Y
		}
		_, mean_loss_val,accuracy_value = sess.run([optimizer, mean_loss,accuracy], feed_dict=feed_dict)
		steps[step]=step
		LOSS[step]=accuracy_value
		if step%10 == 0:
			print ("step = {}\t mean loss ={} acc ={}".format(step, mean_loss_val,accuracy_value))
		

 

转载于:https://my.oschina.net/u/778683/blog/3093329

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值