在python for loop中实现移动窗口的最佳方法?

问题描述

我有一个要迭代的单词(标记)列表。我想对该列表的移动窗口执行某种转换。窗口大小的大小可以是可变长度。

for i in range(0,len(tokens)-(window_size+1),step):
    doc2vec.model.infer_vector(tokens[i:i+window_size])

for循环在变量中定义的步骤中遍历令牌的长度,它需要的变量与window_size变量所说明的一样多。我看到的问题是在最后一次迭代中。迭代在令牌的长度处结束-窗口大小(+1,以便包括减去的值)。假设窗口大小是10,步长是5,令牌的长度是98。在这种情况下,我的代码将在85:95进行最后一次计算,而忽略最后三个元素。我想要一个适用于变量window_size,step和tokens length的解决方案。为了说明,到目前为止,如果令牌的长度为95,则可以正常工作,但如果为98,则将剩下三个元素。我希望将它们一起计算88:98。

解决方法

我认为要走的路是创建自己的自定义迭代器:

class MovingWindow:
    def __init__(self,tokens,window_size,step):
        self.current = -step
        self.last = len(tokens) - window_size + 1
        self.remaining = (len(tokens) - window_size) % step
        self.tokens = tokens
        self.window_size = window_size
        self.step = step

    def __iter__(self):
        return self

    def __next__(self):
        self.current += self.step
        if self.current < self.last:
            return self.tokens[self.current : self.current + self.window_size]
        elif self.remaining:
            self.remaining = 0
            return self.tokens[-self.window_size:]
        else:
            raise StopIteration

您将使用的女巫:

for t in MovingWindow(tokens,10,5):
    doc2vec.model.infer_vector(t)

您还可以修改迭代器,以便它返回索引而不是令牌。 另一种选择是创建一个简单的生成器,更多信息here

演示您提供的案例示例:

indexes = [i for i in range(98)]
for i in MovingWindow(indexes,5):
    print(f'{i[0]}:{i[-1]}')

输出:

0:9
5:14
10:19
15:24
20:29
25:34
30:39
35:44
40:49
45:54
50:59
55:64
60:69
65:74
70:79
75:84
80:89
85:94
88:97