中文情感分类(基于LSTM)
基于LSTM实现中文情感分类,框架在开始的时候使用的是tensorflow,但是不知到为什么,最后网络总是收敛不了,损失几乎不降。但是同样的想法思路使用keras后,训练就十分顺畅。话不多说,总流程如下:
- 准备数据集
- 将数据集中的所有字映射为字典,即每个字都有唯一的标号对应,这里使用tensorflow中的模块很容易就实现了。
if os.path.exists("processor"):
processor = learn.preprocessing.VocabularyProcessor.restore("processor")
else:
processor = learn.preprocessing.VocabularyProcessor(max_document_length=MAX_DOCUMENT_LEN)
processor.fit(all_word)
processor.save("processor")
- 实现Embedding层
针对本文中Embedding层,其主要作用是将每个词的id映射为固定维度的数,每次相同的id映射为相同的数据,这个固定的数据是可以训练的。在不断的迭代中完成训练。如果针对词向量来说,到了最后Embedding层所得到的就是每个词的词向量,只要我们输入词的对应id就可以得到其对应的词向量。所以Embedding层可以使用预先训练好的词向量,这样在训练的过程中,收敛速度会加快。
model.add(Embedding(input_dim=len(all_word), output_dim=EMBEDDING_SIZE))
- *添加LSTM层进行特征抽取
使用LSTM进行数据特征的抽取,我觉得tensorflow中就是这一块使用失误,导致网络不收敛。最后网路使用交叉熵损失,随机梯度下降法进行训练优化。所以直接看看keras的全部实现:
import pandas as pd
from tensorflow.contrib import learn
from keras.layers.embeddings import Embedding
from keras.layers.recurrent import LSTM
from keras.models import Sequential, load_model
from keras.layers import Dense
import numpy as np
import os
MAX_DOCUMENT_LEN = 30
EMBEDDING_SIZE = 100
def train():
train = pd.read_csv("all.csv", encoding="utf-8")
all_word = set([word for seq in train.content.values for word in list(seq)])
if os.path.exists("processor"):
processor = learn.preprocessing.VocabularyProcessor.restore("processor")
else:
processor = learn.preprocessing.VocabularyProcessor(max_document_length=MAX_DOCUMENT_LEN)
processor.fit(all_word)
processor.save("processor")
# fit generate
def get_generate(batch_size):
while True:
sample_data = train.sample(batch_size)
labels = sample_data.label.values
contents = sample_data.content.values
contents = [list(seq) for seq in contents]
x = []
for seq in contents:
item_str = ""
for word in seq:
item_str += " " + str(word)
x.append(item_str)
x = np.array(list(processor.transform(x)))
y = np.array([[1, 0] if int(item) == 0 else [0, 1] for item in labels])
yield x, y
# create embedding
model = Sequential()
model.add(Embedding(input_dim=len(all_word), output_dim=EMBEDDING_SIZE))
model.add(LSTM(units=128, activation="relu"))
model.add(Dense(2, activation="softmax", name="logit"))
model.compile(loss='categorical_crossentropy', optimizer='sgd')
model.fit_generator(get_generate(50), samples_per_epoch=10000, epochs=10)
model.save("lstm.model")
def pre():
text = input("请输入:")
text = list(text)
item_str = ""
for item in text:
item_str += " " + str(item)
processor = learn.preprocessing.VocabularyProcessor.restore("processor")
input_data = np.array(list(processor.transform([item_str])))
print(input_data)
model = load_model("lstm.model")
target = model.predict(input_data)
print(target)