我试图用python实现隐马尔可夫模型训练,结果numpy代码看起来非常慢。训练一个模特需要30分钟。下面是我的代码,我同意这是非常低效的。我试着学习numpy向量化和高级索引方法,但无法理解如何在代码中使用它们。我可以确定大部分的执行是集中的,reestimate()
函数占用了超过99%的执行时间,尤其是打印CHK5和CHK6的部分。在
def reestimate(self):
newTransition = numpy.zeros(shape=(int(self.num_states),int(self.num_states)))
newOutput = numpy.zeros(shape=(int(self.num_states),int(self.num_symbols)))
numerator = numpy.zeros(shape=(int(self.num_obSeq),))
denominator = numpy.zeros(shape=(int(self.num_obSeq),))
sumP = 0
i = 0
print "CHK1"
while i < self.num_states:
j=0
while j < self.num_states:
if j < i or j > i + self.delta:
newTransition[i][j] = 0
else:
k=0
print "CHK2"
while k < self.num_obSeq:
numerator[k] = denominator[k] = 0
self.setObSeq(self.obSeq[k])
sumP += self.computeAlpha()
self.computeBeta()
t=0
while t < self.len_obSeq - 1:
numerator[k] += self.alpha[t][i] * self.transition[i][j] * self.output[j][self.currentSeq[t + 1]] * self.beta[t + 1][j]
denominator[k] += self.alpha[t][i] * self.beta[t][i]
t += 1
k += 1
denom=0
k=0
print "CHK3"
while k < self.num_obSeq:
newTransition[i,j] += (1 / sumP) * numerator[k]
denom += (1 / sumP) * denominator[k]
k += 1
newTransition[i,j] /= denom
newTransition[i,j] += self.MIN_PROBABILITY
j += 1
i += 1
sumP = 0
i = 0
print "CHK4"
while i < self.num_states:
j=0
while j < self.num_symbols:
k=0
while k < self.num_obSeq:
numerator[k] = denominator[k] = 0
self.setObSeq(self.obSeq[k])
# print self.obSeq[k]
sumP += self.computeAlpha()
self.computeBeta()
t=0
print "CHK5"
while t < self.len_obSeq - 1:
if self.currentSeq[t] == j:
numerator[k] += self.alpha[t,i] * self.beta[t,i]
denominator[k] += self.alpha[t,i] * self.beta[t,i]
t += 1
k += 1
denom=0
k=0
print "CHK6"
while k < self.num_obSeq:
newOutput[i,j] += (1 / sumP) * numerator[k]
denom += (1 / sumP) * denominator[k]
k += 1
newOutput[i,j] /= denom
newOutput[i,j] += self.MIN_PROBABILITY,
j += 1
i += 1
self.transition = newTransition
self.output = newOutput
def train(self):
i = 0
while i < 20:
self.reestimate()
print "reestimating....." ,i
i += 1
将内部循环矢量化很简单。下面是代码第二部分的示例(当然未经测试):
也可以将外环矢量化,但到目前为止,最大的增益通常只通过聚焦于内环获得。一些评论:
似乎大多数
while
循环都可以变成for
循环。尽管这对速度没有太大的影响,但是如果在循环之前知道迭代次数,这是首选方法。惯例是使用
import numpy as np
,并在其余代码中使用np.function
只计算求和(
accum = 0; for item in vector: accum += item
)的简单循环应该像accum = np.sum(vector)
一样向量化。循环中的条件求和可以通过布尔索引转换为矢量化和,因此
accum = 0; for i in range(n): if cond[i]: accum += vector[i]
可以替换为accum = np.sum(vector[cond])
我很想知道在这些修改之后,代码的速度有多快,我想您可以轻松地获得超过10的因子。在
相关问题 更多 >
编程相关推荐