在Python中使用TensorFlow进行垃圾短信检测

在Python中使用TensorFlow进行垃圾短信检测

在当今社会,几乎每个人都有一部手机,他们都会定期收到手机上的通信(短信/电子邮件)。但至关重要的一点是,收到的大多数信息都是垃圾邮件,只有少数是火腿或必要的通信。骗子制造欺诈性短信,欺骗你将你的个人信息提供给他们,如你的密码、账号或社会安全号码。如果他们掌握了这些信息,他们可能就能进入你的电子邮件、银行或其他账户。

在这篇文章中,我们将使用Tensorflow开发各种深度学习模型,用于短信垃圾检测,同时分析不同模型的性能指标。

我们将使用短信垃圾检测数据集,它包含短信文本和相应的标签(火腿或垃圾邮件)。

数据集可以从这里下载 https://www.kaggle.com/datasets/uciml/sms-spam-collection-dataset

实现

我们将导入所有需要的库

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers

使用pandas函数.read_csv()加载数据集。

# Reading the data
df = pd.read_csv("/content/spam.csv",encoding='latin-1')
df.head()

Lets, 了解数据

在Python中使用TensorFlow进行垃圾短信检测

我们可以看到,该数据集包含三个未命名的空值的列。所以我们删除这些列,并将v1和v2列分别重命名为label和Text。由于目标变量是字符串形式的,我们将使用pandas函数.map()对其进行数字编码。

df = df.drop(['Unnamed: 2','Unnamed: 3','Unnamed: 4'],axis=1)
df = df.rename(columns={'v1':'label','v2':'Text'})
df['label_enc'] = df['label'].map({'ham':0,'spam':1})
df.head()

上述数据预处理后的输出。

在Python中使用TensorFlow进行垃圾短信检测

让我们把火腿和垃圾邮件的数据分布可视化。

sns.countplot(x=df['label'])
plt.show()

在Python中使用TensorFlow进行垃圾短信检测

火腿的数据相对高于垃圾邮件的数据,这很自然。由于我们要在深度学习模型中使用嵌入,我们不需要平衡数据。现在,让我们找出短信数据中所有句子的平均字数。

# Find average number of tokens in all sentences
avg_words_len=round(sum([len(i.split()) for i in df['Text']])/len(df['Text']))
print(avg_words_len)

输出

在Python中使用TensorFlow进行垃圾短信检测

短信数据中每句话的平均字数

现在,让我们找出语料库中的独特词汇总数

# Finding Total no of unique words in corpus
s = set()
for sent in df['Text']:
  for word in sent.split():
    s.add(word)
total_words_length=len(s)
print(total_words_length)

在Python中使用TensorFlow进行垃圾短信检测

现在,使用train_test_split()函数将数据分割成训练和测试部分。

# Splitting data for Training and testing
from sklearn.model_selection import train_test_split
  
X, y = np.asanyarray(df['Text']), np.asanyarray(df['label_enc'])
new_df = pd.DataFrame({'Text': X, 'label': y})
X_train, X_test, y_train, y_test = train_test_split(
    new_df['Text'], new_df['label'], test_size=0.2, random_state=42)
X_train.shape, y_train.shape, X_test.shape, y_test.shape

训练和测试数据的形状

在Python中使用TensorFlow进行垃圾短信检测

建立模型

首先,我们将建立一个基线模型,然后我们将尝试使用深度学习模型(嵌入、LSTM等)来击败基线模型的性能。

在这里,我们将选择MultinomialNB(),当特征是离散的,如单词的字数或tf-idf向量时,它在文本分类中表现良好。tf-idf是一个衡量标准,它告诉人们一个词在文档中的重要性或相关性。

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import classification_report,accuracy_score
  
tfidf_vec = TfidfVectorizer().fit(X_train)
X_train_vec,X_test_vec = tfidf_vec.transform(X_train),tfidf_vec.transform(X_test)
  
baseline_model = MultinomialNB()
baseline_model.fit(X_train_vec,y_train)

基线模型的性能

在Python中使用TensorFlow进行垃圾短信检测

基线模型的混淆矩阵

在Python中使用TensorFlow进行垃圾短信检测

模式1:创建自定义文本矢量化和嵌入层:

文本矢量化是将文本转换为数字表示的过程。例如。词袋频率,二进制术语频率,等等。

词嵌入是一种学习过的文本表征,其中具有相关含义的词具有类似的表征。每个词都被分配到一个向量,向量的值像神经网络一样被学习。

现在,我们将使用TensorFlow创建一个自定义文本矢量化层。

from tensorflow.keras.layers import TextVectorization
  
MAXTOKENS=total_words_length
OUTPUTLEN=avg_words_len
  
text_vec = TextVectorization(
    max_tokens=MAXTOKENS,
    standardize='lower_and_strip_punctuation',
    output_mode='int',
    output_sequence_length=OUTPUTLEN
)
text_vec.adapt(X_train)
  • MAXTOKENS是先前发现的词汇的最大尺寸。
  • OUTPUTLEN是句子的长度,无论句子的长度如何,都应该被填充到这个长度。

使用文本矢量化的样本句子的输出情况如下所示。

在Python中使用TensorFlow进行垃圾短信检测

现在我们来创建一个嵌入层

embedding_layer = layers.Embedding(
    input_dim=MAXTOKENS,
    output_dim=128,
    embeddings_initializer='uniform',
    input_length=OUTPUTLEN
)
  • input_dim是词汇表的大小。
  • output_dim是嵌入层的维度,即单词将被嵌入的向量的大小。
  • input_length是输入序列的长度。

现在,让我们使用Tensorflow Functional API构建并编译模型1

input_layer = layers.Input(shape=(1,), dtype=tf.string)
vec_layer = text_vec(input_layer)
embedding_layer_model = embedding_layer(vec_layer)
x = layers.GlobalAveragePooling1D()(embedding_layer_model)
x = layers.Flatten()(x)
x = layers.Dense(32, activation='relu')(x)
output_layer = layers.Dense(1, activation='sigmoid')(x)
model_1 = keras.Model(input_layer, output_layer)
  
model_1.compile(optimizer='adam', loss=keras.losses.BinaryCrossentropy(
    label_smoothing=0.5), metrics=['accuracy'])

模型的摘要1

在Python中使用TensorFlow进行垃圾短信检测

训练模型-1

在Python中使用TensorFlow进行垃圾短信检测

绘制模型-1的历史图。

在Python中使用TensorFlow进行垃圾短信检测

让我们创建辅助函数来编译、拟合和评估模型的性能。

from sklearn.metrics import precision_score, recall_score, f1_score
  
def compile_model(model):
    '''
    simply compile the model with adam optimzer
    '''
    model.compile(optimizer=keras.optimizers.Adam(),
                  loss=keras.losses.BinaryCrossentropy(),
                  metrics=['accuracy'])
  
def fit_model(model, epochs, X_train=X_train, y_train=y_train,
              X_test=X_test, y_test=y_test):
    '''
    fit the model with given epochs, train 
    and test data
    '''
    history = model.fit(X_train,
                        y_train,
                        epochs=epochs,
                        validation_data=(X_test, y_test),
                        validation_steps=int(0.2*len(X_test)))
    return history
  
def evaluate_model(model, X, y):
    '''
    evaluate the model and 返回 accuracy, 
    precision, recall and f1-score 
    '''
    y_preds = np.round(model.predict(X))
    accuracy = accuracy_score(y, y_preds)
    precision = precision_score(y, y_preds)
    recall = recall_score(y, y_preds)
    f1 = f1_score(y, y_preds)
  
    model_results_dict = {'accuracy': accuracy,
                          'precision': precision,
                          'recall': recall,
                          'f1-score': f1}
  
    return model_results_dict

模型-2双向LSTM

双向LSTM(长短期记忆)是由两个LSTM组成的,一个接受一个方向的输入,另一个接受另一个方向的输入。双向LSTM有效地提高了网络的可访问信息,提升了算法的上下文(例如,知道在一个句子中紧跟在一个词后面和前面的词是什么)。

建立和编译模型-2

input_layer = layers.Input(shape=(1,), dtype=tf.string)
vec_layer = text_vec(input_layer)
embedding_layer_model = embedding_layer(vec_layer)
bi_lstm = layers.Bidirectional(layers.LSTM(
    64, activation='tanh', return_sequences=True))(embedding_layer_model)
lstm = layers.Bidirectional(layers.LSTM(64))(bi_lstm)
flatten = layers.Flatten()(lstm)
dropout = layers.Dropout(.1)(flatten)
x = layers.Dense(32, activation='relu')(dropout)
output_layer = layers.Dense(1, activation='sigmoid')(x)
model_2 = keras.Model(input_layer, output_layer)
  
compile_model(model_2)  # compile the model
history_2 = fit_model(model_2, epochs=5)  # fit the model

训练模型

在Python中使用TensorFlow进行垃圾短信检测

模型-3转移学习与USE编码器

迁移学习

迁移学习是一种机器学习方法,其中为一项工作产生的模型被用作不同任务的模型的基础。

USE层(通用句子编码器)

通用句子编码器将文本转换为高维向量,可用于文本分类、语义相似性和其他自然语言应用。

USE可以从tensorflow_hub下载,并可以使用.kerasLayer()函数作为一个层。

import tensorflow_hub as hub
  
# model with Sequential api
model_3 = keras.Sequential()
  
# universal-sentence-encoder layer 
# directly from tfhub
use_layer = hub.KerasLayer("https://tfhub.dev/google/universal-sentence-encoder/4",
                           trainable=False,
                           input_shape=[],
                           dtype=tf.string,
                           name='USE')
model_3.add(use_layer)
model_3.add(layers.Dropout(0.2))
model_3.add(layers.Dense(64, activation=keras.activations.relu))
model_3.add(layers.Dense(1, activation=keras.activations.sigmoid))
  
compile_model(model_3)
  
history_3 = fit_model(model_3, epochs=5)

编译和训练模型

在Python中使用TensorFlow进行垃圾短信检测

使用USE的训练模型

分析我们的模型性能

我们将使用我们之前创建的辅助函数来评估模型的性能。

baseline_model_results = evaluate_model(baseline_model, X_test_vec, y_test)
model_1_results = evaluate_model(model_1, X_test, y_test)
model_2_results = evaluate_model(model_2, X_test, y_test)
model_3_results = evaluate_model(model_3, X_test, y_test)
  
total_results = pd.DataFrame({'MultinomialNB Model':baseline_model_results,
                             'Custom-Vec-Embedding Model':model_1_results,
                             'Bidirectional-LSTM Model':model_2_results,
                             'USE-Transfer learning Model':model_3_results}).transpose()
  
total_results

输出

在Python中使用TensorFlow进行垃圾短信检测

绘制结果

在Python中使用TensorFlow进行垃圾短信检测

Metrics

所有四个模型都提供了出色的结果。(所有这些模型的准确率都大于96%),因此对它们进行比较可能很困难。

问题

我们有一个不平衡的数据集;我们的大多数数据点都包含 “火腿 “的标签,这很自然,因为大多数短信都是火腿。在某些情况下,准确度不能成为一个合适的衡量标准。需要其他的衡量标准。

哪种指标更好?

  • 假阴性和假阳性在这个问题上是很重要的。精度和召回率是让我们有能力计算它们的指标,但还有一个,即 “f1-score”。
  • f1-分数是准确率和召回率的谐波平均值。因此,我们可以通过一次拍摄得到这两样东西。
  • USE-Transfer学习模型给出了最好的准确性和f1分数。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程

Tensorflow 教程