1. cnn语言模型python
先大概了解一下cnn语言模型的基本原理。git
cnn语言模型的基本原理和cnn图像模型相似,也是先经过卷积层提取特征,而后经过池化层减小神经元数量,最后经过相似softmax层输出类别可能性。数组
不一样点在于数据结构不同,图像数据是3维度的,长、宽和通道数;而语言模型是2维的,是句子的长度和每一个词的词向量长度。图像卷积通常用tf.nn.conv2d;而文本卷积通常用conv1d。网络
词向量卷积的时候一般利用多个长度不一的卷积核来提取特征。咱们若是分别以3个连续单词、4个连续单词、5个连续单词为卷积核大小来提取特征,那么咱们每每能够认为这种特征提取已经很是接近句子的意思了。语言模型的cnn原理大概就是这个样子了。session
Cnn语言模型将多个不一样大小的卷积核连起来做为特征提取,如3、4、5做为卷积核大小来提取特征,最后展开成总的特征向量。数据结构
咱们以IMDB数据集来训练cnn文本模型,IMDB数据集是影戏评论的情绪数据,它的标签是2分类的,正面情绪和负面情绪。app
2. 常量定义dom
首先咱们定义一些常量。函数
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. 预处理
文本预处理主要是填充成固定长度的向量,填充的单词序号一般是表示为0的PAD字符。
#扩展整数数组让他们拥有相同的长度,这样每个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))