监督学习研讨会(四)

原文:annas-archive.org/md5/20b62d9571c391689a2d53277f7e2459

译者:飞龙

协议:CC BY-NC-SA 4.0

4. 自回归

第十三章:活动 4.01:基于周期数据的自回归模型

导入必要的包、类和库。

注意

该活动将使用早期版本的 pandas,请确保使用以下命令降级 pandas 版本:

pip install pandas==0.24.2

代码如下:

import pandas as pd

import numpy as np

from statsmodels.tsa.ar_model import AR

from statsmodels.graphics.tsaplots import plot_acf

import matplotlib.pyplot as plt

加载数据并将 Date 列转换为 datetime 类型:

df = pd.read_csv(‘…/Datasets/austin_weather.csv’)

df.Date = pd.to_datetime(df.Date)

print(df.head())

print(df.tail())

df.head()的输出应如下所示:

https://github.com/OpenDocCN/freelearn-ml-pt2-zh/raw/master/docs/spr-lrn-ws/img/image-6NRIUD3J.jpg

图 4.22:df.head()的输出

df.tail()的输出应如下所示:

https://github.com/OpenDocCN/freelearn-ml-pt2-zh/raw/master/docs/spr-lrn-ws/img/image-79U4JNOU.jpg

图 4.23:df.tail()的输出

绘制完整的平均温度值集(df.TempAvgF),以 Date 为 x 轴:

fig, ax = plt.subplots(figsize = (10, 7))

ax.scatter(df.Date, df.TempAvgF)

plt.show()

输出如下所示:

https://github.com/OpenDocCN/freelearn-ml-pt2-zh/raw/master/docs/spr-lrn-ws/img/image-MN96GL2H.jpg

图 4.24:奥斯汀温度数据的多年变化图

注意数据的周期性行为。考虑到温度随年度天气周期变化,这是合理的。

构建一个自相关图(使用 statsmodels),以查看是否可以使用自回归模型来预测平均温度。自回归模型的滞后期在哪些地方是可接受的,哪些地方则不可接受?请查看以下代码:

max_lag = 730

fig, ax = plt.subplots(figsize = (10, 7))

acf_plot = plot_acf(x = df.TempAvgF, ax = ax, lags = max_lag, \

use_vlines = False, alpha = 0.9, \

title = ‘奥斯汀温度的自相关’

‘vs. 滞后’)

ax.grid(True)

ax.text(280, -0.01, ‘90%置信区间’, fontsize = 9)

ax.set_xlabel(‘滞后’, fontsize = 14)

ax.tick_params(axis = ‘both’, labelsize = 12)

图表应如下所示:

https://github.com/OpenDocCN/freelearn-ml-pt2-zh/raw/master/docs/spr-lrn-ws/img/image-S6EAOA1L.jpg

图 4.25:自相关与滞后(天数)的关系

只有当自相关线位于 90%置信区间之外时,滞后期才是可接受的,置信区间以阴影区域表示。请注意,在这种情况下,我们看到的是峰值和谷值,而不是稳定下降的 ACF 值。这应该符合你的直觉,因为原始数据展示了周期性模式。另外,请注意,存在非常强的正相关和负相关。在大约 180 天(半年)左右,可能会利用强烈的负相关,但那是一个更高级的时间序列话题,超出了我们这里的讨论范围。从图 4.25 中可以得出的主要结论是,在短滞后期后,ACF 有一个非常陡峭的下降。现在,使用与之前相同的方法查看滞后图与 ACF 的关系。

获取实际的 ACF 值:

corr0 = np.correlate(df.TempAvgF[0: ] - df.TempAvgF.mean(), \

df.TempAvgF[0: ] - df.TempAvgF.mean(), mode = ‘valid’)

corrs = [np.correlate(df.TempAvgF[:(df.TempAvgF.shape[0] - i)] \

  • df.TempAvgF.mean(), df.TempAvgF[i: ] \

  • df.TempAvgF.mean(), mode = ‘valid’)

for i in range(max_lag)] / corr0

我们需要在练习 4.01 中开发的相同实用网格绘图函数,用于创建自回归模型:

“”"

用于绘制一系列滞后图的实用函数

展示自相关的图

“”"

def plot_lag_grid(series, corrs, axis_min, axis_max, \

num_plots, total_lag, n_rows, n_cols):

lag_step = int(total_lag / num_plots)

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

for i, var_name in enumerate(range(num_plots)):

corr = corrs[lag_step * i]

ax = fig.add_subplot(n_rows, n_cols, i + 1)

ax.scatter(series, series.shift(lag_step * i))

ax.set_xlim(axis_min, axis_max)

ax.set_ylim(axis_min, axis_max)

ax.set_title('lag = ’ + str(lag_step * i))

ax.text(axis_min + 0.05 * (axis_max - axis_min), \

axis_max - 0.05 * (axis_max - axis_min), \

'相关性 = ’ + str(round(corr[0], 3)))

fig.tight_layout()

plt.show()

现在,既然我们已经有迹象表明我们对短滞后感兴趣,但也发现半年和一年附近有强相关性,让我们看看两个时间尺度:

plot_lag_grid(df.TempAvgF, corrs, df.TempAvgF.min(), \

df.TempAvgF.max(), 9, 45, 3, 3)

plot_lag_grid(df.TempAvgF, corrs, df.TempAvgF.min(), \

df.TempAvgF.max(), 9, 405, 3, 3)

短滞后的输出结果如下:

https://github.com/OpenDocCN/freelearn-ml-pt2-zh/raw/master/docs/spr-lrn-ws/img/image-I4WY2ZXG.jpg

图 4.26:短滞后的滞后图

较长滞后的输出结果如下:

https://github.com/OpenDocCN/freelearn-ml-pt2-zh/raw/master/docs/spr-lrn-ws/img/image-QG5SLXLX.jpg

图 4.27:较长滞后的滞后图

我们可以从图 4.26 看出,相关性从滞后 5 到 40 一直在下降。随着时间尺度的延长,图 4.27 显示相关性快速下降,然后随着滞后接近一年时逐渐改善。这与原始数据的图表直觉相吻合(附注——这应该加强 EDA 的重要性)。

我们从初步分析中预期,自回归模型将专注于相对短的滞后。让我们使用 statsmodelsAR 函数来构建一个模型并查看结果:

“”"

statsmodels AR 函数构建自回归模型

使用所有默认设置,它将确定最大滞后

并提供所有模型系数

“”"

model = AR(df.TempAvgF)

model_fit = model.fit()

模型拟合现在包含了所有模型信息

max_lag = model_fit.k_ar

“”"

请注意,使用默认设置时,最大滞后是

计算方法为 round(12*(nobs/100.)**(1/4.))

请参见 www.statsmodels.org/devel/generated/statsmodels.tsa.ar_model.AR.fit.html#statsmodels.tsa.ar_model.AR.fit

“”"

print(‘最大滞后:’ + str(max_lag))

print(‘系数:\n’ + str(model_fit.params))

我们想预测多远的未来

max_forecast = 365

从模型生成预测值

pred_temp = pd.DataFrame({‘pred_temp’: \

model_fit.predict(start = max_lag, \

end = df.shape[0] \

  • max_forecast - 1)})

附加日期以便可视化

pred_temp[‘Date’] = df.loc[pred_temp.index, ‘Date’].reindex()

pred_temp.loc[(max(df.index) + 1):, ‘Date’] = \

pd.to_datetime([max(df.Date) \

  • pd.Timedelta(days = i)

for i in range(1, max_forecast + 1)])

结果是一个具有最多 23 天滞后的模型:

https://github.com/OpenDocCN/freelearn-ml-pt2-zh/raw/master/docs/spr-lrn-ws/img/image-0SLEXDL5.jpg

图 4.28:奥斯汀温度数据的 AR 模型

在同一图表上绘制预测、预报和原始数据:

“”"

可视化叠加在实际数据上的预测

以及对未来的外推

“”"

fig, ax = plt.subplots(figsize = (10, 7))

ax.plot(df.Date, df.TempAvgF, c = “blue”, \

linewidth = 4, label = ‘实际平均温度’)

ax.plot(pred_temp.loc[0 : len(df.TempAvgF), ‘Date’], \

pred_temp.loc[0 : len(df.TempAvgF), ‘pred_temp’], \

c = “yellow”, linewidth = 0.5, \

label = ‘预测温度’)

ax.plot(pred_temp.loc[len(df.TempAvgF):, ‘Date’], \

pred_temp.loc[len(df.TempAvgF):, ‘pred_temp’], \

c = “red”, linewidth = 2, \

label = ‘预测温度’)

ax.set_xlabel(‘日期’, fontsize = 14)

ax.tick_params(axis = ‘both’, labelsize = 12)

ax.set_title(‘奥斯汀德克萨斯州每日平均温度’)

ax.tick_params(axis = ‘both’, labelsize = 12)

ax.legend()

plt.show()

输出结果如下:

https://github.com/OpenDocCN/freelearn-ml-pt2-zh/raw/master/docs/spr-lrn-ws/img/image-62BMHFHF.jpg

图 4.29:奥斯汀温度预测与预报

让我们放大查看数据的最后 30 天,以及前 30 个预测值:

放大查看原始数据末端附近的窗口

window = 30

fig, ax = plt.subplots(figsize = (10, 7))

ax.plot(df.Date[(len(df.TempAvgF) - window) : len(df.TempAvgF)], \

df.TempAvgF[(len(df.TempAvgF) - window) : \

len(df.TempAvgF)], \

c = “blue”, linewidth = 4, \

label = ‘实际平均温度’)

ax.plot(pred_temp.Date.iloc[(-max_forecast \

  • window)😦-max_forecast)], \

pred_temp.pred_temp.iloc[(-max_forecast \

  • window)😦-max_forecast)], \

c = “red”, linewidth = 2, label = ‘预测温度’)

ax.plot(pred_temp.loc[len(df.TempAvgF):\

(len(df.TempAvgF) + window), ‘Date’], \

pred_temp.loc[len(df.TempAvgF):\

(len(df.TempAvgF) + window), ‘pred_temp’], \

c = “green”, linewidth = 2, label = ‘预测温度’)

ax.set_xlabel(‘日期’, fontsize = 14)

ax.tick_params(axis = ‘both’, labelsize = 12)

ax.set_title(‘奥斯汀德克萨斯州每日平均温度’)

ax.tick_params(axis = ‘both’, labelsize = 12)

ax.set_xticks(pd.date_range(df.Date[len(df.TempAvgF) - window], \

df.Date[len(df.TempAvgF) - 1] \

  • pd.Timedelta(days = window), 5))

ax.legend()

plt.show()

我们将得到以下输出:

https://github.com/OpenDocCN/freelearn-ml-pt2-zh/raw/master/docs/spr-lrn-ws/img/image-55LKGBXK.jpg

图 4.30:数据末端预测的详细情况

注释

若要访问此特定部分的源代码,请参考 https://packt.live/3hOXUQL.

你也可以在 https://packt.live/313Vmbl 在线运行这个示例。你必须执行整个 Notebook 才能得到预期的结果。

现在活动已成功完成,升级 pandas 的版本,以便顺利运行书中其余部分的练习和活动。要升级 pandas,运行:

pip install pandas==1.0.3

5. 分类技术

第十四章:Activity 5.01: 普通最小二乘分类器 – 二元分类器

解决方案:

导入所需的依赖项:

import struct

import numpy as np

import gzip

import urllib.request

import matplotlib.pyplot as plt

from array import array

from sklearn.linear_model import LinearRegression

将 MNIST 数据加载到内存中:

with gzip.open(‘…/Datasets/train-images-idx3-ubyte.gz’, ‘rb’) as f:

magic, size, rows, cols = struct.unpack(“>IIII”, f.read(16))

img = np.array(array(“B”, f.read())).reshape((size, rows, cols))

with gzip.open(‘…/Datasets/train-labels-idx1-ubyte.gz’, ‘rb’) as f:

magic, size = struct.unpack(“>II”, f.read(8))

labels = np.array(array(“B”, f.read()))

with gzip.open(‘…/Datasets/t10k-images-idx3-ubyte.gz’, ‘rb’) as f:

magic, size, rows, cols = struct.unpack(“>IIII”, f.read(16))

img_test = np.array(array(“B”, f.read()))\

.reshape((size, rows, cols))

with gzip.open(‘…/Datasets/t10k-labels-idx1-ubyte.gz’, ‘rb’) as f:

magic, size = struct.unpack(“>II”, f.read(8))

labels_test = np.array(array(“B”, f.read()))

可视化数据样本:

for i in range(10):

plt.subplot(2, 5, i + 1)

plt.imshow(img[i], cmap=‘gray’);

plt.title(f’{labels[i]}');

plt.axis(‘off’)

输出结果如下:

https://github.com/OpenDocCN/freelearn-ml-pt2-zh/raw/master/docs/spr-lrn-ws/img/image-HVWAR7CZ.jpg

图 5.63:样本数据

构建一个线性分类器模型,用于分类数字 0 和 1。我们将要创建的模型是为了判断样本是数字 0 还是数字 1。为了实现这一点,我们首先需要选择仅包含这些样本的数据:

samples_0_1 = np.where((labels == 0) | (labels == 1))[0]

images_0_1 = img[samples_0_1]

labels_0_1 = labels[samples_0_1]

samples_0_1_test = np.where((labels_test == 0) | (labels_test == 1))

images_0_1_test = img_test[samples_0_1_test]\

.reshape((-1, rows * cols))

labels_0_1_test = labels_test[samples_0_1_test]

可视化选定的信息。以下是数字 0 的代码:

sample_0 = np.where((labels == 0))[0][0]

plt.imshow(img[sample_0], cmap=‘gray’);

输出结果如下:

https://github.com/OpenDocCN/freelearn-ml-pt2-zh/raw/master/docs/spr-lrn-ws/img/image-IPZUMLSW.jpg

图 5.64:第一个样本数据

以下是数字 1 的代码:

sample_1 = np.where((labels == 1))[0][0]

plt.imshow(img[sample_1], cmap=‘gray’);

输出结果如下:

https://github.com/OpenDocCN/freelearn-ml-pt2-zh/raw/master/docs/spr-lrn-ws/img/image-ZJV8H2GT.jpg

图 5.65:第二个样本数据

为了将图像信息提供给模型,我们必须先将数据展平,使每张图像的形状为 1 x 784 像素:

images_0_1 = images_0_1.reshape((-1, rows * cols))

images_0_1.shape

输出结果如下:

(12665, 784)

让我们构建模型;使用 LinearRegression API 并调用 fit 函数:

model = LinearRegression()

model.fit(X=images_0_1, y=labels_0_1)

输出结果如下:

LinearRegression(copy_X=True, fit_intercept=True, n_jobs=None,

normalize=False)

确定训练集准确性:

model.score(X=images_0_1, y=labels_0_1)

输出结果如下:

0.9705320567708795

确定每个训练样本的标签预测值,使用 0.5 的阈值。大于 0.5 的值分类为 1,而小于或等于 0.5 的值分类为 0:

y_pred = model.predict(images_0_1) > 0.5

y_pred = y_pred.astype(int)

y_pred

输出将如下所示:

array([0, 1, 1, …, 1, 0, 1])

计算预测训练值与实际值的分类准确率:

np.sum(y_pred == labels_0_1) / len(labels_0_1)

输出将如下所示:

0.9947887879984209

  1. 比较在测试集上的性能:

y_pred = model.predict(images_0_1_test) > 0.5

y_pred = y_pred.astype(int)

np.sum(y_pred == labels_0_1_test) / len(labels_0_1_test)

输出将如下所示:

0.9938534278959811

注意

要访问此特定部分的源代码,请参阅 https://packt.live/3emRZAk。

您还可以在 https://packt.live/37T4bGh 上在线运行此示例。必须执行整个笔记本才能获得预期的结果。

活动 5.02:KNN 多类别分类器

导入以下包:

import struct

import numpy as np

import gzip

import urllib.request

import matplotlib.pyplot as plt

from array import array

from sklearn.neighbors import KNeighborsClassifier as KNN

将 MNIST 数据加载到内存中。

训练图像:

with gzip.open(‘…/Datasets/train-images-idx3-ubyte.gz’, ‘rb’) as f:

magic, size, rows, cols = struct.unpack(“>IIII”, f.read(16))

img = np.array(array(“B”, f.read())).reshape((size, rows, cols))

训练标签:

with gzip.open(‘…/Datasets/train-labels-idx1-ubyte.gz’, ‘rb’) as f:

magic, size = struct.unpack(“>II”, f.read(8))

labels = np.array(array(“B”, f.read()))

测试图像:

with gzip.open(‘…/Datasets/t10k-images-idx3-ubyte.gz’, ‘rb’) as f:

magic, size, rows, cols = struct.unpack(“>IIII”, f.read(16))

img_test = np.array(array(“B”, f.read()))\

.reshape((size, rows, cols))

测试标签:

with gzip.open(‘…/Datasets/t10k-labels-idx1-ubyte.gz’, ‘rb’) as f:

magic, size = struct.unpack(“>II”, f.read(8))

labels_test = np.array(array(“B”, f.read()))

可视化数据样本:

for i in range(10):

plt.subplot(2, 5, i + 1)

plt.imshow(img[i], cmap=‘gray’);

plt.title(f’{labels[i]}');

plt.axis(‘off’)

输出将如下所示:

https://github.com/OpenDocCN/freelearn-ml-pt2-zh/raw/master/docs/spr-lrn-ws/img/image-DA453QKK.jpg

图 5.66:样本图像

构建一个 k=3 的 KNN 分类器来分类 MNIST 数据集。同样,为了节省处理能力,随机抽取 5,000 张图像用于训练:

np.random.seed(0)

selection = np.random.choice(len(img), 5000)

selected_images = img[selection]

selected_labels = labels[selection]

为了将图像信息提供给模型,我们必须首先将数据展平,使得每个图像的形状为 1 x 784 像素:

selected_images = selected_images.reshape((-1, rows * cols))

selected_images.shape

输出将如下所示:

(5000, 784)

构建三邻居 KNN 模型并拟合数据到模型中。请注意,在此活动中,我们为模型提供了 784 个特征或维度,而不仅仅是 2:

model = KNN(n_neighbors=3)

model.fit(X=selected_images, y=selected_labels)

输出将如下所示:

KNeighborsClassifier(algorithm=‘auto’, leaf_size=30, metric=‘minkowski’,

metric_params=None, n_jobs=None, n_neighbors=3, p=2,

weights=‘uniform’)

确定模型在训练集上的得分:

model.score(X=selected_images, y=selected_labels)

输出将如下所示:

0.9692

显示模型对训练数据的前两个预测结果:

model.predict(selected_images)[:2]

plt.subplot(1, 2, 1)

plt.imshow(selected_images[0].reshape((28, 28)), cmap=‘gray’);

plt.axis(‘off’);

plt.subplot(1, 2, 2)

plt.imshow(selected_images[1].reshape((28, 28)), cmap=‘gray’);

plt.axis(‘off’);

输出将如下所示:

https://github.com/OpenDocCN/freelearn-ml-pt2-zh/raw/master/docs/spr-lrn-ws/img/image-PFHH0LLF.jpg

图 5.67:测试集的前两个值

比较模型在测试集上的表现:

model.score(X=img_test.reshape((-1, rows * cols)), y=labels_test)

输出将如下所示:

0.9376

注意

要访问此特定部分的源代码,请参考 https://packt.live/313xdlc。

您也可以在 https://packt.live/2Nl6DMo 上在线运行此示例。您必须执行整个 Notebook 才能获得预期结果。

活动 5.03:使用 CART 决策树进行二分类

解决方案:

导入所需的依赖项:

import struct

import numpy as np

import pandas as pd

import gzip

import urllib.request

import matplotlib.pyplot as plt

from array import array

from sklearn.model_selection import train_test_split

from sklearn.tree import DecisionTreeClassifier

加载 MNIST 数据到内存:

with gzip.open(‘…/Datasets/train-images-idx3-ubyte.gz’, ‘rb’) as f:

magic, size, rows, cols = struct.unpack(“>IIII”, f.read(16))

img = np.array(array(“B”, f.read())).reshape((size, rows, cols))

with gzip.open(‘…/Datasets/train-labels-idx1-ubyte.gz’, ‘rb’) as f:

magic, size = struct.unpack(“>II”, f.read(8))

labels = np.array(array(“B”, f.read()))

with gzip.open(‘…/Datasets/t10k-images-idx3-ubyte.gz’, ‘rb’) as f:

magic, size, rows, cols = struct.unpack(“>IIII”, f.read(16))

img_test = np.array(array(“B”, f.read()))\

.reshape((size, rows, cols))

with gzip.open(‘…/Datasets/t10k-labels-idx1-ubyte.gz’, ‘rb’) as f:

magic, size = struct.unpack(“>II”, f.read(8))

labels_test = np.array(array(“B”, f.read()))

可视化数据的一个样本:

for i in range(10):

plt.subplot(2, 5, i + 1)

plt.imshow(img[i], cmap=‘gray’);

plt.title(f’{labels[i]}');

plt.axis(‘off’)

输出将如下所示:

https://github.com/OpenDocCN/freelearn-ml-pt2-zh/raw/master/docs/spr-lrn-ws/img/image-HVWAR7CZ.jpg

图 5.68:样本数据

构建一个线性分类器模型来分类数字 0 和 1。我们将要创建的模型是确定样本是否为数字 0 或 1。为此,我们首先需要仅选择这些样本:

samples_0_1 = np.where((labels == 0) | (labels == 1))[0]

images_0_1 = img[samples_0_1]

labels_0_1 = labels[samples_0_1]

samples_0_1_test = np.where((labels_test == 0) | (labels_test == 1))

images_0_1_test = img_test[samples_0_1_test]\

.reshape((-1, rows * cols))

labels_0_1_test = labels_test[samples_0_1_test]

可视化选定的信息。以下是 0 的代码:

sample_0 = np.where((labels == 0))[0][0]

plt.imshow(img[sample_0], cmap=‘gray’);

输出将如下所示:

https://github.com/OpenDocCN/freelearn-ml-pt2-zh/raw/master/docs/spr-lrn-ws/img/image-CC4BKBHF.jpg

图 5.69:第一组样本数据

以下是 1 的代码:

sample_1 = np.where((labels == 1))[0][0]

plt.imshow(img[sample_1], cmap=‘gray’);

输出将如下所示:

https://github.com/OpenDocCN/freelearn-ml-pt2-zh/raw/master/docs/spr-lrn-ws/img/image-0WOP89CS.jpg

图 5.70:第二组样本数据

为了将图像信息提供给模型,我们必须先将数据展平,使得每个图像的形状为 1 x 784 像素:

images_0_1 = images_0_1.reshape((-1, rows * cols))

images_0_1.shape

输出将如下所示:

(12665, 784)

让我们构建模型;使用 DecisionTreeClassifier API 并调用 fit 函数:

model = DecisionTreeClassifier(random_state=123)

model = model.fit(X=images_0_1, y=labels_0_1)

model

输出将如下所示:

DecisionTreeClassifier(class_weight=None, criterion=‘gini’, max_depth=None,

max_features=None, max_leaf_nodes=None,

min_impurity_decrease=0.0, min_impurity_split=None,

min_samples_leaf=1, min_samples_split=2,

min_weight_fraction_leaf=0.0, presort=False,

random_state=None, splitter=‘best’)

确定训练集的准确率:

model.score(X=images_0_1, y=labels_0_1)

输出将如下所示:

1.0

使用 0.5 的阈值来确定每个训练样本的标签预测值。大于 0.5 的值分类为 1,小于或等于 0.5 的值分类为 0:

y_pred = model.predict(images_0_1) > 0.5

y_pred = y_pred.astype(int)

y_pred

计算预测的训练值与实际值的分类准确率:

np.sum(y_pred == labels_0_1) / len(labels_0_1)

与测试集的表现进行比较:

y_pred = model.predict(images_0_1_test) > 0.5

y_pred = y_pred.astype(int)

np.sum(y_pred == labels_0_1_test) / len(labels_0_1_test)

输出将如下所示:

0.9962174940898345

注意

若要访问此特定部分的源代码,请参阅 https://packt.live/3hNUJbT。

您还可以在线运行此示例,网址:https://packt.live/2Cq5W25。您必须执行整个 Notebook 才能获得期望的结果。

活动 5.04:使用人工神经网络进行乳腺癌诊断分类

导入所需的包。对于这个活动,我们将需要 pandas 包来加载数据,matplotlib 包用于绘图,scikit-learn 用于创建神经网络模型,以及将数据集分割为训练集和测试集。导入所有必要的包和相关模块以完成这些任务:

import pandas as pd

导入 matplotlib.pyplot

来自 sklearn.neural_network 的 MLPClassifier

来自 sklearn.model_selection 的 train_test_split

来自 sklearn 的预处理

使用 pandas 加载乳腺癌诊断数据集并检查前五行:

df = pd.read_csv(‘…/Datasets/breast-cancer-data.csv’)

df.head()

输出结果如下:

https://github.com/OpenDocCN/freelearn-ml-pt2-zh/raw/master/docs/spr-lrn-ws/img/image-D4G2QEWK.jpg

图 5.71:乳腺癌数据集的前五行

此外,拆分数据集为输入(X)和输出(y)变量:

X, y = df[[c for c in df.columns if c != ‘diagnosis’]], df.diagnosis

下一步是特征工程。该数据集的不同列具有不同的量级;因此,在构建和训练神经网络模型之前,我们对数据集进行归一化。为此,我们使用来自 sklearn 的 MinMaxScaler API,它将每一列的值归一化到 0 和 1 之间,正如本章的逻辑回归部分所讨论的那样(请参阅练习 5.03,逻辑回归–多类分类器):https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.MinMaxScaler.html:

X_array = X.values # 返回一个 numpy 数组

min_max_scaler = preprocessing.MinMaxScaler()

X_array_scaled = min_max_scaler.fit_transform(X_array)

X = pd.DataFrame(X_array_scaled, columns=X.columns)

检查归一化数据集的前五行:

X = pd.DataFrame(X_array_scaled, columns=X.columns)

X.head()

输出结果如下:

https://github.com/OpenDocCN/freelearn-ml-pt2-zh/raw/master/docs/spr-lrn-ws/img/image-EV96V76B.jpg

图 5.72:归一化数据集的前五行

在我们构建模型之前,必须首先将诊断值转换为可以在模型中使用的标签。将“良性”诊断字符串替换为值 0,将“恶性”诊断字符串替换为值 1:

诊断类别 = [‘良性’, ‘恶性’,]

输出 = [diagnoses.index(diag) for diag in y]

此外,为了公平地评估模型,我们应将训练数据集分割为训练集和验证集:

train_X, valid_X, \

train_y, valid_y = train_test_split(X, output, \

test_size=0.2, random_state=123)

使用归一化后的数据集和分配的诊断标签创建模型:

model = MLPClassifier(solver=‘sgd’, hidden_layer_sizes=(100,), \

max_iter=1000, random_state=1, \

learning_rate_init=.01)

model.fit(X=train_X, y=train_y)

输出结果如下:

MLPClassifier(activation=‘relu’, alpha=0.0001, batch_size=‘auto’,

beta_1=0.9, beta_2=0.999, early_stopping=False,

epsilon=1e-08, hidden_layer_sizes=(100,),

learning_rate=‘constant’,

learning_rate_init=0.01, max_iter=1000, momentum=0.9,

n_iter_no_change=10, nesterovs_momentum=True, power_t=0.5,

random_state=1, shuffle=True, solver=‘sgd’, tol=0.0001,

validation_fraction=0.1, verbose=False, warm_start=False)

计算模型在验证集上的准确性:

model.score(valid_X, valid_y)

输出结果如下:

0.9824561403508771

注意

要访问此特定部分的源代码,请参考 https://packt.live/3dpNt2G。

你也可以在 https://packt.live/37OpdWM 上在线运行此示例。你必须执行整个 Notebook 才能得到期望的结果。

6. 集成建模

第十五章:活动 6.01:使用独立算法和集成算法的堆叠

解决方案

导入相关库:

导入 pandas 库为 pd

导入 numpy 为 np

导入 seaborn 为 sns

%matplotlib inline

导入 matplotlib.pyplot 为 plt

来自 sklearn.model_selection 导入 train_test_split

来自 sklearn.metrics 导入 mean_absolute_error

来自 sklearn.model_selection 导入 KFold

来自 sklearn.linear_model 导入 LinearRegression

来自 sklearn.tree 导入 DecisionTreeRegressor

来自 sklearn.neighbors 导入 KNeighborsRegressor

来自 sklearn.ensemble 导入 GradientBoostingRegressor, \

RandomForestRegressor

读取数据:

data = pd.read_csv(‘boston_house_prices.csv’)

data.head()

注意

上面的代码片段假设数据集与练习笔记本在同一文件夹中。然而,如果您的数据集位于 Datasets 文件夹中,您需要使用以下代码:data = pd.read_csv(‘…/Datasets/boston_house_prices.csv’)

您将获得以下输出:

https://github.com/OpenDocCN/freelearn-ml-pt2-zh/raw/master/docs/spr-lrn-ws/img/image-J3QAVKGH.jpg

图 6.15:波士顿房价数据集的顶部几行

对数据集进行预处理,删除空值,为建模准备数据:

检查有多少列的空值比例小于 10%

perc_missing = data.isnull().mean()*100

cols = perc_missing[perc_missing < 10].index.tolist()

您将获得以下输出:

https://github.com/OpenDocCN/freelearn-ml-pt2-zh/raw/master/docs/spr-lrn-ws/img/image-ZQI9Z8VR.jpg

图 6.16:列的数量

然后填补缺失值(如果有的话):

data_final = data.fillna(-1)

将数据集划分为训练集和验证集 DataFrame:

train, val = train, val = train_test_split(data_final, \

test_size=0.2, \

random_state=11)

x_train = train.drop(columns=[‘PRICE’])

y_train = train[‘PRICE’].values

x_val = val.drop(columns=[‘PRICE’])

y_val = val[‘PRICE’].values

初始化字典以存储训练集和验证集的 MAE 值:

train_mae_values, val_mae_values = {}, {}

使用以下超参数训练决策树(dt)模型并保存分数:

dt_params = {‘criterion’: ‘mae’, ‘min_samples_leaf’: 15, \

‘random_state’: 11}

dt = DecisionTreeRegressor(**dt_params)

dt.fit(x_train, y_train)

dt_preds_train = dt.predict(x_train)

dt_preds_val = dt.predict(x_val)

train_mae_values[‘dt’] = mean_absolute_error(y_true=y_train, \

y_pred=dt_preds_train)

val_mae_values[‘dt’] = mean_absolute_error(y_true=y_val, \

y_pred=dt_preds_val)

使用以下超参数训练 k-近邻(knn)模型并保存分数:

knn_params = {‘n_neighbors’: 5}

knn = KNeighborsRegressor(**knn_params)

knn.fit(x_train, y_train)

knn_preds_train = knn.predict(x_train)

knn_preds_val = knn.predict(x_val)

train_mae_values[‘knn’] = mean_absolute_error(y_true=y_train, \

y_pred=knn_preds_train)

val_mae_values[‘knn’] = mean_absolute_error(y_true=y_val, \

y_pred=knn_preds_val)

使用以下超参数训练随机森林(rf)模型并保存分数:

rf_params = {‘n_estimators’: 20, ‘criterion’: ‘mae’, \

‘max_features’: ‘sqrt’, ‘min_samples_leaf’: 10, \

‘random_state’: 11, ‘n_jobs’: -1}

rf = RandomForestRegressor(**rf_params)

rf.fit(x_train, y_train)

rf_preds_train = rf.predict(x_train)

rf_preds_val = rf.predict(x_val)

train_mae_values[‘rf’] = mean_absolute_error(y_true=y_train, \

y_pred=rf_preds_train)

val_mae_values[‘rf’] = mean_absolute_error(y_true=y_val, \

y_pred=rf_preds_val)

训练一个梯度提升回归(gbr)模型,使用以下超参数并保存评分:

gbr_params = {‘n_estimators’: 20, ‘criterion’: ‘mae’, \

‘max_features’: ‘sqrt’, ‘min_samples_leaf’: 10, \

‘random_state’: 11}

gbr = GradientBoostingRegressor(**gbr_params)

gbr.fit(x_train, y_train)

gbr_preds_train = gbr.predict(x_train)

gbr_preds_val = gbr.predict(x_val)

train_mae_values[‘gbr’] = mean_absolute_error(y_true=y_train, \

y_pred=gbr_preds_train)

val_mae_values[‘gbr’] = mean_absolute_error(y_true=y_val, \

y_pred=gbr_preds_val)

准备训练和验证数据集,其中四个元估计器使用与之前步骤相同的超参数。首先,构建训练集:

num_base_predictors = len(train_mae_values) # 4

x_train_with_metapreds = np.zeros((x_train.shape[0], \

x_train.shape[1]+num_base_predictors))

x_train_with_metapreds[:, :-num_base_predictors] = x_train

x_train_with_metapreds[:, -num_base_predictors:] = -1

kf = KFold(n_splits=5, random_state=11)

for train_indices, val_indices in kf.split(x_train):

kfold_x_train, kfold_x_val = x_train.iloc[train_indices], \

x_train.iloc[val_indices]

kfold_y_train, kfold_y_val = y_train[train_indices], \

y_train[val_indices]

predictions = []

dt = DecisionTreeRegressor(**dt_params)

dt.fit(kfold_x_train, kfold_y_train)

predictions.append(dt.predict(kfold_x_val))

knn = KNeighborsRegressor(**knn_params)

knn.fit(kfold_x_train, kfold_y_train)

predictions.append(knn.predict(kfold_x_val))

gbr = GradientBoostingRegressor(**gbr_params)

rf.fit(kfold_x_train, kfold_y_train)

predictions.append(rf.predict(kfold_x_val))

gbr = GradientBoostingRegressor(**gbr_params)

gbr.fit(kfold_x_train, kfold_y_train)

predictions.append(gbr.predict(kfold_x_val))

for i, preds in enumerate(predictions):

x_train_with_metapreds[val_indices, -(i+1)] = preds

准备验证集:

x_val_with_metapreds = np.zeros((x_val.shape[0], \

x_val.shape[1]+num_base_predictors))

x_val_with_metapreds[:, :-num_base_predictors] = x_val

x_val_with_metapreds[:, -num_base_predictors:] = -1

predictions = []

dt = DecisionTreeRegressor(**dt_params)

dt.fit(x_train, y_train)

predictions.append(dt.predict(x_val))

knn = KNeighborsRegressor(**knn_params)

knn.fit(x_train, y_train)

predictions.append(knn.predict(x_val))

gbr = GradientBoostingRegressor(**gbr_params)

rf.fit(x_train, y_train)

predictions.append(rf.predict(x_val))

gbr = GradientBoostingRegressor(**gbr_params)

gbr.fit(x_train, y_train)

predictions.append(gbr.predict(x_val))

for i, preds in enumerate(predictions):

x_val_with_metapreds[:, -(i+1)] = preds

训练一个线性回归(lr)模型作为堆叠模型:

lr = LinearRegression(normalize=True)

lr.fit(x_train_with_metapreds, y_train)

lr_preds_train = lr.predict(x_train_with_metapreds)

lr_preds_val = lr.predict(x_val_with_metapreds)

train_mae_values[‘lr’] = mean_absolute_error(y_true=y_train, \

y_pred=lr_preds_train)

val_mae_values[‘lr’] = mean_absolute_error(y_true=y_val, \

y_pred=lr_preds_val)

可视化每个单独模型和堆叠模型的训练和验证误差:

mae_scores = pd.concat([pd.Series(train_mae_values, name=‘train’), \

pd.Series(val_mae_values, name=‘val’)], \

axis=1)

mae_scores

首先,你会得到以下输出:

https://github.com/OpenDocCN/freelearn-ml-pt2-zh/raw/master/docs/spr-lrn-ws/img/image-YV2QPP1E.jpg

图 6.17:训练和验证误差的值

现在,使用以下代码绘制 MAE 分数的条形图:

mae_scores.plot(kind=‘bar’, figsize=(10,7))

plt.ylabel(‘MAE’)

plt.xlabel(‘模型’)

plt.show()

最终输出将如下所示:

https://github.com/OpenDocCN/freelearn-ml-pt2-zh/raw/master/docs/spr-lrn-ws/img/image-2OFCL0GD.jpg

图 6.18:训练和验证误差的可视化

注意

要访问此特定部分的源代码,请参考 https://packt.live/3fNqtMG。

你也可以在 https://packt.live/2Yn2VIl 在线运行这个示例。你必须执行整个笔记本才能获得预期的结果。

7. 模型评估

第十六章:活动 7.01:最终测试项目

导入相关库:

import pandas as pd

import numpy as np

import json

%matplotlib inline

import matplotlib.pyplot as plt

from sklearn.preprocessing import OneHotEncoder

from sklearn.model_selection import RandomizedSearchCV, train_test_split

from sklearn.ensemble import GradientBoostingClassifier

from sklearn.metrics import (accuracy_score, precision_score, \

recall_score, confusion_matrix, precision_recall_curve)

读取 breast-cancer-data.csv 数据集:

data = pd.read_csv(‘…/Datasets/breast-cancer-data.csv’)

data.info()

让我们将输入数据(X)和目标(y)分开:

X = data.drop(columns=[‘diagnosis’])

y = data[‘diagnosis’].map({‘malignant’: 1, ‘benign’: 0}.get).values

将数据集分割为训练集和测试集:

X_train, X_test, \

y_train, y_test = train_test_split(X, y, \

test_size=0.2, random_state=11)

print(X_train.shape)

print(y_train.shape)

print(X_test.shape)

print(y_test.shape)

应该得到以下输出:

(455, 30)

(455,)

(114, 30)

(114,)

选择一个基础模型,并定义要搜索超参数调整的模型的超参数值范围。让我们使用梯度提升分类器作为我们的模型。然后,以字典形式定义要调整的所有超参数的值范围:

meta_gbc = GradientBoostingClassifier()

param_dist = {‘n_estimators’: list(range(10, 210, 10)), \

‘criterion’: [‘mae’, ‘mse’],\

‘max_features’: [‘sqrt’, ‘log2’, 0.25, 0.3, \

0.5, 0.8, None], \

‘max_depth’: list(range(1, 10)), \

‘min_samples_leaf’: list(range(1, 10))}

定义参数以初始化 RandomizedSearchCV 对象,并使用 K 折交叉验证来识别最佳模型超参数。定义随机搜索所需的参数,包括 cv 设为 5,表示使用 5 折交叉验证来选择超参数。然后初始化 RandomizedSearchCV 对象,并使用 .fit() 方法启动优化:

rand_search_params = {‘param_distributions’: param_dist, \

‘scoring’: ‘accuracy’, ‘n_iter’: 100, \

‘cv’: 5, ‘return_train_score’: True, \

‘n_jobs’: -1, ‘random_state’: 11 }

random_search = RandomizedSearchCV(meta_gbc, **rand_search_params)

random_search.fit(X_train, y_train)

应该得到以下输出:

https://github.com/OpenDocCN/freelearn-ml-pt2-zh/raw/master/docs/spr-lrn-ws/img/image-B4U09VDI.jpg

图 7.36:RandomizedSearchCSV 对象

调整完成后,找到获得最高平均测试分数的位置(迭代次数)。找到相应的超参数并保存到字典中:

idx = np.argmax(random_search.cv_results_[‘mean_test_score’])

final_params = random_search.cv_results_[‘params’][idx]

final_params

应该得到以下输出:

https://github.com/OpenDocCN/freelearn-ml-pt2-zh/raw/master/docs/spr-lrn-ws/img/image-Q75G5A0N.jpg

图 7.37:超参数

将训练数据集进一步拆分为训练集和验证集,并在训练数据集上使用最终的超参数训练一个新模型。使用 scikit-learn 的 train_test_split() 方法将 X 和 y 拆分为训练集和验证集,验证集占数据集的 15%:

train_X, val_X, \

train_y, val_y = train_test_split(X_train, y_train, \

test_size=0.15, random_state=11)

train_X.shape, train_y.shape, val_X.shape, val_y.shape

你应该得到以下输出:

((386, 30), (386,), (69, 30), (69,))

使用最终的超参数训练梯度增强分类模型,并根据训练和验证集进行预测。同时,计算验证集的概率:

gbc = GradientBoostingClassifier(**final_params)

gbc.fit(train_X, train_y)

preds_train = gbc.predict(train_X)

preds_val = gbc.predict(val_X)

pred_probs_val = np.array([each[1] \

for each in gbc.predict_proba(val_X)])

计算预测的准确度、精度和召回率,并打印混淆矩阵:

print(‘train accuracy_score = {}’\

.format(accuracy_score(y_true=train_y, y_pred=preds_train)))

print(‘validation accuracy_score = {}’\

.format(accuracy_score(y_true=val_y, y_pred=preds_val)))

print(‘confusion_matrix: \n{}’\

.format(confusion_matrix(y_true=val_y, y_pred=preds_val)))

print(‘precision_score = {}’\

.format(precision_score(y_true=val_y, y_pred=preds_val)))

print(‘recall_score = {}’\

.format(recall_score(y_true=val_y, y_pred=preds_val)))

你应该得到以下输出:

https://github.com/OpenDocCN/freelearn-ml-pt2-zh/raw/master/docs/spr-lrn-ws/img/image-RRBUP7VU.jpg

图 7.38: 评估得分和混淆矩阵

尝试不同的阈值,找到具有较高召回率的最佳点。

绘制精度-召回率曲线:

plt.figure(figsize=(10,7))

精度, 召回率, \

thresholds = precision_recall_curve(val_y, \

pred_probs_val)

plt.plot(recall, precision)

plt.xlabel(‘召回率’)

plt.ylabel(‘精度’)

plt.show()

输出将如下所示:

https://github.com/OpenDocCN/freelearn-ml-pt2-zh/raw/master/docs/spr-lrn-ws/img/image-PQXLFL93.jpg

图 7.39: 精度-召回率曲线

“”"

绘制精度和召回率随阈值增加的变化。

“”"

PR_variation_df = pd.DataFrame({‘precision’: precision, \

‘recall’: recall}, \

index=list(thresholds)+[1])

PR_variation_df.plot(figsize=(10,7))

plt.xlabel(‘阈值’)

plt.ylabel(‘P/R 值’)

plt.show()

你应该得到以下输出:

https://github.com/OpenDocCN/freelearn-ml-pt2-zh/raw/master/docs/spr-lrn-ws/img/image-5EQYQMWH.jpg

图 7.40: 精度和召回率随阈值增加的变化

最终确定一个阈值,用于根据测试数据集进行预测。我们设定一个值,例如 0.05。该值完全取决于你在前一步探索中认为最合适的值:

final_threshold = 0.05

根据测试数据集预测最终值并将其保存到文件中。使用第 10 步中确定的最终阈值,找出训练集中每个值的类别。然后,将最终预测写入 final_predictions.csv 文件:

pred_probs_test = np.array([每个值[1] \

对于每个值 in gbc.predict_proba(X_test)])

preds_test = (pred_probs_test > final_threshold).astype(int)

preds_test

输出将如下所示:

https://github.com/OpenDocCN/freelearn-ml-pt2-zh/raw/master/docs/spr-lrn-ws/img/image-M3PSVYTK.jpg

图 7.41:测试数据集的最终值预测

或者,您也可以以 CSV 格式获取输出:

使用 open('final_predictions.csv', 'w') 打开文件:

f.writelines([str(val)+‘\n’ for val in preds_test])

输出将是如下的 CSV 文件:

https://github.com/OpenDocCN/freelearn-ml-pt2-zh/raw/master/docs/spr-lrn-ws/img/image-B4Q64TC3.jpg

图 7.42:最终值的输出

注意

要访问此特定部分的源代码,请参阅 https://packt.live/2Ynw6Lt。

您也可以在 https://packt.live/3erAajt 在线运行此示例。必须执行整个 Notebook 才能得到期望的结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值