我正在做一个深度学习项目,我们使用RNN。我想在数据传输到网络之前对其进行编码。输入是阿拉伯语的韵文,在Python中,这些韵文被视为单独的字符。如果后面的字符是变音符号,我应该用数字来编码/表示字符,否则我只编码字符。在
这样做的数百万诗句,是希望使用lambda
和{
map(lambda ch, next_ch: encode(ch + next_ch) if is_diacritic(next_ch) else encode(ch), verse)
我在这个问题背后的意图是找到实现上述目标的最快方法。对lambda函数没有限制,但是for
循环的答案不是我想要的。在
对于非阿拉伯人来说,这是一个很好的例子,假设您要对以下文本进行编码:
^{pr2}$如果字母是一个特殊字符,则需要在将字母与其后面的字母串联后对其进行编码,否则只对字母进行编码。在
输出:
['X', 'X', 'A)', 'L_', 'I!', 'I%', 'M<', 'L', 'L', 'L>', 'M', 'M', 'Q*', 'Q']
对于阿拉伯人:
诗歌示例:
另一方面则是“ق。”الدّڒولفحَومل”
变音符号是字母上方的小符号(即ّ,ْ)
[更新]
Range of diacritics从64B HEX or 1611 INT开始,到652 HEX or 1618 INT结束。在
字母621 HEX - 1569 INT到63A HEX - 1594 INT,从641 HEX - 1601 INT到{a7}
一个字母最多只能有一个音调符号。
额外信息:
与我所做的类似的编码方法是将韵文的二进制形式表示为具有形状(number of bits needed, number of characters in a verse)
的矩阵。在我们将每个字母与其变音符号(如果存在)合并后,会计算位数和字符数。在
例如,假设诗句如下,变音符号是特殊字符:
X+Y_XX+YYYY_
字母表的不同组合是:
['X', 'X+', 'X_', 'Y', 'Y+', 'Y_']
因此,我需要3
位(至少)来表示这些6
字符,因此number of bits needed
是{
考虑以下编码:
{
'X' : 000,
'X+': 001,
'X_': 010,
'Y': 011,
'Y+': 100,
'Y_': 101,
}
我把矩阵中的例子表示为(二进制表示是垂直的):
X+ Y_ X X+ Y Y Y Y_
0 1 0 0 0 0 0 1
0 0 0 0 1 1 1 0
1 1 0 1 1 1 1 1
这就是为什么我要先把发音和字母结合起来。在
注意:Iterate over a string 2 (or n) characters at a time in Python和{a9}没有给出预期的答案。
我要把我的帽子扔到拳击台上和纽比在一起。可以使用将字符串转换为可用的格式
您可以屏蔽以下字符变音符的位置:
^{pr2}$在这里,范围} 和^{} 的完整形式,以避免对最后一个元素进行可能昂贵的附加。
[upper, lower]
是检查音调符号的一种临时方法。按照你喜欢的方式进行实际检查。在这个例子中,我使用了^{现在,如果你有一种将代码点编码为一个数字的数值方法,我相信你可以向量化,你可以做如下事情:
要获取剩余的未组合字符,您必须同时删除音调符号和它们绑定到的字符。我能想到的最简单的方法就是把面具涂在右边,然后否定它。同样,我假设您有一个矢量化方法来编码单个字符:
将结果组合成一个最终数组在概念上很简单,但需要几个步骤。结果是^{} 个元素比输入短,因为音调符号被删除了。我们需要根据它们的索引量来移动所有的掩码元素。有一种方法可以做到:
我建议numpy的原因是它应该能够在几秒钟内处理几百万个字符。将输出作为字符串返回应该很简单。
建议实施
我一直在考虑你的问题,并决定考虑一些时间安排和可能的实现。我的想法是将0x0621-0x063A,0x0641-0x064A(26+10=36个字母)中的unicode字符映射到a
uint16
的低6位,并将0x064B-0x0652(8个音调符号)映射到下一个更高的3位,假设这些实际上是您需要的唯一音调符号:用新潮的术语来说:
您可以选择进一步编码来稍微缩短表示,但我不建议这样做。这种表示法的优点是与韵文无关,因此您可以比较不同诗句的部分,也不必担心根据编码在一起的诗句数,您将得到哪种表示形式。你甚至可以屏蔽掉所有代码的前几位来比较原始字符,而不使用音调符号。
所以我们假设你的诗句是在这些范围内随机产生的数字的集合,音调符号随机生成,最多跟在一个字母后面。为了进行比较,我们可以很容易地生成一个长度约为百万的字符串:
这些数据完全是随机分布的字符,大约25%的概率是任何字符后面跟一个变音符号。它只需要几秒钟就可以在我的笔记本电脑上生成。
numpy转换如下所示:
基准
现在让我们
%timeit
来看看它是怎么回事。首先,这里是其他实现。我将所有内容转换为numpy数组或整数列表以进行公平比较。我还做了一些小修改,使函数返回相同数量的列表,以验证准确性:现在是时间安排:
对结果数组/列表的比较表明它们也是相等的:
我在这里使用
array_equal
,因为它执行所有必要的类型转换来验证实际数据。所以这个故事的寓意是,有很多方法可以做到这一点,解析几百万个字符本身不应该过于昂贵,直到你开始交叉引用和其他真正耗时的任务。最重要的是不要在列表中使用
reduce
,因为你将比你需要的更多地重新分配。即使是一个简单的for
循环对你的目的来说很好。尽管numpy比其他实现快十倍,但它并没有带来巨大的优势。解码
为了完整起见,下面是一个用于解码结果的函数:
作为旁注,我在这里所做的工作启发了这个问题:Converting numpy arrays of code points to and from strings
map
似乎不是该作业的正确工具。您不希望将字符映射到其他字符,而是将它们组合在一起。相反,您可以尝试reduce
(或者python3中的functools.reduce
)。在这里,我使用isalpha
来测试它是什么类型的字符;您可能需要其他的东西。然而,这几乎不可读,而且还创建了大量中间列表。最好使用一个无聊的旧
^{pr2}$for
循环,即使您明确要求其他东西:通过迭代连续字符对,例如使用
zip(verse, verse[1:])
(即(1,2), (2,3),...
,而不是(1,2), (3,4), ...
),您确实可以使用列表理解,但我还是会投票给for
循环的可读性。你甚至可以使用
map
和lambda来做同样的事情,但是你还需要先使用另一个lambda来filter
,这样整个事情的数量级就会变得更难看,更难阅读。您不会一次读取两个字符,即使是这样,
map
也不会将它们拆分为lambda
的两个参数。相关问题 更多 >
编程相关推荐