【问题标题】:Predict a user input using current datetime and past history使用当前日期时间和过去历史预测用户输入
【发布时间】:2017-03-16 19:58:19
【问题描述】:

项目

我正在做一个小项目,用户可以在其中创建事件(例如EatSleepWatch a movie 等)并记录与这些事件匹配的日志条目。

我的数据模型看起来像这样(应用程序本身在 Python 3 / Django 中,但我认为这并不重要):

# a sample event
event = {
    'id': 1,
    'name': 'Eat',
}

# a sample entry
entry = {
    'event_id': event['id'],
    'user_id': 12,

    # record date of the entry
    'date': '2017-03-16T12:56:32.095465+00:00',

    # user-given tags for the entry
    'tags': ['home', 'delivery'],

    # A user notation for the entry, it can be positive or negative
    'score': 2,

    'comment': 'That was a tasty meal',

}

用户可以为任意数量的事件记录任意数量的条目,他们可以在需要时创建新事件。数据存储在关系数据库中。

现在,我想让用户更轻松地输入数据,方法是在用户访问“添加条目”表单时向他们推荐相关事件。目前,他们可以在下拉列表中选择与其条目对应的事件,但我想在此基础上向他们推荐一些相关事件。

我在想,给定用户历史记录(所有记录的条目),应该可以通过识别条目中的模式来预测可能的输入,例如:

  • Eat 通常在每天中午和晚上 7:00 左右发生
  • Sleep 通常发生在晚上 10:00 之后
  • Watch a movie 通常发生在星期五晚上 8:00 之后

理想情况下,我想要一个函数,给定用户 ID 和日期时间,并使用用户历史记录,将返回更可能发生的事件列表:

def get_events(user_id, datetime, max=3):
    # implementation

    # returns a list of up to max events
    return events

因此,如果我采用前面的示例(包含更多人类日期),我会得到以下结果:

>>> get_events(user_id, 'Friday at 9:00 PM')
['Watch a movie', 'Sleep', 'Eat']

>>> get_events(user_id, 'Friday at 9:00 PM', max=2)
['Watch a movie', 'Sleep']

>>> get_events(user_id, 'Monday at 9:00 PM')
['Sleep', 'Eat', 'Watch a movie']

>>> get_events(user_id, 'Monday at noon')
['eat']

当然,在现实生活中,我会传递真实的日期时间,并且我想获得一个事件 ID,以便从数据库中获取相应的数据。

我的问题

(对不起,如果需要一些时间来解释整个事情)

我的实际问题是,实现这一目标所需的实际算法/工具/库是什么?甚至有可能做到吗?

我目前的猜测是,我需要使用一些花哨的机器学习东西,使用 scikit-learn 和分类器之类的东西,用用户历史记录来训练它,然后让整个东西发挥它的魔力。

我对机器学习完全不熟悉,我担心自己没有足够的数学/科学背景来开始自己的学习。你能提供一些参考资料来帮助我理解如何解决这个问题,我必须挖掘的算法/词汇,或者一些伪代码吗?

【问题讨论】:

  • 我认为这可以通过机器学习来完成,但对于这种特殊情况来说可能有点矫枉过正。看来您有相当静态的存储桶(例如,晚上 7 点到晚上 9 点的存储桶包括睡眠、饮食、电影)。因此,您可以按照您有多少条目的顺序来维护这些存储桶(例如,跟踪用户 1 在存储桶 19:00 中提交吃 50 次,因此按该用户的计数排序)。这基本上就是您的预测性 AI 会做的事情(我相信),除非您独立于用户训练它,然后它将预测所有用户的常用关键字。
  • 对不起,如果不清楚:跟踪确实与用户无关,用户可以提交 10s 或 100s 不同的事件。使用手工计数,我可能还会丢失所有模式(每周、每月、仅一周中的某些天等)。

标签: python algorithm machine-learning scikit-learn


【解决方案1】:

我认为k-nearest neighbours (kNN) 方法将是一个很好的起点。在这种特定情况下的想法是寻找最接近给定时间发生的 k 个事件,并计算最常发生的事件。

示例

假设您有输入Friday at 9:00 PM。拉开所有人的距离 数据库中的事件到该日期,并按升序排列。 例如,如果我们以分钟为单位计算所有元素的距离 数据库,排名示例如下。

('Eat', 34)
('Sleep', 54)
('Eat', 76)
   ...
('Watch a movie', 93)

接下来,您取其中的前 k = 3 个并计算它们的频率 发生,

('Eat', 2)
('Sleep', 1)

以便函数返回['Eat', 'Sleep'](按此顺序)。

选择一个好的k很重要。太小的值将允许意外的异常值(在特定时刻做一次)对结果有很大的影响。选择太大的 k 将使不相关的事件包含在计数中。缓解这种情况的一种方法是使用距离加权 kNN(见下文)。

选择距离函数

如 cmets 中所述,使用两个时间戳之间的简单距离可能会丢失一些信息,例如星期几。我们可以通过使距离函数d(e1, e2) 稍微复杂一些来解决这个问题。在这种情况下,我们可以选择它作为时间和星期几之间的权衡,例如

d(e1, e2) = a * |timeOfDay(e1) - timeOfDay(e2)| * (1/1440) + 
            b * |dayOfWeek(e1) - dayOfWeek(e2)| * (1/7)

我们通过一天中的时间(以分钟为单位)和一周中的天数之间可能存在的最大差异来标准化这两个差异。 ab 是可用于赋予这些差异之一更多权重的参数。例如,如果我们选择a = 3b = 1,我们说在同一天发生的重要性是同时发生的三倍。

距离加权 kNN

您可以通过不简单地选择 k 个最接近的元素,而是通过根据它们与给定点的距离为所有事件分配权重(例如距离)来增加复杂性(并希望提高性能)。让e 为输入示例,o 为数据库中的示例。然后我们计算o相对于e的权重为

          1
w_o = ---------
      d(e, o)^2

我们发现,积分的减重速度快于与e 的距离增加的速度。在您的情况下,将从最终排名中选择一些元素。这可以通过将相同事件的权重相加来计算事件类型的最终排名来完成。

实施

kNN 的好处在于它非常容易实现。您将大致需要以下组件。

  • 距离函数d(e1, e2)的实现。
  • 根据该函数和给定的输入示例对数据库中所有元素进行排名的函数。

    def rank(e, db, d):
        """ Rank the examples in db with respect to e using
            distance function d.
        """
        return sorted([(o, d(e, o)) for o in db],
                      key=lambda x: x[1])
    
  • 从该排名中选择一些元素的函数。

【讨论】:

  • 感谢您的回答!我的印象是它可以用于查找最近的事件(按时间距离),但它无法识别和使用更复杂的模式,例如仅在某些工作日发生的事件(但我可能错了)。无论如何,这是一个很好的起点,你知道在 Python 中从这个解决方案开始的任何参考资料吗?
  • @EliotBerriot 更新了答案,其中包含一些关于选择距离函数的注释和如何开始的指针。
  • 这真的很有帮助!我会再等一会儿看看是否发布了不同的答案,否则我会选择你的答案:)
  • @EliotBerriot 我建议您尝试实现它,看看它是否符合您的需求。如果没有,您已经学习了一种在实践中经常使用的新算法!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多