机器学习笔记:逆置换

1 介绍

  • 给定一个排列 p,它的逆置换(inverse permutation)是一个排列 invp,满足 invp[p[i]] = ip[invp[i]] = i 对所有 i 成立。

2 python实现

'''
计算一个排列的逆排列

给定一个排列 p,它的逆排列是一个排列 invp,满足 invp[p[i]] = i 和 p[invp[i]] = i 对所有 i 成立
'''
def invpermute(p):
    """
    inverse permutation
    """
    p = np.asarray(p)
    invp = np.empty_like(p)
    for i in range(p.size):
        invp[p[i]] = i
    #对于每个 i,设置 invp 在 p[i] 的位置上的值为 i
    return invp

3 举例

p = [2, 0, 1]
invp = invpermute(p)
invp
#[1, 2, 0]
  • invp的第p[0]个位置(第2个位置)值为0
  • invp的第p[1]个位置(第0个位置)值为1
  • invp的第p[2]个位置(第1个位置)值为2

反之亦可

  • p的第invp[0]个位置(第1个位置)值为0
  • p的第invp[1]个位置(第2个位置)值为1
  • p的第invp[2]个位置(第0个位置)值为2

4 部分应用

4.1 RNN

  • 在处理变长序列数据,特别是当我们使用循环神经网络(RNN)时,建议对序列按长度排序
    • RNN处理变长序列时,尽管每个序列的实际长度可能不同,但在单次批处理中,我们需要所有的序列都有相同的长度。为了实现这一点,我们通常会对短的序列进行填充,使其长度与批处理中最长的序列相同。
    • 当我们对序列按长度排序时,那些长度相近的序列会被分到同一个批处理中。这意味着我们不需要为很短的序列填充过多的无效数据。

4.1.1 举例

假设我们有如下序列:

seqs = ["apple", "banana", "cherry", "date", "fig"]

他们的长度分别为:

lengths = [5, 6, 6, 4, 3]

 为了高效地进行批处理,对这些序列按长度进行排序:

sorted_seqs = ["fig", "date", "apple", "banana", "cherry"]

这时,我们需要一个排列索引(按照长度排序后的索引结果)来跟踪这个排序操作:

idx = [4, 3, 0, 1, 2]
#排序后的第0个元素是原来的第4个元素,以此类推

在RNN处理后,我们得到的输出也是按这个顺序排序的。为了将输出恢复到与原始输入相同的顺序,我们需要使用逆排列:

invp = [2, 3, 4, 1, 0]
'''
invp的计算:
invp的第idx[0](4)个元素是0
invp的第idx[1](3)个元素是1
。。。
'''

使用这个逆排列,我们可以将输出重新排序,使其与原始输入的顺序相匹配。

比如RNN之后,得到的输出序列是

outputs = ["output_fig", "output_date", "output_apple", "output_banana", "output_cherry"]

那么 使用逆排列,我们可以将输出重新排序到原始输入的顺序:

original_order_outputs = [outputs[i] for i in invp]
# 返回:['output_apple', 'output_banana', 'output_cherry', 'output_date', 'output_fig']

这样,original_order_outputs 就和 seqs 的顺序一致了。

所以,通过使用逆置换,我们可以确保无论输入序列如何被排序或重排,我们总是可以使用逆置换来恢复原始的顺序。这在处理与序列关联的目标或标签时非常有用,因为我们需要确保输入和标签的顺序始终保持一致。

你可能感兴趣的:(机器学习,笔记)