文本情感倾向分析——神经网络模型

1. 方法

词的向量表示的原理:我们可以将一句话中的每一个词都转换成一个向量,下面这句话有16个单词,可以将输入数据看成是一个16*D的矩阵。

文本情感倾向分析——神经网络模型
文本情感倾向分析——神经网络模型
(1) 构建词典:把文本中的每个词语和其对应的数字,使用字典保存,同时实现方法把句子通过字典映射为包含数字的列表。
构建词典基本思路:

1)对所有句子进行分词。

2)词语存入字典,根据次数对词语进行过滤,并统计次数。

3)实现文本转数字序列的方法。

4)实现数字序列转文本的方法。

 sentences = [["今天","天气","很","好"],["今天","去","吃","什么"]]

 ws = Vocab()
 for sentence in sentences:

   ws.fit(sentence)

 ws.build_vocab(min_count = 1)    print(ws.dict)
 >>> {'':1, '':0, '今天':2, '天气':3, '很':4, '好':5, '去':6, '吃':7, '什么':8}

 ret = ws.transform(["好","好","好","好","好","好","好","热","呀"], max_len = 13)
 print(ret)
 >>> [5,5,5,5,5,5,5,1,1,0,0,0,0]

 ret = ws.inverse_transform(ret)
 print(ret)
 >>>['好','好','好','好','好','好','好','','','','','','','']

(2) 词向量表示(Word Embedding)

因为文本不能够直接被模型计算,所以需要将其转化为向量,常用的有one-hot编码和word embedding方法,这里使用word embedding。

word embedding是深度学习中表示文本常用的一种方法。和one-hot编码不同,wod embedding使用了浮点型的稠密矩阵来表示token。根据词典的大小,我们的向量通常使用不同的维度,如100,256,300等。其中向量中的每一个值是一个参数,其初始值是随机生成的,之后会在训练中进行学习而获得。两个向量之间是有关系的,可以进行相似的的计算。

token —> num —>vector

2.1 使用 word embedding API:torch.nn.Embedding(num_embeddings, embedding_dim)

"""
   param
   1. num_embedding: 词典的大小
   2. embedding_dim: embedding的维度
"""
   embedding = nn.Embedding(vocab_size, 300)
   input_embeded = embedding(input)

2.2 使用 Word2Vec

Word2Vec可以用高维向量来表示词语,并把意思相近的词语放在相近的位置。我们只需要有大量的某种语言的语料,就可以用它来训练模型。

文本情感倾向分析——神经网络模型
假设我们输入的句子是”I thought the movie was incredible and inspiring”。 为了得到词向量,我们可以用TensorFlow的嵌入函数embedding_lookup( )。该函数包含两个参数,一个是嵌入矩阵(词向量矩阵),另一个是每个单词对应的索引。最终得到 一个句子的向量
文本情感倾向分析——神经网络模型
(3) 构建神经网络和训练模型
RNNs的使用原理:Word2Vec将词语转化为高维向量后,一个句子就对应着词向量的集合,使用RNNs可以将高维的句向量编码为较低维度的一维向量,而保留大多数有用的信息。
文本情感倾向分析——神经网络模型
文本情感倾向分析——神经网络模型
LSTM:在RNN的基础上增加了记忆和遗忘功能,解决长期依赖。我们将机器对一个句子的理解称之为状态,一个输入只有能够通过输入门才能够进入到状态中,大多数的词都通过不了输入门,只有少数的关键的词能够进入到状态中去。随着状态读的词越来越长,在状态中的词也越来越多,状态中的词会通过遗忘门进行自循环,只有能够通过遗忘门的词才能够保留下来。最终状态中词的数量达到一个平衡。在输出的时候有一个输出门,只有能够通过输出门的词才能够被输出。即LSTM中的三重门:

1)输入门:决定了哪些词能够进入记忆。
2)遗忘门:决定了哪些词能够被继续记忆。
3)输出门:决定了哪些词能够被输出。

文本情感倾向分析——神经网络模型

2. 代码(BiLSTM)


import jieba
import numpy as np
import pandas as pd

import multiprocessing
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from gensim.models.word2vec import Word2Vec
from gensim.corpora.dictionary import Dictionary

import keras
from keras.preprocessing import sequence
from keras.models import Sequential
from keras.models import load_model
from keras.layers import Bidirectional, Activation
from keras.layers.embeddings import Embedding
from keras.layers.recurrent import LSTM
from keras.layers.core import Dense, Dropout

cpu_count = multiprocessing.cpu_count()
vocab_dim = 100
n_iterations = 1
n_exposures = 10
window_size = 7
n_epoch = 30
maxlen = 100
batch_size = 32

def loadfile():
    neg = pd.read_csv('data/train_neg.csv', header=None, index_col=None)
    pos = pd.read_csv('data/train_pos.csv', header=None, index_col=None)

    combined = np.concatenate((pos[0],neg[0]))
    y = np.concatenate((np.ones(len(pos), dtype=int), np.zeros(len(neg), dtype=int)))

    return combined, y

def tokenizer(data):
    text = [jieba.lcut(document.replace('\n', '')) for document in data]
    return text

def create_dictionaries(model=None, combined=None):

    if (combined is not None) and (model is not None):
        gensim_dict = Dictionary()
        gensim_dict.doc2bow(model.wv.vocab.keys(),
                            allow_update=True)

        w2indx = {v: k + 1 for k, v in gensim_dict.items()}
        f = open("word2index.txt", 'w', encoding='utf8')
        for key in w2indx:
            f.write(str(key))
            f.write(' ')
            f.write(str(w2indx[key]))
            f.write('\n')
        f.close()
        w2vec = {word: model[word] for word in w2indx.keys()}

        def parse_dataset(combined):
            data = []
            for sentence in combined:
                new_txt = []
                for word in sentence:
                    try:
                        new_txt.append(w2indx[word])
                    except:
                        new_txt.append(0)
                data.append(new_txt)
            return data

        combined = parse_dataset(combined)
        combined = sequence.pad_sequences(combined, maxlen=maxlen)
        return w2indx, w2vec, combined
    else:
        print('No data provided...')

def word2vec_train(combined):
    model = Word2Vec(size=vocab_dim,
                     min_count=n_exposures,
                     window=window_size,
                     workers=cpu_count,
                     iter=n_iterations)
    model.build_vocab(combined)
    model.train(combined, total_examples=model.corpus_count, epochs=model.iter)
    model.save('./model/Word2vec_model.pkl')
    index_dict, word_vectors, combined = create_dictionaries(model=model, combined=combined)
    return index_dict, word_vectors, combined

def get_data(index_dict, word_vectors, combined, y):
    n_symbols = len(index_dict) + 1
    embedding_weights = np.zeros((n_symbols, vocab_dim))
    for word, index in index_dict.items():
        embedding_weights[index, :] = word_vectors[word]
    x_train, x_test, y_train, y_test = train_test_split(combined, y, test_size=0.2,random_state=5)
    y_train = keras.utils.to_categorical(y_train, num_classes=2)
    y_test = keras.utils.to_categorical(y_test, num_classes=2)

    return n_symbols, embedding_weights, x_train, y_train, x_test, y_test

def train_bilstm(n_symbols, embedding_weights, x_train, y_train):
    print('Defining a Simple Keras Model...')
    model = Sequential()
    model.add(Embedding(output_dim=vocab_dim,
                        input_dim=n_symbols,
                        mask_zero=True,
                        weights=[embedding_weights],
                        input_length=maxlen))

    model.add(Bidirectional(LSTM(output_dim=50, activation='tanh')))
    model.add(Dropout(0.5))
    model.add(Dense(2, activation='softmax'))

    model.compile(loss='categorical_crossentropy',
                  optimizer='adam', metrics=['accuracy'])

    model.fit(x_train, y_train, batch_size=batch_size, epochs=n_epoch, verbose=2)

    model.save('./model/bilstm.h5')

if __name__ == '__main__':

    print('加载数据集...')
    combined, y = loadfile()
    print(len(combined), len(y))
    print('数据预处理...')
    combined = tokenizer(combined)
    print('训练word2vec模型...')
    index_dict, word_vectors, combined = word2vec_train(combined)

    print('将数据转换为模型输入所需格式...')
    n_symbols, embedding_weights, x_train, y_train, x_test, y_test = get_data(index_dict, word_vectors, combined,
                                                                              y)
    print("特征与标签大小:")
    print(x_train.shape, y_train.shape)

    print('训练bilstm模型...')
    train_bilstm(n_symbols, embedding_weights, x_train, y_train)

    print('加载bilstm模型...')
    model = load_model('./model/bilstm.h5')

    y_pred = model.predict(x_test)

    for i in range(len(y_pred)):
        max_value = max(y_pred[i])
        for j in range(len(y_pred[i])):
            if max_value == y_pred[i][j]:
                y_pred[i][j] = 1
            else:
                y_pred[i][j] = 0

    print(classification_report(y_test, y_pred))

参考:
https://www.bilibili.com/video/BV1Jf4y1b72e?p=6&t=633
https://www.bilibili.com/video/BV1UE411H7Ck?p=1

Original: https://blog.csdn.net/m0_46144891/article/details/118934203
Author: Yue_kk
Title: 文本情感倾向分析——神经网络模型

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/545235/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球