问题的背景
我定期处理巨大的机器学习数据集。一种非常通用的格式,用于 威卡 是个 “ARFF”(属性关系文件格式)。这本质上创建了一个结构良好的,丰富的CSV文件,可以轻松地在Logistic回归,决策树,SVM等中使用。每个文件,例如:
f0 | f1 | f2 | f3 | … | fn |
1 | 0 | 1 | 0 | … | 0 |
进入更简洁的版本,其中您具有功能列表,只需指定功能’的索引和值(如果有):
@ATTRIBUTE f0数值
@ATTRIBUTE f1数值
@ATTRIBUTE f2 NUMERIC
@ATTRIBUTE f3 NUMERIC
…
@属性fn数字
@数据
{0 1,2 1}
即 {feature-index-zero为1,feature-index-two为1}, 只需忽略所有零值。
实施问题
如果您有4个功能,这很容易,但是如果您有超过100万个功能并且需要找到每个功能的索引,该怎么办?在列表中搜索特征是O(n),并且如果您的训练数据也很大,那么创建稀疏的ARFF将会非常低效:
1 2 3 4 5 6 7 8 9 |
特征 = ['名称', 'some_metric', “ an_attribute”, 'some_boolean'] #搜索特征的存在为O(n) >>> 'some_metric' 在 特征 真正 #检索列表中要素的索引也是O(n) >>> 特征.指数('some_metric') 1 |
我以为可以通过使用OrderedDict来改善这一点。很简单,这是一个维护其项目顺序的字典–因此您可以以类似堆栈的方式从最后弹出()项目。但是,之后 关于StackOverflow的一些研究,这令人失望’包含任何有效的方法来计算键的索引:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
从 馆藏 进口 OrderedDict 特征 = ['名称', 'some_metric', “ an_attribute”, 'some_boolean'] od = OrderedDict() 对于 f 在 特征: od[f] = 0 #搜索特征的存在为O(1) >>> 'some_metric' 在 od 真正 #尽管检索列表中要素的索引仍然是O(n)! >>> 特征.键().指数('some_metric') 1 #keys()必须创建内存中所有键的完整列表,才能 #检索索引。您可以使用iterkeys()来改善内存 #performance,但仍然很可笑。 |
解决方案
我们该怎么办?输入我最喜欢的东西,默认为lambdas:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
从 馆藏 进口 defaultdict 特征 = ['名称', 'some_metric', “ an_attribute”, 'some_boolean'] dd = defaultdict(拉姆达: 伦(dd)) 对于 f 在 特征: dd[f] #不需要给它一个值,只需要调用它 #所以现在我们可以在O(1)中进行查找 >>> 'some_metric' 在 dd 真正 #并在O(1)中获得其索引 >>> dd['some_metric'] 1 |
稍微修改一下lambda,除了索引之外,分配项目值也很简单:
1 2 3 4 5 6 7 8 9 10 11 |
dd = defaultdict(拉姆达: {'指数':伦(dd)}) #然后可以无缝添加更多信息: dd['some_metric']['信息'] = 1 dd['some_attribute']['信息'] = 2 #保持自动生成索引的O(1)查找: >>> dd['some_attribute']['指数'] 1 |
局限性
这是一个有趣的修复程序,但没有’支持完整的词典功能– deleting items won’重新排序索引,您可以’轻松地依次进行迭代。但是,由于在创建此ARFF文件时,’无需删除或迭代’s not a problem.