Machine learning 在单个特征中保留顺序信息

Machine learning 在单个特征中保留顺序信息,machine-learning,dataset,feature-engineering,Machine Learning,Dataset,Feature Engineering,以下是我试图为其设计的数据集的一列: +---+-----------------------------+ |Id |events_list | +---+-----------------------------+ |1 |event1,event3,event2,event1 | +---+-----------------------------+ |2 |event3,event2 | +---+----------

以下是我试图为其设计的数据集的一列:

+---+-----------------------------+
|Id |events_list                  |
+---+-----------------------------+
|1  |event1,event3,event2,event1  |
+---+-----------------------------+
|2  |event3,event2                |
+---+-----------------------------+
有3种可能的事件类型,它们到达的顺序保存为字符串。 我将“事件”列转换为:

+---+--------------------+
|Id |event1|event2|event3|
+---+--------------------+
|1  |2     |1     |1     |
+---+--------------------+
|2  |0     |1     |1     |
+---+--------------------+
保留计数信息,但丢失订单信息

问:有没有办法将订单编码为功能

更新:对于那天我计算的每一行事件的分数,模型应该预测新的每日事件的未来分数。无论如何,我的事件顺序和计数会影响每日分数


更新:我的数据集包含其他每日信息,如会话计数等,目前我的模型是按日期消化每行的LSTM。我想尝试通过将订单信息添加到现有模型来改进我的预测

一种可能性是一系列向量,表示在第n次事件之前发生的事件
n
是可能发生的最大事件数,向量长度是可能发生的事件数。这将隐含地将事件的顺序编码到一个固定大小的特征空间中

+---+-----------------------------+
|Id |events_list                  |
+---+-----------------------------+
|1  |event1,event3,event2,event1  |
+---+-----------------------------+
|2  |event3,event2                |
+---+-----------------------------+



+---+--------------------------------------------------+
|Id | events_1  events_2  events_3  events_4  events_5 |
+---+--------------------------------------------------+
|1  | [1,0,0]   [1,0,1]   [1,1,1]   [2,1,1]   [2,1,1]  |
+---+--------------------------------------------------+
|2  | [0,0,1]   [0,1,1]   [0,1,1]   [0,1,1]   [0,1,1]  |
+---+--------------------------------------------------+

具有相同信息的特征尺寸越少,记录在事件步骤n发生的事件的可能性就越大

+---+--------------------------------------------------+
|Id | event_1  event_2  event_3  event_4  event_5      |
+---+--------------------------------------------------+
|1  |   1         3        2        1        0         |
+---+--------------------------------------------------+
|2  |   3         2        0        0        0         |
+---+--------------------------------------------------+

这有较少的维度,这是好的,但可能的缺点是没有显式编码最终状态。由于不知道问题本身或您计划使用的模型,很难知道这是否重要。

一个选项是通过创建有意义的映射1-->1(即一对一)直接转换/转换字符串。 在这种情况下,保持秩序是可行的,并且有意义

这是一个简单的演示:

data = ['event1,event3,event2,event1', 'event2,event2', 'event1,event2,event3']

def mapper(data):
    result = []
    for d in data:
        events = d.replace(' ', '').split(',')
        v = 0
        for i, e in enumerate(events):
            # for each string: get the sum of char values,
            # normalized by their orders
            # here 100 is optional, just to make the number small
            v += sum(ord(c) for c in e) / (i + 100) 
        result.append(v)
    return result

new_data = mapper(data)
print(new_data)
输出:

[23.480727373137086, 11.8609900990099, 17.70393127548049]
尽管碰撞概率非常低,但对于庞大的数据集,无法100%保证不会发生任何碰撞

检查此分析:

# check for clashes on huge dataset
import random as r
import matplotlib.pyplot as plt

r.seed(2020)

def ratio_of_clashes(max_events):
    MAX_DATA = 1000000
    events_pool = [','.join(['event' + str(r.randint(1, max_events))
                         for _ in range(r.randint(1, max_events))])
                   for _ in range(MAX_DATA)]
    # print(events_pool[0:10])  # print few to see
    mapped_events = mapper(events_pool)
    return abs(len(set(mapped_events)) - len(set(events_pool))) / MAX_DATA * 100


n_samples = range(5, 100)
ratios = []
for i in n_samples:
    ratios.append(ratio_of_clashes(i))

plt.plot(n_samples, ratios)
plt.title('The Trend of Crashes with Change of Number of Events')
plt.show()

因此,事件或数据越少,碰撞率就越低,直到达到某个阈值,然后它就消失了——但这毕竟不坏(就我个人而言,我可以接受)


更新和最终想法:

[23.480727373137086, 11.8609900990099, 17.70393127548049]
我刚刚注意到您已经在使用LSTM,因此顺序非常重要。在这种情况下,我强烈建议您将事件编码为整数,然后创建一个完全符合LSTM的时间序列,遵循以下步骤:

  • 预处理每个字符串并将其拆分为事件(如我在示例中所做的)
  • 对其进行拟合并将其转换为整数
  • 通过拟合将结果缩放为[0-1]
  • 你会得到这样的结果:

    “事件1”:1

    “事件2”:2

    “事件3”:3

    。 .

    'eventN':N

    对于'event1,event3,event2,event3',它将变成:[1,3,2,3]。 缩放-->[0,1,0.5,1]


    然后,LSTM就完全能够从本质上确定顺序。忘了维度点吧,因为LSTM的主要任务是记住并选择性地忘记步骤和步骤顺序

    谢谢你的回复,请看我的更新看看有一些很好的例子,我会选择散列嵌入。谢谢你的回复,不幸的是,如果一行有1000个事件,而其他行只有2个事件,那么列计数将是1000。是的,但是,根据您的模型,可能存在对每一行的固定大小要素空间的要求吗?除非你用的是递归神经网络什么的?但如果是这样的话,我怀疑你会问这样的问题。请提供有关问题、约束条件和您想要使用的模型的更多具体信息,也许可以针对您的情况给出一个更具体的示例。感谢您的回复,这是否意味着
    'event1,event2'=='event2,event1'
    因为它们的总和相同?@ShlomiSchwartz欢迎您Shlomi。关于你的问题:不,他们肯定会不同(11.850,11.851)。然而,我们假设事件在一个字符上不同(这不是很现实,尽管结果是唯一的),但事实上,我认为你的事件有真正不同的名称,对吗?非常聪明的想法!如果我理解正确的话,“魔法”就是将总和除以事件的索引,对吗?@ShlomiSchwartz确切地说,总和只是为了得到事件的相对唯一的表示,它随后被该序列中事件的顺序规范化。因此,每个序列将根据事件、事件数量和顺序转换为唯一的数值。最后一件事,在将数据提交给LSTM之前(作为一般方法),请不要忘记在最后对数据进行规范化/标准化。@ShlomiSchwartz已经包含了大量的信息。例如,10个事件的序列映射为比3个事件的序列更大的值。但是,如果两个序列的长度非常接近(如9和10),我可以看到您的观点。在这种情况下,如果您想通过每个序列的事件数(这确实是一个非常有效的点)进行规范化,那么您需要在结尾处将序列除以
    /len(events)
    ,如下所示:
    result.append(v/len(events))
    。在这种情况下,序列通过每个序列的信息量进行规范化。