Обновление: Memory Views побеждает. Cython использует типизированные memoryviews: 0,0253449
Особая благодарность lothario, который указал на несколько критических изменений.
Смешной. Конечно, теперь проблема в том , что с ними не так много арифметических действий (суммы и умножения). Исходный пост Вдохновлен Реализация тематической модели с помощью Python (numpy) , что невероятно медленно. Я подумал, что было бы хорошей идеей cythonize это. Однако я мог только понять, как вдвое сократить время с cython. Здесь явно есть операции с массивами, которые не оптимизируются - некоторые мысли и предложения будут приветствоваться. Я всегда хотел поиграть с cython, и это, кажется, хорошая возможность!
для 15 документов по 300 слов в каждом, python: 39.6903322834 cython: 19.2733114806 Cython с использованием типизированных просмотров памяти: 0.547822975
Я специально хочу использовать nogil, так что это может еще больше ускориться: 1) с представлениями памяти, помогает ли добавление nogil в цикл? 2) У меня есть список документов, каждый документ представлен массивом чисел. Какой объект C мне лучше всего использовать? nogil не работает с объектами Python. В настоящее время у меня есть это как список массивов.
Я не фанат C, но буду рад любым дальнейшим предложениям по оптимизации.
Реализация Java от друга, на 1000 документов по 300 слов, 3 секунды.
код lda_pyx Cython
import numpy as np
cimport numpy as np
cimport cython
DTYPE = np.int
ctypedef np.int_t DTYPE_t
cdef class LDA:
cdef int iteration, M
cdef int[:] docSizes
cdef double[:, ::1] n_k_w ,n_m_k
#cdef
cdef double[:] n_k
cdef list k_m_n
cdef list numbered_docs
#def __init__(self,int iteration,int M, np.ndarray[np.double_t, ndim=2] n_k_w ,np.ndarray[np.double_t, ndim=2] n_m_k, np.ndarray[np.double_t, ndim=1] n_k,np.ndarray[np.int_t, ndim=1] docSizes, list numbered_docs, list k_m_n):
def __init__(self,int iteration,int M, double[:, ::1] n_k_w ,double[:, ::1] n_m_k, double[:] n_k, int[:] docSizes, list numbered_docs, list k_m_n):
self.iteration = iteration
self.M = M
self.n_k_w = n_k_w
self.n_m_k = n_m_k
self.n_k = n_k
self.k_m_n = k_m_n
self.numbered_docs = numbered_docs
self.docSizes = docSizes
@cython.boundscheck(False)
@cython.wraparound(False)
cdef int _sample(self) :
#cdef np.ndarray[np.double_t, ndim=2, mode="c"] n_k_w = self.n_k_w
#cdef np.ndarray[np.double_t, ndim=2, mode="c"] n_m_k = self.n_m_k
#cdef np.ndarray[np.double_t, ndim=1, mode="c"] n_k = self.n_k
cdef double[:, ::1] n_k_w = self.n_k_w
cdef double[:] n_k = self.n_k
cdef double[:, ::1] n_m_k = self.n_m_k
#cdef np.ndarray[np.int_t, ndim=1, mode="c"] docSizes = self.docSizes
cdef int[:] docSizes = self.docSizes
cdef int m , n, t , k ,new_k
#cdef np.ndarray[np.int_t, ndim=1, mode="c"] doc
cdef int[:] doc
for m in xrange(self.M):
doc = self.numbered_docs[m]
for n in xrange(docSizes[m]):
t = doc[n]
# discount for n-th word t with topic z
k = self.k_m_n[m][n]
#print k
n_m_k[m,k] -= 1
n_k_w[k,t] -= 1
n_k[k] -= 1
#print "ok"
# sampling topic new_z for t
#p_k = n_k_w[:, t] * n_m_k[m][k] / n_k
new_k = 1
#np.random.multinomial(1, p_z / p_z.sum()).argmax()
# set z the new topic and increment counters
self.k_m_n[m][n] = new_k
#print n_m_k[m, new_k] ,"after"
n_m_k[m, new_k] += 1
#print n_m_k[m, new_k] ,"after"
n_k_w[new_k][t] += 1
n_k[new_k] += 1
#print self.n_k_w ,"before"
self.n_k_w = n_k_w
#print self.n_k_w ,"after"
self.n_m_k = n_m_k
self.n_k = n_k
#self.k_m_n = k_m_n
return 1
@cython.boundscheck(False)
@cython.wraparound(False)
cdef int _iterate(self) :
while self.iteration >0 :
self._sample()
self.iteration -= 1
return 1
def iterate(iteration, M, n_k_w , n_m_k, n_k, docSizes, numbered_docs, k_m_n ):
cdef LDA lda
lda= LDA(iteration, M, n_k_w , n_m_k, n_k, docSizes, numbered_docs, k_m_n)
lda._iterate()
return lda.n_k_w , lda.n_m_k, lda.n_k , lda.k_m_n
чистая версия Python
def gibbs_sample():
for i in xrange(iteration):
#print i
for m in xrange(M):
doc = numbered_docs[m]
for n in xrange(docSizes[m]):
#print t
t = doc[n]
# discount for n-th word t with topic z
k = k_m_n[m][n]
n_m_k[m][k] -= 1
n_k_w[k][t] -= 1
n_k[k] -= 1
# sampling topic new_z for t
#p_k = n_k_w[:, t] * n_m_k[m][k] / n_k
new_k = 1
#np.random.multinomial(1, p_z / p_z.sum()).argmax()
# set z the new topic and increment counters
k_m_n[m][n] = new_k
n_m_k[m][new_k] += 1
n_k_w[new_k][t] += 1
n_k[new_k] += 1
cProfile
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.419 0.419 <string>:1(<module>)
1 0.419 0.419 0.419 0.419 {lda_pyx.iterate}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
cython -a
? - person JoshAdel   schedule 17.04.2013