通过一次移动 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 f0
、b0 00 f0 05
、00 f0 05 fc
...等等。这只是通过一个一个地滑动来创建 4-grams。但是,我的要求不是一张一张地滑动,而是需要两两滑动,同时创建 n-gram。所以预期输出 8c b0 00 f0
、00 f0 05 fc
、05 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 一个迭代器而不是一个预先生成的列表。
我有一个数据序列,我希望从中构建 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 f0
、b0 00 f0 05
、00 f0 05 fc
...等等。这只是通过一个一个地滑动来创建 4-grams。但是,我的要求不是一张一张地滑动,而是需要两两滑动,同时创建 n-gram。所以预期输出 8c b0 00 f0
、00 f0 05 fc
、05 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 一个迭代器而不是一个预先生成的列表。