65.9K
CodeProject 正在变化。 阅读更多。
Home

首次在 kaggle.com 上参赛

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2019年1月26日

CPOL

8分钟阅读

viewsIcon

8318

首次在 kaggle.com 上参赛

如果人工智能是新的电力,那么现在正是学习这项新技术的好时机。实践人工智能和机器学习技能的一个好方法是在 kaggle.com 上参加挑战。然而,直接跳入那里发布的复杂问题,一开始可能会让人望而生畏。在这篇博文中,我将分享我的进展,从一个空白的 Python 项目到一个能够做出至少像样预测的可用模型。

挑战

在当时活跃的 kaggle 竞赛中,https://www.kaggle.com/c/LANL-Earthquake-Prediction/ 最吸引我。这个挑战的目标是根据一系列代表当时地震活动的输入电压来预测实验性地震。因此,它可以被归类为时间序列问题。想了解更多关于这个挑战的信息,请访问 kaggle 上的讨论页面
您可以在我的 github 页面 上找到此项目的源代码。

分析数据

任何机器学习挑战的第一步都是分析给定的输入和预期的输出数据。对于这个挑战,我们提供了一个大约 9.6 GB 的大型 csv 文件,包含 629,145,480 行和 2 列:acoustic_datatime_to_failure。其中,第一列是我们的输入或自变量,第二列包含我们要预测的值,也称为因变量。

正如我们所见,acoustic_data 列包含看似随机的正负整数序列,而 time_to_failure 列包含缓慢接近零的浮点值。一旦它达到零,就会发生实际的地震。

在测试数据中,我们只有 acoustic_data 列,需要预测最后一个输入值之后的最终 time_to_failure

在深入研究任何机器学习算法之前,让我们可视化我们的数据。我们可以轻松地使用 pandas 加载数据,并使用 matplotlib 进行可视化。

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

data = pd.read_csv('../data/train.csv', 
       dtype={'acoustic_data': np.float32, 'time_to_failure': np.float64})
step = 1000

figure, axis1 = plt.subplots()
x_axis = np.arange(0, len(data), step)
save_plot_data
axis1.plot(x_axis, data.iloc[:, 0][0::step], '-b')
axis1.set_ylabel('sequence')
axis1.set_ylabel('seismic activity', color='b')

axis2 = axis1.twinx()
axis2.plot(x_axis, data.iloc[:, 1][0::step], '-r')
axis2.set_ylabel('time to failure', color='r')

plt.show()

我使用了一个 step 变量来减少 matplotlib 需要绘制的点数。当 step 设置为 1000 时,我们将只添加原始数据的每第 1000 个点到图中。
请注意,此代码将占用您高达 10GB 的内存,因此如果您使用的是较旧的机器,则可能需要分块加载数据。
调用 plt.show() 会得到以下精美图表:

从这个图表中,我们可以看到 seismic_activity 列的值从大约 -1500 到 +2000 不等,而 time_to_failure 从 16 秒下降到 0 秒。通过计算红色线条达到 0 的次数,我们可以看到训练数据中总共有 16 次实验性地震。看起来在每次地震发生前几秒钟,活动都会出现高峰。

特征工程

在我们实现任何复杂的神经网络或回归模型之前,我们必须考虑可以从这个 dataset 中提取哪些特征。这样,我们的预测算法就不必处理超过 6 亿行输入,而是可以使用汇总值,如平均值和标准差、分位数、最小值和最大值、希尔伯特变换、滚动特征等等。Numpy 使提取这些特征变得非常直接。

def append_features(index: int, stat_summary: pd.core.frame.DataFrame, 
                    step_data: pd.core.frame.DataFrame):
    stat_summary.loc[index, 'mean'] = step_data.mean()
    stat_summary.loc[index, 'std'] = step_data.std()
    stat_summary.loc[index, 'min'] = step_data.min()
    stat_summary.loc[index, 'max'] = step_data.max()

    absolutes = np.abs(step_data)

    stat_summary.loc[index, 'abs_mean'] = absolutes.mean()
    stat_summary.loc[index, 'abs_std'] = absolutes.std()
    stat_summary.loc[index, 'abs_min'] = absolutes.min()
    stat_summary.loc[index, 'abs_max'] = absolutes.max()
    ...

此方法接受一个 index(代表我们当前正在为统计摘要模型创建的行)、一个我们将写入的 stat_summary DataFrame 和一个代表我们上面看到的原始数据的 step_data DataFrame

我们可以调用这个辅助方法来创建一个摘要特征的 dataset

def get_stat_summaries(data: pd.core.frame.DataFrame, aggregate_length: int = 150000):
    size = len(data)
    stat_summary = pd.DataFrame(dtype=np.float64)

    index = 0
    for i in range(0, size, aggregate_length):
        step_data = data[i:i + aggregate_length]
        append_features(index, stat_summary, step_data.iloc[:, 0])
        index += 1

    return stat_summary

在这里,我们简单地遍历我们的 dataset,并将每 150,000 行传递给上面创建的辅助方法。我选择 150,000 作为默认的 aggregate_length,因为我们的测试 dataset 实际上也是 150,000 行长,我们希望训练数据和测试数据具有相同的条件。
请注意,为了保持代码片段简洁,我省略了从 dataset 中提取的许多统计值。要查看我们可以提取的完整数据范围,请查看 源代码kaggle 上的其他内核

将上述代码应用于我们的训练数据,会得到如下的 csv 文件:

我们现在准备了一个新的训练数据集,包含 4195 行和 94 列。当然,这并不意味着所有这些列都将对我们的模型有用,但拥有过多的数据总比数据不足要好。

创建模型以进行预测

选择合适的算法是每个机器学习问题的关键步骤。因此,研究可能的解决方案,然后实现和测试其中一些算法至关重要。当您搜索时间序列预测问题时,一个会迅速引起您注意的算法是 循环神经网络 (RNN)。RNN 允许我们通过在 LSTMGRU 中“记忆”先前的输入参数来预测输入序列。本质上,它们允许我们基于过去的输入参数进行预测。
我们可以尝试的其他模型包括不同类型的 支持向量机 (SVM)时延神经网络LightGBMXGB

我决定从 LSTM 开始,但尝试所有上述模型是一个好主意。
现在,在您想到为神经网络添加 50 个隐藏输入层之前,让我们保持简单,从尽可能小的规模开始。我为这个挑战创建的网络包括:
一个 LSTM 层、一个隐藏的全连接层和一个最终的输出层来进行预测。


(使用 http://alexlenail.me/NN-SVG/index.html 创建)

在 Python 中创建 RNN 的一种更简单的方法由 Keras API 提供。使用 Keras 创建 RNN 的一种方法是使用 CuDNNLSTM 层,这是一个现成的 LSTM 实现。
有了它,创建我们的 RNN 模型就像以下代码一样简单:

self.model = Sequential()
self.model.add(CuDNNLSTM(64, input_shape=(self.num_features, 1)))
self.model.add(Dense(32, activation='relu'))
self.model.add(Dense(1))   

self.model.compile(optimizer=adam(lr=0.005), loss="mae")

为了将我们的训练数据拟合到这个神经网络,我们首先需要将输入数据集分割成 xy 变量。为此,我创建了以下辅助函数:

def _create_x_y(self, data: pd.core.frame.DataFrame):
    x_train, y_train = np.array(data[:, :self.num_features]), np.array(data[:, self.num_features])
    x_train = np.reshape(x_train, (x_train.shape[0], x_train.shape[1], 1))

    return x_train, y_train

在这里,我们将准备好的输入 dataset 分割成两个独立的 numpy 数组并返回它们。
使用这个辅助函数,我们只需再用两行 Python 代码就可以拟合我们的模型:

x_train, y_train = self._create_x_y(data)
self.model.fit(x_train, y_train, epochs=100, batch_size=64)

这将开始使用 100 个 epoch 和 64 的批次大小来训练我们的模型。在确保此代码正常工作后,就是时候拿一杯茶,等待训练完成了(根据您的硬件,这可能需要一段时间)。

预测测试结果

现在我们的模型已经训练好了,是时候利用它来进行一些预测了。为此,我们需要加载训练数据并从中提取所有统计特征(就像我们对训练数据所做的那样)。然后,我们可以调用我们的 RNN 模型来预测测试数据集的最终 time_to_failure。然后,我们只需要将这些预测保存到一个 CSV 文件中,稍后上传到 kaggle。我将所有这些步骤实现到一个新的辅助函数中:

def predict(model):
    submission = pd.read_csv(
        '../data/sample_submission.csv',
        index_col='seg_id',
        dtype={"time_to_failure": np.float32})

    for i, seg_id in enumerate(submission.index):
        seg = pd.read_csv('../data/test/' + seg_id + '.csv')
        summary = get_stat_summaries(seg, 150000, False)
        submission.time_to_failure[i] = model.predict(summary.values)

    submission.head()
    submission.to_csv('submission.csv')

predict 方法是在我们的 RNN 中实现的。

def predict(self, x: pd.core.frame.DataFrame):
    x_test = x.reshape(-1, self.num_features)
    scaled = self.scaler.transform(x_test)

    x_test = np.array(scaled[:, :self.num_features])
    x_test = np.reshape(x_test, (x_test.shape[0], x_test.shape[1], 1))

    return self.model.predict(x_test)

在这里,我们必须对我们的训练数据应用相同的转换和特征缩放。一旦完成,我们就可以调用 predict 方法来获取基于我们测试集的预测值。

评估版

将这些预测提交到 kaggle 提交页面,结果平均为 1.520,这处于 600 多个不同团队的预测中间水平,因此仍有很大的改进空间。
例如,我们可以尝试向我们的 RNN 添加更多层或调整其许多参数。应用一些特征选择算法或尝试不同的统计值也很有用。
交叉验证是此实现尚未涵盖的另一个主题。

Kaggle 入门技巧

1. 从其他模型中学习

阅读和理解其他参与者在此挑战中的内核,可能是我开始创建这个模型最有帮助的事情。您将看到解决给定挑战的不同方法,并且您将能够重用或整合他们的一些想法到您自己的模型中。

2. 理解数据集

尽量多地了解问题的领域。输入值是如何测量的?单位是什么?一旦您理解了当前的问题,就更容易想出创新的解决方案。

3. 做好失败的准备

接受您的模型一开始不会很棒。准备好写大量的代码,如果它不起作用就扔掉。这是学习和进步的唯一途径。只要您在旅途中学到新东西,就是双赢!最终,您的预测会变得更好,您将能够微调您的模型以做出越来越好的预测。

4. 享受乐趣

最重要的是,保持乐趣!机器学习是当今科技领域最有趣的研究领域之一,所以即使遇到挑战,也要坚持下去。如果您因为模型无法正常工作而感到沮丧,请休息一下。散散步,做些运动或睡个好觉。然后用清醒的头脑重新开始。

© . All rights reserved.