微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

嵌套枚举for循环到理解列表

如何解决嵌套枚举for循环到理解列表

我正在使用textdistance.needleman_wunsch.normalized_distance库(https://github.com/life4/textdistance)中的textdistance。我将其与cdist库中的Scipy配合使用,以计算序列的配对距离。但是由于嵌套的枚举for循环,该过程非常漫长。

在这里您可以找到textdistance库中使用的代码,这需要花费时间,我想知道您是否对如何加快嵌套嵌套的for循环有任何想法,也许可以使用列表理解功能

s1 = "sentence1"
s2 = "sentevfers2"
gap = 1


def sim_func(*elements):
    """Return True if all sequences are equal.
    """
    try:
        # for hashable elements
        return len(set(elements)) == 1
    except TypeError:
        # for unhashable elements
        for e1,e2 in zip(elements,elements[1:]):
            if e1 != e2:
                return False
        return True


dist_mat = numpy.zeros(
    (len(s1) + 1,len(s2) + 1),dtype=numpy.float,)

# DP initialization
for i in range(len(s1) + 1):
    dist_mat[i,0] = -(i * gap)

# DP initialization
for j in range(len(s2) + 1):
    dist_mat[0,j] = -(j * gap)

""" Possible enhancement with list comprehension ? """
# Needleman-Wunsch DP calculation
for i,c1 in enumerate(s1,1):
    for j,c2 in enumerate(s2,1):
        match = dist_mat[i - 1,j - 1] + sim_func(c1,c2)
        delete = dist_mat[i - 1,j] - gap
        insert = dist_mat[i,j - 1] - gap
        dist_mat[i,j] = max(match,delete,insert)
distance = dist_mat[dist_mat.shape[0] - 1,dist_mat.shape[1] - 1]
print(distance)

解决方法

此代码运行缓慢有几个原因:

  • (可能)在CPython中执行并用纯Python编写,这是慢速解释器,不适用于此类数字代码
  • sim_func是比较各种元素的一种通用方法,但也非常效率低(分配,哈希,异常处理和字符串处理)。

代码不容易并行化,因此必须向量化numpy。但是,您可以使用Numba加快速度。仅当输入字符串很大或此处理执行了很多时间时,才值得这样做。如果不是这种情况,请使用更适合的编程语言(例如C,C ++,D,Rust等)或专用于该语言的原生Python模块

以下是优化的Numba代码:

s1 = "sentence1"
s2 = "sentevfers2"
gap = 1  # Assume this is an integer

@njit
def NeedlemanWunschDP(dist_mat,s1,s2):
    for i in range(1,len(s1)+1):
        for j in range(1,len(s2)+1):
            match = dist_mat[i - 1,j - 1] + (s1[i-1] == s2[j-1])
            delete = dist_mat[i - 1,j] - gap
            insert = dist_mat[i,j - 1] - gap
            dist_mat[i,j] = max(match,delete,insert)

dist_mat = numpy.empty(
    (len(s1) + 1,len(s2) + 1),dtype=numpy.int64,)

# DP initialization
for i in range(len(s1) + 1):
    dist_mat[i,0] = -(i * gap)

# DP initialization
for j in range(len(s2) + 1):
    dist_mat[0,j] = -(j * gap)

# Transform the strings to fast integer arrays
tmp_s1 = numpy.array([ord(e) for e in s1],dtype=numpy.int64)
tmp_s2 = numpy.array([ord(e) for e in s2],dtype=numpy.int64)
# Needleman-Wunsch DP calculation
NeedlemanWunschDP(dist_mat,tmp_s1,tmp_s2)
distance = dist_mat[dist_mat.shape[0] - 1,dist_mat.shape[1] - 1]
print(distance)

NeedlemanWunschDP的编译时间在我的计算机上大约需要400毫秒,但是在巨大的字符串上,生成的代码要快 1800倍

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?