17、异构集成分类器与文本分类:从H2O到NLP的实践

异构集成分类器与文本分类:从H2O到NLP的实践

1. 异构集成分类器使用H2O

1.1 模型训练与评估

在使用H2O进行异构集成分类器的构建时,我们首先训练了堆叠集成模型,使用 H2OStackedEnsembleEstimator 。具体步骤如下:
1. 步骤18 - 20 :使用 H2OStackedEnsembleEstimator 训练堆叠集成模型,并在测试数据上评估其性能。
2. 步骤21 :在测试数据上评估所有构建的GLM模型,同样对使用RF和GBM训练的所有模型进行评估。
3. 步骤22 :找出具有最大AUC分数的模型。
4. 步骤23 :评估堆叠集成模型在测试数据上的AUC分数,以便与单个基础学习器的性能进行比较。

1.2 交叉验证

在训练所有模型时,我们使用了交叉验证。通过 nfolds 选项设置交叉验证的折数,例如设置 nfolds = 5 ,也可以设置为更高的数字。需要注意的是,所有构建的模型的折数必须相同。

当指定了 nfolds 的值后,还可以为 fold_assignment 参数提供值。 fold_assignment 可以取 auto random modulo stratified 等值:
- auto :算法自动选择一个选项,目前选择 Random
- Random :将数据随机拆分为 nfolds 个集合。
- Modulo :使用确定性方法将数据均匀拆分为 nfolds 个集合,不依赖于种子参数。

在使用交叉验证方法构建模型时,要确保为所有模型指定种子值或使用 fold_assignment = "Modulo"

1.3 网格搜索参数

在网格搜索中,我们使用了两个参数: stopping_metric stopping_rounds 。这些参数适用于GBM和随机森林算法,但不适用于GLM。
- stopping_metric :指定在指定提前停止时要考虑的指标,可以通过将 stopping_rounds 设置为大于零的值来实现。例如,我们将 stopping_metric 设置为AUC, stopping_rounds 设置为5。这意味着如果在指定的轮数(这里是5轮)内AUC没有改善,算法将在停止进一步训练之前测量AUC。
- stopping_rounds :如果指定了 stopping_metric ,则必须设置 stopping_rounds
- stopping_tolerance :当也设置了 stopping_tolerance 时,如果模型的 stopping_metric 没有提高 stopping_tolerance 值,模型将在达到 stopping_rounds 中提到的轮数后停止训练。

以下是相关参数的总结表格:
| 参数 | 适用算法 | 说明 |
| ---- | ---- | ---- |
| stopping_metric | GBM、随机森林 | 指定提前停止时考虑的指标 |
| stopping_rounds | GBM、随机森林 | 与 stopping_metric 配合使用,指定轮数 |
| stopping_tolerance | GBM、随机森林 | 与 stopping_rounds 配合,指定指标改善的容忍度 |

2. 基于NLP的文本分类异构集成

2.1 文本分类概述

文本分类是语言处理和文本挖掘中广泛研究的领域。通过文本分类机制,我们可以根据文档的内容将其分类到预定义的类别中。在这个例子中,我们将关注如何对手机收到的短文本消息进行分类,以避免垃圾邮件并防止错过重要消息。

2.2 垃圾邮件过滤

我们使用UCI ML存储库中的SMS Spam Collection数据集来创建一个垃圾邮件分类器。可以使用各种分类器将消息分类为垃圾邮件(spam)或正常邮件(ham),这里我们选择了朴素贝叶斯、随机森林和支持向量机等算法来训练模型。

2.3 数据预处理

在使用数据之前,我们需要对其进行预处理,具体步骤如下:
1. 将所有文本转换为小写
2. 去除标点符号
3. 去除停用词
4. 进行词干提取
5. 对数据进行分词

我们还使用词频 - 逆文档频率(TF - IDF)对数据进行处理。TF的计算公式为:
[TF = \frac{一个单词在文档中出现的次数}{文档中的总单词数}]

TF - IDF根据单词在文档或文档集合中出现的频率对单词的重要性进行数值评分。简单来说,TF - IDF分数越高,该术语越罕见;分数越低,越常见。其数学表示为:
[tfidf(w,d,D) = tf(t,d) \times idf(t,D)]
其中,$w$表示单词,$d$表示文档,$D$表示文档集合。

2.4 代码实现

2.4.1 导入所需库
import os
import numpy as np
import pandas as pd
import itertools
import warnings
import string
import matplotlib.pyplot as plt
from nltk.corpus import stopwords
from nltk.stem import WordNetLemmatizer
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import confusion_matrix
from sklearn.model_selection import GridSearchCV
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report
from sklearn.metrics import roc_auc_score as auc
from sklearn.metrics import roc_curve
from sklearn.metrics import accuracy_score
from scipy.stats import mode
2.4.2 定义绘制混淆矩阵的函数
def plot_confusion_matrix(cm, classes,
                          normalize=False,
                          title='Confusion matrix',
                          cmap=plt.cm.Blues):
    plt.imshow(cm, interpolation='nearest', cmap=cmap)
    plt.title(title)
    plt.colorbar()
    tick_marks = np.arange(len(classes))
    plt.xticks(tick_marks, classes, rotation=45)
    plt.yticks(tick_marks, classes)
    fmt = '.2f' if normalize else 'd'
    thresh = cm.max() / 2.
    for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
        plt.text(j, i, format(cm[i, j], fmt),
                 horizontalalignment="center",
                 color="white" if cm[i, j] > thresh else "black")
    plt.ylabel('True label')
    plt.xlabel('Predicted label')
    plt.tight_layout()
2.4.3 设置工作目录并读取数据集
os.chdir("/.../Chapter 11/CS - SMS Classification")
os.getcwd()
df_sms = pd.read_csv("sms_labeled_data.csv", encoding = 'utf8')
2.4.4 检查数据加载情况
df_sms.head()
df_sms.shape
2.4.5 查看垃圾邮件和正常邮件的数量
# 正常邮件数量
print(df_sms["type"].value_counts()[0])
no_of_ham_messages = df_sms["type"].value_counts()[0]
# 垃圾邮件数量
print(df_sms["type"].value_counts()[1])
no_of_spam_messages = df_sms["type"].value_counts()[1]
2.4.6 可视化垃圾邮件和正常邮件的比例
sms_count = pd.value_counts(df_sms["type"], sort= True)
ax = sms_count.plot(kind='bar', figsize=(10,10), color= ["green", "orange"], fontsize=13)
ax.set_alpha(0.8)
ax.set_title("Percentage Share of Spam and Ham Messages")
ax.set_ylabel("Count of Spam & Ham messages");
ax.set_yticks([0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500, 5000, 5500])
totals = []
for i in ax.patches:
    totals.append(i.get_height())
total = sum(totals)

# 设置单个条形图标签
for i in ax.patches:
    string = str(round((i.get_height()/total)*100, 2))+'%'
    ax.text(i.get_x()+0.16, i.get_height(), string, fontsize=13, color='black')
2.4.7 定义文本处理函数
lemmatizer = WordNetLemmatizer()
# 定义去除标点符号、将文本转换为小写并去除停用词的函数
def process_text(text):
    no_punctuations = [char for char in text if char not in string.punctuation]
    no_punctuations = ''.join(no_punctuations)
    clean_words = [word.lower() for word in no_punctuations.split() if word.lower() not in stopwords.words('english')]
    clean_words = [lemmatizer.lemmatize(lem) for lem in clean_words]
    clean_words = " ".join(clean_words)
    return clean_words
2.4.8 应用文本处理函数
df_sms['text'] = df_sms['text'].apply(process_text)
2.4.9 分离特征和目标变量,并进行数据拆分
X = df_sms.loc[:,'text']
Y = df_sms.loc[:,'type']
Y = Y.astype('int')
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=.3, random_state=1)
2.4.10 使用CountVectorizer和TfidfVectorizer转换文本
count_vectorizer = CountVectorizer(stop_words='english')
count_train = count_vectorizer.fit_transform(X_train)
count_test = count_vectorizer.transform(X_test)

tfidf = TfidfVectorizer(stop_words='english')
tfidf_train = tfidf.fit_transform(X_train)
tfidf_test = tfidf.transform(X_test)

2.5 模型训练与评估

接下来,我们将使用朴素贝叶斯、支持向量机和随机森林算法在计数数据和TF - IDF数据上进行模型训练,并评估模型性能。具体步骤如下:
1. 训练朴素贝叶斯模型 :分别在计数数据和TF - IDF数据上训练朴素贝叶斯模型,评估训练和测试数据的准确性,打印分类报告和绘制混淆矩阵。
2. 训练支持向量机模型 :使用 GridSearchCV 在计数数据和TF - IDF数据上进行参数搜索,评估模型性能。
3. 训练随机森林模型 :使用 GridSearchCV 在计数数据和TF - IDF数据上进行参数搜索,评估模型性能。
4. 绘制ROC曲线 :收集每个模型的预测概率,绘制ROC曲线,并比较不同模型的性能。
5. 集成模型评估 :平均所有模型的概率,绘制集成模型的ROC曲线,并检查集成结果的准确性。

以下是训练朴素贝叶斯模型在计数数据上的代码示例:

from sklearn.naive_bayes import MultinomialNB
nb = MultinomialNB()
nb.fit(count_train, Y_train)
nb_pred_train = nb.predict(count_train)
nb_pred_test = nb.predict(count_test)
nb_pred_train_proba = nb.predict_proba(count_train)
nb_pred_test_proba = nb.predict_proba(count_test)
print('The accuracy for the training data is {}'.format(nb.score(count_train, Y_train)))
print('The accuracy for the testing data is {}'.format(nb.score(count_test, Y_test)))

# 打印分类报告
print(classification_report(Y_test, nb_pred_test))

# 绘制混淆矩阵
target_names = ['Spam','Ham']
cm = confusion_matrix(Y_test, nb_pred_test)
plt.figure()
plot_confusion_matrix(cm, classes=target_names)
plt.show()

这个流程可以用mermaid流程图表示:

graph LR
    A[数据预处理] --> B[特征提取]
    B --> C[模型训练]
    C --> D[模型评估]
    D --> E[集成模型评估]

通过以上步骤,我们可以构建一个有效的文本分类异构集成模型,对短信进行垃圾邮件过滤。

2.6 各模型详细训练与评估步骤

2.6.1 朴素贝叶斯模型在TF - IDF数据上的训练与评估

在计数数据上训练完朴素贝叶斯模型后,我们还需要在TF - IDF数据上进行同样的操作。具体代码如下:

nb.fit(tfidf_train, Y_train)
nb_pred_train_tfidf = nb.predict(tfidf_train)
nb_pred_test_tfidf = nb.predict(tfidf_test)
nb_tfidf_pred_train_proba = nb.predict_proba(tfidf_train)
nb_tfidf_pred_test_proba = nb.predict_proba(tfidf_test)
print('The accuracy for the training data is {}'.format(nb.score(tfidf_train, Y_train)))
print('The accuracy for the testing data is {}'.format(nb.score(tfidf_test, Y_test)))

# 检查TF - IDF测试数据的性能统计
print(classification_report(Y_test, nb_pred_test_tfidf))
target_names = ['Spam','Ham']
cm = confusion_matrix(Y_test, nb_pred_test_tfidf)
plt.figure()
plot_confusion_matrix(cm, classes=target_names)
plt.show()

通过上述代码,我们可以得到朴素贝叶斯模型在TF - IDF数据上的训练和测试准确率,以及分类报告和混淆矩阵,从而评估模型性能。

2.6.2 支持向量机模型的训练与评估

对于支持向量机模型,我们使用 GridSearchCV 进行参数搜索,分别在计数数据和TF - IDF数据上进行训练和评估。

在计数数据上的训练与评估

from sklearn.svm import SVC
svc = SVC(kernel='rbf', probability=True)
svc_params = {'C': [0.001, 0.01, 0.1, 1, 10]}
svc_gcv_rbf_count = GridSearchCV(svc, svc_params, cv=5)
svc_gcv_rbf_count.fit(count_train, Y_train)

# 使用网格模型预测类别
svc_rbf_train_predicted_values = svc_gcv_rbf_count.predict(count_train)
svc_rbf_test_predicted_values = svc_gcv_rbf_count.predict(count_test)

# 使用网格模型预测类别概率
svc_gcv_train_proba_rbf = svc_gcv_rbf_count.predict_proba(count_train)
svc_gcv_test_proba_rbf = svc_gcv_rbf_count.predict_proba(count_test)

print('The best parameters {}'.format(svc_gcv_rbf_count.best_params_))
print('The best score {}'.format(svc_gcv_rbf_count.best_score_))

# 查看计数数据的测试准确率
print(classification_report(Y_test, svc_rbf_test_predicted_values))
target_names = ['Spam','Ham']
cm = confusion_matrix(Y_test, svc_rbf_test_predicted_values)
plt.figure()
plot_confusion_matrix(cm, classes=target_names)
plt.show()

在TF - IDF数据上的训练与评估

svc = SVC(kernel='rbf', probability=True)
svc_params = {'C': [0.001, 0.01, 0.1, 1, 10]}
svc_gcv = GridSearchCV(svc, svc_params, cv=5)
svc_gcv.fit(tfidf_train, Y_train)

# 使用网格模型预测类别
svc_tfidf_rbf_train_predicted_values = svc_gcv.predict(tfidf_train)
svc_tfidf_rbd_test_predicted_values = svc_gcv.predict(tfidf_test)

# 使用网格模型预测类别概率
svc_gcv_tfidf_train_proba_rbf = svc_gcv.predict_proba(tfidf_train)
svc_gcv_tfidf_test_proba_rbf = svc_gcv.predict_proba(tfidf_test)

print('The best parameters {}'.format(svc_gcv.best_params_))
print('The best score {}'.format(svc_gcv.best_score_))

# 打印分类报告和混淆矩阵
print(classification_report(Y_test, svc_tfidf_rbd_test_predicted_values))
target_names = ['Spam','Ham']
cm = confusion_matrix(Y_test, svc_tfidf_rbd_test_predicted_values)
plt.figure()
plot_confusion_matrix(cm, classes=target_names)
plt.show()

通过 GridSearchCV ,我们可以找到支持向量机模型在不同数据上的最优参数和最佳得分,同时通过分类报告和混淆矩阵评估模型性能。

2.6.3 随机森林模型的训练与评估

随机森林模型同样使用 GridSearchCV 进行参数搜索,分别在计数数据和TF - IDF数据上进行训练和评估。

在计数数据上的训练与评估

# 设置网格搜索参数
rf_params = {"criterion": ["gini", "entropy"], "min_samples_split": [2, 3], "max_depth": [None, 2, 3], "min_samples_leaf": [1, 5], "max_leaf_nodes": [None], "oob_score": [True]}
# 创建随机森林分类器实例
rf = RandomForestClassifier()
# 使用GridSearchCV进行网格搜索
rf_gcv = GridSearchCV(rf, rf_params, cv=5)
# 拟合模型到训练数据
rf_gcv.fit(count_train, Y_train)

# 使用网格模型预测类别
rf_train_predicted_values = rf_gcv.predict(count_train)
rf_test_predicted_values = rf_gcv.predict(count_test)

# 使用网格模型预测类别概率
rf_gcv_pred_train_proba = rf_gcv.predict_proba(count_train)
rf_gcv_pred_test_proba = rf_gcv.predict_proba(count_test)

print('The best parameters {}'.format(rf_gcv.best_params_))
print('The best score {}'.format(rf_gcv.best_score_))

# 查看随机森林模型在计数数据上的性能指标
print(classification_report(Y_test, rf_test_predicted_values))
target_names = ['Spam','Ham']
cm = confusion_matrix(Y_test, rf_test_predicted_values)
plt.figure()
plot_confusion_matrix(cm, classes=target_names)
plt.show()

在TF - IDF数据上的训练与评估

# 设置网格搜索参数
rf_params = {"criterion": ["gini", "entropy"], "min_samples_split": [2, 3], "max_depth": [None, 2, 3], "min_samples_leaf": [1, 5], "max_leaf_nodes": [None], "oob_score": [True]}
# 创建随机森林分类器实例
rf = RandomForestClassifier()
# 使用GridSearchCV进行网格搜索
rf_gcv = GridSearchCV(rf, rf_params, cv=5)
rf_gcv.fit(tfidf_train, Y_train)

# 使用网格模型预测类别
rf_tfidf_train_predicted_values = rf_gcv.predict(tfidf_train)
rf_tfidf_test_predicted_values = rf_gcv.predict(tfidf_test)

# 使用网格模型预测类别概率
rf_gcv_tfidf_pred_train_proba = rf_gcv.predict_proba(tfidf_train)
rf_gcv_tfidf_pred_test_proba = rf_gcv.predict_proba(tfidf_test)

print('The best parameters {}'.format(rf_gcv.best_params_))
print('The best score {}'.format(rf_gcv.best_score_))

print(classification_report(Y_test, rf_tfidf_test_predicted_values))
target_names = ['Spam','Ham']
cm = confusion_matrix(Y_test, rf_tfidf_test_predicted_values)
plt.figure()
plot_confusion_matrix(cm, classes=target_names)
plt.show()

通过上述代码,我们可以得到随机森林模型在不同数据上的最优参数、最佳得分,以及分类报告和混淆矩阵,从而全面评估模型性能。

2.7 ROC曲线绘制与集成模型评估

2.7.1 单个模型的ROC曲线绘制

我们可以使用 roc_curve auc 函数绘制每个模型的ROC曲线,以直观地比较它们的性能。以下是朴素贝叶斯模型在计数数据上的ROC曲线绘制代码示例:

fpr, tpr, thresholds = roc_curve(Y_test, nb_pred_test_proba[:, 1])
roc_auc = auc(Y_test, nb_pred_test_proba[:, 1])
plt.title('ROC Naive Bayes (Count)')
plt.plot(fpr, tpr, 'b', label='AUC = %0.3f' % roc_auc)
plt.legend(loc='lower right')
plt.plot([0, 1], [0, 1], 'r--')
plt.xlim([-0.1, 1.0])
plt.ylim([-0.1, 1.01])
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')

通过绘制ROC曲线,我们可以根据AUC值评估模型的性能,AUC值越接近1,模型性能越好。

2.7.2 集成模型的ROC曲线绘制与评估

为了评估集成模型的性能,我们将所有模型的概率进行平均,并绘制集成模型的ROC曲线。具体代码如下:

# 测试计数数据
d = (nb_pred_test_proba + svc_gcv_test_proba_rbf + rf_gcv_pred_test_proba) / 3
fpr, tpr, thresholds = roc_curve(Y_test, d[:, 1])
roc_auc = auc(Y_test, d[:, 1])
plt.subplot(4, 3, 7)
plt.title('ROC Ensemble (Count)')
plt.plot(fpr, tpr, 'b', label='AUC = %0.3f' % roc_auc)
plt.legend(loc='lower right')
plt.plot([0, 1], [0, 1], 'r--')
plt.xlim([-0.1, 1.0])
plt.ylim([-0.1, 1.01])
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')

# 测试TF - IDF数据
d = (nb_tfidf_pred_test_proba + svc_gcv_tfidf_test_proba_rbf + rf_gcv_tfidf_pred_test_proba) / 3
fpr, tpr, thresholds = roc_curve(Y_test, d[:, 1])
roc_auc = auc(Y_test, d[:, 1])
plt.subplot(4, 3, 8)
plt.title('ROC Ensemble (TF - IDF)')
plt.plot(fpr, tpr, 'b', label='AUC = %0.3f' % roc_auc)
plt.legend(loc='lower right')
plt.plot([0, 1], [0, 1], 'r--')
plt.xlim([-0.1, 1.0])
plt.ylim([-0.1, 1.01])
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')

plt.tight_layout(pad=1, rect=(0, 0, 3.5, 4))
plt.show()

通过绘制集成模型的ROC曲线,我们可以直观地看到集成模型在计数数据和TF - IDF数据上的性能。

2.7.3 集成模型的准确性检查

最后,我们可以通过创建预测结果数组来检查集成模型的准确性:

predicted_array = np.array([nb_pred_test_tfidf, svc_tfidf_rbd_test_predicted_values, rf_tfidf_test_predicted_values])
print("Each array is the prediction of the respective models")
print(predicted_array)

通过以上步骤,我们完成了基于NLP的文本分类异构集成模型的构建、训练、评估和可视化,能够有效地对短信进行垃圾邮件过滤。整个流程可以总结为以下表格:
| 步骤 | 操作 | 代码实现 |
| ---- | ---- | ---- |
| 数据预处理 | 文本转换、去标点、去停用词等 | 多个函数和操作 |
| 特征提取 | CountVectorizer和TfidfVectorizer | 对应代码 |
| 模型训练 | 朴素贝叶斯、支持向量机、随机森林 | 各模型训练代码 |
| 模型评估 | 准确率、分类报告、混淆矩阵、ROC曲线 | 对应评估代码 |
| 集成模型评估 | 平均概率、绘制ROC曲线、检查准确性 | 对应集成评估代码 |

综上所述,通过异构集成分类器和基于NLP的文本分类方法,我们可以构建出高效的短信垃圾邮件过滤系统。在实际应用中,我们可以根据具体需求调整模型参数和算法选择,以获得更好的性能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值