在信息爆炸的时代,如何从海量的社交媒体信息中快速识别出与灾难相关的推文,成为了一个重要的研究课题。这不仅涉及到自然语言处理(NLP)的技术,还需要对文本数据进行深入的分析和处理。本文将带了解如何通过NLP技术实现灾难推文的分类,并探讨文本预处理和LSTM模型创建的过程。
所使用的数据集是灾难推文数据集,它包含五列数据,但主要关注的是“text”列,即推文内容,以及“target”列,它指示给定的推文是否与灾难相关。为了获得良好的分类结果,需要对推文数据进行一系列的文本预处理技术。
首先,需要导入项目所需的所有库。这些库包括pandas、numpy、re、nltk等,它们将帮助进行数据处理和模型训练。
import warnings
warnings.simplefilter(action='ignore', category=Warning)
import pandas as pd
import numpy as np
import re
import nltk
from nltk.corpus import stopwords
from tqdm import tqdm
import seaborn as sns
sns.set_style("darkgrid")
import matplotlib.pyplot as plt
%matplotlib inline
接下来,使用pandas导入灾难推文数据集,并分析数据的几行和列。
data = pd.read_csv("train.csv")
data.head()
使用seaborn,绘制灾难和非灾难推文的数量。
sns.countplot(data["target"])
计算归一化值计数,以了解数据集中灾难和非灾难推文的比例。
data["target"].value_counts(normalize=True)
作为数据分析的重要步骤,将计算每条推文的长度,并创建一个基于长度数据绘制直方图的函数。
def length_plot(data, name):
length = [len(sentence.split()) for sentence in data]
plt.hist(length)
plt.title(name)
现在,将分离依赖和独立特征,并计算灾难推文中存在的不重复单词数量。
X = data["text"] # 独立特征
y = data["target"] # 依赖特征
y = np.array(y) # 转换为数组
定义了一个函数来计算不重复单词,并打印出总数量。
def unq_words(sentence):
unq_words_list = []
for sent in tqdm(sentence):
for word in sent.split():
if word.lower() not in unq_words_list:
unq_words_list.append(word.lower())
else:
pass
return unq_words_list
unique_words = unq_words(X)
print("Total unique words present :",len(unique_words))
接下来,将处理推文中的特殊符号,如“#”和“@”。定义了两个符号,并分别找出以这些符号开头的单词。
SYMBOL_1 = "#"
sym1_words = [word for word in unique_words if word.startswith(SYMBOL_1)]
len(sym1_words) # 1965
得出结论,以“@”开头的单词对模型的准确性没有影响,因此决定移除它们。
SYMBOL_2 = "@"
sym2_words = [word for word in unique_words if word.startswith(SYMBOL_2)]
len(sym2_words) # 2264
在数据集中,存在许多URL,因此编写一个函数来移除它们。
def url_remover(text):
url_patterns = re.compile(r'https?://S+|www.S+')
return url_patterns.sub(r'', text)
现在,开始实际的预处理,并编写一个函数来实现它。
from nltk.stem import WordNetLemmatizer
wl = WordNetLemmatizer()
def preprocessing(text):
tweets = []
for sentence in tqdm(text):
sentence = sentence.lower() # 转换为小写
sentence = url_remover(sentence) # 移除URL
sentence = re.sub(r'@w+', '', sentence).strip() # 移除以"@"开头的单词
sentence = re.sub("[^a-zA-Z0-9 ']", "", sentence) # 移除符号
sentence = sentence.split()
sentence1 = [wl.lemmatize(word) for word in sentence if word not in set(stopwords.words("english"))] # 词形还原和停用词移除
sentence1 = " ".join(sentence1)
tweets.append(sentence1)
return tweets
tweets = preprocessing(X)
至此,移除了不必要的符号、停用词,并进行了词形还原。在将数据输入模型之前,需要将这些推文转换为数值特征,因此需要执行one-hot编码。
from tensorflow.keras.layers import (Embedding,
LSTM,
Dense,
Dropout,
GlobalMaxPool1D,
BatchNormalization)
from tensorflow.keras.models import Sequential
from tensorflow.keras.preprocessing.sequence import pad_sequences
from tensorflow.keras.preprocessing.text import one_hot
执行one-hot编码。
VOC_SIZE = 30000
onehot_vector = [one_hot(words, VOC_SIZE) for words in tweets]
找到每条推文的单词长度,并执行零填充以使序列长度相等。
SENTENCE_LENGTH = 15
embedded_docs = pad_sequences(onehot_vectors, padding="post", maxlen=SENTENCE_LENGTH)
接下来是创建模型的重要步骤。第一层是词嵌入层,后面跟着LSTM模型。
def model():
VECTOR_FEATURES = 32
lstm_model = Sequential()
lstm_model.add(Embedding(VOC_SIZE,
VECTOR_FEATURES,
input_length=SENTENCE_LENGTH))
lstm_model.add(LSTM(100, return_sequences = True))
lstm_model.add(GlobalMaxPool1D())
lstm_model.add(BatchNormalization())
lstm_model.add(Dropout(0.5))
lstm_model.add(Dense(10, activation="relu"))
lstm_model.add(Dropout(0.25))
lstm_model.add(Dense(1, activation = "sigmoid"))
return lstm_model
创建模型并获取模型摘要。
lstm_model = model()
lstm_model.compile(optimizer = "adam", loss = "binary_crossentropy", metrics = ["accuracy"])
lstm_model.summary() #摘要
训练模型。
history = lstm_model.fit(embedded_docs, y, epochs=8, batch_size=32)
plt.plot(history.history["accuracy"])
plt.xlabel("Epochs")
plt.ylabel("Accuracy")
plt.title("Accuracy")
plt.plot(history.history["loss"])
plt.xlabel("Epochs")
plt.ylabel("Loss")
plt.title("Loss")
pickle.dump(lstm_model, open("model.pkl", "wb"))
# 加载模型
lstm_model = pickle.load(open("model.pkl", "rb"))