2017-06-06 67 views
12

我想了解使用Tensorflow進行情緒分析的LSTM模型,我已經通過了LSTM model瞭解使用張量流進行情緒分析的LSTM模型

以下代碼(create_sentiment_featuresets.py)生成從5000肯定句和5000否定句詞庫。

import nltk 
from nltk.tokenize import word_tokenize 
import numpy as np 
import random 
from collections import Counter 
from nltk.stem import WordNetLemmatizer 

lemmatizer = WordNetLemmatizer() 

def create_lexicon(pos, neg): 
    lexicon = [] 
    with open(pos, 'r') as f: 
     contents = f.readlines() 
     for l in contents[:len(contents)]: 
      l= l.decode('utf-8') 
      all_words = word_tokenize(l) 
      lexicon += list(all_words) 
    f.close() 

    with open(neg, 'r') as f: 
     contents = f.readlines()  
     for l in contents[:len(contents)]: 
      l= l.decode('utf-8') 
      all_words = word_tokenize(l) 
      lexicon += list(all_words) 
    f.close() 

    lexicon = [lemmatizer.lemmatize(i) for i in lexicon] 
    w_counts = Counter(lexicon) 
    l2 = [] 
    for w in w_counts: 
     if 1000 > w_counts[w] > 50: 
      l2.append(w) 
    print("Lexicon length create_lexicon: ",len(lexicon)) 
    return l2 

def sample_handling(sample, lexicon, classification): 
    featureset = [] 
    print("Lexicon length Sample handling: ",len(lexicon)) 
    with open(sample, 'r') as f: 
     contents = f.readlines() 
     for l in contents[:len(contents)]: 
      l= l.decode('utf-8') 
      current_words = word_tokenize(l.lower()) 
      current_words= [lemmatizer.lemmatize(i) for i in current_words] 
      features = np.zeros(len(lexicon)) 
      for word in current_words: 
       if word.lower() in lexicon: 
        index_value = lexicon.index(word.lower()) 
        features[index_value] +=1 
      features = list(features) 
      featureset.append([features, classification]) 
    f.close() 
    print("Feature SET------") 
    print(len(featureset)) 
    return featureset 

def create_feature_sets_and_labels(pos, neg, test_size = 0.1): 
    global m_lexicon 
    m_lexicon = create_lexicon(pos, neg) 
    features = [] 
    features += sample_handling(pos, m_lexicon, [1,0]) 
    features += sample_handling(neg, m_lexicon, [0,1]) 
    random.shuffle(features) 
    features = np.array(features) 

    testing_size = int(test_size * len(features)) 

    train_x = list(features[:,0][:-testing_size]) 
    train_y = list(features[:,1][:-testing_size]) 
    test_x = list(features[:,0][-testing_size:]) 
    test_y = list(features[:,1][-testing_size:]) 
    return train_x, train_y, test_x, test_y 

def get_lexicon(): 
    global m_lexicon 
    return m_lexicon 

下面的代碼(sentiment_analysis.py)是使用簡單的神經網絡模型情感分析和工作正常

from create_sentiment_featuresets import create_feature_sets_and_labels 
from create_sentiment_featuresets import get_lexicon 
import tensorflow as tf 
import numpy as np 
# extras for testing 
from nltk.tokenize import word_tokenize 
from nltk.stem import WordNetLemmatizer 
lemmatizer = WordNetLemmatizer() 
#- end extras 

train_x, train_y, test_x, test_y = create_feature_sets_and_labels('pos.txt', 'neg.txt') 


# pt A------------- 

n_nodes_hl1 = 1500 
n_nodes_hl2 = 1500 
n_nodes_hl3 = 1500 

n_classes = 2 
batch_size = 100 
hm_epochs = 10 

x = tf.placeholder(tf.float32) 
y = tf.placeholder(tf.float32) 

hidden_1_layer = {'f_fum': n_nodes_hl1, 
       'weight': tf.Variable(tf.random_normal([len(train_x[0]), n_nodes_hl1])), 
       'bias': tf.Variable(tf.random_normal([n_nodes_hl1]))} 
hidden_2_layer = {'f_fum': n_nodes_hl2, 
       'weight': tf.Variable(tf.random_normal([n_nodes_hl1, n_nodes_hl2])), 
       'bias': tf.Variable(tf.random_normal([n_nodes_hl2]))} 
hidden_3_layer = {'f_fum': n_nodes_hl3, 
       'weight': tf.Variable(tf.random_normal([n_nodes_hl2, n_nodes_hl3])), 
       'bias': tf.Variable(tf.random_normal([n_nodes_hl3]))} 
output_layer = {'f_fum': None, 
       'weight': tf.Variable(tf.random_normal([n_nodes_hl3, n_classes])), 
       'bias': tf.Variable(tf.random_normal([n_classes]))} 


def nueral_network_model(data): 
    l1 = tf.add(tf.matmul(data, hidden_1_layer['weight']), hidden_1_layer['bias']) 
    l1 = tf.nn.relu(l1) 
    l2 = tf.add(tf.matmul(l1, hidden_2_layer['weight']), hidden_2_layer['bias']) 
    l2 = tf.nn.relu(l2) 
    l3 = tf.add(tf.matmul(l2, hidden_3_layer['weight']), hidden_3_layer['bias']) 
    l3 = tf.nn.relu(l3) 
    output = tf.matmul(l3, output_layer['weight']) + output_layer['bias'] 
    return output 

# pt B-------------- 

def train_neural_network(x): 
    prediction = nueral_network_model(x) 
    cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits= prediction, labels= y)) 
    optimizer = tf.train.AdamOptimizer(learning_rate= 0.001).minimize(cost) 

    with tf.Session() as sess: 
     sess.run(tf.global_variables_initializer()) 
     for epoch in range(hm_epochs): 
      epoch_loss = 0 
      i = 0 
      while i < len(train_x): 
       start = i 
       end = i+ batch_size 
       batch_x = np.array(train_x[start: end]) 
       batch_y = np.array(train_y[start: end]) 
       _, c = sess.run([optimizer, cost], feed_dict= {x: batch_x, y: batch_y}) 
       epoch_loss += c 
       i+= batch_size 
      print('Epoch', epoch+ 1, 'completed out of ', hm_epochs, 'loss:', epoch_loss) 

     correct= tf.equal(tf.argmax(prediction, 1), tf.argmax(y, 1)) 
     accuracy = tf.reduce_mean(tf.cast(correct, 'float')) 
     print('Accuracy:', accuracy.eval({x:test_x, y:test_y})) 

     # testing -------------- 
     m_lexicon= get_lexicon() 
     print('Lexicon length: ',len(m_lexicon))   
     input_data= "David likes to go out with Kary"  
     current_words= word_tokenize(input_data.lower()) 
     current_words = [lemmatizer.lemmatize(i) for i in current_words] 
     features = np.zeros(len(m_lexicon)) 
     for word in current_words: 
      if word.lower() in m_lexicon: 
       index_value = m_lexicon.index(word.lower()) 
       features[index_value] +=1 

     features = np.array(list(features)).reshape(1,-1) 
     print('features length: ',len(features)) 
     result = sess.run(tf.argmax(prediction.eval(feed_dict={x:features}), 1)) 
     print(prediction.eval(feed_dict={x:features})) 
     if result[0] == 0: 
      print('Positive: ', input_data) 
     elif result[0] == 1: 
      print('Negative: ', input_data) 

train_neural_network(x) 

我想修改上述(sentiment_analysis。 py)代替LSTM模型 在讀取RNN w/ LSTM cell example in TensorFlow and Python之後,這是用於LSTM的mnist圖像數據集

一些如何通過多打帶跑的小徑,我能得到下面運行的代碼(sentiment_demo_lstm.py)

輸出的
import tensorflow as tf 
from tensorflow.contrib import rnn 
from create_sentiment_featuresets import create_feature_sets_and_labels 
from create_sentiment_featuresets import get_lexicon 

import numpy as np 

# extras for testing 
from nltk.tokenize import word_tokenize 
from nltk.stem import WordNetLemmatizer 
lemmatizer = WordNetLemmatizer() 
#- end extras 

train_x, train_y, test_x, test_y = create_feature_sets_and_labels('pos.txt', 'neg.txt') 

n_steps= 100 
input_vec_size= len(train_x[0]) 
hm_epochs = 8 
n_classes = 2 
batch_size = 128 
n_hidden = 128 

x = tf.placeholder('float', [None, input_vec_size, 1]) 
y = tf.placeholder('float') 

def recurrent_neural_network(x): 
    layer = {'weights': tf.Variable(tf.random_normal([n_hidden, n_classes])), # hidden_layer, n_classes 
      'biases': tf.Variable(tf.random_normal([n_classes]))} 

    h_layer = {'weights': tf.Variable(tf.random_normal([1, n_hidden])), # hidden_layer, n_classes 
      'biases': tf.Variable(tf.random_normal([n_hidden], mean = 1.0))} 

    x = tf.transpose(x, [1,0,2]) 
    x = tf.reshape(x, [-1, 1]) 
    x= tf.nn.relu(tf.matmul(x, h_layer['weights']) + h_layer['biases']) 

    x = tf.split(x, input_vec_size, 0) 

    lstm_cell = rnn.BasicLSTMCell(n_hidden, state_is_tuple=True) 
    outputs, states = rnn.static_rnn(lstm_cell, x, dtype= tf.float32) 
    output = tf.matmul(outputs[-1], layer['weights']) + layer['biases'] 

    return output 

def train_neural_network(x): 
    prediction = recurrent_neural_network(x) 
    cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits= prediction, labels= y)) 
    optimizer = tf.train.AdamOptimizer(learning_rate= 0.001).minimize(cost) 

    with tf.Session() as sess: 
     sess.run(tf.global_variables_initializer()) 

     for epoch in range(hm_epochs): 
      epoch_loss = 0 
      i = 0 
      while (i+ batch_size) < len(train_x): 
       start = i 
       end = i+ batch_size 
       batch_x = np.array(train_x[start: end]) 
       batch_y = np.array(train_y[start: end]) 
       batch_x = batch_x.reshape(batch_size ,input_vec_size, 1) 
       _, c = sess.run([optimizer, cost], feed_dict= {x: batch_x, y: batch_y}) 
       epoch_loss += c 
       i+= batch_size 
      print('--------Epoch', epoch+ 1, 'completed out of ', hm_epochs, 'loss:', epoch_loss) 

     correct= tf.equal(tf.argmax(prediction, 1), tf.argmax(y, 1)) 
     accuracy = tf.reduce_mean(tf.cast(correct, 'float')) 

     print('Accuracy:', accuracy.eval({x:np.array(test_x).reshape(-1, input_vec_size, 1), y:test_y})) 

     # testing -------------- 
     m_lexicon= get_lexicon() 
     print('Lexicon length: ',len(m_lexicon)) 
     input_data= "Mary does not like pizza" #"he seems to to be healthy today" #"David likes to go out with Kary" 

     current_words= word_tokenize(input_data.lower()) 
     current_words = [lemmatizer.lemmatize(i) for i in current_words] 
     features = np.zeros(len(m_lexicon)) 
     for word in current_words: 
      if word.lower() in m_lexicon: 
       index_value = m_lexicon.index(word.lower()) 
       features[index_value] +=1 
     features = np.array(list(features)).reshape(-1, input_vec_size, 1) 
     print('features length: ',len(features)) 

     result = sess.run(tf.argmax(prediction.eval(feed_dict={x:features}), 1)) 
     print('RESULT: ', result) 
     print(prediction.eval(feed_dict={x:features})) 
     if result[0] == 0: 
      print('Positive: ', input_data) 
     elif result[0] == 1: 
      print('Negative: ', input_data) 

train_neural_network(x) 

print(train_x[0]) 
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] 

print(train_y[0]) 
[0, 1] 

len(train_x)= 9596len(train_x[0]) = 423含義train_x是9596x423的列表?

堅韌我現在有一個運行代碼,我仍然有很多疑問。

  1. sentiment_demo_lstm,我無法理解下面的部分

    x = tf.transpose(x, [1,0,2]) 
    x = tf.reshape(x, [-1, 1]) 
    x = tf.split(x, input_vec_size, 0) 
    

    我有打印以下形狀:

    x = tf.placeholder('float', [None, input_vec_size, 1]) ==> TensorShape([Dimension(None), Dimension(423), Dimension(1)])) 
    x = tf.transpose(x, [1,0,2]) ==> TensorShape([Dimension(423), Dimension(None), Dimension(1)])) 
    x = tf.reshape(x, [-1, 1]) ==> TensorShape([Dimension(None), Dimension(1)])) 
    x = tf.split(x, input_vec_size, 0) ==> ? 
    
  2. 這裏我把隱藏數層數爲128,它是否需要與輸入數量相同,即len(train_x)= 9596

  3. x = tf.placeholder('float', [None, input_vec_size, 1]) 
    

    x = tf.reshape(x, [-1, 1]) 
    

    值1是因爲train_x[0]是428x ?

  4. 以下是爲了匹配佔位

    batch_x = np.array(train_x[start: end]) ==> (128, 423) 
    batch_x = batch_x.reshape(batch_size ,input_vec_size, 1) ==> (128, 423, 1) 
    

    x = tf.placeholder('float', [None, input_vec_size, 1])尺寸,對不對?

  5. 如果我修改的代碼:

    while (i+ batch_size) < len(train_x): 
    

    作爲

    while i < len(train_x): 
    

    我得到以下錯誤:

    Traceback (most recent call last): 
        File "sentiment_demo_lstm.py", line 131, in <module> 
        train_neural_network(x) 
        File "sentiment_demo_lstm.py", line 86, in train_neural_network 
        batch_x = batch_x.reshape(batch_size ,input_vec_size, 1) 
    ValueError: cannot reshape array of size 52452 into shape (128,423,1) 
    

=>我不能包括訓練中最後124個記錄/功能集G?

+0

您目前使用編碼詞模型的袋子你的句子,LSTMs需要一個時間維度(使每個字的特徵向量或的形狀),使其與工作通常你可以通過一個嵌入層來完成。看一看Keras中的例子,它基本上滿足你的需求(https://github.com/fchollet/keras/blob/master/examples/imdb_lstm.py)。 –

+1

這裏有很多問題。或者把這個問題分開來,這可能是件好事。 – erip

回答

9

這是加載的問題。讓我試着把它放在簡單的英文中,隱藏所有複雜的內部細節:

一個簡單的展開3個步驟的展開LSTM模型如下所示。每個LSTM單元採用輸入矢量和前一個LSTM單元的隱藏輸出矢量,併產生輸出矢量和下一個LSTM單元的隱藏輸出。

enter image description here

同一模型的簡明表示如下所示。

enter image description here

LSTM模型序列序列的機型,即,它們被用於問題時,一個序列具有與一個另一序列進行標記,如詞性標註或句子中的每個單詞的NER標記。

你似乎正在使用它來分類問題。有兩種可能的方法來使用LSTM模型進行分類

1)取所有狀態的輸出(在我們的例子中爲O1,O2和O3)並應用softmax層輸出大小等於類數的softmax層(2你的情況)

2)取出最後狀態(O3)的輸出並應用一個softmax層。 (這是你在你的鱈魚在做什麼輸出[-1]的輸出返回的最後一行。)

所以我們回去傳播(BP算法通過時間 - BTT)在SOFTMAX輸出的錯誤。

即將實現使用Tensorflow,讓我們看看什麼是輸入和輸出到LSTM模型。每個LSTM需要一個輸入,但是我們有3個這樣的LSTM單元,所以輸入(X佔位符)的大小應該是sizeize(inputsize *時間步長)。但是我們並不計算單輸入和BTT的誤差,而是我們在一批輸入 - 輸出組合上進行。所以LSTM的輸入將是(batchsize * inputsize * time steps)。

LSTM單元用隱藏狀態的大小定義。 LSTM單元的輸出和隱藏輸出矢量的大小將與隱藏狀態的大小相同(檢查LSTM內部計算爲什麼!)。然後,我們使用這些LSTM單元格的列表定義一個LSTM模型,其中列表的大小將等於模型的展開次數。因此,我們定義了每次展開期間要展開的展開次數和輸入的大小。

我跳過了很多東西,比如如何處理變長序列,序列錯誤計算的順序,LSTM如何計算輸出和隱藏輸出等。

即將實施,您在每個LSTM單元的輸入之前應用了一個relu層。我不明白你爲什麼這樣做,但我想你是這樣做的將輸入大小映射到LSTM輸入大小。

編輯您的問題:

  1. x是佔位符的大小(張量/基質/ ndarray)[無,input_vec_size,1]。即它可以佔用可變數量的行,但每行都有input_vec_size列,每個元素是一個向量,大小爲1.通常,行中的佔位符用「無」定義,以便我們可以改變輸入的批量大小。

可以說input_vec_size = 3

你傳入大小的ndarray [128 * 3 * 1]

X = tf.transpose(X,[1,0,2]) - - > [3 * 128 * 1]

X = tf.reshape(X,[1,1]) - > [384 * 1]

h_layer [ '權重'] - > [ 1,128]

x = tf.nn.relu(tf.matmul (X,h_layer [ '權重'])+ h_layer [ '偏壓']) - > [384 * 128]

  • 沒有輸入尺寸被隱藏大小是不同的。 LSTM對輸入和前一個隱藏輸出執行一組操作,並給出一個輸出和下一個隱藏輸出,這兩個輸出都是隱藏大小的。

  • X = tf.placeholder( '浮動',[無,input_vec_size,1])

  • 它定義了一張量或行的ndarray或可變數目的,每行有input_vec_size列的,並且每個值是一個單值向量。

    x = tf.reshape(x,[-1,1]) - >將輸入x重塑爲固定爲1列和任意數量行的大小矩陣。

  • batch_x = batch_x.reshape(的batch_size,input_vec_size,1)
  • batch_x.reshape將失敗數在batch_x值!= *的batch_size input_vec_size * 1。這可能是最後一批的情況,因爲len(train_x)可能不是batch_size的倍數,導致未完全填充的最後一批。

    您可以通過使用

    batch_x = batch_x.reshape(-1 ,input_vec_size, 1) 
    

    避免這個問題,但我仍然不知道爲什麼你在輸入層的正面使用RELU。

    您正在應用logistic迴歸在最後一個細胞的罰款。

    你可以看看我的玩具的例子,它是一個分類器使用雙向LSTM分類序列是否增加或減少或混合。

    Toy sequence_classifier using LSTM in Tensorflow

    +0

    你能告訴我關於x = tf.split(x,input_vec_size,0)的信息。另外,你能否參考我的任何參考資料,論文或教程,以便徹底理解LSTM模型及其在分類中的張量流的實現 – LinuxBeginner

    +0

    x = tf.split(x,input_vec_size,0) - > [3個張量,每個大小爲384/3 * 1]即將第0維(本例中爲行)的輸入張量切割爲3,因此每個分割張量的大小將爲384/3 * 1。您可以在我給出的鏈接中從零開始找到一個非常簡單的實現在上面的答案。或者你可以按照這個鏈接https://github.com/aymericdamien/TensorFlow-Examples和「自然語言處理」部分,你會有一些很好的實現,但他們使用tflearn這是一個抽象的tensorflow – mujjiga

    +0

    在** sentiment_analysis.py **我們可以定義每個隱藏層中的節點數量,我們如何在LSTM模型中定義相同的節點? – LinuxBeginner