本文共 8660 字,大约阅读时间需要 28 分钟。
我又回来了,这次进行英文垃圾短信分类任务。下面将分别用机器学习
和深度学习
的方法进行操作,此外深度学习
的方法又分别用RNN
和CNN
的方法进行展示,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来实现CounterVectorizer
和TfidfVectorizer
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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!