Im Folgenden ist der einfachste Weg den ich kenne, Übergänge in einer Markow-Kette zu zählen und es zu verwenden, einen Übergang Matrix zu besiedeln:Wie kann ich die Erstellung der Übergangsmatrix in Numpy beschleunigen?
def increment_counts_in_matrix_from_chain(markov_chain, transition_counts_matrix):
for i in xrange(1, len(markov_chain)):
old_state = markov_chain[i - 1]
new_state = markov_chain[i]
transition_counts_matrix[old_state, new_state] += 1
ich habe versucht, bis auf 3 verschiedene Arten zu beschleunigen:
1) eine spärliche Matrix Einzeiler auf diesem Code Matlab basierte Anwendung:
transition_matrix = full(sparse(markov_chain(1:end-1), markov_chain(2:end), 1))
die in Numpy/SciPy, sieht wie folgt aus:
def get_sparse_counts_matrix(markov_chain, number_of_states):
return coo_matrix(([1]*(len(markov_chain) - 1), (markov_chain[0:-1], markov_chain[1:])), shape=(number_of_states, number_of_states))
Und ich habe noch ein paar Python zwickt versucht, wie mit Reißverschluss():
for old_state, new_state in zip(markov_chain[0:-1], markov_chain[1:]):
transition_counts_matrix[old_state, new_state] += 1
And Queues:
old_and_new_states_holder = Queue(maxsize=2)
old_and_new_states_holder.put(markov_chain[0])
for new_state in markov_chain[1:]:
old_and_new_states_holder.put(new_state)
old_state = old_and_new_states_holder.get()
transition_counts_matrix[old_state, new_state] += 1
Aber keine dieser drei Methoden beschleunigt Dinge. In der Tat war alles außer der Zip() Lösung mindestens 10x langsamer als meine ursprüngliche Lösung.
Gibt es noch andere Lösungen, die sich zu untersuchen lohnt?
Modified Lösung
Die beste Antwort auf die obige Frage war eine Übergangsmatrix aus vielen Ketten für den Aufbau speziell von DSM. Doch für alle, die eine Übergangsmatrix auf der Grundlage einer Liste von Millionen von Markow-Ketten füllen will, ist der schnellste Weg, um dies:
def fast_increment_transition_counts_from_chain(markov_chain, transition_counts_matrix):
flat_coords = numpy.ravel_multi_index((markov_chain[:-1], markov_chain[1:]), transition_counts_matrix.shape)
transition_counts_matrix.flat += numpy.bincount(flat_coords, minlength=transition_counts_matrix.size)
def get_fake_transitions(markov_chains):
fake_transitions = []
for i in xrange(1,len(markov_chains)):
old_chain = markov_chains[i - 1]
new_chain = markov_chains[i]
end_of_old = old_chain[-1]
beginning_of_new = new_chain[0]
fake_transitions.append((end_of_old, beginning_of_new))
return fake_transitions
def decrement_fake_transitions(fake_transitions, counts_matrix):
for old_state, new_state in fake_transitions:
counts_matrix[old_state, new_state] -= 1
def fast_get_transition_counts_matrix(markov_chains, number_of_states):
"""50% faster than original, but must store 2 additional slice copies of all markov chains in memory at once.
You might need to break up the chains into manageable chunks that don't exceed your memory.
"""
transition_counts_matrix = numpy.zeros([number_of_states, number_of_states])
fake_transitions = get_fake_transitions(markov_chains)
markov_chains = list(itertools.chain(*markov_chains))
fast_increment_transition_counts_from_chain(markov_chains, transition_counts_matrix)
decrement_fake_transitions(fake_transitions, transition_counts_matrix)
return transition_counts_matrix
Ich werde diese Antwort akzeptieren, aber ich möchte mit einer zusätzlichen Frage folgen. Wenn ich bincount wiederholt verwende, um eine Übergangszählmatrix basierend auf Tausenden von Markovketten zu füllen, ist mein ursprünglicher Code immer noch schneller. Ich nehme an, das liegt daran, dass counts_matrix.flat + = numpy.bincount (flat_coords, minlength = counts_matrix.size) bei der Aktualisierung der counts_matrix langsamer ist als mein ursprünglicher Code. Gedanken dazu? –
Update dazu: Die schnellste Lösung, die ich gefunden habe, um eine Übergangsmatrix basierend auf Tonnen Markovketten zu füllen, besteht darin, die Ketten nacheinander zu verschmelzen, binounts zu verwenden und dann die falschen Übergänge zu bekommen (vom Ende einer Kette bis zum Anfang) des nächsten), dann dekrementieren Sie die Zählwerte für jeden gefälschten Übergang. Diese Lösung war ungefähr 25% schneller als mein Original. –
@ some-guy: Fühlen Sie sich frei, die beste Lösung zu finden, die Sie für Ihren Anwendungsfall finden, posten Sie das als Antwort und akzeptieren Sie es. – DSM