使用TensorFlow训练垃圾评论过滤模型
TensorFlow 是目前流行的深度学习开源框架之一,其特点是系统生态完整,扩展灵活,并提供多语言支持(Python、C++、Java、JavaScript、R等),通过集成 Keras 高阶 API,可以方便、快捷地构建学习模型,非常适合做生产级别的应用部署。另一个框架 PyTorch 也很受欢迎,而且在学术界用的很多。
我们知道评论内容过滤属于文本分类方面的深度学习应用,主要是根据语料库(评论内容)提取出词向量(词的向量表征),词向量的表征可以建立词之间语义相关性的描述,即词的上下文关系,比如语义相似的词在向量表征上距离是靠近的。
如何得到词向量呢,那就是词嵌入(Word Embedding),词嵌入把单独的词(高维度)转换成向量(低维度),并通过深度学习模型的建立和训练找出词之间的语义分类及相关性表征(词向量)。训练好的模型可以对新的文字信息进行语义分类并据此作出相应的判断。
对于评论内容过滤的深度学习应用,主要分成三个步骤来实现,即词数据集的建立、创建学习模型/训练模型、借助模型做预测,下面分别详细说明。
一、准备评论内容数据集
可以使用已有的数据集(网上有很多| 1 | 2)或者自建数据集,这里举例导入 WordPress 中的评论建立数据集。
首先到 WordPress 管理工具后台,选择工具->导出,选择“文章”,点击“下载导出的文件”按钮,生成一个带日期的 XML 格式的文件,里面包含了所有文章及其评论的数据,下面用代码提取评论数据。
1、建立 Python 虚拟环境
为方便后面的介绍,先建立工作环境,创建 Python 虚拟环境有很多方法,这里使用Mini Conda
$ mkdir work
$ cd work
$ mkdir data
$ mkdir model
### 去官网下载安装脚本,注意OS和Python版本号
$bash Miniconda3-latest-Linux-x86_64.sh
### 创建并激活虚拟环境
$ conda create –name tf python=3.9
$ conda activate tf
### 安装 TensorFlow
$ pip install tensorflow
2、提取 WordPress 评论数据集
### 把下载的WordPress.xml文件放到data目录下
### 数据集的格式:
### ham 有效评论
### spam 无效评论
### 安装 Python 包 wpparser
$ pip install wpparser
#!/usr/bin/python
import wpparser
MAX_NUM_WORDS = 700
data = wpparser.parse("./data/WordPress.xml")
#有效评论
ham = [0,3,5,10,12,13,14,16,17,18,19,20]
#评论数据集在data目录下,文件名是my-spam-datasets
handle = open("./data/my-spam-datasets", "a+")
i = 0
for post in data['posts']:
comment = post['comments']
if(comment):
comm_content = post['comments'][0]['content'].replace("\n", "")
if(len(comm_content) > MAX_NUM_WORDS):
comm_content = comm_content[:MAX_NUM_WORDS]
print(comm_content)
print("-------------\n")
if(i in ham):
handle.writelines('ham\t' + comm_content + '\n')
else:
handle.writelines('spam\t' + comm_content + '\n')
i += 1
handle.close()
二、使用评论数据集建立、训练、评估和保存模型
保存的模型可重新装载使用,也能用于再训练。保存模型有两种格式,即 SaveModel 和 HDF5,这里使用了 HDF5 的格式。SaveModel 格式更加全面、灵活,可以自适应 TensorFlow Serving。保存后的 HDF5 格式的模型是一个文件,SaveModel 格式的模型是一个目录。
import pickle
import tensorflow as tf
import numpy as np
from tensorflow.keras import layers
from tensorflow.keras.layers import TextVectorization
from tensorflow.keras.utils import to_categorical
from sklearn.model_selection import train_test_split
from tensorflow.keras.models import Sequential
VOCAB_SIZE = 10000
SEQUENCE_LENGTH = 100
EMBEDDING_DIM = 128 # 嵌入层的维度
TEST_SIZE = 0.3 # 测试数据集合的比例
EPOCHS = 5 # 迭代次数
lstm_units = 196
label2int = {"ham": 0, "spam": 1}
int2label = {0: "ham", 1: "spam"}
texts, labels = [], []
with open("data/my-spam-datasets") as f:
for line in f:
split = line.split()
labels.append(split[0].strip())
texts.append(' '.join(split[1:]).strip())
X, y = texts, labels
int_vectorize_layer = TextVectorization(
max_tokens=VOCAB_SIZE,
output_mode='int',
output_sequence_length=SEQUENCE_LENGTH)
int_vectorize_layer.adapt(X)
def int_vectorize_text(text, label):
text = tf.expand_dims(text, -1)
return int_vectorize_layer(text), label
X, y = int_vectorize_text(X, y)
X = np.array(X)
y = np.array(y)
y = [ label2int[label] for label in y ]
y = to_categorical(y)
X_train, X_test, y_train, y_test = train_test_split(X, y,test_size=TEST_SIZE, random_state=42)
#创建模型
model = tf.keras.Sequential([
layers.Embedding(VOCAB_SIZE + 1, EMBEDDING_SIZE, mask_zero=True),
layers.Conv1D(64, 6, padding="valid", activation="relu", strides=2),
layers.GlobalMaxPooling1D(),
layers.Dense(num_labels, activation="softmax")
])
model.compile(loss="categorical_crossentropy", optimizer='adam',
metrics=['accuracy'])
model.summary()
# 训练模型
model.fit(X_train, y_train, validation_data=(X_test, y_test),
epochs=EPOCHS, verbose=1)
# 评估模型,获取准确率数据
loss, accuracy = model.evaluate(X_test, y_test)
print(f"Loss: {loss*100:.2f}%")
print(f"Accuracy: {accuracy*100:.2f}%")
# 使用文本向量层和训练好的模型建立新模型
export_model = tf.keras.Sequential(
[int_vectorize_layer, model])
export_model.compile(
loss="categorical_crossentropy",
optimizer='adam',
metrics=['accuracy'])
# 保存模型到当前目录的model子目录下
model.save("model")
三、预测
newcomment = "VPS of any kind Open VZ, KVM and Hyper-V starting from $25.00 per month,Free Setup and no Hidden Charges."
prediction = export_model.predict([newcomment])
print("该条评论是", int2label[np.argmax(prediction)])
# 结果应该是 "spam"。
###写到一个单独的文件中(predict.py),可以在命令行中使用。
$ python predict.py “Hello World!”
import sys
import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.layers import TextVectorization
VOCAB_SIZE = 10000
SEQUENCE_LENGTH = 100
int2label = {0: "ham", 1: "spam"}
model = keras.models.load_model("model")
model.summary()
int_vectorize_layer = TextVectorization(
max_tokens=VOCAB_SIZE,
output_mode='int',
output_sequence_length=SEQUENCE_LENGTH)
def int_vectorize_text(text):
text = tf.expand_dims(text, -1)
return int_vectorize_layer(text)
def get_predictions(text):
prediction = model.predict(text)
return int2label[np.argmax(prediction)]
input_text = [sys.argv[1]]
int_vectorize_layer.adapt(input_text)
X, y = int_vectorize_text(input_text, None)
X = np.array(X)
print(get_predictions(X))
另外网上有很多训练好的词向量,可以在训练自己模型的时候使用,详细的使用方法可以参考这篇文章的介绍。更多的数据集还可以用 Google Dataset Search 查找。