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))