通过一次移动 2 个数据单元来制作 4 克数据

Making 4-gram data by shifting 2 units of data at a time

我有一个数据序列,我希望从中构建 n-gram。序列外观的摘录如下。 8c b0 00 f0 05 fc 04 46 00 f0 fe fb 40 f2 00 05 c2 f2 00 05 28 78 00 我目前使用 ntlk 的 ngrams() 函数从该数据构建 4-grams 作为 8c b0 00 f0b0 00 f0 0500 f0 05 fc...等等。这只是通过一个一个地滑动来创建 4-grams。但是,我的要求不是一张一张地滑动,而是需要两两滑动,同时创建 n-gram。所以预期输出 8c b0 00 f000 f0 05 fc05 fc 04 46...等。我进行了搜索,但找不到任何方法来执行此操作,而不是像现在这样一个一个地移动。以下是强调当前工作的 4 行代码的一部分

 s = finalString.lower()
 s = re.sub(r'[^a-zA-Z0-9\s]', ' ', s)
 tokens = [token for token in s.split(" ") if token != ""]
 output = list(ngrams(tokens, 4))

你可以做以下技巧,

s = '8c b0 00 f0 05 fc 04 46 00 f0 fe fb 40 f2 00 05 c2 f2 00 05 28 78 00'

from nltk import ngrams
output = list(ngrams(s.split(), 4))[::2]     # Using only alternate records from ngrams,
                                             # Here 2 is the sliding window that you want. 

输出:

[('8c', 'b0', '00', 'f0'), ('00', 'f0', '05', 'fc'), ('05', 'fc', '04', '46'), ('04', '46', '00', 'f0'), ('00', 'f0', 'fe', 'fb'), ('fe', 'fb', '40', 'f2'), ('40', 'f2', '00', '05'), ('00', '05', 'c2', 'f2'), ('c2', 'f2', '00', '05'), ('00', '05', '28', '78')]

几件事:

tokens = [token for token in s.split(" ") if token != ""]

这可以缩短,因为 .split() 默认情况下在 space 上拆分(而且您已经用 space 替换了其余部分)并且它不会 return '',因为任何长度的白色 space 只会导致一次分裂。

所以:'ab 12 23'.split() == ['ab', '12', '23']

ngrams() from nltk 根据给定的任何可迭代对象创建 n-gram,但您实际上是在从可迭代对象中寻找扁平的 2-gram 值对。

from nltk.util import ngrams

s = '8c b0 00 f0 05 fc 04 46 00 f0 fe fb 40 f2 00 05 c2 f2 00 05 28 78 00'

parts = iter(s.split())
result = [(*t[0], *t[1]) for t in ngrams(zip(parts, parts), 2)]

print(result)

表达式 (*t[0], *t[1]) 只是取 2 元组 t 的两个元组部分并将它们的部分放入一个新的元组中。它对从 zip(parts, parts) 生成的 n-gram 中的每个元组 t 这样做,它从 s.

的拆分部分上的单个迭代器创建对

这也避免了生成所有 ngram 然后丢弃不需要的 ngram。

一个更好但略有不同的解决方案:

parts = iter(s.split())
result = ((*t[0], *t[1]) for t in ngrams(zip(parts, parts), 2))

print(list(result))

注意圆括号而不是方括号,这导致 result 成为生成器而不是列表。这样,即使 s 是一个非常长甚至无限的值系列,您仍然可以根据需要从 result 中获得 2 步 4-gram。这很有意义,因为 ngrams() 本身也是 return 一个迭代器而不是一个预先生成的列表。