Ukryte Modele Markowa w progresji jazzowej II V I
W ostatnim wpisie pokazałem jak z wykorzystaniem łańcucha Markowa można wygenerować fragment melodii na podstawie innej wykorzystując macierz przejścia. Był do dość prosty model, ponieważ był w stanie opisać tylko jedną cechę: wysokość dźwięku. Utwór muzyczny to nie tylko zbiór nut, które posiadają tylko jedną cechę – wysokość. Można wyodrębnić klika, a nawet kilkanaście cech, można tutaj wymienić np.:
- długość trwania dźwięku
- siła uderzenia
- tempo
- harmonia
- melodyka
- inne
Aby móc realizować bardziej skomplikowane operacje potrzeba trochę bardziej zaawansowanego modelu niż sam prosty łańcuch Markowa. Pozostając w temacie można tutaj przywołać specjalny rodzaj łańcuchów Markowa jakim są Ukryte Modele Markowa (Ukryte Łańcuchy Markowa, HMM, ang. hidden Markov models). Motele te mają zastosowanie w rozpoznawaniu mowy, bioinformatyce czy graniu na giełdzie. HMM są rozszerzeniem standardowej definicji łańcucha Markowa. Używane są głównie do modelowania związku między ukrytymi, a obserwowanymi sekwencjami. Ukrytym modelem Markowa jest łańcuch Markowa z dyskretnym rozkładem prawdopodobieństwa w każdym stanie. Dyskretne rozkłady prawdopodobieństwa definiują prawdopodobieństwa emisji określonego symbolu alfabetu w danym stanie.
Wszystko stanie się jasne jeżeli taki model przedstawimy w postaci rysunku.
![]()
Na rysunku powyżej wyróżnić można dwa stany: Rainy i Sunny (podobnie jak w tradycyjnym modelu Markowa). Stany te nazywane są stanami obserwowanymi. Tradycyjnie jest zadana macierz prawdopodobieństw przejścia ze stanu do stanu. Dodatkowo na rysunku są jeszcze trzy stany pośrednie (ukryte): Walk, Shop, Clean. Dlaczego te stany nazywane są ukrytymi? Znalezienie się w stanie ukrytym nie zmieni zachowania modelu stan ukryty jest cechą dla stanu obserwowanego. Nie używam tutaj żadnych formalizmów w postaci wzorów, nie mniej mam nadzieje, że to jest jasne. Jeżeli jeszcze nie do końca to można się na chwilę zatrzymać. Będąc np. w stanie Rainy możemy trafić na 3 stany pośrednie Walk, Shop, Clean. Mówiąc potocznie, w przypadku pogody deszczowej z prawdopodobieństwem 0.1 wybierzemy spacer, z prawdopodobieństwem 0.4 wybierzemy zakupy, a z prawdopodobieństwem 0.5 sprzątanie. Podobnie jak w macierzy przejścia w standardowym modelu Markowa macierz przejścia dla stanów ukrytych musi również sumować się wierszami do 1. Załóżmy, że w stanie Rainy został wybrany stan Shop, nie zaburza to jednak pracy modelu – dalej znajdujemy się w stanie Rainy i z prawdopodobieństwem 0.3 możemy przeskoczyć do stanu Sunny. Macierz przejścia dla stanówobserwowanych przedstawia się następująco.
[latex]
\[
M =
\begin{bmatrix}
0.7 & 0.3 \\
0.4 & 0.6 \\
\end{bmatrix}\\
\]
[/latex]
Macierz przejścia dla stanów ukrytych wygląda:
[latex]
\[
U =
\begin{bmatrix}
0.1 & 0.4 & 0.5 \\
0.6 & 0.3 & 0.1 \\
\end{bmatrix}\\
\]
[/latex]
Podsumowując, mając ukryty model markowa możemy dla każdego stanu dodać jedną cechę. W przypadku muzyki może to być, długość trwania dźwięku, dynamika czy rodzaj akordu. Jeżeli by połączyć ukryte modele Markowa w warstwy można zamodelować nawet kilka cech – są już to początki do stworzenia półautomatycznego systemu służącego do komponowania muzyki.
Generowanie akordów
Jako dość prosty przykład ukryty model Markowa można wykorzystać w muzyce do generowania akordów na podstawie progresji II V I. Progresja II V I jako następstwo akordów, jest wykorzystywana w szerokim zakresie gatunków muzycznych oraz jest podstawą harmonii jazzowej. W przykładzie będziemy rozważać progresje II V I dla akordów tonacji C-dur. Poszczególne akordy będą stanami w łańcuchu Markowa. Stany ukryte będą odpowiedzialne za typ akordu (minor7, major7, dominant7). Poniższy rysunek powinien wyjaśnić różnice w rodzajach akordów na przykładzie gamy C-dur:

Podstawowe rodzaje akordów dla gamy C-dur
Akordów można posłuchać w serwisie 8notes.
W przypadku progresji II V I, akordy są budowane kolejno na II stopniu gamy V i I, dla gamy C-dur II stopień to nuta D, V to G i I C. Poniżej przykład progresji II V I w tonacji C-dur:

II V I w tonacji C-dur

Wszystkie rodzaje akordów użyte w przykładzie
Analogicznie można utworzyć progresje w innych tonacjach, mając na uwadze jej reguły (ilość bemoli czy krzyżyków). Więcej o teorii nie będę pisał, chodzi o wstępną intuicję. Przykład podkładu muzycznego w tonacji II V I w tonacji C-dur można zobaczyć tutaj: https://www.youtube.com/watch?v=kcEKcl1WgFk&t=33s.
Przygotowanie
W pierwszym kroku należy zdefiniować macierz przejścia dla stanów łańcucha Markowa. W przykładzie będą wykorzystane trzy stany, które będą odpowiadały nutą D, G, C – progresja II V I.
[latex]
\[
P =
\begin{bmatrix}
0.4 & 0.4 & 0.2 \\
0.1 & 0.1 & 0.8 \\
0.0 & 0.3 & 0.7
\end{bmatrix}\\
\]
[/latex]
Następnie musi zostać stworzona macierz emisji dla stanów ukrytych. Warstwa ukryta będzie odpowiedzialna za rodzaj akordu. Do dyspozycji będą trzy rodzaje akordów: minor7, major7, dominant7.
[latex]
\[
M =
\begin{bmatrix}
0.4 & 0.0 & 0.4 \\
0.3 & 0.3 & 0.3 \\
0.2 & 0.8 & 0.0
\end{bmatrix}\\
\]
[/latex]
Dla danego stanu z macierzy P będzie wybierany dany stan z macierzy M z uwzględnieniem reguł łańcucha Markowa. Model można przedstawić w postaci grafu na ilustracji poniżej. Strzałkami z liniami przerywanymi są poprowadzone wyprowadzenia do stanów ukrytych, które mówią o rodzaju akordu.

O wybraniu danego stanu ukrytego w ukrytych Markowa decyduje algorytm Viterbiego, nie będę go tutaj opisywał. Z algorytmem można się zapoznać tutaj.
Implementacja
Ostatnim krokiem przy reprezentacji pomysły jest jego implementacja. Wykorzystałem tutaj język Python. Do zaimplementowania ukrytego modelu Markowa wykorzystałem bibliotekę hmmlearn, do prezentacji wyników w postaci plików MIDI i grafik PNG posłużyła mi biblioteka music21. Szczegóły implementacji opiszę w następnym wpisie. Poniżej kilka przykładowych wyników.
Wynik 1 – 10 iteracji

Wynik 2 – 20 iteracji

Wynik 3 – 20 iteracji

Wynik 3 – 20 iteracji
Nie jest to oczywiście jeszcze pełnowartościowa muzyka, ale pewien krok w kierunku zbudowania półautomatycznego systemu. Tak jak pisałem na początku utwór muzyczny posiada sporo cech, które trzeba w jakiś sposób zamodelować. Można do tego wykorzystać wielowarstwowe ukryte modele Markowa, w których to każda warstwa może być odpowiedzialna za osobną cechę. Pozostawiam to do przemyślenia.
Źródła:
- https://www.youtube.com/watch?v=EqUfuT3CC8s
- https://en.wikipedia.org/wiki/Hidden_Markov_model
- http://www.ismir.net/ – International Society for Music Information Retrieval
- https://ieeexplore.ieee.org/document/5492670/
- https://www.researchgate.net/publication/224148842_Music_Generation_with_Markov_Models

