原文:
annas-archive.org/md5/20b62d9571c391689a2d53277f7e2459
译者:飞龙
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.))
“”"
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
- 比较在测试集上的性能:
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 才能得到期望的结果。