介绍
对自然语言进行分类是当今自然语言处理面临的巨大挑战之一。
它涉及到能够有效区分目标文本和正常文本的技术。其他服务,如聊天机器人,也严重依赖用户输入的文本。他们需要处理大量数据,以确定用户需求并引导正确的路径。
Tensorflow的使用
在本垃圾邮件分类器的第1部分中,我展示了如何使用nltk包对文本进行词干分析和分类,然后将其输入分类器模型,以训练并最终评估模型性能。我已经展示了朴素贝叶斯、SVC和随机森林作为电子邮件分类器的性能。
https://towardsdatascience.com/ml-classifier-performance-comparison-for-spam-emails-detection-77749926d508
在本文中,我将演示如何使用Tensorflow对电子邮件进行token化和有效分类。让我们开始吧。
import numpy as np
import pandas as pd
import tensorflow as tf
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
我已经包括了pad_sequence,它将用于使所有文本数组大小相等。padding可以根据最大尺寸进行,可以是后填充或预填充。下面定义超参数
vocab_size = 1000
embedding_dim = 64
max_length = 120
trunc_type='post'
padding_type='post'
oov_tok = "<OOV>"
用户可以使用这些参数来防止训练数据过拟合。例如,可以减少词汇量,以尽量减少对低频词的过拟合。同样,嵌入维数越低,模型得到训练的速度就越快。我还包括了一个词汇表外单词的标记。
我将使用第1部分中使用的相同数据集。
spam = pd.read_csv('spam.csv', encoding='latin-1')
spam = spam.filter(['v1','v2'], axis=1)
spam.columns = ['label', 'text']
sentences = []
labels = []
for i in range(0,spam.shape[0],1):
sentences.append(spam['text'][i])
labels.append(spam['label'][i])
我已经分配了整个数据集的80%用于训练,剩下的将用于测试。
training_size = int(spam.shape[0]*0.8)
training_sentences = sentences[0:training_size]
testing_sentences = sentences[training_size:]
training_labels_str = labels[0:training_size]
testing_labels_str = labels[training_size:]
对标签进行编码
由于数据集的标签为字符串,因此将通过编码为0和1(0表示垃圾邮件,1表示真实文本)将其转换为整数。
training_labels = [0] * len(training_labels_str)
for ind,item in enumerate(training_labels_str):
if item == 'ham':
training_labels[ind] = 1
else:
training_labels[ind] = 0
testing_labels = [0] * len(testing_labels_str)
for ind,item in enumerate(testing_labels_str):
if item == 'ham':
testing_labels[ind] = 1
else:
testing_labels[ind] = 0
接下来将完成将文本和标签转换为numpy数组。
training_padded = np.array(training_padded)
testing_padded = np.array(testing_padded)
training_labels = np.array(training_labels)
testing_labels = np.array(testing_labels)
tokenizer = Tokenizer(num_words=vocab_size, oov_token=oov_tok)
tokenizer.fit_on_texts(training_sentences)
word_index = tokenizer.word_index
如前所述,需要进行填充以使数组长度相等。
training_sequences = tokenizer.texts_to_sequences(training_sentences)
training_padded = pad_sequences(training_sequences, maxlen=max_length, padding=padding_type, truncating=trunc_type)
testing_sequences = tokenizer.texts_to_sequences(testing_sentences)
testing_padded = pad_sequences(testing_sequences, maxlen=max_length, padding=padding_type, truncating=trunc_type)
模型定义
然后使用RNN和双向LSTM算法定义模型。这里利用双向LSTM在RNN上获得最佳性能。
model = tf.keras.Sequential([
tf.keras.layers.Embedding(vocab_size, embedding_dim, input_length=max_length),
tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(32)),
tf.keras.layers.Dense(24, activation='relu'),
tf.keras.layers.Dropout(0.25),
tf.keras.layers.Dense(1, activation='sigmoid')
])
adam = tf.keras.optimizers.Adam(learning_rate=0.0001, beta_1=0.9, beta_2=0.999, amsgrad=False)
model.compile(loss='binary_crossentropy',optimizer=adam,metrics=['accuracy'])
model.summary()
num_epochs = 20
history = model.fit(training_padded, training_labels, epochs=num_epochs, \
validation_data=(testing_padded, testing_labels), verbose=1)
训练模型
经过20个epoch后,模型得到了良好的训练,验证数据(此处为测试数据)的准确度约为98%
然后预测。
X_train = training_padded
X_test = testing_padded
y_train = training_labels
y_test = testing_labels
from sklearn.metrics import confusion_matrix, classification_report, accuracy_score
y_pred = model.predict(X_test)
# 将预测值转换为0或1
y_prediction = [0] * y_pred.shape[0]
for ind,item in enumerate(y_pred):
if item > 0.5:
y_prediction[ind] = 1
else:
y_prediction[ind] = 0
rep = classification_report(y_test, y_prediction)
报告显示,该模型对这两个文本类都有很好的精确度、召回率和F1分数(0表示垃圾邮件,1表示正常邮件)。对于0,召回率比精度稍低,这表明存在一些假阴性。该模型错误地将一些正常电子邮件识别为垃圾邮件。
我们可以识别任何示例文本,以检查它是垃圾邮件还是正常文本。由于tokenizer已经定义,我们不再需要再次定义它。我们所需要的只是token化示例文本,用0填充它,然后传递给模型进行预测。
选择一些朗朗上口的词,如“WINNER”, “free”, ”prize”,最终会使此文本被检测为垃圾邮件。
sample_text = ["Winner!!! Darling please click the link to claim your free prize"]
sample_text_tokenized = tokenizer.texts_to_sequences(sample_text)
sample_text_tokenized_padded = pad_sequences(sample_text_tokenized, maxlen=max_length, padding=padding_type, truncating=trunc_type)
# 0是垃圾邮件,1是正常邮件
pred = float(model.predict(sample_text_tokenized_padded))
if (pred>0.5):
print ("This is a real email")
else:
print("This is a spam")
结论
本文演示了如何使用Tensorflow有效地训练具有高精度的NLP模型,然后评估模型性能参数,如精度、召回率和F1分数。有了这个小数据集,20个epoch似乎可以生成一个优秀的模型,验证准确率约为98%。
Github页面:https://mdsohelmahmood.github.io/2021/06/23/Spam-email-classification-Part2-Tensorflow.html