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的时间序列,遵循以下步骤:
然后,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))
。在这种情况下,序列通过每个序列的信息量进行规范化。