如何使用梯度提升机和H2O库进行自然语言处理

283 阅读13分钟

使用梯度提升机和H2O库进行自然语言处理

[H2O]是一个开源的、用于机器学习的内存平台。H2O提供了许多流行算法的实现。它同时支持有监督和无监督的机器学习算法。

H20支持以下算法。[Naive Bayes算法],[随机森林],[梯度提升机],[广义线性模型],[K-Means算法],[主成分分析]和[深度神经网络]。

H2O是快速和可扩展的,使其成为构建机器学习模型的最佳平台。它还可以通过[H2O的AutoML]管道实现机器学习的自动化。

在本教程中,我们将重点介绍梯度提升机。这种算法可以建立分类和回归模型。在梯度提升机中,我们依次训练多个决策树。然后将它们结合起来,创建一个最终模型。

我们将使用梯度提升机来训练一个自然语言处理模型。该模型将进行情感分析。它将把客户评论分类为正面或负面。

前提条件

要跟上本教程,你需要熟悉。

  • [自然语言处理]。
  • [文本预处理的步骤]。
  • [流行的机器学习算法]。
  • 机器学习中的[集合学习技术]。

注意:你必须使用谷歌Colab笔记本来建立模型。Google Colab笔记本有快速的CPU和GPU。

梯度提升机简介

如前所述,梯度提升机依次训练了多个决策树。然后,这些决策树被组合起来,形成一个最终的模型。最初的决策树模型是基础模型或弱学习者。

Boosting使用一系列算法将弱学习者转化为强学习者。它最小化/减少了训练误差。选择一个随机的数据样本,用一个模型进行拟合,然后依次进行训练。

由于高方差或高偏差,弱的学习者可能不会单独表现良好。然而,当我们把弱的学习者集合起来时,它们就形成了一个强的学习者。它们的组合可以减少偏差或方差,产生更好的模型性能。

让我们开始使用H2O。

开始使用H2O

为了使用H2O,我们要安装一些依赖项。H2O依赖于64位的JDK来运行。它使用的是Java编程语言。要安装64位JDK,请运行此命令。

!apt-get install default-jre
!java -version

安装完依赖项后,用以下命令安装H2O。

!pip install h2o

这个命令将安装最新的H2O版本。要导入H2O,请使用此代码。

import h2o

初始化H2O

我们使用下面的代码来初始化H2O。

h2o.init()

初始化H2O将使我们能够连接到H2O集群。因此,我们将使用其内存进行机器学习。当我们运行上面的代码时,它产生了以下输出。

Initializing H2O

从上面的图片来看,我们已经成功连接到了H2O集群。它还显示了集群的版本和集群的总可用内存。下一步是加载数据集。

情感分析的数据集

我们将使用亚马逊的数据集。它有顾客对个人护理用品的评论。

我们从tensorflow_datasetstensorflow_datasets 是一个TensorFlow资源库,其中包含随时可用的数据集。要导入tensorflow_datasets ,使用这个代码。

import tensorflow_datasets as tfds

要从tensorflow_datasets 下载数据集,使用以下代码。

dowloaded_dataset, dataset_info = tfds.load('amazon_us_reviews/Personal_Care_Appliances_v1_00', with_info=True, batch_size=-1)

从上面的代码中,我们使用tfds.load 方法从tensorflow_datasets 资源库加载数据集。然后我们将使用下面的代码将数据集保存到train 变量中。

train_dataset = dowloaded_dataset['train']

要查看数据集的信息,请运行这个命令。

dataset_info

它产生的输出如下。

Sentiment analysis dataset

从上面的图片来看,该数据集有超过1.3亿条顾客评论。我们将使用以下列作为输入:review_body,review_headline,star_rating, 和helpful_votes

  • review_body:它显示了产品评论的详细描述。

  • review_headline:它显示了评论的标题。

  • star_rating:它显示购买产品的1-5星评级。

  • helpful_votes:它显示了给亚马逊产品的投票数。

在加载数据集后,我们需要使用NumPy将亚马逊数据集转换为一个NumPy数组。NumPy数组很容易操作和使用。

将数据集转换为数组

要导入NumPy包,请使用以下代码。

import numpy as np

我们使用Numpy将数据集转换成数组,使用下面的代码。

dowloaded_dataset=tfds.as_numpy(train_dataset)

要看到数据集的数组,请运行这段代码。

dowloaded_dataset

它产生的输出如下。

Converted dataset array

从上面的图片来看,亚马逊的数据集是在NumPy数组中。接下来,我们需要选择我们将用于建立情感分析模型的列。

选择列

要选择这些列,请使用这段代码。

review_body=dowloaded_dataset['data']['review_body']
review_headline=dowloaded_dataset['data']['review_headline']
helpful_votes=dowloaded_dataset['data']['helpful_votes']
rating=dowloaded_dataset['data']['star_rating']

上面的代码从我们的数据集中选择了四列。这四列是模型在训练阶段的输入。然后我们将使用H2O DataFrame函数创建一个DataFrame。DataFrame是一种数据结构,它将数据组织成一个行和列的二维表格。

创建数据框

我们将使用H2O DataFrame函数创建DataFrame。

h2o_df=h2o.H2OFrame(np.hstack((helpful_votes[:,None],review_headline[:,None],review_body[:,None],rating[:,None])),column_names=['votes','headline','reviews','rating'],column_types=['numeric','string','string','numeric'])

上面的代码将使用h2o.H2OFrame 函数创建一个DataFrame。该函数也被分配了人类可读的列名。指定的列名如下。votes,headline,reviews, 和rating

要查看创建的DataFrame,请运行这段代码。

h2o_df

该代码产生以下输出。

Created DataFrame

添加输出列

我们需要给我们的DataFrame添加一个输出列。输出列包含模型进行预测后的输出。该模型将把客户的评论分类为正面或负面。我们用1 表示正面评论,而用0 表示负面评论。

如果客户的评论是正面的,star_rating 应该大于4 。如果star_rating 小于4 ,该评论就是负面的。为了增加输出列,我们将使用这个逻辑。

我们使用下面的代码来表示这个逻辑。

h2o_df["output"] = h2o_df["rating"].apply(lambda x: 1 if x>= 4 else 0) 

当我们执行该代码时,它将添加输出列。要想看到添加了输出列的新数据框,请使用这段代码。

h2o_df

它产生以下输出。

Output column

下一步是进行文本预处理。

文本预处理

文本处理是自然语言处理的一个重要步骤。在文本预处理中,我们对数据集进行清理并去除噪音。文本处理使我们的数据集准备好供模型使用。

在本教程中,我们将进行的一些文本预处理步骤如下。

  • 去除停顿词。停止词是任何语言中最常见的词。停止词是指冠词、介词、代词和连词。它们不会给文本增加多少信息。

  • 将文本转换为小写字母。将文本转换为小写,确保我们有一个统一的数据集。

  • 符号化。符号化是将文本分割成较小的单词单位,称为标记。

在本教程中,我们将只执行三个步骤。我们将使用自然语言工具箱(NLTK)。

安装自然语言工具箱

我们用这个命令来安装自然语言工具包(NLTK)。

!pip install nltk

要导入nltk ,请使用此代码。

import nltk

现在让我们使用nltk 来进行文本预处理。

下载止损词

停止词是某一语言中最常用的词。停止词携带的信息非常少,对模型的影响也不大。去除停顿词将使模型专注于数据集中的独特词汇。

我们将使用nltk ,下载英语语言的停止词。

from nltk.corpus import stopwords
nltk.download('stopwords')
stop_words = set(stopwords.words('english'))

然后,我们将从数据集中过滤掉这些停顿词。我们将创建一个单一的函数,删除停止词,进行标记化,并将文本转换为小写。

创建该函数

我们使用下面的代码片断来创建这个函数。

def tokenize(line):
  tokenized = line.tokenize("\\W+")
  tokenized = tokenized.tolower()
  tokenized = tokenized[(tokenized.nchar() >= 2) | (tokenized.isna()),:]
  tokenized_filter = tokenized[(tokenized.isna()) | (~ tokenized.isin(stop_words)),:]
 return tokenized_filter

函数名称为tokenize 。在这个函数中,line.tokenize 方法执行标记化。tokenized.tolower 方法将文本转换为小写。(~ tokenized.isin(stop_words)) 将对停止词列表中没有的词进行标记化。它将过滤掉数据集中的停止词。然后,该函数返回一个经历了所有三个步骤的干净文本。让我们把这个函数应用于我们的reviewsheadline 列。

应用该函数

reviewsheadline 列包含文本。要在这两列中应用该函数,请使用以下代码。

words_reviews = tokenize(h2o_df["reviews"])
words_headline = tokenize(h2o_df["headline"])

要查看应用函数后的reviews 列,请使用这段代码。

words_reviews.head()

它产生以下输出。

Reviews column

要查看应用函数后的headline 列,请使用这段代码。

words_headline.head()

它产生的输出结果如下。

Headline column

上面的步骤显示了如何删除停顿词,将文本转换成小写字母,并进行标记化。下一步是对标记化后的文本进行矢量化。

矢量化

矢量化将标记化的文本转换为一个数字列表。这个数字列表被称为词向量,模型将其作为输入。机器并不理解文本。这就是为什么我们需要将文本转换为数字形式(数字列表)。在H2O中,我们使用H2OWord2vecEstimator 算法,将标记化的文本转换为词向量。

要进一步了解H2OWord2vecEstimator 算法如何将标记化的文本转换为字向量,请阅读以下文档

我们使用以下代码导入H2OWord2vecEstimator

from h2o.estimators.word2vec import H2OWord2vecEstimator

H2OWord2vecEstimator 算法训练了一个模型,该模型将执行矢量化。为了使用训练好的模型,我们将其应用于words_reviewswords_headline 列。矢量化模型产生相应的词向量。

现在我们来训练矢量化模型。

训练矢量化模型

我们将使用words_reviewswords_headline 列来训练矢量化模型。我们使用下面的代码。

vec_model = H2OWord2vecEstimator(vec_size = 100, model_id = "w2v_amazon.model")
vec_model.train(training_frame=words_reviews)
vec_model.train(training_frame=words_headline)

从上面的代码中,我们使用以下方法和参数。

  • vec_size = 100:它表示词向量将有的列数。

-model_id = "w2v_amazon.model" 。它是我们的矢量化模型的名称。

  • vec_model.train:它是训练矢量化模型的函数。

然后,我们将training_frame 作为参数传递。它指定了训练矢量化模型的列。我们同时使用words_reviewswords_headline 列来训练模型。

上面的代码将建立我们的矢量化模型。

保存矢量化模型

要保存模型,请使用这段代码。

h2o.save_model(vec_model,path='./')

保存模型后,我们现在可以用它来将标记化的文本转化/转换为词向量。

应用该模型

我们将把训练好的模型应用于words_reviewswords_headline 列。这两列包含标记化的文本。

words_reviews

review_vecs = vec_model.transform(words_reviews, aggregate_method = "AVERAGE")

vec_model.transform 函数将标记化文本转换/转化为词向量。该函数有以下参数。

  • words_reviews:它是输入列。

  • aggregate_method = "AVERAGE":它指定了函数将如何聚合标记化的词。"AVERAGE" ,将确保词在转换后不会失去意义。

要查看转换后的词向量的大小,请使用此代码。

review_vecs.shape

它产生的输出如下。

(85981, 100)

从上面的输出中,我们有85981 字向量。要查看转换后的词向量的输出,请使用这段代码。

review_vecs.head()

它产生以下输出。

Converted word vectors

从上面的图片中,我们已经转换了words_reviews 列。

我们还用同样的过程对words_headline 列进行了矢量化。

words_headline

我们将使用下面的代码。

headline_vecs = vec_model.transform(words_headline, aggregate_method = "AVERAGE")
headline_vecs.names = ["headline_" + s for s in headline_vecs.names]

我们使用相同的vec_model.transform 函数对words_headline 列进行矢量化。我们还使用相同的aggregate_method = "AVERAGE" 参数来执行矢量化。

要查看矢量化后的文本,请使用这段代码。

headline_vecs.head()

它产生的输出如下。

Converted word vectors

从上面的图片来看,我们已经转换了words_headline 列。

我们将使用review_vecsheadline_vecs 作为我们模型的输入。我们需要将它们添加/附加到原始DataFrame中。

将矢量列添加到数据框中

我们将使用cbind 函数将矢量列添加/附加到原始的h2o_df 数据框架中。

h2o_df_ext=h2o_df.cbind(review_vecs)
h2o_df_ext = h2o_df_ext.cbind(headline_vecs)

cbind 函数将把review_vecs 数据框添加到h2o_df 。同一函数还将headline_vecs 数据框添加到创建的h2o_df_ext

合并所有的数据框架后,我们将最终的h2o_df_ext 数据框架分成两组。第一组是用于模型训练,第二组是用于模型验证。

分割数据框

我们把数据集分成两组。一个用于训练,另一个用于验证,使用此代码。

h2o_train,h2o_valid = h2o_df_ext.split_frame(ratios=[.8])

模型将从训练集中学习,以了解情感分析。验证集将在训练中对模型的超参数进行微调。

我们使用.8 。80%的数据框将是训练集,20%将是验证集。

让我们使用梯度提升机来训练模型。

使用梯度提升机进行模型训练

我们将从H2O库中导入H2OGradientBoostingEstimator 算法。它是训练模型的算法。

from h2o.estimators import H2OGradientBoostingEstimator

让我们初始化H2OGradientBoostingEstimator 。我们还将设置将产生最佳结果的超参数。

Gradient_Boosting_Machine= H2OGradientBoostingEstimator(ntrees=100,
 max_depth = 6,  learn_rate=0.1
                                             )

初始化的H2OGradientBoostingEstimator 算法有以下参数。

  • ntrees:它指定了用于建立模型的决策树的数量。我们将树的数量设置为100H2OGradientBoostingEstimator 算法将依次创建100棵决策树。然后,它将它们结合起来,创建一个具有最佳结果的最终模型。

  • max_depth:它是所用决策树的最大深度。我们将该值设置为6 。增加max_depth 值可能会导致模型过拟合。

  • learn_rate:它规定了训练期间模型的学习率。

在初始化模型后,我们用准备好的数据集喂养模型。

用数据集喂养模型

要用数据集喂养模型,请使用这段代码。

Gradient_Boosting_Machine.train(x=headline_vecs.names+review_vecs.names, y='output', training_frame = h2o_train, validation_frame=h2o_valid)

从上面的代码中,train 函数训练了模型。它有以下参数。

  • x 变量。它是包含所有输入列的变量。 和 是输入列。headline_vecs review_vecs

  • y 变量。它是包含输出列的变量。

  • training_frame:它指定了用于训练的DataFrame。我们使用h2o_train DataFrame进行训练。

  • validation_frame:它指定了我们将用于验证的数据框架。我们使用h2o_valid 数据框进行验证。

该算法将对模型进行训练,并给出最佳的准确性分数。

准确率得分

要获得准确率分数,请使用此代码。

print(" Hyperparameter AUC: " + str(round(Gradient_Boosting_Machine.auc(valid = True), 3)))

上面的代码将打印准确率分数。

Hyperparameter AUC: 0.934

准确率得分是0.934 ,是93.4%。这是一个很高的准确率分数,表明该模型训练有素。我们现在可以使用这个模型来进行预测。

进行预测

我们使用该模型将客户评论分类为负面或正面。

predictions = ["The shippers and loaders were great....willing to consider speedier shipping options, the good news is that at the end the shipping arrived quickly enough"]

让我们对这个文本输入进行矢量化。

predictions = vec_model.transform(predictions)

矢量化之后,我们使用矢量化的文本进行预测。

prediction_result = Gradient_Boosting_Machine.predict(predictions)
print(prediction_result)

它产生的预测结果如下。

array([1])

预测结果是1 ,是一个正面评论。从上面的预测结果来看,我们的模型可以做出准确的预测。

总结

在本教程中,我们建立了一个情感分析模型。我们使用梯度提升机和H2O库创建了这个模型。该教程还包括文本预处理。我们对数据集进行了清理并去除噪音。最后,我们使用H2OGradientBoostingEstimator 算法来训练模型。最终的模型能够做出准确的预测。