Python-应用监督学习-三-

21 阅读1小时+

Python 应用监督学习(三)

原文:annas-archive.org/md5/d906d6d9346f8d8b7965d192afaf9a47

译者:飞龙

协议:CC BY-NC-SA 4.0

第九章:使用 Keras 的同质集成

在本章中,我们将涵盖以下主题:

  • 用于能量预测的同质模型集成

  • 用于手写数字分类的同质模型集成

简介

在集成模型的情况下,每个基础分类器必须在自身内部具有一定的多样性。这种多样性可以通过以下方式之一获得:

  • 通过使用各种重采样方法或训练数据的随机化来使用不同的训练数据子集

  • 通过为不同的基础学习器使用不同的学习超参数

  • 通过使用不同的学习算法

在集成模型的情况下,如果基础学习器使用了不同的算法,则该集成被称为异质集成方法。如果所有基础学习器在不同的训练集分布上使用了相同的算法,则该集成被称为同质集成

用于能量预测的同质模型集成

在以下示例中,我们将使用 Keras API。Keras 是一个开源的高级框架,用于构建深度神经网络。它建立在 TensorFlow 或 Theano 之上,并在幕后使用它们进行计算。Keras 可以在 CPU 和 GPU 上运行。Keras 的默认设置旨在在大多数情况下提供良好的结果。

Keras 的重点是模型的概念。Keras 支持两种类型的模型。主要类型的模型是一系列层,称为顺序。Keras 中的另一种模型是非顺序模型,称为模型

要构建一个顺序模型,执行以下步骤:

  1. 使用Sequential()实例化一个顺序模型

  2. 使用Dense类逐个添加层

  3. 使用以下方式编译模型:

    • 一个强制性的损失函数

    • 一个强制性的优化器

    • 可选评估参数

  4. 使用数据拟合模型

  5. 评估模型

这里是前面步骤的流程图:

在下面的代码块中,我们可以看到一个简短的代码示例:

# Instantiate a sequential model
seqmodel = Sequential()

# Add layers using the Dense class
seqmodel.add(Dense8, activation='relu')

# Compile the model
seqmodel.compile(loss='binary_crossentropy, optimizer='adam', metric=['accuracy'])

# Fit the model
seqmodel.fit(X_train, Y_train, batch_size=10)

准备工作

我们将首先安装 Keras。为了安装 Keras,您需要在您的系统中安装 Theano 或 TensorFlow。在这个例子中,我们将选择 TensorFlow 作为 Keras 的后端。

TensorFlow 有两种变体:CPU 版本和 GPU 版本。

要安装当前仅 CPU 版本,请使用以下命令:

pip install tensorflow

如果您必须安装 GPU 包,请使用以下命令:

pip install tensorflow-gpu

安装 TensorFlow 后,您需要使用以下命令安装 Keras:

sudo pip install keras

为了升级您已安装的 Keras 库,请使用以下命令:

sudo pip install --upgrade keras

安装完库后,让我们导入所需的库:

import os
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split

from sklearn.metrics import mean_squared_error

from keras.models import Sequential
from keras.layers import Dense

我们根据我们的要求设置我们的工作目录:

os.chdir("..../Chapter 9")
os.getcwd()

我们读取我们的energydata.csv数据集:

df_energydata = pd.read_csv("energydata.csv")

我们检查我们的数据集中是否有任何空值:

df_energydata.isnull().sum() 

如何做到这一点...

我们现在将构建我们的test子集并训练我们的神经网络模型:

  1. test子集分离出来,以便应用模型进行预测:
df_traindata, df_testdata = train_test_split(df_energydata, test_size=0.3)
  1. 检查traintest子集的形状:
print(df_traindata.shape)
print(df_testdata.shape)
  1. test子集拆分为目标和特征变量:
X_test = df_testdata.iloc[:,3:27] 
Y_test = df_testdata.iloc[:,28] 
  1. 通过检查X_testY_test的形状来验证前面的拆分:
print(X_test.shape)
print(Y_test.shape)
  1. 让我们使用 Keras 创建多个神经网络模型。我们使用For...Loop来构建多个模型:
ensemble = 20
frac = 0.7

predictions_total = np.zeros(5921, dtype=float)

for i in range(ensemble):
    print("number of iteration:", i)
    print("predictions_total", predictions_total)

    # Sample randomly the train data
    Traindata = df_traindata.sample(frac=frac)
    X_train = Traindata.iloc[:,3:27] 
    Y_train = Traindata.iloc[:,28] 

    ############################################################

    model = Sequential()
    # Adding the input layer and the first hidden layer
    model.add(Dense(units=16, kernel_initializer = 'normal', activation = 'relu', input_dim = 24))

    # Adding the second hidden layer
    model.add(Dense(units = 24, kernel_initializer = 'normal', activation = 'relu'))

    # Adding the third hidden layer
    model.add(Dense(units = 32, kernel_initializer = 'normal', activation = 'relu'))

    # Adding the output layer
    model.add(Dense(units = 1, kernel_initializer = 'normal', activation = 'relu'))

    # Compiling the ANN
    adam = optimizers.Adam(lr=0.001, beta_1=0.9, beta_2=0.9, epsilon=None, decay=0.0)
    model.compile(loss='mse', optimizer=adam, metrics=['mean_squared_error'])
    # Fitting the ANN to the Training set

    model.fit(X_train, Y_train, batch_size = 16, epochs = 25)

    ############################################################

    # We use predict() to predict our values
    model_predictions = model.predict(X_test)

    model_predictions = model_predictions.flatten()
    print("TEST MSE for individual model: ", mean_squared_error(Y_test, model_predictions))
    print("")
    print(model_predictions)
    print("")

predictions_total = np.add(predictions_total, model_predictions)
  1. 将预测值的总和除以迭代次数,得到平均预测值。我们使用平均预测值来计算集成模型的均方误差MSE):
predictions_total = predictions_total/ensemble
print("MSE after ensemble: ", mean_squared_error(np.array(Y_test), predictions_total))

它是如何工作的...

下面是集成同质模型工作流程的图示表示:

图示

在前面的图中,我们假设我们有 100 个训练样本。我们在我们的 100 个训练样本上训练了 100 个模型,并将它们应用于我们的测试样本。我们得到了 100 组预测结果,通过平均是否目标变量是数值变量或是否在计算分类问题的概率来集成。在类别预测的情况下,我们会选择最大投票。

步骤 1中,我们分离了我们的训练和测试样本。这是我们在这个菜谱中构建的所有模型用于预测的相同测试样本。在步骤 2中,我们检查了traintest子集的形状。在步骤 3中,我们将测试子集拆分为目标和预测变量,然后在步骤 4中再次检查形状,以确保我们得到了正确的拆分。

步骤 5中,我们使用 Keras 库构建我们的神经网络模型。我们初始化了两个变量,ensemblefrac。我们使用ensemble变量运行一个循环,进行一定次数的迭代(在我们的例子中,我们将其设置为200)。然后我们使用frac变量来分配从训练子集中提取的 bootstrap 样本的数据比例。在我们的例子中,我们将frac设置为0.8

步骤 5中,在for...loop循环迭代中,我们构建了多个神经网络模型,并将这些模型应用于我们的测试子集以获取预测结果。我们通过使用add()方法传递一个层列表来创建顺序模型。在第一层中,我们使用input_dim参数指定输入维度。因为我们有 24 个输入维度,所以将input_dim设置为24。我们还通过设置Activation参数提到了在每个层中要使用的Activation函数。

您也可以通过Activation层设置Activation函数,如下所示:

# Example code to set activation function through the activation layer

from keras.layers import Activation, Dense 

model.add(Dense(64)) 
model.add(Activation('tanh'))

在这一步中,在我们构建模型之前,我们使用compile方法配置学习过程。compile方法接受必选的loss function、必选的optimizer和可选的metrics作为参数。

optimizer参数可以取随机梯度下降SGD)、RMSpropAdagradAdadeltaAdamAdamaxNadam等值。

loss function 可以取值如 mean_squared_errormean_absolute_errormean_absolute_percentage_errormean_squared_logarithmic_errorsquared_hingecategorical_hingebinary_crossentropy。更多详情请参阅 keras.io/losses/

我们还使用 np.add() 方法将预测数组添加到名为 predictions_total 的数组变量中。

一旦我们在 步骤 5 中的 for 循环中完成了所有迭代,我们将预测的总和除以迭代次数,这个迭代次数存储在 ensemble 变量中,并设置为 200,以获得平均预测。我们使用平均预测来计算集成结果的均方误差(MSE)。

还有更多...

如果你具有高计算需求,你可以使用 Google Colaboratory。Colaboratory 是一个免费的 Jupyter 笔记本环境,无需设置,完全在云端运行。它是一个免费的云服务,支持免费的 GPU。你可以使用 Google Colab 来构建你的深度学习应用程序,使用 TensorFlow、Keras、PyTorch 和 OpenCV。

一旦你使用 colab.research.google.com/ 创建了账户,你可以使用你的凭据登录。

一旦你登录,你可以直接点击“文件”菜单来创建你的 Python 笔记本:

图片

一旦你点击了“文件”标签,你会看到“新建 Python 3 笔记本”;一个支持 Python 3 的新笔记本将被创建。

你可以点击左上角的 Untitled0.ipynb 来重命名文件:

图片

前往“编辑”然后“笔记本设置”。一个窗口会弹出,显示你可以有不同的设置:

图片

选择图形处理单元GPU)作为硬件加速器,如前面的截图所示,以便使用免费的 GPU。

关于 Google Colab 的一个很酷的事情是它可以在你自己的 Google Drive 上工作。你可以选择在你的 Google Drive 中创建自己的文件夹,或者使用默认的 Colab 笔记本文件夹。为了使用默认的 Google Colab 笔记本文件夹,请按照以下截图中的步骤操作:

图片

要开始读取你的数据集,你可以将它们存储在 Google Drive 的文件夹中。

在你登录 Google Colab 并创建了一个新的笔记本之后,你必须在笔记本中执行以下代码来挂载驱动器:

from google.colab import drive

# This can be your folder path as per your drive
drive.mount('/content/drive')

当运行前面的代码时,它会要求输入授权码,如下所示:

图片

点击前面的 URL 获取授权码:

图片

将授权码粘贴到文本框中。每次授权时都会得到不同的授权码。授权后,驱动器将被挂载。

一旦挂载驱动器,您可以使用pandas读取.csv文件,就像我们在本章前面所展示的那样。其余的代码,如如何做部分所示,将按原样运行。如果您使用 GPU,您会注意到您的计算性能速度有显著提高。

为了在 Google Colab 中安装额外的库,您需要运行带有!符号的pip install命令。例如,您可以在 Google Colab 实例中运行!pip install utils来安装 utils。

参见

Keras 库中有各种激活函数可供使用:

  • Softmax 激活函数

  • 指数线性单元

  • 缩放指数线性单元

  • Softplus 激活函数

  • 矩形线性单元

  • 双曲正切激活函数

  • Sigmoid 激活函数

  • 线性激活函数

  • 指数激活函数

关于前面提到的激活函数的更多信息,请访问keras.io/activations/.

手写数字分类的同质模型集成

在本例中,我们将使用一个名为 The Street View House Numbers (SVHN)的数据集,该数据集来自ufldl.stanford.edu/housenumbers/。该数据集也以.hd5f格式提供在 GitHub 上。

此数据集是一个真实世界的数据集,并从 Google 街景图像中的门牌号码获得。

我们使用 Google Colab 来训练我们的模型。在第一阶段,我们使用 Keras 构建单个模型。在第二阶段,我们集成多个同质模型并将结果集成。

准备工作

该数据集包含 60,000 个门牌号码图像。每个图像标记为 1 到 10 之间。数字 1 标记为 1,数字 9 标记为 9,数字 0 标记为 10。图像是围绕单个字符的 32 x 32 图像。在某些情况下,我们可以看到图像在视觉上不清晰。

我们导入所需的库:

import os
import matplotlib.pyplot as plt
import numpy as np
from numpy import array

from sklearn.metrics import accuracy_score

from keras.models import Sequential, load_model
from keras.layers.core import Dense, Dropout, Activation

我们挂载 Google Drive:

from google.colab import drive
drive.mount('/content/drive')

现在,我们导入一个名为h5py的库来读取 HDF5 格式文件和我们的数据文件,该文件称为SVHN_single_grey.h5

import h5py

# Open the file as readonly
h5f = h5py.File('/content/drive/My Drive/DLCP/SVHN_single_grey.h5', 'r')

我们加载训练和测试子集,并关闭文件:

# Load the training and test set
x_train = h5f['X_train'][:]
y_train = h5f['y_train'][:]
x_test = h5f['X_test'][:]
y_test = h5f['y_test'][:]

# Close this file
h5f.close()

我们重塑我们的训练和测试子集。我们还更改数据类型为浮点数:

x_train = x_train.reshape(x_train.shape[0], 1024)
x_test = x_test.reshape(x_test.shape[0], 1024)

我们现在通过除以 255.0 来归一化我们的数据。这也将值的类型转换为浮点数:

# normalize inputs from 0-255 to 0-1
x_train = x_train / 255.0
x_test = x_test / 255.0

我们检查训练和测试子集的形状:

print("X_train shape", x_train.shape)
print("y_train shape", y_train.shape)
print("X_test shape", x_test.shape)
print("y_test shape", y_test.shape)

我们看到traintest特征以及我们的目标子集的形状如下:

我们可视化了一些图像。我们还在图像上方打印标签:

# Visualizing the 1st 10 images in our dataset
# along with the labels
%matplotlib inline
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 1))
for i in range(10):
 plt.subplot(1, 10, i+1)
 plt.imshow(x_train[i].reshape(32,32), cmap="gray")
 plt.title(y_train[i], color='r')
 plt.axis("off")
plt.show()

如下所示显示前 10 张图像:

现在我们对目标变量进行独热编码。同时,我们将y_test标签存储在另一个变量中,称为y_test_actuals,以备后用:

# Let us store the original y_test to another variable y_test_actuals
y_test_actuals = y_test

# one-hot encoding using keras' numpy-related utilities
n_classes = 10

print("Before one-hot encoding:")
print("Shape of Y_TRAIN before one-hot encoding: ", y_train.shape)
print("Shape of Y_TEST before one-hot encoding: ", y_test.shape)

y_train = np_utils.to_categorical(y_train, n_classes)
y_test = np_utils.to_categorical(y_test, n_classes)

print("After one-hot encoding:")
print("Shape of Y_TRAIN after one-hot encoding: ", y_train.shape)
print("Shape of Y_TRAIN after one-hot encoding: ", y_test.shape)

独热编码前后的形状如下:

如何做...

现在,我们将使用 Keras 库构建一个单一模型:

  1. 使用序列模型构建一个线性的层堆叠:
# building a linear stack of layers with the sequential model
model = Sequential()
model.add(Dense(512, input_shape=(1024,)))
model.add(Activation('relu')) 

model.add(Dense(512))
model.add(Activation('relu'))

model.add(Dense(10))
model.add(Activation('softmax'))
  1. 编译模型:
# compiling the sequential model
model.compile(loss='categorical_crossentropy', metrics=['accuracy'], optimizer='adam')
  1. 将模型拟合到train数据,并使用test数据进行验证:
# training the model and saving metrics in history
svhn_model = model.fit(x_train, y_train,
          batch_size=128, epochs=100,
          verbose=2,
          validation_data=(x_test, y_test))
  1. 在每个 epoch 绘制模型的准确率:
# plotting the metrics
fig = plt.figure(figsize=(12,4))

#plt.subplot(2,1,1)
plt.plot(svhn_model.history['acc'])
plt.plot(svhn_model.history['val_acc'])
plt.title('Model Accuracy')
plt.ylabel('Accuracy')
plt.xlabel('Epochs')
plt.legend(['Train', 'Test'], loc='uppper left')

plt.tight_layout()

我们可以看到以下模型准确率图:

图片

  1. 在每个 epoch 绘制损失:
# plotting the metrics
fig = plt.figure(figsize=(12,4))

plt.plot(svhn_model.history['loss'])
plt.plot(svhn_model.history['val_loss'])
plt.title('Model Loss')
plt.ylabel('Loss')
plt.xlabel('Epochs')
plt.legend(['Train', 'Test'], loc='upper right')

plt.tight_layout()

我们可以看到以下模型损失图:

图片

  1. 重用 scikit-learn 网站上的代码来绘制混淆矩阵:
# code from http://scikit-learn.org
def plot_confusion_matrix(cm, classes,
normalize=False,
title='Confusion matrix',
cmap=plt.cm.Blues):
"""
This function prints and plots the confusion matrix.
"""
plt.imshow(cm, 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)

thresh = cm.max() / 2.
for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
plt.text(j, i, cm[i, j],
horizontalalignment="center",
color="white" if cm[i, j] > thresh else "black")

plt.ylabel('Actuals')
plt.xlabel('Predicted')
  1. 以数值和图形两种方式绘制混淆矩阵:
target_names = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']

# Formulating the Confusion Matrix
import itertools
from sklearn.metrics import confusion_matrix

cm = confusion_matrix(y_test_actuals, predicted_classes)
print(cm)

plt.figure(figsize=(10,10))
plot_confusion_matrix(cm, classes=target_names, normalize=False)
plt.show()

混淆矩阵如下所示:

图片

  1. 现在,我们将查看如何集成多个同质模型的成果。定义一个函数来将模型拟合到训练数据:
# fit model on dataset
def train_models(x_train, y_train):
  # building a linear stack of layers with the sequential model
  model = Sequential()
  model.add(Dense(512, input_shape=(1024,)))
  model.add(Activation('relu')) 
  model.add(Dropout(0.2))

  model.add(Dense(512))
  model.add(Activation('relu'))
  model.add(Dropout(0.2))

  model.add(Dense(10))
  model.add(Activation('softmax'))

  # compiling the sequential model
  model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

  # training the model and saving metrics in history
  svhn_model = model.fit(x_train, y_train, batch_size=32, epochs=25)

  return model
  1. 编写一个函数来集成所有模型的预测:
# make an ensemble prediction for multi-class classification
def ensemble_predictions(models, x_test):
  # make predictions
  y_predicted = [model.predict(x_test) for model in models]
  y_predicted = np.array(y_predicted)

  # sum predictions from all ensemble models
  predicted_total = np.sum(y_predicted, axis=0)

  # argmax across classes
  result = np.argmax(predicted_total, axis=1)

  return result

numpy.argmax返回数组在特定轴上的最大元素的索引。

  1. 编写一个函数来评估模型并获取每个模型的准确率分数:
# evaluate a specific number of members in an ensemble
def evaluate_models(models, no_of_models, x_test, y_test):
 # select a subset of members
 subset = models[:no_of_models]

 # make prediction
 y_predicted_ensemble = ensemble_predictions(subset, x_test)

 # calculate accuracy
 return accuracy_score(y_test_actuals, y_predicted_ensemble)
  1. 拟合所有模型:
# fit all models
no_of_models = 50

models = [train_models(x_train, y_train) for _ in range(no_of_models)]

# evaluate different numbers of ensembles
all_scores = list()
for i in range(1, no_of_models+1):
  score = evaluate_models(models, i, x_test, y_test)
  print("Accuracy Score of model ", i, " ", score)
  all_scores.append(score)
  1. 将准确率分数与每个 epoch 对应:
# plot score vs number of ensemble members
x_axis = [i for i in range(1, no_of_models+1)]
plt.plot(x_axis, all_scores)
plt.show()

它是如何工作的...

第 1 步第 7 步中,我们构建了一个单一的神经网络模型,以了解如何使用标记的图像数据集来训练我们的模型并预测未见过的图像的实际标签。

第 1 步中,我们使用 Keras 的序列模型构建了一个线性的层堆叠。我们定义了三个层:一个输入层、一个隐藏层和一个输出层。由于我们有 32 x 32 的图像,我们将input_shape=1024提供给输入层。我们在第一层和第二层使用了 relu 激活函数。因为这是一个多类分类问题,所以我们为输出层使用了 softmax 激活函数。

第 2 步中,我们使用loss='categorical_crossentropy'optimizer='adam'编译了模型。在第 3 步中,我们将模型拟合到我们的训练数据,并在测试数据上验证它。

第 4 步第 5 步中,我们绘制了每个 epoch 的模型准确率和损失指标。

第 6 步第 7 步中,我们重用了 scikit-learn 网站上的plot_confusion_matrix()函数来绘制我们的混淆矩阵,既以数值形式又以可视形式。

第 8 步开始,我们集成了多个模型。我们编写了三个自定义函数:

  • train_models(): 使用序列层训练和编译我们的模型。

  • ensemble_predictions(): 对预测进行集成,并找到所有观察值跨类中的最大值。

  • evaluate_models(): 计算每个模型的准确率分数。

第 11 步中,我们拟合了所有模型。我们将no_of_models变量设置为50。我们通过调用train_models()函数在循环中训练我们的模型。然后,我们将x_trainy_train传递给每个迭代中构建的每个模型的train_models()函数。我们还调用了evaluate_models(),它返回了每个构建的模型的准确率分数。然后,我们将所有准确率分数附加在一起。

第 12 步中,我们绘制了所有模型的准确率分数。

第十章:使用 H2O 的异构集成分类器

在本章中,我们将介绍以下食谱:

  • 使用异构集成分类器预测信用卡违约者

简介

在本章中,我们将展示如何使用 H2O 构建异构集成分类器,H2O 是一个开源的、分布式的、内存中的机器学习平台。H2O 中提供了大量的监督和无监督算法。

在监督算法中,H2O 为我们提供了神经网络、随机森林(RF)、广义线性模型、梯度提升机、朴素贝叶斯分类器和 XGBoost。

H2O 还为我们提供了一个旨在通过堆叠过程找到一组预测算法最佳组合的堆叠集成方法。H2O 的堆叠集成支持回归和分类。

使用异构集成分类器预测信用卡违约者

我们将以台湾的信用卡支付违约者数据为例。这是我们之前在第三章,“重采样方法”中使用的相同数据集,用于构建逻辑回归模型。在本食谱中,我们将使用不同的算法构建多个模型,并最终构建一个堆叠集成模型。

此数据集包含有关台湾信用卡客户的信息。这包括有关支付违约者、客户的人口统计因素、他们的信用数据和他们的支付历史信息。数据集可在 GitHub 上找到。它也可以从其主要来源 UCI ML 存储库获得:bit.ly/2EZX6IC

在我们的例子中,我们将使用以下来自 H2O 的监督算法来构建我们的模型:

  • 广义线性模型

  • 分布式随机森林

  • 梯度提升机

  • 堆叠集成

我们将了解如何在 Python 中使用这些算法,并学习如何为每个算法设置一些超参数。

准备工作

我们将使用 Google Colab 来构建我们的模型。在第十章,“使用 H2O 的异构集成分类器”,我们在“更多内容”部分解释了如何使用 Google Colaboratory。

我们将首先按照以下步骤在 Google Colab 中安装 H2O:

! pip install h2o

执行前面的命令将显示一些指令,最后一行将显示以下消息(H2O 的版本号将根据最新版本而有所不同):

Successfully installed colorama-0.4.1 h2o-3.22.1.2

我们将按照以下方式导入所有必需的库:

import pandas as pd
import numpy as np

from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, roc_curve, auc
from sklearn import tree

import h2o
from h2o.estimators.glm import H2OGeneralizedLinearEstimator
from h2o.estimators.random_forest import H2ORandomForestEstimator
from h2o.estimators.gbm import H2OGradientBoostingEstimator
from h2o.grid.grid_search import H2OGridSearch
from h2o.estimators.stackedensemble import H2OStackedEnsembleEstimator

import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline

然后,我们将初始化 H2O:

# Initialize H2o
h2o.init()

在成功初始化后,我们将看到以下截图所示的信息。这些信息可能因环境而异:

图片

我们将从 Google Drive 读取我们的数据集。为了做到这一点,我们首先需要挂载驱动器:

from google.colab import drive
drive.mount('/content/drive')

它将指导你访问一个 URL 以获取授权代码。你需要点击该 URL,复制授权代码,并将其粘贴。在成功挂载后,你可以从 Google Drive 的相应文件夹中读取你的文件:

# Reading dataset from Google drive
df_creditcarddata = h2o.import_file("/content/drive/My Drive/Colab Notebooks/UCI_Credit_Card.csv")

注意,使用 h2o.import_file,我们创建 h2o.frame.H2OFrame。这与 pandas DataFrame 类似。然而,在 pandas DataFrame 的情况下,数据存储在内存中,而在这个案例中,数据位于 H2O 集群上。

你可以在 H2O DataFrame 上运行与在 pandas 上类似的方法。例如,为了查看 DataFrame 中的前 10 个观测值,你可以使用以下命令:

df_creditcarddata.head()

为了检查 DataFrame 的维度,我们使用以下命令:

df_creditcarddata.shape

为了查看所有列名,我们运行以下语法:

df_creditcarddata.columns

pandas DataFrame 中,我们使用 dtypes 来查看每列的数据类型。在 H2o DataFrame 中,我们会使用以下:

df_creditcarddata.types

这给出了以下输出。请注意,分类变量以 'enum' 的形式出现:

图片

我们在数据集中有目标变量 default.payment.next.month。这告诉我们哪些客户已经违约或未违约。我们想看到违约者和非违约者的分布:

df_creditcarddata['default.payment.next.month'].table()

这给出了 default.payment.next.month 变量中每个类别的计数:

图片

我们不需要 ID 列进行预测建模,所以我们将其从 DataFrame 中删除:

df_creditcarddata = df_creditcarddata.drop(["ID"], axis = 1) 

我们可以使用 hist() 方法查看数值变量的分布:

import pylab as pl
df_creditcarddata[['AGE','BILL_AMT1','BILL_AMT2','BILL_AMT3','BILL_AMT4','BILL_AMT5','BILL_AMT6', 'LIMIT_BAL']].as_data_frame().hist(figsize=(20,20))
pl.show()

下面的屏幕截图显示了绘制的变量。这可以帮助我们分析每个变量:

图片

为了扩展我们的分析,我们可以通过性别、教育和婚姻状况查看违约者和非违约者的分布:

# Defaulters by Gender
columns = ["default.payment.next.month","SEX"]
default_by_gender = df_creditcarddata.group_by(by=columns).count(na ="all")
print(default_by_gender.get_frame())

# Defaulters by education
columns = ["default.payment.next.month","EDUCATION"]
default_by_education = df_creditcarddata.group_by(by=columns).count(na ="all")
print(default_by_education.get_frame())

# Defaulters by MARRIAGE
columns = ["default.payment.next.month","MARRIAGE"]
default_by_marriage = df_creditcarddata.group_by(by=columns).count(na ="all")
print(default_by_marriage.get_frame())

在下面的屏幕截图中,我们可以看到不同类别的违约者分布:

图片

现在,我们将分类变量转换为因子:

# Convert the categorical variables into factors

df_creditcarddata['SEX'] = df_creditcarddata['SEX'].asfactor()
df_creditcarddata['EDUCATION'] = df_creditcarddata['EDUCATION'].asfactor()
df_creditcarddata['MARRIAGE'] = df_creditcarddata['MARRIAGE'].asfactor()
df_creditcarddata['PAY_0'] = df_creditcarddata['PAY_0'].asfactor()
df_creditcarddata['PAY_2'] = df_creditcarddata['PAY_2'].asfactor()
df_creditcarddata['PAY_3'] = df_creditcarddata['PAY_3'].asfactor()
df_creditcarddata['PAY_4'] = df_creditcarddata['PAY_4'].asfactor()
df_creditcarddata['PAY_5'] = df_creditcarddata['PAY_5'].asfactor()
df_creditcarddata['PAY_6'] = df_creditcarddata['PAY_6'].asfactor()

我们还将二元目标变量 default.payment.next.month 编码为因子变量。转换后,我们使用 levels() 方法检查目标变量的类别:

# Also, encode the binary response variable as a factor
df_creditcarddata['default.payment.next.month'] = df_creditcarddata['default.payment.next.month'].asfactor() 
df_creditcarddata['default.payment.next.month'].levels()

然后,我们将定义我们的预测变量和目标变量:

# Define predictors manually
predictors = ['LIMIT_BAL','SEX','EDUCATION','MARRIAGE','AGE','PAY_0','PAY_2','PAY_3',\
 'PAY_4','PAY_5','PAY_6','BILL_AMT1','BILL_AMT2','BILL_AMT3','BILL_AMT4',\
 'BILL_AMT5','BILL_AMT6','PAY_AMT1','PAY_AMT2','PAY_AMT3','PAY_AMT4','PAY_AMT5','PAY_AMT6']

target = 'default.payment.next.month'

然后,我们使用 split_frame() 方法分割我们的 DataFrame:

splits = df_creditcarddata.split_frame(ratios=[0.7], seed=1) 

以下代码给出了两个分割输出:

splits

在下面的屏幕截图中,我们可以看到以下两个分割:

图片

我们将分割分为训练和测试子集:

train = splits[0]
test = splits[1] 

如何做到这一点...

让我们继续使用本章前面提到的算法来训练我们的模型。我们将首先训练我们的 广义线性模型GLM)模型。我们将构建三个 GLM 模型:

  • 带有默认参数值的 GLM 模型

  • 带有 Lambda 搜索(正则化)的 GLM 模型

  • 带有网格搜索的 GLM 模型

现在我们将在下一节开始训练我们的模型。

  1. 让我们训练我们的第一个模型:
GLM_default_settings = H2OGeneralizedLinearEstimator(family='binomial', \
                                            model_id='GLM_default',nfolds = 10, \
                                            fold_assignment = "Modulo", \
                                            keep_cross_validation_predictions = True)

H2OGeneralizedLinearEstimator拟合一个广义线性模型。它接受一个响应变量和一组预测变量。

H2OGeneralizedLinearEstimator可以处理回归和分类任务。在回归问题的情况下,它返回一个H2ORegressionModel子类,而对于分类,它返回一个H2OBinomialModel子类。

  1. 我们在“准备就绪”部分创建了预测变量和目标变量。将预测变量和目标变量传递给模型:
GLM_default_settings.train(x = predictors, y = target, training_frame = train)
  1. 使用lambda_search参数训练 GLM 模型:
GLM_regularized = H2OGeneralizedLinearEstimator(family='binomial', model_id='GLM', \
                                                lambda_search=True, nfolds = 10, \
                                                fold_assignment = "Modulo", \
                                                keep_cross_validation_predictions = True)

GLM_regularized.train(x = predictors, y = target, training_frame = train)

lambda_search帮助 GLM 找到最优的正则化参数λ。lambda_search参数接受一个布尔值。当设置为True时,GLM 将首先拟合一个具有最高λ值的模型,这被称为最大正则化。然后它将逐步降低λ值,直到达到最小λ值。得到的最佳模型基于最佳的λ值。

  1. 使用 GLM 和网格搜索训练模型:
hyper_parameters = { 'alpha': [0.001, 0.01, 0.05, 0.1, 1.0],
                     'lambda': [0.001, 0.01, 0.1, 1] }
search_criteria = { 'strategy': "RandomDiscrete", 'seed': 1,
                    'stopping_metric': "AUTO",
                    'stopping_rounds': 5 }

GLM_grid_search = H2OGridSearch(H2OGeneralizedLinearEstimator(family='binomial', \
                  nfolds = 10, fold_assignment = "Modulo", \
                  keep_cross_validation_predictions = True),\
                  hyper_parameters, grid_id="GLM_grid", search_criteria=search_criteria)

GLM_grid_search.train(x= predictors,y= target, training_frame=train)
  1. 使用get_grid()方法按auc值排序网格结果:
# Get the grid results, sorted by validation AUC
GLM_grid_sorted = GLM_grid_search.get_grid(sort_by='auc', decreasing=True)
GLM_grid_sorted

在以下屏幕截图中,我们可以看到每个模型的auc分数,它由不同的alphalambda参数组合而成:

图片

  1. 我们可以看到我们的训练数据和交叉验证数据上的模型指标:
# Extract the best model from random grid search
Best_GLM_model_from_Grid = GLM_grid_sorted.model_ids[0]

# model performance
Best_GLM_model_from_Grid = h2o.get_model(Best_GLM_model_from_Grid)
print(Best_GLM_model_from_Grid)

从前面的代码块中,您可以评估模型指标,包括MSERMSENullResidual DevianceAUCGini以及Confusion Matrix。在稍后的阶段,我们将使用网格搜索中的最佳模型进行我们的堆叠集成。

让我们看一下以下图像并评估模型指标:

图片

  1. 使用随机森林训练模型。使用默认设置的随机森林代码如下:
# Build a RF model with default settings
RF_default_settings = H2ORandomForestEstimator(model_id = 'RF_D',\
                                nfolds = 10, fold_assignment = "Modulo", \
                                keep_cross_validation_predictions = True)

# Use train() to build the model
RF_default_settings.train(x = predictors, y = target, training_frame = train)
  1. 要获取模型的摘要输出,请使用以下代码:
RF_default_settings.summary()
  1. 使用网格搜索训练随机森林模型。将超参数设置如下所示:
hyper_params = {'sample_rate':[0.7, 0.9],
                'col_sample_rate_per_tree': [0.8, 0.9],
                'max_depth': [3, 5, 9],
                'ntrees': [200, 300, 400]
               }
  1. 使用H2OGridSearch()上的超参数使用gridsearch训练RF模型:
RF_grid_search = H2OGridSearch(H2ORandomForestEstimator(nfolds = 10, \
                             fold_assignment = "Modulo", \
                             keep_cross_validation_predictions = True, \
                             stopping_metric = 'AUC',stopping_rounds = 5), \
                             hyper_params = hyper_params, \
                             grid_id= 'RF_gridsearch')

# Use train() to start the grid search
RF_grid_search.train(x = predictors, y = target, training_frame = train)
  1. 按 AUC 分数排序结果以查看哪个模型表现最佳:
# Sort the grid models
RF_grid_sorted = RF_grid_search.get_grid(sort_by='auc', decreasing=True)
print(RF_grid_sorted)
  1. 从网格搜索结果中提取最佳模型:
Best_RF_model_from_Grid = RF_grid_sorted.model_ids[0]

# Model performance
Best_RF_model_from_Grid = h2o.get_model(Best_RF_model_from_Grid) 
print(Best_RF_model_from_Grid)

在以下屏幕截图中,我们可以看到网格模型在训练数据和交叉验证数据上的模型指标:

图片

  1. 使用 GBM 训练模型。以下是使用默认设置训练 GBM 的方法:
GBM_default_settings = H2OGradientBoostingEstimator(model_id = 'GBM_default', \
                       nfolds = 10, \
                       fold_assignment = "Modulo", \
                       keep_cross_validation_predictions = True)

# Use train() to build the model
GBM_default_settings.train(x = predictors, y = target, training_frame = train)
  1. 在 GBM 上使用网格搜索。要执行网格搜索,请设置以下超参数:
hyper_params = {'learn_rate': [0.001,0.01, 0.1],
                'sample_rate': [0.8, 0.9],
                'col_sample_rate': [0.2, 0.5, 1],
                'max_depth': [3, 5, 9]}
  1. 使用H2OGridSearch()上的超参数使用网格搜索训练 GBM 模型:
GBM_grid_search = H2OGridSearch(H2OGradientBoostingEstimator(nfolds = 10, \
                        fold_assignment = "Modulo", \
                        keep_cross_validation_predictions = True,\
                        stopping_metric = 'AUC', stopping_rounds = 5),
                        hyper_params = hyper_params, grid_id= 'GBM_Grid')

# Use train() to start the grid search
GBM_grid_search.train(x = predictors, y = target, training_frame = train)
  1. 与早期模型一样,我们可以按 AUC 排序查看结果:
# Sort and show the grid search results
GBM_grid_sorted = GBM_grid_search.get_grid(sort_by='auc', decreasing=True)
print(GBM_grid_sorted)
  1. 从网格搜索中提取最佳模型:
Best_GBM_model_from_Grid = GBM_grid_sorted.model_ids[0]

Best_GBM_model_from_Grid = h2o.get_model(Best_GBM_model_from_Grid) 
print(Best_GBM_model_from_Grid)

我们可以使用H2OStackedEnsembleEstimator构建一个堆叠集成 ML 模型,该模型可以使用我们使用 H2O 算法构建的模型来提高预测性能。H2OStackedEnsembleEstimator帮助我们找到一组预测算法的最佳组合。

  1. 创建一个列表,包含我们使用网格搜索构建的早期模型的最佳模型:
# list the best models from each grid
all_models = [Best_GLM_model_from_Grid, Best_RF_model_from_Grid, Best_GBM_model_from_Grid]
  1. 使用H2OStackedEnsembleEstimator设置堆叠集成模型:
# Set up Stacked Ensemble
ensemble = H2OStackedEnsembleEstimator(model_id = "ensemble", base_models = all_models, metalearner_algorithm = "deeplearning")

# uses GLM as the default metalearner
ensemble.train(y = target, training_frame = train)
  1. 在测试数据上评估集成性能:
# Eval ensemble performance on the test data
Ens_model = ensemble.model_performance(test)
Ens_AUC = Ens_model.auc()
  1. test数据上比较基学习器的性能。以下代码测试了我们构建的所有 GLM 模型的表现:
# Checking the model performance for all GLM models built
model_perf_GLM_default = GLM_default_settings.model_performance(test)
model_perf_GLM_regularized = GLM_regularized.model_performance(test)
model_perf_Best_GLM_model_from_Grid = Best_GLM_model_from_Grid.model_performance(test)

以下代码测试了我们构建的所有随机森林模型的表现:

# Checking the model performance for all RF models built
model_perf_RF_default_settings = RF_default_settings.model_performance(test)
model_perf_Best_RF_model_from_Grid = Best_RF_model_from_Grid.model_performance(test)

以下代码测试了我们构建的所有 GBM 模型的表现:

# Checking the model performance for all GBM models built
model_perf_GBM_default_settings = GBM_default_settings.model_performance(test)
model_perf_Best_GBM_model_from_Grid = Best_GBM_model_from_Grid.model_performance(test)
  1. 要从基学习器中获得最佳的 AUC,请执行以下命令:
# Best AUC from the base learner models
best_auc = max(model_perf_GLM_default.auc(), model_perf_GLM_regularized.auc(), \
 model_perf_Best_GLM_model_from_Grid.auc(), \
 model_perf_RF_default_settings.auc(), \
 model_perf_Best_RF_model_from_Grid.auc(), \
 model_perf_GBM_default_settings.auc(), \
 model_perf_Best_GBM_model_from_Grid.auc())

print("Best AUC out of all the models performed: ", format(best_auc))
  1. 以下命令显示了堆叠集成模型的 AUC:
# Eval ensemble performance on the test data
Ensemble_model = ensemble.model_performance(test)
Ensemble_model = Ensemble_model.auc()

它是如何工作的...

我们使用 Google Colab 来训练我们的模型。在我们在 Google Colab 中安装 H2O 之后,我们初始化了 H2O 实例。我们还导入了所需的库。

为了使用 H2O 库,我们从h2o.estimators中导入了H2OGeneralizedLinearEstimatorH2ORandomForestEstimatorH2OGradientBoostingEstimator。我们还导入了H2OStackedEnsembleEstimator,以使用堆叠集成训练我们的模型。

我们挂载了 Google Drive 并使用h2o.import_file()读取我们的数据集。这创建了一个 H2O DataFrame,它与pandas DataFrame 非常相似。然而,数据不是存储在内存中,而是在远程 H2O 集群中的一个位置。

然后,我们对 H2O DataFrame 进行了基本操作以分析我们的数据。我们查看维度、前几行以及每列的数据类型。shape属性返回一个包含行数和列数的元组。head()方法返回前 10 个观测值。types属性返回每列的数据类型。

注意,H2O DataFrame 中的分类变量被标记为enum

我们的目标变量是default.payment.next.month。使用table()方法,我们看到了目标变量两个类的分布。在这种情况下,table()方法返回了类10的计数。

我们不需要ID列,因此使用带有axis=1参数的drop()方法将其删除。使用axis=1,它删除了列。否则,axis=0的默认值将删除索引中的标签。

我们分析了数值变量的分布。你可以探索数据到任何程度。我们还通过性别、教育、婚姻等各种类别看到了目标变量两个类的分布。

然后,我们使用asfactor()方法将分类变量转换为因子类型。这也适用于目标变量。

我们创建了一个预测变量列表和目标变量列表。我们使用split_frame()方法将我们的 DataFrame 拆分为训练集和测试集。

我们将比率传递给split_frame()方法。在我们的例子中,我们将数据集拆分为 70%和 30%。然而,请注意,这并没有给出精确的 70%-30%拆分。H2O 使用概率拆分方法而不是使用精确比率来拆分数据集。这是为了使在大数据上的拆分更加高效。

在我们将数据集拆分为训练集和测试集之后,我们开始训练我们的模型。我们使用了 GLM、随机森林、梯度提升机GBM)和堆叠集成来训练堆叠模型。

如何做...部分,在步骤 1步骤 2中,我们展示了使用默认设置训练 GLM 模型的代码。我们使用交叉验证来训练我们的模型。

步骤 3中,我们使用lambda_search训练了一个 GLM 模型,这有助于找到最佳的正则化参数。

步骤 4中,我们使用网格搜索参数来训练我们的 GLM 模型。我们设置了超参数并将它们提供给H2OGridSearch()方法。这有助于我们在模型之间搜索最佳参数。在H2OGridSearch()方法中,我们使用了RandomDiscrete搜索标准策略。

默认的搜索标准策略是笛卡尔,它涵盖了超参数组合的全部空间。随机离散策略执行所有提供的超参数组合的随机搜索。

步骤 5中,通过get_grid()方法,我们查看使用提供的参数的不同组合构建的每个模型的 AUC 分数。在步骤 6中,我们从随机网格搜索中提取了最佳模型。我们还可以在最佳模型上使用print()方法来查看模型在训练数据和交叉验证数据上的性能指标。

步骤 7中,我们使用默认设置训练了一个随机森林模型,并在步骤 8 中查看结果的模型摘要。在步骤 9步骤 10中,我们展示了使用网格搜索训练随机森林模型的代码。我们为各种可接受的超参数设置了多个值,例如sample_ratecol_sample_rate_per_treemax_depthntreessample_rate指的是不重复的行采样。它的值在01之间,表示数据的采样百分比。col_sample_rate_per_tree是每个树的不重复列采样。max_depth用于指定每个树应构建的最大深度。更深的树可能在训练数据上表现更好,但将花费更多计算时间,并且可能过拟合,无法泛化到未见过的数据。ntrees参数用于基于树的算法,用于指定在模型上构建的树的数量。

步骤 11步骤 12中,我们打印了由网格搜索生成的每个模型的 AUC 分数,并从中提取了最佳模型。

我们还训练了 GBM 模型来拟合我们的数据。在第 13 步中,我们使用默认设置构建了 GBM。在第 14 步中,我们为网格搜索设置了超参数空间。我们在第 15 步中使用了它,在那里我们训练了我们的 GBM。在 GBM 中,我们为超参数设置了值,例如learn_ratesample_ratecol_sample_ratemax_depthntreeslearn_rate参数用于指定 GBM 算法训练模型的速度。较低的learn_rate参数值更好,可以帮助避免过拟合,但可能会在计算时间上付出代价。

在 H2O 中,learn_rate在 GBM 和 XGBoost 中可用。

第 16 步显示了网格搜索产生的每个模型的 AUC 分数。我们在第 17 步中提取了最佳的网格搜索 GBM。

在第 18 步到第 20 步中,我们使用 H2O 的H2OStackedEnsembleEstimator训练了我们的堆叠集成模型。我们在测试数据上评估了所得模型的性能。

在第 21 步中,我们评估了我们构建的所有 GLM 模型在测试数据上的表现。我们用 RF 和 GBM 训练的所有模型也做了同样的事情。在第 22 步中,我们得到了 AUC 分数最高的模型。在第 23 步中,我们评估了堆叠集成模型在测试数据上的 AUC 分数,以便比较堆叠集成模型与单个基础学习器的性能。

还有更多...

注意,我们使用了交叉验证来训练所有模型。我们使用nfolds选项来设置用于交叉验证的折数。在我们的例子中,我们使用了nfolds=5,但我们也可以将其设置为更高的数字。

每个构建的模型中折数需要相同。

指定了nfolds的值后,我们还可以为fold_assignment参数提供一个值。fold_assignment可以取autorandommodulostratified等值。如果我们将其设置为Auto,算法将自动选择一个选项;目前,它选择Random。将fold_assignment设置为Random将启用将数据随机分割成nfolds个集合。当fold_assignment设置为Modulo时,它使用确定性方法将数据均匀分割成nfolds,这些nfolds不依赖于seed参数。

当我们使用交叉验证方法构建模型时,确保您为所有模型指定一个seed值或使用fold_assignment="Modulo"

在网格搜索中,我们使用了两个参数:stopping_metricstopping_rounds。这些参数适用于 GBM 和随机森林算法,但不适用于 GLM。stopping_metric指定了在指定提前停止时考虑的指标,这可以通过将stopping_rounds设置为一个大于零的值来实现。

在我们的示例中,我们将stopping_metric设置为 AUC,将stopping_rounds设置为五。这意味着如果 AUC 在指定的轮次(在我们的例子中是五轮)内没有改善,算法将测量 AUC 并在进一步训练之前停止。

如果指定了stopping_metric,则必须设置stopping_rounds。当也设置了stopping_tolerance时,如果模型的stopping_metric没有通过stopping_tolerance值改善,模型将在达到stopping_rounds中提到的轮数后停止训练。

参见

H2O 文档可在docs.h2o.ai/找到。

第十一章:使用 NLP 进行文本分类的异构集成

在本章中,我们将涵盖以下主题:

  • 使用异构算法集成的垃圾邮件过滤

  • 使用集成模型进行电影评论的情感分析

简介

文本分类是语言处理和文本挖掘广泛研究的一个领域。使用文本分类机制,我们可以根据其内容将文档分类到预定义的类别中。

在本章中,我们将探讨如何对发送到我们手机上的短文本消息进行分类。虽然我们收到的某些消息很重要,但其他消息可能对我们的隐私构成严重威胁。我们希望能够正确地分类文本消息,以避免垃圾邮件并避免错过重要消息。

使用异构算法集成的垃圾邮件过滤

我们将使用来自 UCI ML 存储库的 SMS 垃圾邮件收集数据集来创建垃圾邮件分类器。使用垃圾邮件分类器,我们可以估计这些消息的极性。我们可以使用各种分类器将消息分类为垃圾邮件或非垃圾邮件。

在这个例子中,我们选择如朴素贝叶斯、随机森林和支持向量机之类的算法来训练我们的模型。

我们使用各种数据清洗和准备机制来准备我们的数据。为了预处理我们的数据,我们将执行以下序列:

  1. 将所有文本转换为小写

  2. 删除标点符号

  3. 删除停用词

  4. 执行词干提取

  5. 数据分词

我们还使用词频-逆文档频率TF-IDF)处理我们的数据,这告诉我们单词在消息或文档中出现的频率。TF 的计算如下:

TF = 单词在文档中出现的次数 / 文档中单词的总数

TF-IDF 根据单词在文档或文档集合中出现的频率对单词的重要性进行数值评分。简单来说,TF-IDF 分数越高,术语越罕见。分数越低,则越常见。TD-IDF 的数学表示如下:

tfidf(w,d,D)= tf(t,d) × idf(t,D)

其中 w 代表单词,d 代表文档,D 代表文档集合。

在这个例子中,我们将使用 SMS 垃圾邮件收集数据集,该数据集包含用于手机垃圾邮件研究收集的有标签消息。此数据集可在 UCI ML 存储库中找到,并在 GitHub 存储库中提供。

准备工作

我们首先导入所需的库:

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

注意,在这个例子中,我们导入如nltk之类的库来准备我们的数据。我们还从sklearn.feature_extraction导入CountVectorizerTfidfVectorizer模块。这些模块用于机器学习算法中的特征提取。

我们重用来自 scikit-learn 网站的plot_confusion_matrix来绘制混淆矩阵。这是我们之前章节中使用的相同函数:

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()

我们设置工作目录并读取数据集:

os.chdir("/.../Chapter 11/CS - SMS Classification")
os.getcwd()

df_sms = pd.read_csv("sms_labeled_data.csv", encoding = 'utf8')

注意,我们使用encoding='utf8'。这是为了指导read_csv()方法使用 UTF 编码来读取文件。Python 附带了许多编解码器。完整的列表可在docs.python.org/3/library/codecs.html#standard-encodings找到。

在读取数据后,我们检查它是否已正确加载:

df_sms.head()

我们还使用dataframe.shape检查数据集中的观测值和特征数量:

df_sms.shape

我们查看垃圾邮件和正常邮件的数量:

# Gives the count for ham messages
print(df_sms["type"].value_counts()[0])
no_of_ham_messages = df_sms["type"].value_counts()[0]

# Gives the count for spam messages
print(df_sms["type"].value_counts()[1])
no_of_spam_messages = df_sms["type"].value_counts()[1]

我们还可以可视化垃圾邮件和正常邮件的比例:

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)

# set individual bar lables using above list
for i in ax.patches:
string = str(round((i.get_height()/total)*100, 2))+'%'
# get_x pulls left or right; get_height pushes up or down
ax.text(i.get_x()+0.16, i.get_height(), string, fontsize=13, color='black')

使用前面的代码,我们看到以下图表:

图片

我们还定义了一个函数来删除标点符号,将文本转换为小写,并删除停用词:

lemmatizer = WordNetLemmatizer()

# Defining a function to remove punctuations, convert text to lowercase and remove stop words
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 nopunc.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

我们将定义的process_text()函数应用于数据集中的文本变量:

df_sms['text'] = df_sms['text'].apply(text_processing)

我们将特征和目标变量分开,并将数据分为traintest子集:

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)

我们使用CountVectorizer模块将文本转换为向量:

count_vectorizer = CountVectorizer(stop_words='english')

count_train = count_vectorizer.fit_transform(X_train)
count_test = count_vectorizer.transform(X_test)

我们还使用TfidfVectorizer模块将文本转换为 TF-IDF 向量:

tfidf = TfidfVectorizer(stop_words='english')

tfidf_train = tfidf.fit_transform(X_train)
tfidf_test = tfidf.transform(X_test)

现在让我们继续训练我们的模型。我们在计数数据和 TF-IDF 数据上使用以下算法,并查看单个模型的表现:

  • 朴素贝叶斯

  • 支持向量机

  • 随机森林

我们还结合模型预测以查看集成结果。

如何做到这一点...

让我们从训练我们的模型开始,看看它们在本节中的表现:

  1. 使用朴素贝叶斯算法训练模型。将此算法应用于计数数据和 TF-IDF 数据。

下面的代码用于在计数数据上训练朴素贝叶斯:

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)))

查看前面模型的traintest准确率:

图片

  1. 使用classification_report()方法打印分类报告。将Y_testnb_pred_test传递给classification_report()方法:
print(classification_report(Y_test, nb_pred_test))

这给出了以下输出,显示了目标变量中每个类的precisionrecallf1-scoresupport

图片

  1. Y_testnb_pred_test传递给plot_confusion_matrix()函数以绘制混淆矩阵,如下所示:
target_names = ['Spam','Ham']

# Pass actual & predicted values to the confusion matrix()
cm = confusion_matrix(Y_test, nb_pred_test)
plt.figure()
plot_confusion_matrix(cm, classes=target_names)
plt.show()

下面的图表显示了真正的负例、假正例、假负例和真正例的值:

图片

注意,在之前的准备部分中,我们使用了TfidfVectorizer模块将文本转换为 TF-IDF 向量。

  1. 将朴素贝叶斯模型拟合到 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(count_train, Y_train)))
print('The accuracy for the testing data is {}'.format(nb.score(count_test, Y_test)))
  1. 检查 TF-IDF 测试数据的性能统计信息:
print(classification_report(Y_test, nb_pred_test_tfidf))

target_names = ['Spam','Ham']

# Pass actual & predicted values to the confusion matrix()
cm = confusion_matrix(Y_test, nb_pred_test_tfidf)
plt.figure()

plot_confusion_matrix(cm, classes=target_names)
plt.show()

在下面的屏幕截图,我们可以看到前面代码块的结果:

图片

  1. 使用支持向量机分类器对计数数据进行模型拟合。使用GridSearchCV在估计器的指定参数值范围内进行搜索:
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)

# We use the grid model to predict the class 
svc_rbf_train_predicted_values = svc_gcv_rbf_count.predict(count_train)
svc_rbf_test_predicted_values = svc_gcv_rbf_count.predict(count_test)

# We use the grid model to predict the class probabilities
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_))

网格搜索为我们提供了最佳模型。我们可以看到最佳模型的参数值和得分:

图片

  1. 使用以下代码查看计数数据的test准确率:
print(classification_report(Y_test, svc_rbf_test_predicted_values))

target_names = ['Spam','Ham']

# Pass actual & predicted values to the confusion matrix()
cm = confusion_matrix(Y_test, svc_rbf_test_predicted_values)
plt.figure()
plot_confusion_matrix(cm,classes=target_names)
plt.show()

这是classification_report()和混淆矩阵的输出:

图片

  1. 使用 TF-IDF 数据使用 SVM:
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)

# We use the grid model to predict the class 
svc_tfidf_rbf_train_predicted_values = svc_gcv.predict(tfidf_train)
svc_tfidf_rbd_test_predicted_values = svc_gcv.predict(tfidf_test)

# We use the grid model to predict the class probabilities
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_))

以下输出显示了使用 SVM 和 RBF 核在 TF-IDF 数据上训练的模型的最佳得分:

图片

  1. 打印前一个模型的分类报告和混淆矩阵:

图片

  1. 使用网格搜索交叉验证在计数数据上拟合随机森林模型,就像我们对 SVM 所做的那样:
# Set the parameters for grid search
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]}

# Create an instance of the Random Forest Classifier()
rf = RandomForestClassifier()

# Use gridsearchCV(), pass the values you have set for grid search
rf_gcv = GridSearchCV(rf, rf_params, cv=5)

# Fit the model onto the train data
rf_gcv.fit(count_train, Y_train)

# We use the grid model to predict the class 
rf_train_predicted_values = rf_gcv.predict(count_train)
rf_test_predicted_values = rf_gcv.predict(count_test)

# We use the grid model to predict the class probabilities
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_))

网格搜索随机森林的网格参数返回最佳参数和最佳得分,如下截图所示:

图片

  1. 使用分类报告和混淆矩阵,查看我们在测试数据上使用计数数据的随机森林模型的性能指标:
print(classification_report(Y_test, rf_test_predicted_values))

target_names = ['Spam','Ham']

# Pass actual & predicted values to the confusion matrix()
cm = confusion_matrix(Y_test, rf_test_predicted_values)
plt.figure()
plot_confusion_matrix(cm,classes=target_names)
plt.show() 

报告如下所示:

图片

  1. 在 TF-IDF 数据上使用网格搜索在随机森林上构建模型:
# Set the parameters for grid search
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]}

# Create an instance of the Random Forest Classifier()
rf = RandomForestClassifier()

# Use gridsearchCV(), pass the values you have set for grid search
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']
# Pass actual & predicted values to the confusion matrix()
cm = confusion_matrix(Y_test, rf_tfidf_test_predicted_values)
plt.figure()
plot_confusion_matrix(cm, classes=target_names)
plt.show()
  1. predict_proba()方法的输出取出来,收集每个模型的预测概率以绘制 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 图并进行比较:

图片

  1. 将所有模型的概率平均值并绘制 ROC 曲线:
plt.subplot(4,3,7)

### Test Count Data
d = (nb_pred_test_proba + svc_gcv_test_proba_rbf + rf_gcv_pred_test_proba)/4

fpr, tpr, thresholds = roc_curve(Y_test,d[:,1])
roc_auc = auc(Y_test,d[:,1])

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')

plt.subplot(4,3,8)

### Test TF-IDF Data
d = (nb_tfidf_pred_test_proba + svc_gcv_tfidf_test_proba_rbf + rf_gcv_tfidf_pred_test_proba)/4

fpr, tpr, thresholds = roc_curve(Y_test,d[:,1])
roc_auc = auc(Y_test,d[:,1])

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.show()

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

我们可以在以下屏幕截图中看到 ROC 和 AUC 得分的平均值:

图片

  1. 检查集成结果的准确性。创建一个包含预测结果的数组,如下所示:
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)
  1. 计算各个观测值的预测值的众数,以执行最大投票以获得最终的预测结果:
# Using mode on the array, we get the max vote for each observation
predicted_array = mode(predicted_array)

# Check the array
print(predicted_array)

print("The accuracy for test")
accuracy_score(Y_test, predicted_array[0][0])
  1. 分别绘制在计数数据和 TF-IDF 数据上训练的模型的测试准确率:

图片

它是如何工作的...

准备就绪部分,我们导入了所有必需的库并定义了绘制混淆矩阵的函数。我们使用 UTF8 编码读取我们的数据集。我们检查了数据集中垃圾邮件和正常邮件的比例,并使用CountVectorizerTfidfVectorizer模块将文本转换为向量以及 TF-IDF 向量。

之后,我们使用各种算法构建了多个模型。我们还对计数数据和 TF-IDF 数据都应用了每个算法。

模型需要按照以下顺序构建:

  1. 计数数据上的朴素贝叶斯

  2. TF-IDF 数据上的朴素贝叶斯

  3. 计数数据上的 RBF 核 SVM

  4. 基于 RBF 核的 SVM 在 TF-IDF 数据上

  5. 计数数据的随机森林

  6. TF-IDF 数据的随机森林

基于朴素贝叶斯分类器在机器学习中的文本分类被广泛使用。朴素贝叶斯算法基于特征属于一个类的条件概率。在步骤 1中,我们使用朴素贝叶斯算法在计数数据上构建了我们的第一个模型。在步骤 2中,我们使用classification_report()检查性能指标,以查看precisionrecallf1-scoresupport。在步骤 3中,我们调用plot_confusion_matrix()绘制混淆矩阵。

然后,在步骤 4中,我们在 TF-IDF 数据上构建了朴素贝叶斯模型,并在步骤 5中评估了其性能。在步骤 6步骤 7中,我们使用支持向量机在计数数据上训练模型,使用classification_report的输出评估其性能,并绘制了混淆矩阵。我们使用 RBF 核训练了 SVM 模型。我们还展示了使用GridSearchCV寻找最佳参数的示例。在步骤 8步骤 9中,我们重复了步骤 6步骤 7中的操作,但这次我们在 TF-IDF 数据上训练了 SVM。

步骤 10中,我们使用网格搜索在计数数据上训练了一个随机森林模型。我们将criterion超参数设置为ginientropy。我们还为参数设置了多个值,例如min_samples_splitmax_depthmin_samples_leaf。在步骤 11中,我们评估了模型的表现。

然后,在步骤 12中,我们在 TF-IDF 数据上训练了另一个随机森林模型。使用predict_proba()函数,我们在测试数据上得到了类别概率。我们在步骤 13中使用相同的方法绘制了带有 AUC 分数的 ROC 曲线,标注在每个模型的图表上。这有助于我们比较模型的表现。

步骤 14中,我们平均了从计数和 TF-IDF 数据模型中得到的概率,然后绘制了集成结果的 ROC 曲线。从步骤 15步骤 17,我们绘制了基于计数数据和 TF-IDF 数据构建的每个模型的测试准确率。

使用集成模型对电影评论进行情感分析

情感分析是自然语言处理NLP)中另一个广泛研究的研究领域。它是一个流行的任务,用于分析评论以确定评论者提供的评论的情感。在这个例子中,我们将专注于分析来自互联网电影数据库IMDb)的电影评论数据,并根据其是正面还是负面进行分类。

我们有存储在.txt文件中的电影评论,这些文件被分成了两个文件夹:负面和正面。有 1,000 条正面评论和 1,000 条负面评论。这些文件可以从 GitHub 获取。

我们将这个案例研究分成了两部分:

  • 第一部分是准备数据集。我们将读取提供的 .txt 格式的评论文件,将它们附加起来,根据它们被放入哪个文件夹来标记为正面或负面,并创建一个包含标签和文本的 .csv 文件。

  • 在第二部分,我们将在计数数据和 TF-IDF 数据上构建多个基础学习器。我们将评估基础学习器的性能,然后评估预测的集成。

准备就绪

我们首先导入所需的库:

import os
import glob
import pandas as pd

我们将工作文件夹设置如下:

os.chdir("/.../Chapter 11/CS - IMDB Classification")
os.getcwd()

我们设置路径变量并遍历文件夹中的 .txt 文件。

注意,我们有一个子文件夹 /txt_sentoken/pos,其中包含正面评论的 TXT 文件。同样,我们还有一个子文件夹 /txt_sentoken/neg,其中包含负面评论的 TXT 文件。

正面评论的 TXT 文件被读取,评论被附加到一个数组中。我们使用这个数组创建一个 DataFrame,df_pos

path="/.../Chapter 11/CS - IMDB Classification/txt_sentoken/pos/*.txt"

files = glob.glob(path)
text_pos = []

for p in files:
 file_read = open(p, "r")
 to_append_pos = file_read.read()
 text_pos.append(to_append_pos)
 file_read.close()

df_pos = pd.DataFrame({'text':text_pos,'label':'positive'})
df_pos.head()

使用 head() 方法,我们查看正面评论。

我们还遍历负文件夹中的 TXT 文件来读取负面评论,并将它们附加到一个数组中。我们使用这个数组创建一个 DataFrame,df_neg

path="/Users/Dippies/CODE PACKT - EML/Chapter 11/CS - IMDB Classification/txt_sentoken/neg/*.txt"

files = glob.glob(path)
text_neg = []

for n in files:
    file_read = open(n, "r")
    to_append_neg = file_read.read()
    text_neg.append(to_append_neg)
    file_read.close()

df_neg = pd.DataFrame({'text':text_neg,'label':'negative'})
df_neg.head()

最后,我们使用 concat() 方法将正面和负面的 DataFrame 合并成一个单一的 DataFrame:

df_moviereviews=pd.concat([df_pos, df_neg])

我们可以使用 head()tail() 方法查看准备好的 DataFrame:

print(df_moviereviews.head())
print(df_moviereviews.tail())

之前的代码给出了以下输出:

从前面的图像中,我们注意到正面和负面评论是顺序添加的。DataFrame 的前半部分包含正面评论,而后半部分包含负面评论。

让我们打乱数据,使其不保持顺序:

from sklearn.utils import shuffle

df_moviereviews=shuffle(df_moviereviews)
df_moviereviews.head(10)

现在,我们可以看到 DataFrame 中的数据已经被打乱了:

我们验证合并后的 DataFrame 的维度,看看它是否包含 2,000 个观测值,这将是我们将 1,000 个负面评论和 1,000 个正面评论合并的结果:

df_moviereviews.shape

从之前的代码中,我们注意到我们有 2,000 个观测值和 2 列。

我们还可以将结果 DataFrame 写入另一个 .csv 文件,以避免像之前步骤那样从 TXT 文件重新创建 CSV 文件:

df_moviereviews.to_csv("/.../Chapter 11/CS - IMDB Classification/Data_IMDB.csv") 

接下来,我们将定义之前使用过的 plot_confusion_matrix() 方法。

现在,我们可以看到我们数据中正面和负面评论的占比。在我们的案例中,比例正好是 50:50:

df_moviereviews["label"].value_counts().plot(kind='pie')
plt.tight_layout(pad=1,rect=(0, 0, 0.7, 1))

plt.text(x=-0.9,y=0.1, \
         s=(np.round(((df_moviereviews["label"].\
                       value_counts()[0])/(df_moviereviews["label"].value_counts()[0] + \
                       df_moviereviews["label"].value_counts()[1])),2)))

plt.text(x=0.4,y=-0.3, \
         s=(np.round(((df_moviereviews["label"].\
                       value_counts()[1])/(df_moviereviews["label"].value_counts()[0] + \
                       df_moviereviews["label"].value_counts()[1])),2)))

plt.title("% Share of the Positive and Negative reviews in the dataset")

之前代码的输出可以在以下屏幕截图中看到:

现在,我们将“正面”标签替换为“1”,“负面”标签替换为“0”:

df_moviereviews.loc[df_moviereviews["label"]=='positive',"label",]=1
df_moviereviews.loc[df_moviereviews["label"]=='negative',"label",]=0

我们使用各种数据清理和准备机制来准备我们的数据。我们将遵循与之前配方中相同的顺序来预处理我们的数据:

  1. 将所有文本转换为小写

  2. 删除标点符号

  3. 删除停用词

  4. 执行词干提取

  5. 分词数据

接下来,我们将定义一个函数来执行前面的清理步骤:

lemmatizer = WordNetLemmatizer()
def process_text(text):
    nopunc = [char for char in text if char not in string.punctuation]
    nopunc = ''.join(nopunc)

    clean_words = [word.lower() for word in nopunc.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

我们调用前面的函数来处理我们的文本数据:

df_moviereviews['text'] = df_moviereviews['text'].apply(process_text)

我们现在将构建我们的基础学习器并评估集成结果。

如何操作...

我们首先导入我们需要的剩余库:

  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
  1. 分离目标变量和预测变量:
X = df_moviereviews.loc[:,'text']
Y = df_moviereviews.loc[:,'label']
Y = Y.astype('int')
  1. 执行数据的训练集-测试集划分:
X_train,X_test,y_train,y_test = train_test_split(X, Y, test_size=.3, random_state=1)
  1. 使用CountVectorizer()将文本转换为向量:
count_vectorizer = CountVectorizer()
count_train = count_vectorizer.fit_transform(X_train)
count_test = count_vectorizer.transform(X_test)
  1. 使用TfidfVectorizer()将文本转换为 TF-IDF 向量:
tfidf = TfidfVectorizer()
tfidf_train = tfidf.fit_transform(X_train)
tfidf_test = tfidf.transform(X_test)

我们继续在计数数据和 TF-IDF 数据上训练基础学习器。我们使用随机森林模型、朴素贝叶斯模型和支持向量分类器模型训练基础学习器。

  1. 使用网格搜索在计数数据上训练随机森林模型:
# Set the parameters for grid search
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]}

# Create an instance of the RandomForestClassifier()
rf = RandomForestClassifier()
warnings.filterwarnings("ignore")

# Use gridsearchCV(), pass the values you have set for grid search
rf_count = GridSearchCV(rf, rf_params, cv=5)

rf_count.fit(count_train, Y_train)

# Predict class predictions & class probabilities with test data
rf_count_predicted_values = rf_count.predict(count_test)
rf_count_probabilities = rf_count.predict_proba(count_test)

rf_count_train_accuracy = rf_count.score(count_train, Y_train)
rf_count_test_accuracy = rf_count.score(count_test, Y_test)

print('The accuracy for the training data is {}'.\
      format(rf_count_train_accuracy))

print('The accuracy for the testing data is {}'.\
      format(rf_count_test_accuracy))
  1. 评估precisionrecallf1-scoresupportaccuracy
print(classification_report(Y_test, rf_count_predicted_values))

# Pass actual & predicted values to the confusion_matrix()
cm = confusion_matrix(Y_test, rf_count_predicted_values)
plt.figure()
plot_confusion_matrix(cm, classes=target_names,normalize=False)
plt.show()

在以下屏幕截图中,我们可以看到前面代码的输出:

图片

  1. 使用网格搜索在 TF-IDF 数据上训练随机森林模型:
# Set the parameters for grid search
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]}

# Create an instance of the RandomForestClassifier()
rf = RandomForestClassifier()
warnings.filterwarnings("ignore")

# Use gridsearchCV(), pass the values you have set for grid search
rf_tfidf = GridSearchCV(rf, rf_params, cv=5)

rf_tfidf.fit(tfidf_train, Y_train)
  1. 评估模型的性能:
rf_tfidf_predicted_values = rf_tfidf.predict(tfidf_test)
rf_tfidf_probabilities = rf_tfidf.predict_proba(tfidf_test)

rf_train_accuracy = rf_tfidf.score(tfidf_train, Y_train)
rf_test_accuracy = rf_tfidf.score(tfidf_test, Y_test)

print('The accuracy for the training data is {}'.format(rf_train_accuracy))
print('The accuracy for the testing data is {}'.format(rf_test_accuracy))

print(classification_report(Y_test, rf_tfidf_predicted_values))

# Pass actual & predicted values to the confusion_matrix()
cm = confusion_matrix(Y_test, rf_tfidf_predicted_values)
plt.figure()
plot_confusion_matrix(cm, classes=target_names,normalize=False)
plt.show()
  1. 在计数数据上训练朴素贝叶斯模型,并检查测试数据的准确率:
nb_count = MultinomialNB()
nb_count.fit(count_train, Y_train)

nb_count_predicted_values = nb_count.predict(count_test)
nb_count_probabilities = nb_count.predict_proba(count_test)

nb_train_accuracy = nb_count.score(count_train, Y_train)
nb_test_accuracy = nb_count.score(count_test, Y_test)

print('The accuracy for the training data is {}'.format(nb_train_accuracy))
print('The accuracy for the testing data is {}'.format(nb_test_accuracy))
  1. 使用classification_report()和混淆矩阵评估其他模型的性能参数:
print(classification_report(Y_test, nb_predicted_values))

# Pass actual & predicted values to the confusion matrix()
cm = confusion_matrix(Y_test, nb_predicted_values)
plt.figure()
plot_confusion_matrix(cm, classes=target_names,normalize=False)
plt.show()
  1. 在 TF-IDF 数据上训练朴素贝叶斯模型,并按我们之前对早期模型所做的方式评估其性能:
nb_tfidf = MultinomialNB()
nb_tfidf.fit(count_train, Y_train)

nb_tfidf_predicted_values = nb_tfidf.predict(tfidf_test)
nb_tfidf_probabilities = nb_tfidf.predict_proba(tfidf_test)

nb_train_accuracy = nb_tfidf.score(tfidf_train, Y_train)
nb_test_accuracy = nb_tfidf.score(tfidf_test, Y_test)

print('The accuracy for the training data is {}'.format(nb_train_accuracy))
print('The accuracy for the testing data is {}'.format(nb_test_accuracy))

print(classification_report(Y_test, nb_predicted_values))

#Pass actual & predicted values to the confusion matrix()
cm = confusion_matrix(Y_test, nb_predicted_values)
plt.figure()
plot_confusion_matrix(cm, classes=target_names,normalize=False)
plt.show()
  1. 在计数数据上使用具有线性核的支持向量分类器算法训练模型。我们还对 SVC 的C参数进行了网格搜索:
svc_count = SVC(kernel='linear',probability=True)
svc_params = {'C':[0.001, 0.01, 0.1, 1, 10]}

svc_gcv_count = GridSearchCV(svc_count, svc_params, cv=5)
svc_gcv_count.fit(count_train, Y_train)

svc_count_predicted_values = svc_gcv_count.predict(count_test)
svc_count_probabilities = svc_gcv_count.predict_proba(count_test)

svc_count_train_accuracy = svc_gcv_count.score(count_train, Y_train)
svc_count_test_accuracy = svc_gcv_count.score(count_test, Y_test)

print('The accuracy for the training data is {}'.format(svc_gcv_count.score(count_train, Y_train)))
print('The accuracy for the testing data is {}'.format(svc_gcv_count.score(count_test, Y_test)))

print(classification_report(Y_test, svc_count_predicted_values))
# Pass actual & predicted values to the confusion_matrix()
cm = confusion_matrix(Y_test, svc_count_predicted_values)
plt.figure()
plot_confusion_matrix(cm, classes=target_names,normalize=False)
plt.show()
  1. 在 TF-IDF 数据上使用具有线性核的支持向量分类器算法训练模型。我们还对 SVC 的C参数进行了网格搜索:
svc_tfidf = SVC(kernel='linear',probability=True)
svc_params = {'C':[0.001, 0.01, 0.1, 1, 10]}

svc_gcv_tfidf = GridSearchCV(svc_tfidf, svc_params, cv=5)
svc_gcv_tfidf.fit(tfidf_train, Y_train)

svc_tfidf_predicted_values = svc_gcv_tfidf.predict(tfidf_test)
svc_tfidf_probabilities = svc_gcv_tfidf.predict_proba(tfidf_test)

svc_tfidf_train_accuracy = svc_gcv_count.score(tfidf_train, Y_train)
svc_tfidf_test_accuracy = svc_gcv_count.score(tfidf_test, Y_test)

print('The accuracy for the training data is {}'.format(svc_gcv_tfidf.score(count_train, Y_train)))
print('The accuracy for the testing data is {}'.format(svc_gcv_tfidf.score(count_test, Y_test)))

print(classification_report(Y_test, svc_tfidf_predicted_values))
# Pass actual & predicted values to the confusion_matrix()
cm = confusion_matrix(Y_test, svc_tfidf_predicted_values)
plt.figure()
plot_confusion_matrix(cm, classes=target_names)
plt.show()
  1. 绘制每个模型的 ROC 曲线。以下是一个绘图代码示例(完整代码包含在本书的代码包中):
fpr, tpr, thresholds = roc_curve(Y_test, rf_count_probabilities[:,1])
roc_auc = auc(Y_test, rf_count_probabilities[:,1])

plt.title('ROC Random Forest Count Data')
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 曲线:

图片

  1. 在计数和 TF-IDF 数据上绘制集成结果的 ROC 曲线:

图片

  1. 使用最大投票计算集成模型的准确率:
predicted_values_count = np.array([rf_count_predicted_values, \
                                   nb_count_predicted_values, \
                                   svc_count_predicted_values])

predicted_values_tfidf = np.array([rf_tfidf_predicted_values, \
                                   nb_tfidf_predicted_values, \
                                   svc_tfidf_predicted_values])

predicted_values_count = mode(predicted_values_count)
predicted_values_tfidf = mode(predicted_values_tfidf)
  1. 绘制在计数数据和 TF-IDF 数据上训练的每个模型的测试准确率:
count = np.array([rf_count_test_accuracy,\
                  nb_count_test_accuracy,\
                  svc_count_test_accuracy,\
                  accuracy_score(Y_test, predicted_values_count[0][0])])

tfidf = np.array([rf_tfidf_test_accuracy,\
                  nb_tfidf_test_accuracy,\
                  svc_tfidf_test_accuracy,\
                  accuracy_score(Y_test, predicted_values_tfidf[0][0])])

label_list = ["Random Forest", "Naive_Bayes", "SVM_Linear", "Ensemble"] 
plt.plot(count)
plt.plot(tfidf)
plt.xticks([0,1,2,3],label_list)

for i in range(4):
    plt.text(x=i,y=(count[i]+0.001), s=np.round(count[i],4))

for i in range(4):
    plt.text(x=i,y=tfidf[i]-0.003, s=np.round(tfidf[i],4))

plt.legend(["Count","TFIDF"])
plt.title("Test accuracy")

plt.tight_layout(pad=1,rect=(0, 0, 2.5, 2))
plt.show()

以下图表显示了所有模型和集成结果在计数数据和 TF-IDF 数据上的准确率比较:

图片

它是如何工作的...

我们首先导入所需的库。在本章中,我们使用了一个名为glob的模块。glob模块用于定义匹配指定模式到路径、目录和文件名的技术。我们使用 glob 模块来查找指定路径中的所有文件。之后,我们使用open()方法以读取模式打开每个文件。我们读取每个文件,并将其追加到形成包含所有评论的评论数据集。我们还创建了一个标签列,用于标记每个评论为正面或负面标签。

然而,在我们添加了所有正面和负面评论之后,我们注意到它们是按顺序添加的,这意味着前半部分包含了所有正面评论,而后半部分包含了负面评论。我们使用shuffle()方法对这些数据进行随机排序。

我们通过将其转换为小写、删除标点符号和停用词、执行词干提取和分词来清理数据,以创建特征向量。

如何做...部分,我们首先在第 1 步中导入了库。在第 2 步中,我们将目标变量和特征变量分别分离到XY

我们在第 3 步中将数据分为训练集和测试集。我们使用test_size=.3将数据分为训练集和测试集。

第 4 步第 5 步中,我们使用了CountVectorizer()TfidfVectorizer()将文本转换为向量,并将文本转换为 TF-IDF 向量。注意,使用CountVectorizer(),我们生成了count_traincount_test数据集。使用TfidfVectorizer(),我们生成了tfidf_traintfidf_test数据集。

第 6 步中,我们设置了网格搜索的超参数来训练一个随机森林模型。我们在计数数据上训练了我们的随机森林模型,并检查了我们的训练和测试准确率。

我们对构建的所有模型在测试数据上使用了predict()predict_proba()方法来预测类别以及类别概率。

第 7 步中,我们生成了混淆矩阵来评估我们在前一步构建的随机森林模型的表现。在第 8 步第 9 步中,我们在 TF-IDF 数据上对另一个随机森林模型进行了重复训练,并评估了其性能。从第 10 步第 12 步,我们在计数数据和 TF-IDF 数据上训练了朴素贝叶斯模型。

第 13 步第 14 步中,我们分别使用线性核在计数数据和 TF-IDF 数据上训练了支持向量机分类算法。在第 15 步中,我们为构建的每个基本学习器绘制了 ROC 曲线和 AUC 分数。在第 16 步中,我们还绘制了集成模型的 RUC 曲线,以比较与基本学习器的性能。最后,在第 17 步中,我们绘制了每个模型在计数和 TF-IDF 数据上的测试准确率。

还有更多...

在当今世界,文本信息的可用性和流动是无限的。这意味着我们需要各种技术来处理这些文本问题,以提取有意义的信息。例如,**词性标注(POS)**是自然语言处理(NLP)空间中的基本任务之一。词性标注用于将文本中的单词标注为它们各自的词性。这些标签可以用于更复杂的任务,如句法和语义解析、机器翻译(MT)和问答。

有八个主要词性:

  • 名词

  • 代词

  • 形容词

  • 动词

  • 副词

  • 介词

  • 连词

  • 呼语:

图片

NLTK 库有在分词后应用于文本的获取词性标注的功能。让我们导入所需的库:

import os
import pandas as pd
import nltk
from nltk.tag import pos_tag
from nltk.corpus import stopwords

我们使用之前创建的 DataFrame df_moviereviews。我们将文本转换为小写:

df_moviereviews['text'] =df_moviereviews['text'].apply(lambda x: " ".join(x.lower() for x in x.split()))
df_moviereviews['text'].head()

我们通过去除停用词、标点符号、词形还原和分词来预处理文本:

from nltk.stem.wordnet import WordNetLemmatizer
import string
stop = set(stopwords.words('english'))
exclude = set(string.punctuation) 
lemma = WordNetLemmatizer()
def clean(doc):
    stop_free = " ".join([i for i in doc.lower().split() if i not in stop])
    stop_free = ''.join(ch for ch in stop_free if ch not in exclude)
    normalized = " ".join(lemma.lemmatize(word) for word in stop_free.split())
    return normalized

tokenized_sent = [clean(doc).split() for doc in df_moviereviews["text"]]

我们来看一下第一篇电影评论的前 10 个标记词列表:

tokenized_sent[0][0:10]

这生成了以下输出:

我们进行词性标注:

postag=[nltk.pos_tag(token) for token in tokenized_sent]

我们打印出第一篇电影评论的前 10 个词性标注:

postag[0][0:10]

我们看到词性标注的单词:

分块处理是另一个可以增加词性标注结构性的过程。分块处理用于实体检测;它将多个标记词标记为有意义的实体。有多种分块器可供选择;NLTK 提供了 ne_chunk,它可以识别人名(姓名)、地点和组织。其他常用的分块器包括 OpenNLPYamchaLingpipe。还可以使用分块器的组合,并对结果应用最大投票法来提高分类性能。

第十二章:使用 Keras 进行多类分类的同质集成

在本章中,我们将介绍以下配方:

  • 一个用于分类时尚产品的同质模型集成

引言

在分类问题中,许多研究已经进行了,以找出如何获得更好的分类准确率。当有大量类别需要预测时,这个问题往往更加复杂。在多类分类的情况下,假设目标变量中的每个类别都是相互独立的。多类分类技术涉及训练一个或多个模型来分类目标变量,该变量可以超过两个类别。

一个用于分类时尚产品的同质模型集成

在这个例子中,我们将使用 Fashion-MNIST 数据集。这个数据集包含来自十个类别的 60,000 个时尚产品图像。目标变量可以被分类为十个类别:

  • T 恤/上衣

  • 裤子

  • 开衫

  • 服装

  • 外套

  • 凉鞋

  • 衬衫

  • 运动鞋

  • 靴子

每个图像都是一个 28 x 28 的灰度图像。我们将通过读取数据,在几次迭代中构建几个同质模型,以查看集成是否可以提供更高的准确率。

准备工作

我们将使用 Google Colab 来训练我们的模型。Google Colab 自带 TensorFlow,所以我们不需要在我们的系统中单独安装它。

我们按照以下方式导入所需的库:

import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

import tensorflow as tf
from tensorflow import keras
from sklearn.utils import resample
from sklearn.metrics import accuracy_score
from sklearn.metrics import confusion_matrix
from sklearn.metrics import classification_report
from scipy import stats

我们从tf.keras附带的数据集中加载数据:

# Load the fashion-mnist pre-shuffled train data and test data
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.fashion_mnist.load_data()

我们检查训练集和测试集的维度:

# Print training set shape 
print("x_train shape:", x_train.shape, "y_train shape:", y_train.shape)

这给我们以下输出:

图片

我们记录目标变量中的唯一值:

np.unique(y_train)

我们可以看到有 10 个类别被标记为 0 到 9:

图片

我们可以快速查看前几个观察结果如下:

fig=plt.figure(figsize=(16,8))

# number of columns for images in plot
columns=5 

# number of rows for images in plot
rows=3

for i in range (1,columns*rows+1):
      fig.add_subplot(rows,columns,i)
      plt.title("Actual Class: {}".\
              format((y_train[i])),color='r',fontsize=16)
      plt.imshow(x_train[i])
plt.show()

使用前面的代码,我们绘制了前 15 个图像及其相关标签:

图片

如何做...

我们现在将进入训练模型阶段:

  1. 在下面的代码块中,我们将使用tf.keras在几个迭代中创建多个同质模型:
accuracy = pd.DataFrame( columns=["Accuracy","Precision","Recall"])
predictions = np.zeros(shape=(10000,7))
row_index = 0
for i in range(7):
        # bootstrap sampling 
        boot_train = resample(x_train,y_train,replace=True, n_samples=40000, random_state=None)
        model = tf.keras.Sequential([
            tf.keras.layers.Flatten(input_shape=(28, 28)),
            tf.keras.layers.Dense(256, activation=tf.nn.relu),
            tf.keras.layers.Dense(128, activation=tf.nn.relu),
            tf.keras.layers.Dense(128, activation=tf.nn.relu),
            tf.keras.layers.Dense(128, activation=tf.nn.relu),
            tf.keras.layers.Dense(128, activation=tf.nn.relu),
            tf.keras.layers.Dense(128, activation=tf.nn.relu),
            tf.keras.layers.Dense(128, activation=tf.nn.relu),
            tf.keras.layers.Dense(128, activation=tf.nn.relu),
            tf.keras.layers.Dense(128, activation=tf.nn.relu),
            tf.keras.layers.Dense(128, activation=tf.nn.relu),
            tf.keras.layers.Dense(10, activation=tf.nn.softmax)])

        # compile the model
        model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

        # Train the model
        model.fit(x_train,y_train,epochs=10,batch_size=64)

        # Evaluate accuracy
        score = model.evaluate(x_test, y_test, batch_size=64)
        accuracy.loc[row_index,"Accuracy"]=score[1]

        # Make predictions
        model_pred= model.predict(x_test)
        pred_classes =model_pred.argmax(axis=-1)
        accuracy.loc[row_index, 'Precision'] = precision_score(y_test, pred_classes, average='weighted')
        accuracy.loc[row_index, 'Recall'] = recall_score(y_test, pred_classes,average='weighted')

        # Save predictions to predictions array
        predictions[:,i] = pred_classes

        print(score)
        row_index+=1

        print("Iteration " + str(i+1)+ " Accuracy : " + "{0}".format(score[1]))

我们在每个迭代中提到七个迭代和十个时期。在下面的屏幕截图中,我们可以看到随着模型训练的进展:

图片

  1. 步骤 1的代码中,我们收集了每个迭代在测试数据上的准确率、精确率和召回率:
accuracy

在下面的屏幕截图中,我们可以看到前三个指标在每个迭代中的变化:

图片

  1. 我们将创建一个包含每个迭代中所有模型返回的预测的 DataFrame:
# Create dataframe using prediction of each iteration
df_iteration = pd.DataFrame([predictions[:,0],\
                           predictions[:,1],\
                           predictions[:,2],\
                           predictions[:,3],\
                           predictions[:,4],\
                           predictions[:,5],\
                           predictions[:,6]])
  1. 我们将类型转换为整数:
df_iteration = df_iteration.astype('int64')
  1. 我们执行最大投票来识别每个观察值预测的最可能类别。我们简单地使用mode来找出对于每个观察值预测次数最多的类别:
# find the mode for result
mode = stats.mode(df_iteration)
  1. 我们计算测试数据的准确率:
# calculate the accuracy for test dataset
print(accuracy_score( y_test, mode[0].T))
  1. 我们使用所需的标签生成混淆矩阵:
# confusion matrix
cm = confusion_matrix(y_test, mode[0].T, labels=[0, 1, 2, 3, 4, 5, 6, 7, 8])
  1. 我们绘制了混淆矩阵:
ax= plt.subplot()

# annot=True to annotate cells
sns.heatmap(cm, annot=True, ax = ax, fmt='g', cmap='Blues')

混淆矩阵的图表如下所示:

  1. 我们创建了一个包含所有迭代编号的 DataFrame:
accuracy["Models"]=["Model 1",\
                   "Model 2",\
                   "Model 3",\
                   "Model 4",\
                   "Model 5",\
                   "Model 6",\
                   "Model 7"]
  1. 然后,我们将准确率、精确率和召回率合并到一个单独的表中:
accuracy=accuracy.append(pd.DataFrame([[\
                                        accuracy_score(y_test,\
                                        mode[0].T),0,0,\
                                        "Ensemble Model"]], \
                                        columns=["Accuracy",\
                                        "Precision","Recall",\
                                        "Models"]))

accuracy.index=range(accuracy.shape[0])

accuracy.set_value(7, 'Precision', precision_score(y_test, mode[0].T, average='micro'))
accuracy.set_value(7, 'Recall', recall_score(y_test, mode[0].T, average='micro'))

在下面的屏幕截图中,我们可以看到包含每个模型和集成模型指标的结构的截图:

  1. 我们绘制了每个迭代的准确率和最大投票的准确率:
plt.figure(figsize=(20,8))
plt.plot(accuracy.Models,accuracy.Accuracy)
plt.title("Accuracy across all Iterations and Ensemble")
plt.ylabel("Accuracy")
plt.show()

这给我们以下图表。我们注意到与单个模型相比,最大投票方法返回的准确率是最高的:

  1. 我们还绘制了每个模型和集成模型的精确率和召回率:
plt.figure(figsize=(20,8))
plt.plot(accuracy.Models,accuracy.Accuracy,accuracy.Models,accuracy.Precision)
plt.title("Metrics across all Iterations and models")
plt.legend(["Accuracy","Precision"])
plt.show()

这在下面的屏幕截图中显示:

从前面的屏幕截图中,我们注意到集成模型的精确率和召回率有所提高。

它是如何工作的...

准备就绪部分,我们导入了所需的库。请注意,我们已经导入了TensorFlow库。我们可以通过导入tf.keras.datasets模块直接访问数据集。此模块包含各种内置数据集,包括以下内容:

  • boston_housing:波士顿房价回归数据集

  • cifar10:CIFAR10 小型图像分类数据集

  • fashion_mnist:Fashion-MNIST 数据集

  • imdb:IMDB 情感分类数据集

  • mnist:MNIST 手写数字数据集

  • reuters:路透社主题分类数据集

我们使用了此模块中的fashion_mnist数据集。我们加载了预洗牌的培训和测试数据,并检查了培训和测试子集的形状。

准备就绪部分,我们注意到训练子集的形状是(60000,28,28),这意味着我们有 60000 个大小为 28 X 28 像素的图像。

我们使用unique()方法检查目标变量的不同级别。我们看到从 0 到 9 共有 10 个类别。

我们还快速浏览了一些图像。我们定义了我们所需的列数和行数。运行迭代后,我们使用matplotlib.pyplot.imshow()以灰度形式绘制了图像。我们还使用matplotlib.pyplot.title()打印了每个图像的实际类别标签。

如何做...部分的步骤 1中,我们使用tf.keras模块创建了多个同质模型。在每个迭代中,我们使用resample()方法创建自助样本。我们将replace=True传递给resample()方法,以确保我们有带替换的样本。

在此步骤中,我们还定义了模型架构。我们使用tf.keras.layers向模型中添加层。在每个层中,我们定义了单元数。

“模型架构”指的是整个神经网络结构,它包括称为层的单元组。这些层以链状结构排列。每一层是其前一层的函数。确定模型架构是神经网络的关键。

在我们的例子中,我们进行了一些迭代。我们设置了迭代次数。在每次迭代中,我们编译模型并将其拟合到我们的训练数据上。我们在测试数据上进行了预测,并在 DataFrame 中捕获以下指标:

  • 准确度

  • 精确度

  • 召回率

我们将Rectified Linear Units (RELU)作为隐藏层的激活函数。ReLU 表示为f(x) = max{0, x}。在神经网络中,ReLU 被推荐为默认的激活函数。

注意,在模型架构的最后一层,我们使用了 softmax 作为激活函数。softmax 函数可以看作是 sigmoid 函数的推广。虽然 sigmoid 函数用于表示二元变量的概率分布,但 softmax 函数用于表示具有两个以上类别的目标变量的概率分布。当 softmax 函数用于多类分类时,它为每个类别返回一个介于 0 和 1 之间的概率值。所有概率值的总和将等于 1。

步骤 2中,我们检查了我们在步骤 1中创建的准确度 DataFrame 的结构。我们注意到我们有三个列用于准确度、精确度和召回率,以及每个迭代的指标都被捕获。在步骤 3中,我们将 DataFrame 中的数据类型转换为整数。

步骤 4中,我们使用stats.mode()对每个观测值进行了最大投票。由于我们进行了七次迭代,因此每个观测值都有七个预测。stats.mode()返回了出现次数最多的预测。

步骤 5中,我们检查了使用最大投票预测的模型的准确度。在步骤 6步骤 7中,我们生成了混淆矩阵来可视化正确的预测。图表中的对角线元素是正确的预测,而离对角线元素是误分类。我们发现正确的分类数量比误分类的数量要多。

步骤 8步骤 9中,我们继续创建一个结构来保存性能指标(准确度、精确度和召回率),以及每个迭代和集成标签。我们使用这个结构来绘制性能指标的图表。

步骤 10中,我们绘制了每个迭代和最大投票预测的准确度。同样,在步骤 11中,我们绘制了每个迭代和最大投票预测的精确度和召回率。

从我们在步骤 10步骤 11中生成的图表中,我们注意到最大投票预测的准确度、精确度和召回率都有所提高。

参见

tf.keras 模块为我们提供了 TensorFlow 特定的功能,例如即时执行、数据管道和估计器。您可以查看tf.keras模块为我们提供的各种选项。

在我们的示例中,我们使用了tf.keras.optimizer模块提供的内置优化器类。在我们的示例中,我们使用了Adam 优化器,但您还可以使用其他优化器,例如 Adadelta、Adagrad、Adamax、RMSprop 或 SGD。

在当今时代,Adam 优化器是最佳优化器之一。它是随机梯度下降SGD)的扩展。SGD 考虑所有权重更新使用单个学习率,并且在模型训练过程中学习率保持不变。Adam 算法考虑自适应学习率方法来计算每个参数的单独学习率。

tf.keras.losses 模块为我们提供了各种选项,以便我们可以选择我们的损失函数。我们使用了sparse_categorical_crossentropy。根据您的任务,您可能需要选择其他选项,例如binary_crossentropycategorical_crossentropymean_squared_error等等。

在多类分类的情况下,如果目标变量是独热编码的,请使用categorical_crossentropy。如果目标变量中的类别表示为整数,请使用sparse_categorical_crossentropy

您可以在www.tensorflow.org/api_docs/python/tf/keras上获取有关可用于tf.keras的其他超参数的更详细信息。