How to speed up this Python code?

走远了吗. 提交于 2019-12-05 09:29:08

if topScore is called repeatedly for same seq you could memoize its value.

E.g. http://code.activestate.com/recipes/52201/

The reason it is slow is because it is O(N*N)

The maximum subsequence algorithm may help you improve this

Wangnick

What about precomputing xrange(l) outside the for i loop?

i don't have any idea what i'm doing but maybe this can help speed up your algo:

ret = -1e9999
logProbs = self.logProbs  # save indirection
l = len(logProbs)

scores = collections.defaultdict(int)

for j in xrange(l):
    prob = logProbs[j]
    for i in xrange(len(seq) - l + 1):
        scores[i] += prob[seq[j + i]]


ret = max(ret, max(scores.values()))

Nothing jumps out as being slow. I might rewrite the inner loop like this:

score = sum(logProbs[j][seq[j+i]] for j in xrange(l))

or even:

seqmatch = zip(seq[i:i+l], logProbs)
score = sum(posscores[base] for base, posscores in seqmatch)

but I don't know that either would save much time.

It might be marginally quicker to store DNA bases as integers 0-3, and look up the scores from a tuple instead of a dictionary. There'll be a performance hit on translating letters to numbers, but that only has to be done once.

Definitely use numpy and store logProbs as a 2D array instead of a list of dictionaries. Also store seq as a 1D array of (short) integers as suggested above. This will help if you don't have to do these conversions every time you call the function (doing these conversions inside the function won't save you much). You can them eliminate the second loop:

import numpy as np
...
print np.shape(self.logProbs) # (20, 4)
print np.shape(seq) # (1000,)
...
def topScore(self, seq):
ret = -1e9999
logProbs = self.logProbs  # save indirection
l = len(logProbs)
for i in xrange(len(seq) - l + 1):
    score = np.sum(logProbs[:,seq[i:i+l]])
    ret = max(ret, score)

return ret

What you do after that depends on which of these 2 data elements changes the most often:

If logProbs generally stays the same and you want to run many DNA sequences through it, then consider stacking your DNA sequences as a 2D array. numpy can loop through the 2D array very quickly so if you have 200 DNA sequences to process, it will only take a little longer than a single.

Finally, if you really need speed up, use scipy.weave. This is a very easy way to write a few lines of fast C to accelerate you loops. However, I recommend scipy >0.8.

You can try hoisting more than just self.logProbs outside the loops:

def topScore(self, seq):
    ret = -1e9999
    logProbs = self.logProbs  # save indirection
    l = len(logProbs)
    lrange = range(l)
    for i in xrange(len(seq) - l + 1):
        score = 0.0
        for j in lrange:
            score += logProbs[j][seq[j + i]]
        if score > ret: ret = score # avoid lookup and function call

    return ret

I doubt it will make a significant difference, but you could try changing:

  for j in xrange(l):
        score += logProbs[j][seq[j + i]]

to

  for j,lP in enumerate(logProbs):
        score += lP[seq[j + i]]

or even hoisting that enumeration outside the seq loop.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!