如何处理预测时间序列数据

机器算法验证 时间序列 k-最近邻
2022-03-25 12:12:56

我是统计新手,在选择一种好的方法来分析我所拥有的数据方面的任何帮助都将非常受欢迎:

我们有一个客户有一个活跃的 Facebook 页面,该页面会定期发布。我有他们最后的数据,比如说,200 个帖子(从上个月开始)——帖子得到了多少赞以及发布的时间。如果我们假设所有内容都同样受到好评,我会尝试更改他们的发布时间,以便内容获得更多浏览量,从而获得更多喜欢/评论/等。我想要计算周二上午 11 点发帖比周二上午 10 点发帖获得多 X 点赞的概率。如果随着来自帖子的新数据的出现,这可以很容易地重新训练,那就太好了。

我一直在寻找一些方法来解决这个问题,K-最近邻或神经网络似乎最有可能正常工作(也许 SVM 也可以适用于此)。

谢谢您的帮助!

PS:我附上了样本数据的图表。因为我只有一个月的数据,所以我想我会把一周分成 168 个 1 小时的片段。X 轴是一周中的小时(从 0 到 168),y 轴是帖子获得的参与度: 在此处输入图像描述

更新:真实数据的间隔非常不均匀,例如早上发了 4 个帖子,直到深夜才发帖。你会建议如何进行呢?我认为重采样会导致数据丢失。

2个回答

一个简单的方法是在您希望获得最多赞的时段发帖。

您的描述表明您的时间序列的唯一预期组成部分是一天中的几个小时的季节性。

更准确地说,假设影响是乘法的。下面给出了该模型 30 天的参数化实现。

运行喜欢的序列

如果我们每天都进行归一化和叠加,我们可以对其进行回归。

趋势

好像通过作弊,我们已经恢复了我们的季节性成分。

运行季节性喜欢的序列

编码。

import numpy as np
import pandas
from matplotlib import pyplot as plt
from sklearn.neighbors import KNeighborsRegressor


def generate_ts(hours=24, days=30):
    np.random.seed(123)
    # Generate some iid like data
    x = np.random.binomial(10, .5, hours * days)
    # Generate your trend
    slice = np.linspace(-np.pi, np.pi, hours)
    hourly_trend = np.round(np.cos(slice) * 5)
    hourly_trend -= hourly_trend.min()
    rep_hourly_trend = np.tile(hourly_trend, days)
    data = x * rep_hourly_trend
    # Generate a index
    ind = pandas.DatetimeIndex(freq='h',
                            start='2013-09-29 00:00:00',
                            periods=days * hours)
    return pandas.Series(data, index=ind), hourly_trend


def recover_trend(ts, hours=24, days=30):
    obs_trend = ts.values.reshape(-1, hours)
    obs_trend = (obs_trend.T - obs_trend.mean(axis=1)) / obs_trend.std(axis=1)
    y = obs_trend.ravel()
    x = (np.repeat(np.arange(hours), days)).reshape(-1, 1)
    model = KNeighborsRegressor()
    model.fit(x, y)
    rec_trend = model.predict(np.arange(hours).reshape(-1, 1))
    return x, y, rec_trend


def main():
    hours, days = 24, 30
    ts, true_trend = generate_ts(hours=hours, days=days)
    true_trend = (true_trend - true_trend.mean()) / true_trend.std()
    ts.plot()
    plt.title("Run Sequence Plot of Likes")
    plt.ylabel("Likes")
    plt.xlabel("Time")
    plt.show()
    x, y, rec_trend = recover_trend(ts, hours=hours, days=days)
    plt.scatter(x.ravel(), y, c='k', label='Observed Trend')
    plt.plot(np.arange(hours), rec_trend, 'g', label='Recovered Trend', linewidth=5)
    plt.plot(np.arange(hours), true_trend, 'r', label='True Trend', linewidth=5)
    plt.grid()
    plt.title("Trend Regression")
    plt.ylabel("Normalized Like Influence")
    plt.xlabel("Hours")
    plt.legend()
    plt.show()
    season_comp = pandas.Series(np.tile(rec_trend, days), index=ts.index)
    season_comp.plot()
    plt.title("Run Sequence Plot of Seasonal Component of Likes")
    plt.ylabel("Likes")
    plt.xlabel("Time")
    plt.show()


if __name__ == '__main__':
    main()

在使用它之前,我必须注意有几个问题。

  • 如果有趋势成分,必须先处理。低阶多项式回归或滞后算子是流行的选择。

  • 仔细检查自相关和偏自相关图可能会揭示要考虑的时间序列的其他组成部分。

  • 去除时间序列的趋势后,您应该检查残差的平稳性。

  • 没有提供关于在收集的数据中发布帖子的时间分布的信息。

  • 尽管最佳发布时间似乎明显早于恢复的季节性趋势的最大值,但情况可能并非如此。

  • 更改发帖时间,可能会改变点赞的季节性。

  • 在收到最多赞的时间里聚集所有帖子,可能会改变用户行为。

  • 这个问题更适合强化学习。原则性方法是通过上下文老虎机执行发布时间的顺序优化。

听起来您只关心一周中的哪一天和那一天中的哪个小时可能会获得最多的关注。您可以将数据格式化为每周一小时,并将每周视为一组观察结果,就像您所做的那样。从这里,您可以按一周中的小时计算源自数据的预期点赞数。如果你对数据进行标准化,那么一周内每小时的点赞数超过一周的总点赞数将为你提供一周中那个小时的概率。

您可以对这些数据进行回归,但要利用像 k-NN 这样的聚类算法,或基于潜在特征的神经网络进行预测,您需要的不仅仅是 x 和 y。添加诸如一般主题之类的功能,也许是一些词频或语义分析,也许是帖子的格式(图像与否,链接与否,问题与否等),将为您提供聚类依据的数据。您可能需要根据整体活动进行调整,并且需要更多的时间来获得对输出的任何信心。

但是,如果您获得了一组很好的特征并且可以消除一般不相关的活动趋势,那么您可能最好通过生成自组织图(一种神经网络)来为您提供最佳服务,其中一周中的小时是一个节点,其响应相关最好具有特定的组合功能集。一个好的,简单的 Python 实现在这里然后,当您获得特定帖子并将其分解为特征集时,您可以查看哪个节点响应良好并在一周的那个小时发布。然后,将真实响应添加回您的训练数据并重新训练地图以包含新数据。