cnn文本模型分類影視情感數據IMDB(CNN模型)

1. cnn語言模型python

先大概瞭解一下cnn語言模型的基本原理。git

cnn語言模型的基本原理和cnn圖像模型相似,也是先經過卷積層提取特徵,而後經過池化層減小神經元數量,最後經過相似softmax層輸出類別可能性。數組

不一樣點在於數據結構不同,圖像數據是3維度的,長、寬和通道數;而語言模型是2維的,是句子的長度和每一個詞的詞向量長度。圖像卷積通常用tf.nn.conv2d;而文本卷積通常用conv1d網絡

詞向量卷積的時候一般利用多個長度不一的卷積核來提取特徵。咱們若是分別以3個連續單詞、4個連續單詞、5個連續單詞爲卷積核大小來提取特徵,那麼咱們每每能夠認爲這種特徵提取已經很是接近句子的意思了。語言模型的cnn原理大概就是這個樣子了。session

Cnn語言模型將多個不一樣大小的卷積核連起來做爲特徵提取,如345做爲卷積核大小來提取特徵,最後展開成總的特徵向量。數據結構

咱們以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. 預處理

文本預處理主要是填充成固定長度的向量,填充的單詞序號一般是表示爲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))
相關文章
相關標籤/搜索