我正在编写一个代码,用于使用 HMM 和维特比算法提出拼写错误更正建议。在某些时候,对于文本中的每个单词,我必须执行以下操作。 (假设我有 10,000 个单词)
#FYI Windows 10, 64bit, interl i7 4GRam, Python 2.7.3
import numpy as np
import pandas as pd
for k in range(10000):
tempWord = corruptList20[k] #Temp word read form the list which has all of the words
delta = np.zeros(26, len(tempWord)))
sai = np.chararray(26, len(tempWord)))
sai[:] = '@'
# INITIALIZATION DELTA
for i in range(26):
delta[i][0] = #CALCULATION matrix read and multiplication each cell is different
# INITILIZATION END
# 6.DELTA CALCULATION
for deltaIndex in range(1, len(tempWord)):
for j in range(26):
tempDelta = 0.0
maxDelta = 0.0
maxState = ''
for i in range(26):
# CALCULATION to fill each cell involve in:
# 1-matrix read and multiplication
# 2 Finding Column Max
# logical operation and if-then-else operations
# 7. SAI BACKWARD TRACKING
delta2 = pd.DataFrame(delta)
sai2 = pd.DataFrame(sai)
proposedWord = np.zeros(len(tempWord), str)
editId = 0
for col in delta2.columns:
# CALCULATION to fill each cell involve in:
# 1-matrix read and multiplication
# 2 Finding Column Max
# logical operation and if-then-else operations
editList20.append(''.join(editWord))
#END OF LOOP
如您所见,它涉及计算,当我运行时,它需要花费太多时间才能运行。 目前我的笔记本电脑被盗,我在 Windows 10、64 位、4GRam、Python 2.7.3 上运行它
我的问题:任何人都可以看到我可以用来优化的任何点吗?在循环进入下一轮之前,我是否必须删除我在循环中创建的矩阵以释放内存,还是自动完成?
在下面的评论和使用 xrange 而不是 range 之后,性能几乎提高了 30%。在此更改后,我将在此处添加屏幕截图。
请您参考如下方法:
我不认为 range 的讨论有什么不同。在 Python3 中,range 是迭代器,在迭代前将其扩展为列表不会改变太多时间。
In [107]: timeit for k in range(10000):x=k+1
1000 loops, best of 3: 1.43 ms per loop
In [108]: timeit for k in list(range(10000)):x=k+1
1000 loops, best of 3: 1.58 ms per loop
使用 numpy 和 pandas 加速循环的真正关键是将它们替换为适用于整个数组或数据帧的编译操作。但即使在纯 Python 中,也应专注于精简迭代的内容,而不是迭代机制。
======================
for i in range(26):
delta[i][0] = #CALCULATION matrix read and multiplication
一个小改动:delta[i, 0] = ...;这是寻址单个元素的数组方式;在功能上它通常是相同的,但意图更清楚。但是想一想,您不能将所有该列设置为一次吗?
delta[:,0] = ...
====================
N = len(tempWord)
delta = np.zeros(26, N))
etc
在紧密循环中,像这样的临时变量可以节省时间。这并不严密,所以这里只是为了增加清晰度。
===========================
这个丑陋的嵌套三重循环;诚然 26 步并不大,但 26*26*N 是:
for deltaIndex in range(1,N):
for j in range(26):
tempDelta = 0.0
maxDelta = 0.0
maxState = ''
for i in range(26):
# CALCULATION
# 1-matrix read and multiplication
# 2 Finding Column Max
# logical operation and if-then-else operations
专注于用数组操作替换它。需要更改的是那 3 行注释,而不是迭代机制。
================
使 proposedWord 成为列表而不是数组可能会更快。小型列表操作通常比数组操作更快,因为 numpy 数组有创建开销。
In [136]: timeit np.zeros(20,str)
100000 loops, best of 3: 2.36 µs per loop
In [137]: timeit x=[' ']*20
1000000 loops, best of 3: 614 ns per loop
创建“空”列表时必须注意元素是真正独立的,而不仅仅是同一事物的副本。
In [159]: %%timeit
x = np.zeros(20,str)
for i in range(20):
x[i] = chr(65+i)
.....:
100000 loops, best of 3: 14.1 µs per loop
In [160]: timeit [chr(65+i) for i in range(20)]
100000 loops, best of 3: 7.7 µs per loop
