Hallo zusammen
Google hat einen selbstgesteuerten Songlerner namens Magenta erstellt, sodass Sie so viele Songs erstellen können, wie Sie möchten! Ich dachte, aber es war nicht wirklich so einfach. Die Lernquelldatei scheint Midi zu sein, und es scheint nicht möglich zu sein, durch Einfügen einer aufgezeichneten Datei zu lernen.
Deshalb habe ich verschiedene Dinge ausprobiert, weil ich keine eigene selbstgesteuerte Song-Lernmaschine erstellen konnte, die mit WAV erstellt werden kann. Die letzten Artikel sind Experimente für diese Zeit.
TL;DR
Das Repository verwendet Folgendes https://github.com/niisan-tokyo/music_generator
Die folgenden Dateien werden für das eigentliche Lernen verwendet. https://github.com/niisan-tokyo/music_generator/blob/master/src/stateful_learn.py
Google hat Magenta veröffentlicht, ein selbstgesteuertes Song-Tool, das Tensorflow verwendet. https://magenta.tensorflow.org/ Dies ist ein großartiges Tool, aber ich bin ein wenig unbekannt damit, da die Zieldatei Midi ist. (Früher gab es viel, aber heute gibt es viel MP3 ...)
Zur einfachen Handhabung der aufgezeichneten Datei erscheint es vorerst gut, die Daten der Wellenform selbst wie wav zu verwenden. Darüber hinaus kann Python wav nativ verarbeiten, sodass ich dachte, ich müsste es versuchen.
Ich dachte darüber nach, die rohen Wellenformdaten zum Lernen zu verwenden, aber sie waren völlig nutzlos, also dachte ich an den folgenden Plan.
Mit anderen Worten, ich dachte, ich könnte so etwas machen Sobald Sie eine Häufigkeitsverteilung für Zeitreihen haben, können Sie Musik machen, indem Sie sie umgekehrt in Fourier umwandeln.
Im vorherigen Artikel war die von der inversen Konvertierung für die 256-Frame-Fourier-Konvertierung zurückgegebene WAV-Datei problemlos zu hören. Ich denke, dies ist genug als eine Merkmalsmenge, die den Klang selbst ausdrückt. http://qiita.com/niisan-tokyo/items/764acfeec77d8092eb73
Eine schnelle Fourier-Transformation (FFT) mit der Numpy-Bibliothek liefert 256 Frequenzverteilungen, beispielsweise in einem Intervall von 256 Bildern. Normalerweise beträgt die Bildrate (Bilder pro Sekunde) einer Audiodatei 44100, sodass Sie alle 256/44100 = 5,8 (ms) eine Häufigkeitsverteilung erhalten können. Die Idee ist, dass Musik automatisch erstellt wird, wenn wir eine Lernmaschine erstellen können, die diesen Zeitübergang automatisch alle 5,8 ms generiert.
stateful RNN RNN ist ein wiederkehrendes neuronales Netzwerk, bei dem es sich um einen Netzwerktyp handelt, der kontinuierliche Zustände verarbeitet, indem auf zuvor berechnete Inhalte verwiesen wird, wenn eine Ausgabe von der Eingabe erhalten wird. http://qiita.com/kiminaka/items/87afd4a433dc655d8cfd
Beim Umgang mit RNNs in Keras werden normalerweise mehrere aufeinanderfolgende Zustände als Eingaben verwendet und eine Ausgabe erstellt, aber bei jeder Eingabe wird der vorherige Zustand zurückgesetzt. stateful RNN führt die folgende Verarbeitung durch, während der Status nach dieser vorherigen Verarbeitung beibehalten wird. Es wird erwartet, dass dies eine komplexe Serienverarbeitung in unregelmäßigen Abständen ermöglicht.
Dieses Mal dachte ich, dass es möglich sein würde, einen Generator mit einem Fluss von Liedern zu erstellen, indem der Eingang als Frequenzverteilung im aktuellen Moment und der Ausgang als Frequenzverteilung im nächsten Moment mit Stateful RNN sequentiell gelernt werden.
Für m4a- und mp3-Dateien können Sie sie mit ffmpeg in wav konvertieren. http://qiita.com/niisan-tokyo/items/135824905e4a3021d358 Ich nehme meine Lieblingsspielmusik auf dem Mac auf und spucke sie auf WAV aus.
Da der Datensatz durch Fourier-Transformation WAV erstellt wird, können Sie grundsätzlich auf den Code verweisen, es gibt jedoch einige Einschränkungen.
def create_test_data(left, right):
arr = []
for i in range(0, len(right)-1):
#Vektorisierung komplexer Zahlen
temp = np.array([])
temp = np.append(temp, left[i].real)
temp = np.append(temp, left[i].imag)
temp = np.append(temp, right[i].real)
temp = np.append(temp, right[i].imag)
arr.append(temp)
return np.array(arr)
Dies ist der Teil, der Daten für die Eingabe erstellt, indem die Frequenzverteilungen der Stereo-Klangquelle kombiniert werden, die einer Fourier-Transformation unterzogen wurde. Hier werden der Real- und Imaginärteil der durch komplexe Zahlen dargestellten Häufigkeitsverteilung wieder in separate Elemente des Vektors eingefügt. Dies liegt daran, dass der Imaginärteil gelöscht wird, wenn Sie versuchen, mit einer komplexen Zahl zu berechnen. Infolgedessen beträgt die Anzahl der Abtastwerte in einem Abschnitt 256 Frames, die tatsächliche Eingabedimension jedoch 1024.
Das Modell ist so einfach wie das Verbinden von drei LSTMs und das endgültige Einfügen einer vollständig verbundenen Schicht.
model = Sequential()
model.add(LSTM(256,
input_shape=(1, dims),
batch_size=samples,
return_sequences=True,
activation='tanh',
stateful=True))
model.add(Dropout(0.5))
model.add(LSTM(256, stateful=True, return_sequences=True, activation='tanh'))
model.add(Dropout(0.3))
model.add(LSTM(256, stateful=True, return_sequences=False, activation='tanh'))
model.add(Dropout(0.2))
model.add(Dense(dims))
model.compile(loss='mse', optimizer='adam')
Nun gibt es einige Bedingungen bei der Verwendung eines statusbehafteten RNN. Zunächst müssen Sie die Eingabedimension pro Stapel angeben. Dann muss jede Probe in der vorherigen Charge und jede Probe in der nächsten Charge als Serie fortlaufend sein. Als spezifisches Beispiel gibt es, wenn es eine erste Charge "X_1" und eine zweite Charge "X_2" gibt, eine Beziehung zwischen der i-ten Stichprobe $ X_1 [i] $ und $ X_2 [i] $ von beiden. Es bedeutet, dass es geben muss. Dieses Mal nehmen wir an, dass der Generator aus $ x_ {n + 1} = RNN (x_n) $ besteht, und erstellen den nächsten Satz derselben Anzahl von Zuständen aus mehreren aufeinanderfolgenden Zuständen.
Mit anderen Worten, $ X_2 [i] $ liegt immer um $ X_1 [i] $ vor der Anzahl der Abtastwerte. Ich denke nicht, dass es ein bisschen zu schlampig ist, aber ich denke, es ist eine Maschine, die die Anzahl der Samples wiederholt, dh jeweils 32 Stück, um den nächsten Zustand zu erzeugen.
Jetzt, da Sie bereit sind, beginnen wir zu lernen.
for num in range(0, epochs):
print(num + 1, '/', epochs, ' start')
for one_data in test:
in_data = one_data[:-samples]
out_data = np.reshape(one_data[samples:], (batch_num, dims))
model.fit(in_data, out_data, epochs=1, shuffle=False, batch_size=samples)
model.reset_states()
print(num+1, '/', epochs, ' epoch is done!')
model.save('/data/model/mcreator')
Da die Reihenfolge der Chargen beim Lernen wichtig ist, versuche ich, die Proben auf der Charge nicht zu mischen. Zusätzlich wird für jede Welle gelernt, und der interne Zustand wird nach einmaligem Lernen zurückgesetzt.
Erstens, wenn ich versuche, es zu lernen, scheint es, dass die Anpassung irgendwie voranschreitet.
1 / 10 start
Epoch 1/1
16384/16384 [==============================] - 87s - loss: 1.9879e-04
Epoch 1/1
16384/16384 [==============================] - 84s - loss: 1.9823e-04
Epoch 1/1
16384/16384 [==============================] - 75s - loss: 1.1921e-04
Epoch 1/1
16384/16384 [==============================] - 82s - loss: 2.3389e-04
Epoch 1/1
16384/16384 [==============================] - 80s - loss: 3.7428e-04
Epoch 1/1
16384/16384 [==============================] - 90s - loss: 3.3968e-04
Epoch 1/1
16384/16384 [==============================] - 87s - loss: 5.0188e-04
Epoch 1/1
16384/16384 [==============================] - 76s - loss: 4.9725e-04
Epoch 1/1
16384/16384 [==============================] - 74s - loss: 3.7447e-04
Epoch 1/1
16384/16384 [==============================] - 87s - loss: 4.1855e-04
1 / 10 epoch is done!
2 / 10 start
Epoch 1/1
16384/16384 [==============================] - 82s - loss: 1.9742e-04
Epoch 1/1
16384/16384 [==============================] - 85s - loss: 1.9718e-04
Epoch 1/1
16384/16384 [==============================] - 90s - loss: 1.1876e-04
Epoch 1/1
16384/16384 [==============================] - 104s - loss: 2.3144e-04
Epoch 1/1
16384/16384 [==============================] - 97s - loss: 3.7368e-04
Epoch 1/1
16384/16384 [==============================] - 78s - loss: 3.3906e-04
Epoch 1/1
16384/16384 [==============================] - 87s - loss: 5.0128e-04
Epoch 1/1
16384/16384 [==============================] - 79s - loss: 4.9627e-04
Epoch 1/1
16384/16384 [==============================] - 82s - loss: 3.7420e-04
Epoch 1/1
16384/16384 [==============================] - 90s - loss: 4.1857e-04
2 / 10 epoch is done!
...
Lassen Sie uns mit dem fertigen Modell einen Sound machen.
Ich überlasse den detaillierten Code stateful_use.py im Repository. Wenn Sie also nur den allgemeinen Ablauf schreiben,
Der Generatorteil ist wie folgt
#Fourier-Transformation der Seed-Datei
Kl = fourier(left, N, samples * steps)
Kr = fourier(right, N, samples * steps)
sample = create_test_data(Kl, Kr)
sample = np.reshape(sample, (samples * steps, 4 * N))
music = []
#Geben Sie die Startdaten in das Modell ein=>Den Staat "fördern"
for i in range(steps):
in_data = np.reshape(sample[i * samples:(i + 1) * samples], (samples, 1, 4 * N))
model.predict(np.reshape(in_data, (samples, 1, 4 * N)))
#Erstellen Sie selbst Musik, indem Sie die letzten Ausgabedaten nacheinander in das Modell einsetzen, dessen Status durch Startdaten geändert wurde
for i in range(0, frames):
if i % 50 == 0:
print('progress: ', i, '/', frames)
music_data = model.predict(np.reshape(in_data, (samples, 1, 4 * N)))
music.append(np.reshape(music_data, (samples, 4 * N)))
in_data = music_data
music = np.array(music)
Die auf diese Weise erhaltenen Daten werden umgekehrt Fourier-transformiert, in den realen Raum konvertiert und dann in wav geschrieben. Wenn man die Wellenform im realen Raum betrachtet, sieht es wie folgt aus.
Etwas länger Wenn ich das mit WAV höre, ist es in einem surrealen Zustand, in dem die ganze Zeit ein Summer-Sound mit einem konstanten Ton von "Boo" gespielt wird. .. ..Weit entfernt von Musik ist es zu einer mysteriösen Maschine geworden, die nur einen konstanten Klang erzeugt. Unabhängig davon, welche Art von Musikdatei Sie einfügen, wird derselbe Sound erzeugt.
Ich denke, der Grund, warum es nicht funktioniert hat, war, dass der Übergang des Klangs so schnell war, dass das Lernen in Richtung der Konstante ging, die den Fehler minimierte. Vielleicht ist deshalb die Fehlerschwankung trotz des komplizierten Systems zu gering. Wenn Sie versuchen, es zustandslos zu machen, wissen Sie nicht, wie viele Sequenzen Sie nehmen sollen, und die Anzahl der Dimensionen nimmt mit der Anzahl der Sequenzen zu, was das Lernen schwierig macht. Oder es kann sein, dass die Anzahl der Lernvorgänge zu gering ist, aber da der Verlust bereits sehr gering ist, kann es eine andere Idee sein.
In jedem Fall müssen wir uns weiter verbessern.
Wenn Sie ein Lied so einfach machen könnten, wäre es nicht so einfach. Es hat nicht sehr gut funktioniert, aber ich denke, ich habe bis zu einem gewissen Grad gelernt, wie man Python benutzt, insbesondere die Bedeutung von Numpy, also denke ich, dass das ein guter Punkt ist.
Es ist mir auch egal, aber ich habe mich am Ende sehr mit Numpys Umformung beschäftigt.
Diesmal ist so ein Ort
2017/06/18 Die folgenden Änderungen wurden vorgenommen.
Ich habe die folgende Wellenform. Das Hintergrundgeräusch blieb wie gewohnt, aber jetzt klingt es so, als würde es einen bestimmten Rhythmus schnitzen. Zusätzlich ist die erhaltene Häufigkeitsverteilung (der Realteil) wie folgt. Die Verteilungskarte für 10 Teile wird mit jeweils 5 Frames überlagert.
N = 256, Anzahl der LSTM-Neuronen = 256 N = 1024, Anzahl der LSTM-Neuronen = 512 Wenn N = 1024 und die Anzahl der Neuronen 256 ist, ist es dasselbe wie wenn N = 256 ist.
Wenn der anzuwendende Faktor während der Fourier-Transformation geändert wurde, nahm der Verlust selbstverständlich zu. Da mse für den Verlust verwendet wird, erhöht das Ändern des Faktors den Verlust um das Quadrat. Dies ermöglicht es, Änderungen an kleineren Komponenten zu beobachten, die möglicherweise eine verbesserte Genauigkeit aufweisen. Durch Erhöhen der Anzahl von Neuronen erhöhte sich auch die Expressionskraft.
Als Verbesserung ist es möglich, den während der Fourier-Transformation angewendeten Faktor zu erhöhen oder die Anzahl der Neuronen weiter zu erhöhen. Da die Anzahl der Epochen 10 und die Anzahl der Original-Songs 9 beträgt, ist es in Ordnung, dies zu ändern, aber da die Änderung des Verlusts gering ist, konnte ich den Effekt nicht gut sehen, so dass ich dachte, es sei vorerst reserviert.
Recommended Posts