编程技术网

关注微信公众号,定时推送前沿、专业、深度的编程技术资料。

 找回密码
 立即注册

QQ登录

只需一步,快速开始

极客时间

使用双向堆叠LSTM的情感分析

Rohit Hazare Python 2022-1-10 23:44 169人围观

腾讯云服务器

This article was published as a part of the Data Science Blogathon

情绪分析

情绪分析是找到文本数据情绪的过程。情绪分析在自然语言处理中的文本分类下降。情感分析将有助于我们了解我们的客户评论更好。情绪表示以下任何一种,正,负和中性。当我们分析我们产品的否定审查时,我们可以轻松地使用这些审查来超越我们所面临的问题并提供更好的产品。

Image Source

使用情感分析的益处包括,

  • Understand customer better
  • Improvise the product features based on customer reviews
  • We will be able to identify the mistakes in the features and resolve them to satisfy the customer.

情感分析可以用两种不同的方式完成,

  • Rule-based sentiment analysis
  • Automated sentiment analysis

在基于规则的情感分析中,我们定义一组规则,如果数据满足这些规则,那么我们可以相应地对其进行分类。例如,如果文本数据包含良好,美丽,惊人等的单词,我们可以将其分类为积极的情绪。基于规则的情感分析的问题是它无法概括且可能无法准确分类。例如,基于规则的系统更有可能根据规则将以下句子分类为正,“产品不好”。原因是基于规则的系统标识句子中的良好词,并将其分类为积极情绪,但上下文是不同的,句子是否定的。为了超越这些问题,我们可以使用深度学习技术来进行情感分析。

在自动化情绪分析中,我们利用深度学习来学习数据中的特征目标映射。在我们的案例中,这些功能是评论,目标是情绪。所以在我们的帖子中,我们利用深度学习模型利用自动化情绪分析。

使用Tensorflow的情感分析

In this post, we are going to leverage deep learning to find the sentiments of the IMDB reviews.  We are going to use the IMDB reviews data in this post. You can download the data here. The data contains two columns namely review and sentiment. The sentiment column contains only two unique values namely positive and negative indicating the sentiment of the corresponding reviews. So we can infer that our problem is a binary classification problem. Our model is going to learn the feature-target mapping, in our case, it is the review-sentiment mapping.

在这篇文章中,我们将使用Regex和Spacy进行预处理和Tensorflow的双向LSTM模型进行培训。

To install spaCy refer to this webpage for instructions. To install TensorFlow refer to this webpage for instructions.

安装Spacy后,使用以下命令下载培训的流水线包,称为en_core_web_sm,我们将使用预处理。

python -m spacy download en_core_web_sm

导入所需的库

import re
import spacy
import numpy as np
import pandas as pd
import en_core_web_sm
import tensorflow as tf
from nltk.stem import WordNetLemmatizer
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.models import Sequential
from spacy.lang.en.stop_words import STOP_WORDS
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
from tensorflow.keras.layers.experimental.preprocessing import TextVectorization
from tensorflow.keras.layers import Embedding, LSTM, Dense, Bidirectional, Dropout
nlp = en_core_web_sm.load()
lemmatizer = WordNetLemmatizer()
stopwords = STOP_WORDS
EMOJI_PATTERN = re.compile(
    "["
    u"U0001F600-U0001F64F"  # emoticons
    u"U0001F300-U0001F5FF"  # symbols & pictographs
    u"U0001F680-U0001F6FF"  # transport & map symbols
    u"U0001F1E0-U0001F1FF"  # flags (iOS)
    u"U00002702-U000027B0"
    u"U000024C2-U0001F251"
    "]+", flags=re.UNICODE
)
FILTERS = '!"#$%&()*+,-/:;[email protected][\]^_`{|}~tn'
HTML_TAG_PATTERN = re.compile(r']*>')
NUMBERING_PATTERN = re.compile('d+(?:st|[nr]d|th)')
DISABLE_PIPELINES = ["tok2vec", "parser", "ner", "textcat", "custom", "lemmatizer"]

我们正在使用命令en_core_web_sm.load()加载Spacy的培训管道,称为en_core_web_sm。我们还加载了Spacy中可用的止动件。StopWords是没有大部分与他们相关的含义的词汇,其中一些示例包括像,他,她,它等的单词。

上面定义的表情符号模式用于在审阅数据中删除EMOJIS。上面定义的过滤器是可能在评论中提供的特殊字符。上面定义的HTML标记模式用于删除HTML标记并仅保留标签内的数据。上面定义的编号模式用于删除1st,2nd,第3或依此类推的编号。上面定义的禁用管道用于禁用SPACY语言模型中的某些管道,使得导致有效地完成处理并具有低延迟。

def initial_preprocessing(text):

    """

    - Remove HTML tags

    - Remove Emojis

    - For numberings like 1st, 2nd

    - Remove extra characters > 2 eg:

    ohhhh to ohh

    """

    tag_removed_text = HTML_TAG_PATTERN.sub('', text)

    emoji_removed_text = EMOJI_PATTERN.sub(r'', tag_removed_text)

    numberings_removed_text =  NUMBERING_PATTERN.sub('', emoji_removed_text)

    extra_chars_removed_text = re.sub(

        r"(.)1{2,}",  r'11', numberings_removed_text

    )

    return extra_chars_removed_text

def preprocess_text(doc):

    """

    Removes the 

    1. Spaces

    2. Email

    3. URLs

    4. Stopwords

    5. Punctuations

    6. Numbers

    """

    tokens = [

        token

        for token in doc

        if not token.is_space and

           not token.like_email and

           not token.like_url and

           not token.is_stop and

           not token.is_punct and

           not token.like_num

    ]

    """

    Remove special characters in tokens except dot

    (would be useful for acronym handling)

    """

    translation_table = str.maketrans('', '', FILTERS)

    translated_tokens = [

        token.text.lower().translate(translation_table)

        for token in tokens

    ]

    """

    Remove integers if any after removing 

    special characters, remove single characters 

    and lemmatize

    """

    lemmatized_tokens = [

        lemmatizer.lemmatize(token)

        for token in translated_tokens

        if len(token) > 1

    ]

    return lemmatized_tokens

labels = imdb_data['sentiment'].iloc[:10000]

labels = labels.map(lambda x: 1 if x=='positive' else 0)

"""

Preprocess the text data

"""

data = imdb_data.iloc[:10000, :]

column = 'review'

not_null_data = data[data[column].notnull()]

not_null_data[column] = not_null_data[column].apply(initial_preprocessing)

texts = [

    preprocess_text(doc)

    for doc in nlp.pipe(not_null_data[column], disable=DISABLE_PIPELINES)

]
 

上述代码如何工作?

首先,我们正在采取第一个10000行的数据。此数据中的标签/目标是名为“情绪”的列。情绪列由两个独特的价值观组成,即“正面”和“否定”表示相应评论的情绪。我们正在用整数1替换值“正”,并具有整数0的值“否定”。

我们只占用的行,这意味着我们省略了使用空值的评论。获取NOT NULL QULL后,我们正在应用上面定义的初始预处理功能。

方法后跟方法初始预处理是,

  • Removing HTML tags like , and extracting the data defined inside the tag
  • Removing the emojis in the data
  • Removing the numbering patterns in the data like 1st, 2nd, 3rd, and etc.
  • Removing extra characters in the word. For example, the word ohhh is replaced with ohh.

在应用初始预处理步骤后,我们正在使用spacy预处理数据。预处理方法之后的步骤是,

  • Removing spaces in the data.
  • Removing emails in the data.
  • Removing stopwords in the data.
  • Removing URLs in the data.
  • Removing punctuations in the data.
  • Removing numbers in the data.
  • Lemmatization.

函数nlp.pipe将在spacy中生成一系列doc对象。spacy中的一个doc是一系列令牌对象。我们使用禁用管道加快预处理时间。

lemmatization是找到单词根的过程。例如,将运行Word运行的LEMMA,这是运行单词的根目录。进行lemmat化的目的是降低词汇的大小。lemmatize从NLTK包中使用WordNetLemmatizer的单词。

tokenizer = Tokenizer(
    filters=FILTERS,
    lower=True
)
padding = 'post'
tokenizer.fit_on_texts(texts)
vocab_size = len(tokenizer.word_index) + 1
sequences = []
max_sequence_len = 0
for text in texts:
    # convert texts to sequence
    txt_to_seq = tokenizer.texts_to_sequences([text])[0]
    sequences.append(txt_to_seq)
    # find max_sequence_len for padding
    txt_to_seq_len = len(txt_to_seq)
    if txt_to_seq_len > max_sequence_len:
        max_sequence_len = txt_to_seq_len
# post padding
padded_sequences = pad_sequences(
    sequences, 
    maxlen=max_sequence_len, 
    padding=padding
)

执行预处理后,我们将授予数据,将令牌的单词转换为序列,并返回令牌句子。令牌化是将句子分解成一系列单词的过程。例如,“我喜欢苹果”可以被授予[“我”,“喜欢”,“苹果”]。将令牌化句子转换为序列看起来像[1,2,3]。“i”,“喜欢”和“苹果”单词映射到数字1,2和3.然后填充序列将看起来像[1,2,3,0,0,0]。在第3号之后的三个零是填充序列。这也被称为填充后。

model = Sequential()
model.add(Embedding(vocab_size, 64, input_length=max_sequence_len-1))
model.add(Bidirectional(LSTM(64, return_sequences=True, input_shape=(None, 1))))
model.add(Dropout(0.2))
model.add(Bidirectional(LSTM(32)))
model.add(Dropout(0.2))
model.add(Dense(64, activation='relu'))
model.add(Dropout(0.1))
model.add(Dense(1, activation='sigmoid'))
adam = Adam(learning_rate=0.01)
model.compile(
    loss=tf.keras.losses.BinaryCrossentropy(from_logits=True), 
    optimizer=adam, 
    metrics=['accuracy']
)
model.summary()
Image Source: Author’s Jupyter Notebook 

在这里,我们使用了使用tensorflow使用双向LSTM模型。让我们潜入模型的工作。

首先,我们定义了一个嵌入层。嵌入层将单词转换为单词向量。例如,“Apple”一词可以嵌入为[0.2,0.12,0.45]。维度的数量是超参数。使用Word Embeddings的目的是在单词之间找到更好的相似之处,这是一个热编码失败的地方。在这里,我们选择了64的维度。

我们在这里使用的模型是堆叠的双向LSTM。第一双向层由64个小区限定,第二层用32个双向LSTM单元定义。之后,我们使用了具有64个单位的密集层,激活函数Relu。最终层是具有Sigmoid激活功能的输出层,因为我们的问题是我们使用的二进制分类问题,我们使用了Sigmoid函数。我们还使用了辍学层来防止称为过度装备的现象。

We have used the Adam optimization function for backpropagation and we have used the binary cross-entropy loss function for loss and accuracy for metric. The loss function is used to optimize the model whereas the metric is used for our comparison. To know more about the working of LSTM refer to this blog.

history = model.fit(
    padded_sequences, 
    labels.values, 
    epochs=10,
    verbose=1,
    batch_size=64
)

现在是时候训练模型了。我们使用了10个时期和批量64到培训。我们将填充序列用作特征和情绪作为目标。

Image Source: Author’s Jupyter Notebook
import matplotlib.pyplot as plt
fig = plt.plot(history.history['accuracy'])
title = plt.title("History")
xlabel = plt.xlabel("Epochs")
ylabel = plt.ylabel("Accuracy")
Image Source: Author’s Jupyter Notebook

如果我们绘制历史,我们可以清楚地看到,随着时代的增加,我们的准确性也会增加。我们获得了99.82%的准确性。

现在我们训练了我们的模型,我们可以用它来制作预测。

predictions = model.predict(padded_sequences[:4])
for pred in predictions:
    print(pred[0])

我们使用了预处理和预测的前四个评论。我们正在获得以下结果。

Output
0.99986255
0.9999008
0.99985176
0.00030466914

输出表示积极情绪的概率。让我们检查一下是否正确。

Image Source: Author’s Jupyter Notebook

预测非常令人印象深刻。通过这种方式,您可以利用Tensorflow来执行情绪分析。

概括

在这篇文章中,我们已经了解了基于规则的情感分析与自动情绪分析之间的差异。此外,我们利用了深入学习的自动化情绪分析来分析情绪。

  • Preprocess the data using spaCy. Use tokenizer to convert text to sequences.
  • Use stacked Bidirectional LSTM to train the data
  • Plot the history after training
  • Use the trained model to make predictions

随意调整模型的超级参数,如改变优化器功能,添加额外的层,更改激活功能,并尝试增加嵌入向量中的尺寸。通过这种方式,您将能够实现更加精致和良好的结果。

快乐的深度学习!

Connect with me on LinkedIn.

本文中显示的媒体不受分析vidhya所拥有的,并在提交人的自由裁量权使用。

有关的

腾讯云服务器 阿里云服务器
关注微信
^