2017-06-06 79 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