【实战】英文垃圾短信分类
发布日期:2021-06-29 15:32:17 浏览次数:3 分类:技术文章

本文共 8660 字,大约阅读时间需要 28 分钟。

我又回来了,这次进行英文垃圾短信分类任务。下面将分别用机器学习深度学习的方法进行操作,此外深度学习的方法又分别用RNNCNN的方法进行展示,Let’s go!!!

充满活力的冲啊!!!

一、英文垃圾短信分类

这次的任务很简单,就是一个二分类的任务。不过属于nlp的二分类的任务。给出短信内容,判别该短信是否是垃圾短信。

那么,那么,那么,重点来了!既然要做本次实验,怎么能没有数据集呢?

数据集才是驱动力呀!

数据集是kaggle下载的,来判别短信内容是否为垃圾短信。

二、机器学习方法进行英文垃圾短信分类

1.数据集

首先先读取数据集,我们先看一下数据集的模样。

不对,应该是这样的。

之后,统计一下,数据的分布情况。从图中我们看到短信的类别存在不平衡的情况。

# 以图方式表示sns.countplot(sms_data["label"])plt.xlabel("Label")plt.title("Number of ham of spam messages")

既然存在样本不平衡的情况,那么下面对数据预处理的时候,我们就需要对这情况进行处理,这里的处理在深度学习的部分。

2.数据预处理

a.分割数据

为了评估效果,我们需要对数据集进行分割,来划出一部分,用来测试。

b.文本特征提取

这里将短信的内容,将文本数据转为特征向量。

比较常用的文本特征表示法为词袋法

词袋法:

  • 不考虑词语出现的顺序,每个出现过的词汇单独作为一列特征
  • 这些不重复的特征词汇集合为词表
  • 每一个文本都可以在很长的词表上统计出一个很多列的特征向量
  • 如果每个文本都出现的词汇,一般被标记为停用词 不计入特征向量

主要有两个api来实现CounterVectorizerTfidfVectorizer

CountVectorizer:

  • 只考虑词汇在文本中出现的频率

TfidfVectorizer:

  • 除了考量某词汇在文本出现的频率,还关注包含这个词汇的所有文本的数量
  • 能够消减高频没有意义的词汇出现带来的影响,挖掘更有意义的特征。

这里给出TfidfVectorizer的部分代码,

3.机器学习大杂烩

a.模型满汉全席

将常见的模型,拿出来,进行评估,废话不多讲,直接上代码

models = {
"SVC":SVC(kernel="linear"), "MultinomialNB":MultinomialNB(), "LogisticRegression":LogisticRegression(), "KNeighborsClassifier":KNeighborsClassifier(), "DecisionTreeClassifier":DecisionTreeClassifier(), "RandomForestClassifier":RandomForestClassifier(), "AdaBoostClassifier":AdaBoostClassifier(), "BaggingClassifier":BaggingClassifier(), "ExtraTreesClassifier":ExtraTreesClassifier()}prediction = dict()score_map = {
}for model_name in models: model = models[model_name] model.fit(x_train_df,y_train) prediction[model_name]=model.predict(x_test_df) score=accuracy_score(y_test,prediction[model_name]) score_map[model_name]=score result = pd.DataFrame()result["model"] = score_map.keys()result["score" ]=score_map.values()result["score"]=result["score"].apply(lambda x : x*100)

最后让我们看一下结果,可以看到支持向量机的效果很好,而且这只是默认参数的情况下,下面调一下参,在看一下。

def plot_model_performace(result):    sns.set_style("ticks")    figsize=(22,6)        ticksize=12    titlesize=ticksize+8    labelsize=ticksize+5        xlabel="Model"    ylabel="Score"        title="Model Performance"        params={
"figure.figsize":figsize, "axes.labelsize":labelsize, "axes.titlesize":titlesize, "xtick.labelsize":ticksize, "ytick.labelsize":ticksize} plt.rcParams.update(params) col1="model" col2="score" sns.barplot(x=col1,y=col2,data=result) plt.title(title.title()) plt.xlabel(xlabel) plt.ylabel(ylabel) plt.xticks(rotation=90) plt.grid() plt.plot() plt.show() print(result)

b.超参数调参

现在就由最伟大的炼丹师出场了。

from sklearn.model_selection import GridSearchCVparam_grid = {
"alpha":np.concatenate( [ np.arange(0.0001,0.001,0.0001), np.arange(0.001,0.01,0.001), np.arange(0.01,0.1,0.01), np.arange(0.1,1,0.1), np.arange(1,10,1), np.arange(10,100,5) ] )}model = MultinomialNB()grid_cv_model = GridSearchCV(model,param_grid,n_jobs=-1,verbose=3,cv=3)grid_cv_model.fit(x_train_df,y_train)#对指标评价print("{}{}".format("Best Estimator: ",grid_cv_model.best_estimator_))print("{}{}".format("Besr Params: ",grid_cv_model.best_params_))print("{}{}".format("Bset Scores: ",grid_cv_model.best_score_))

并用混淆矩阵来评价一下

# 混淆矩阵def plot_confusion_matrix(y_test,y_pred,title=""):    conf_mat=confusion_matrix(y_test,y_pred)    conf_mat_normalized=conf_mat.astype("float")/conf_mat.sum(axis=1)[:,np.newaxis]        figsize=(22,5)        ticksize=18    titlesize=ticksize+8    labelsize=ticksize+5        xlabel="Predicted label"    ylabel="True label"        params={
"figure.figsize":figsize, "axes.labelsize":labelsize, "axes.titlesize":titlesize, "xtick.labelsize":ticksize, "ytick.labelsize":ticksize} plt.rcParams.update(params) plt.subplot(121) sns.heatmap(conf_mat,annot=True) plt.title(title) plt.xlabel(xlabel) plt.ylabel(ylabel) plt.subplot(122) sns.heatmap(conf_mat_normalized,annot=True) plt.title(title) plt.xlabel(xlabel) plt.ylabel(ylabel) plt.show() print("Confusion Matrix:\n") print(conf_mat) print("\n\nConfusion Matrix Normalized:\n") print(conf_mat_normalized)

终于终于终于才写了一半,好想拆开,这样就能水两篇了。(其实这篇也是来水的)

三、深度学习英文垃圾短信分类

在本节,将分别用CNN和RNN模型进行操作,准备好了么,让我们出发!

1.数据集

数据集可参照上部分,并没有多大变化,都是驱动力。

2.数据预处理

a.样本不均衡

我们在上述数据集的观察下,发现样本数据存在不均衡的情况,这里处理一下。

使用sklearn.utils.class_weight样本均衡操作。当我们的数据,有多个类别,每个类别的数据量有很大差距时,这时需要对每个类别的样本做一次均衡,这样会让每个类别的特征都在一定程度上被模型学习。

# 计算各个类别的weightsdef get_weight(y):    class_weight_current = cw.compute_class_weight("balanced",np.unique(y),y)    return class_weight_currentclass_weight = get_weight(y_train.flatten())

b.文本数据处理

使用分词器Tokenier进行文本数据处理。分词器Tokenizer Tokenizer是一个用于向量化文本,或将文本转换为序列(即单词在字典中的下标构成的列表,从1算起)的类方法

# 分词器Tokenizer   Tokenizer是一个用于向量化文本,或将文本转换为序列(即单词在字典中的下标构成的列表,从1算起)的类方法           # fit_on_texts(texts) :texts用于训练的文本列表          # texts_to_sequences(texts):texts待转为序列的文本列表 返回值:序列的列表,列表中的每个序列对应于一段输入文本# 填充序列pad_sequences  将长为nb_smaples的序列转换为(nb_samples,nb_timesteps)2Dnumpy attay.如果提供maxlen,nb_timesteps=maxlen,否则其值为最长序列的长度。# 其它短于该长度的序列都会在后部填充0以达到该长度。长与nb_timesteps的序列会被阶段,以使其匹配该目标长度。#max_words = 1000#max_len = 150max_words = len(set(" ".join(x_train).split()))max_len = x_train.apply(lambda x:len(x)).max()tok = Tokenizer(num_words=max_words)tok.fit_on_texts(x_train)sequences = tok.texts_to_sequences(x_train)sequences_matrix = sequence.pad_sequences(sequences,maxlen=max_len)

c.超参数的设置

  • ModelCheckpoint:

    • 作用:该回调函数将在每个epoch后保存模型到filepath
    • 参数:
      • filename:字符串,保存模型的路径,filepath可以是格式化的字符串,里面的
      • monitor:需要监视的值,通常为:val_acc或val_loss或acc或loss
      • verbose:信息展示模型,0或1。默认为0表示不输出该信息,为1表示输出epoch模型保存信息。
      • save_best_only:当设置为Trur时,将只保存在验证集上性能最好的模型
      • mode:“auto”,“min”,"max"之一,在save_best_only=True时决定性能最佳模型的评判准则。
      • save_weights_only:若设置为True时,则只保存模型权重,否则将保存整个模型(包括模型结构,配置信息等)
      • period:CheckPoint之间的间隔的epoch数
  • EarlyStopping:

    • 作用:当监测值不再改善时,该回调函数将中止训练
    • 参数:
      • monitor:需要监视的量,通常为val_acc或val_loss或acc或loss
      • patience:当early stop被激活(如发现loss相比上patience个epoch训练没有下降),则经过patience个epoch后停止训练。
      • verbose:信息展示模型
      • mode:“auto”,“min”,"max"之一,在min模式下,如果检测值停止下降则中止训练。在max模式下,当检测值不再上升则停止训练。
  • ReduceLROnPlateau:

    • 作用:当评价指标不再提升时,减少学习率。当学习停滞时,减少2倍或10倍的学习率通常能够获得较好的效果。该回调函数检测指标的情况,如果在patience个epoch中看不到模型性能提升,则减少学习率。
    • 参数:
      • monitor:被监测的量
      • factor:每次减少学习率的因子,学习率将以lr=lr*factor的形式被技术那好
      • patience:当patience个epoch过去而模型性能不提升时,学习率减少的动作会被触发
      • mode:“auto”,“min”,"max"之一,在min模式下,如果检测值触发学习率减少。在max模式下,当检测值不再上升则触发学习率减少
      • epsilon:阈值,用来确定是否进入检测值的“平原区”
      • cooldown:学习率减少后,会经过cooldown个epoch才重新进行正常操作
      • min_lr:学习率的下限。
print("Setting Callbacks")checkpoint = ModelCheckpoint("model.hdf5",                                                     monitor="val_acc",                                                     save_best_only=True,                                                     mode="max")early_stopping = EarlyStopping(monitor="val_loss",                                                     patience=2,                                                     verbose=1,                                                     restore_best_weights=True,                                                     mode="min")reduce_lr = ReduceLROnPlateau(monitor="val_loss",                                                      factor=0.6,                                                      patience=1,                                                      verbose=1,                                                      mode="min")callbacks=[checkpoint,early_stopping,reduce_lr]print("Set Callbacks at",date_time(1))

3.深度学习模型

下面,分别定义一个CNN模型和RNN模型,然后进行训练和测试。

a.定义RNN模型

# 定义RNN模型def RNN():    model = Sequential()        model.add(Embedding(max_words,50,input_length=max_len))    model.add(LSTM(64))        model.add(Dropout(0.5))    model.add(BatchNormalization())    model.add(Dropout(0.5))        model.add(Dense(256,activation="relu"))        model.add(Dropout(0.5))    model.add(BatchNormalization())    model.add(Dropout(0.5))        model.add(Dense(1,activation="sigmoid"))        model.summary()        return model

给出最后的曲线结果图。

b.定义CNN模型

# 定义CNN模型def CNN():    model=Sequential()        model.add(Embedding(max_words,50,input_length=max_len))        model.add(Conv1D(64,3,padding="valid",activation="relu",strides=1))    model.add(GlobalMaxPooling1D())    model.add(Dropout(0.5))    model.add(BatchNormalization())    model.add(Dropout(0.5))        model.add(Dense(256,activation="relu"))        model.add(Dropout(0.5))    model.add(BatchNormalization())    model.add(Dropout(0.5))        model.add(Dense(1,activation="sigmoid"))    model.summary()    return model

效果的话,还是RNN更好一些。

好了,终于写完了,过一阵,再写一个关于音频分类的,最近找音频分类的代码,发现这类代码好少,不过我也不是做这方向,就随意水一水,好不好。

转载地址:https://codingchaozhang.blog.csdn.net/article/details/104505984 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:手把手搭建一套简单的直播系统
下一篇:[实战]200类鸟类细粒度图像分类

发表评论

最新留言

表示我来过!
[***.240.166.169]2024年04月24日 15时41分35秒