Dieser Artikel ist eine Serie. Klicken Sie hier für weitere Artikel ↓ 0. Design (Was ist AI, um den Schlüssel zu bestimmen?) 1. Datenerfassung (Crawlen) 2. Datenformung (Scraping) 4. Entwicklung von Webanwendungen mit Django
Seit der Entwicklung sind 3-4 Monate vergangen. Zum Zeitpunkt der Entwicklung war das Ziel die Bereitstellung, und ich habe nicht viel Zeit damit verbracht, das wesentliche Modell auszuwählen.
Dieses Mal möchte ich verschiedene Ansätze ausprobieren und die Genauigkeit vergleichen. Ich werde auch versuchen, regelbasierte Genauigkeit zu finden, ohne maschinelles Lernen zu verwenden.
Die Aufgabe dieses Mal ist es, die Tonart aus der Akkordfolge des Songs zu bestimmen. Code-Fortschritt? Schlüssel? Weitere Informationen finden Sie im folgenden Artikel.
Ich habe die Häufigkeit, mit der die Akkorde erschienen, und die Tonart von der Website für die Veröffentlichung von Akkorddiagrammen mit dem Namen J-Total Music abgekratzt. Unter den veröffentlichten Songs gibt es Daten für die Songs (20848 Songs), für die der Schlüssel erhalten werden konnte.
Einige Songs haben jedoch nur wenige Codes. Beispiel: https://music.j-total.net/data/012si/071_shinohara_tomoe/001.html Da diese Songs nicht für Trainingsdaten geeignet sind, werden Daten mit einer Gesamtzahl von Akkorden, die 20 Mal oder weniger im Song erscheinen, gelöscht. Als Ausreißerentfernung werden außerdem Daten mit einer Gesamtzahl von Akkorden im Song von 250 oder mehr gelöscht. Im Folgenden werden wir verschiedene Dinge basierend auf den verbleibenden ** 20481 Songdaten ** </ u> tun.
Es ist so.
key
ist die erklärte Variable und rechts von key
die erklärende Variable. Beschriften Sie den Schlüssel mit einem Label und ändern Sie ihn in eine Zahl von 0 bis 23, um in das Modell des maschinellen Lernens einzutauchen. Andere werden so verwendet, wie sie sind.
Insgesamt gibt es 24 Arten von Schlüsseln, aber die Anzahl der Daten ist natürlich nicht gerade. Es gibt einen fast zehnfachen Unterschied zwischen den meisten Schlüsseln und den kleinsten Schlüsseln. Es ist nicht so viel wie sogenannte unausgeglichene Daten, aber es ist ein wenig besorgniserregend. Übrigens beträgt das Verhältnis von Dur-Tonart zu Moll-Tonart ** 149 55: 5526 **, und 73% ist Dur-Song </ u>. Wenn Sie sich die Grafik oben ansehen, sehen Sie, dass die Minderjährigen unten gruppiert sind.
Probieren Sie verschiedene Ansätze aus, um zu sehen, wie genau sie sind.
Die Bewertungsindikatoren für die Klassifizierung mehrerer Klassen werden auf den folgenden Seiten ausführlich beschrieben. https://analysis-navi.com/?p=553
Berechnen Sie die folgenden drei Werte und die richtige Antwortrate für jede Klasse.
Bei den Testdaten bereitet sklearns "train_test_split" 25% der Gesamtdaten vor (ca. 5000 Songs). Der Wert des 5-fachen Durchschnitts wird unter Berücksichtigung der Abweichung der Genauigkeit in Abhängigkeit von den Daten berechnet. Überprüfen Sie als weitere Testdaten die korrekte Antwortrate mit 90 Flumpool-Songs, die auf U-fret veröffentlicht sind. Das liegt daran, dass ich Flumpool mag und die Tasten aller Songs kenne. Im Folgenden werden diese Daten als fp-Daten bezeichnet.
Da es lange dauern wird, werde ich zuerst die Ergebnisse zusammenfassen.
Index | Regelbasis 1 | Regelbasis 2 | Logistische Rückgabe | Unterstützung Vektormaschine | LightGBM | LGBM × LGBM |
---|---|---|---|---|---|---|
Richtige Antwortrate | 0.528 | 0.613 | 0.843 | 0.854 | 0.857 | 0.839 |
Makrorückruf | 0.566 | 0.626 | 0.836 | 0.832 | 0.836 | 0.826 |
Makro F1 Punktzahl | 0.567 | 0.581 | 0.82 | 0.827 | 0.833 | 0.812 |
fp Daten korrekte Antwortrate | 0.178 | 0.611 | 0.889 | 0.889 | 0.911 | 0.867 |
LightGBM ist das genaueste!
Zum Zeitpunkt der Entwicklung habe ich maschinelles Lernen verwendet, weil meine Motivation lautete: "Ich möchte vorerst etwas mit maschinellem Lernen anfangen!", Aber es kann ein Problem sein, das in erster Linie auf Regelbasis gelöst werden kann. Versuchen Sie die folgenden zwei. 1-1. [Der am häufigsten verwendete Akkord im Lied (im Folgenden als der am häufigsten verwendete Akkord bezeichnet) wird als Tonart verwendet](## 1-1. Der am häufigsten verwendete Akkord wird als Tonart verwendet) 1-2. [Berechnen Sie die Gesamtzahl der diatonischen Codes für jede Taste und geben Sie die beliebteste Taste aus](## 1-2. Berechnen Sie die Gesamtzahl der diatonischen Codes für jede Taste)
Angenommen, der am häufigsten verwendete Akkord im Song ist die Tonart. Wenn beispielsweise "Dm" in einem Song am häufigsten verwendet wird, wird die Tonart dieses Songs als Dm identifiziert. Es ist einfach. Wenn es mehrere häufigste Codes gibt, werde ich den Schlüssel zufällig bestimmen.
import random
def mode_pred(data):
#Suchen Sie den häufigsten Code und speichern Sie den Codenamen
tmp_max = -1
for c in num_cols:
if tmp_max < data[c]:
ans = [c]
tmp_max = data[c]
elif tmp_max == data[c]:
ans.append(c)
#Wenn es mehrere häufigste Codes gibt, wählen Sie sie zufällig aus
if len(ans) == 1:
return ans[0]
else:
return random.choice(ans)
df['mode_pred'] = df.apply(mode_pred, axis=1)
5 mal Durchschnitt Richtige Antwortrate: 0,528 Makrorückruf: 0,556 Makro F1 Punktzahl: 0,567
fp Daten Richtige Antwortrate: 0,178
Schlüssel | Richtige Antwortrate (Rückrufrate) |
---|---|
C_minor | 0.763 |
F_minor | 0.747 |
G_minor | 0.699 |
D_minor | 0.684 |
B_minor | 0.681 |
A_minor | 0.676 |
D#/E♭_minor | 0.668 |
C#/D♭_minor | 0.663 |
E_minor | 0.663 |
A#/B♭_minor | 0.654 |
F#/G♭_minor | 0.641 |
G#/A♭_minor | 0.611 |
E_Major | 0.522 |
G_Major | 0.504 |
A_Major | 0.496 |
A#/B♭_Major | 0.494 |
D_Major | 0.485 |
C_Major | 0.483 |
F_Major | 0.433 |
F#/G♭_Major | 0.425 |
B_Major | 0.412 |
C#/D♭_Major | 0.408 |
D#/E♭_Major | 0.402 |
G#/A♭_Major | 0.379 |
Wenn wir uns jede Klasse ansehen, sehen wir, dass der Prozentsatz der richtigen Antworten in Moll höher ist als der in Dur. Wenn Sie es mit Ihrem eigenen Domain-Wissen vergleichen, können Sie es irgendwie verstehen. Die fp-Daten sind nutzlos, nicht wahr? .. .. Dies liegt wahrscheinlich daran, dass es viele Hauptlieder gibt.
Wie ich in Vorheriger Artikel geschrieben habe, wenn ich die Tonart aus dem Akkorddiagramm bestimme Wenn man sich den verwendeten Code ansieht, wird festgestellt, dass "es dieser Schlüssel ist, weil der diatonische Code dieses Schlüssels häufig verwendet wird". Lassen Sie uns diese Methode implementieren. Insbesondere ist der Fluss wie folgt.
Da die for-Anweisung in jeder Zeile 24 Mal (die Anzahl der Tasten) gedreht wird, nimmt der Vorgang viel Zeit in Anspruch. Insgesamt dauerte es ungefähr 20 Minuten, um den Durchschnitt von 5 Mal zu berechnen. .. ..
def diatonic_pred(data):
tmp_max = -1
#Ermitteln Sie die Gesamtzahl der Vorkommen des diatonischen Codes für jede Taste
for key, cols in diatonic_dict.items():
sum_value = data[cols].sum()
if tmp_max < sum_value:
ans = [key]
tmp_max = sum_value
elif tmp_max == sum_value:
ans.append(key)
#Diskriminierung
if len(ans) == 1:
return ans[0]
else:
return random.choice(ans)
tqdm_notebook.pandas()
df['diatonic_pred'] = df.progress_apply(diatonic_pred, axis=1)
5 mal Durchschnitt Richtige Antwortrate: 0,613 Durchschnittliche korrekte Antwortrate für jede Klasse: 0,626 F-Wert: 0,581
fp Daten Richtige Antwortrate: 0,611
Schlüssel | Richtige Antwortrate (Rückrufrate) |
---|---|
F_minor | 0.711 |
G_minor | 0.702 |
C_minor | 0.688 |
A#/B♭_minor | 0.688 |
A_minor | 0.67 |
D_minor | 0.667 |
G_Major | 0.651 |
F#/G♭_minor | 0.649 |
B_minor | 0.649 |
E_minor | 0.633 |
C#/D♭_minor | 0.632 |
G#/A♭_minor | 0.615 |
F_Major | 0.614 |
G#/A♭_Major | 0.614 |
A#/B♭_Major | 0.61 |
B_Major | 0.61 |
D#/E♭_Major | 0.607 |
F#/G♭_Major | 0.604 |
E_Major | 0.596 |
D_Major | 0.586 |
D#/E♭_minor | 0.579 |
A_Major | 0.572 |
C_Major | 0.566 |
C#/D♭_Major | 0.504 |
Die durchschnittliche Genauigkeit ist höher als die Unterscheidung durch den häufigsten Code. Der Maximalwert der korrekten Antwortrate beträgt ungefähr 70%, was für beide Methoden ungefähr gleich ist, aber es gibt einen beträchtlichen Unterschied im Minimalwert. Die niedrigste korrekte Antwortrate für den häufigsten Code betrug 38%, diese Methode beträgt jedoch 50%. Auch nach wie vor ist die Klassifizierungsgenauigkeit von Liedern in Moll hoch.
Schauen wir uns hier die Verwirrungsmatrix an. Seltsamerweise gibt es einige Schlüssel, die für jeden Schlüssel um etwa 20% falsch klassifiziert sind. Dies ist parallel, was ein Schlüssel mit fast demselben Code ist. Da diese Unterscheidungsmethode die Häufigkeit verwendet, mit der der Code verwendet wurde, ist es meines Erachtens ein natürliches Ergebnis, ihn als Parallelschlüssel falsch zu klassifizieren.
Die korrekte Antwortrate für fp-Daten hat sich im Vergleich zum vorherigen Zeitpunkt erheblich erhöht, liegt jedoch bei etwa 60%. Ich habe mir die Fehlklassifizierungsdaten angesehen, aber die meisten wurden parallel falsch klassifiziert. Es stellt sich heraus, dass diese Methode für die Klassifizierung paralleler Töne nicht funktioniert.
Nachdem Sie die regelbasierte Genauigkeit kennen, ist es Zeit, maschinelles Lernen auszuprobieren. Ich werde auch hier einige Methoden ausprobieren. 2-1. [Als 24-Klassen-Klassifikation diskriminieren](## 2-1.24 Klassenklassifikation) 2-2. [Verwenden Sie Domänenwissen, um das Problemdesign zu ändern](## 2-2. Verwenden Sie Domänenwissen, um das Problemdesign zu ändern)
Behandeln Sie es als ein 24-Klassen-Klassifizierungsproblem. Die Methode ist ** logistische Regression ** als Vertreter des klassischen linearen Trennungsalgorithmus, ** Support Vector Machine ** als Vertreter des nichtlinearen Trennungsalgorithmus und ist die stärkste in Bezug auf hohe Genauigkeit, hohe Lerngeschwindigkeit und geringe Vorverarbeitung. Verwenden Sie das hochkarätige ** LightGBM **. Ich möchte die Methoden vergleichen, daher verzichte ich auf auffällige Parameteranpassungen.
Teilen Sie die Daten mit train_test_split
und tauchen Sie sie so wie sie sind in das Modell ein.
Die Hyperparameter werden nicht angepasst, aber auf "class_weight = balance" gesetzt. Auf diese Weise wird es mit "Anzahl der Stichproben der entsprechenden Klasse / (Anzahl der Klassen * Gesamtzahl der Stichproben)" gewichtet.
Vorerst habe ich versucht, mit den Parametern des Regularisierungsbegriffs zu spielen, aber da es keinen großen Unterschied gab, trainiere ich standardmäßig.
for seed in [1, 4, 9, 16, 25]:
X_train, X_test, y_train, y_test = train_test_split(df[num_cols], df['target_key'], random_state=seed)
lr = LogisticRegression(class_weight='balanced')
lr.fit(X_train, y_train)
y_pred = lr.predict(X_test)
Als Test habe ich die Kernelfunktion mit der rbf-Kernel-Eins-zu-Anderen-Klassifizierungsmethode trainiert. Das Lernen dauerte jedoch fast eine Stunde, und die Genauigkeit betrug im Durchschnitt etwa 30%, was ein enttäuschendes Ergebnis war. Da es für Support-Vektor-Maschinen besser ist, Variablen zu standardisieren, haben wir beschlossen, die Genauigkeit mit "Standardisierung von Variablen + RBF-Kernel + 1 im Vergleich zu anderen Klassifizierungsmethoden" zu messen. Durch die Standardisierung wurde die Ausführungszeit um eine Größenordnung schneller und ich war beeindruckt. Ein Lernvorgang dauert jedoch etwa 2-3 Minuten, sodass die Ausführungszeit langsamer ist als die beiden anderen.
from sklearn.svm import SVC
from sklearn.multiclass import OneVsRestClassifier
from sklearn.preprocessing import StandardScaler
#1 gegen andere Klassifizierung
svc = SVC(kernel='rbf', class_weight='balanced', verbose=True)
ovr = OneVsRestClassifier(svc)
#Standardisierung
sc = StandardScaler()
for seed in [1, 4, 9, 16, 25]:
X_train, X_test, y_train, y_test = train_test_split(sc.fit_transform(X), y, random_state=seed)
ovr.fit(X_train, y_train)
y_pred = ovr.predict(X_test)
LightGBM Ich habe es mit den Standardparametern ausgeführt.
import lightgbm as lgbm
for seed in [1, 4, 9, 16, 25]:
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=seed)
clf = lgbm.LGBMClassifier(class_weight='balanced')
clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)
Logistische Rückgabe | Unterstützung Vektormaschine | LightGBM | |
---|---|---|---|
Richtige Antwortrate | 0.843 | 0.854 | 0.857 |
Makrorückruf | 0.836 | 0.832 | 0.836 |
Makro F1 Punktzahl | 0.820 | 0.827 | 0.833 |
Obwohl es keinen großen Unterschied in der Genauigkeit gibt, ist das Ergebnis, dass LightGBM am genauesten ist. Unter dem Gesichtspunkt der Ausführungszeit war es jedoch wie "LightGBM >> Logistische Regression >>> Support Vector Machine". Die für 5 Lernvorgänge erforderliche Zeit betrug für LightGBM weniger als 1 Minute, während sie für die Support-Vektor-Maschine etwa 10 Minuten dauerte. Es braucht Zeit, um einmal zu lernen, daher habe ich das Gefühl, dass ich die Parameter nicht einfach anpassen kann.
Schauen wir uns als nächstes den Prozentsatz der richtigen Antworten für jede Klasse an.
Schlüssel | Logistische Rückgabe | Unterstützung Vektormaschine | LightGBM |
---|---|---|---|
C_Major | 0.838 | 0.866 | 0.856 |
C_minor | 0.883 | 0.885 | 0.837 |
C#/D♭_Major | 0.825 | 0.859 | 0.878 |
C#/D♭_minor | 0.809 | 0.748 | 0.755 |
D_Major | 0.84 | 0.875 | 0.871 |
D_minor | 0.851 | 0.814 | 0.827 |
D#/E♭_Major | 0.841 | 0.842 | 0.869 |
D#/E♭_minor | 0.808 | 0.782 | 0.761 |
E_Major | 0.871 | 0.897 | 0.9 |
E_minor | 0.844 | 0.84 | 0.842 |
F_Major | 0.851 | 0.857 | 0.87 |
F_minor | 0.881 | 0.827 | 0.836 |
F#/G♭_Major | 0.805 | 0.828 | 0.847 |
F#/G♭_minor | 0.793 | 0.751 | 0.791 |
G_Major | 0.857 | 0.872 | 0.872 |
G_minor | 0.861 | 0.849 | 0.832 |
G#/A♭_Major | 0.86 | 0.865 | 0.866 |
G#/A♭_minor | 0.773 | 0.704 | 0.725 |
A_Major | 0.849 | 0.874 | 0.887 |
A_minor | 0.826 | 0.83 | 0.833 |
A#/B♭_Major | 0.822 | 0.853 | 0.867 |
A#/B♭_minor | 0.823 | 0.796 | 0.777 |
B_Major | 0.815 | 0.847 | 0.855 |
B_minor | 0.847 | 0.815 | 0.804 |
Es ist ersichtlich, dass die logistische Regression einen höheren Prozentsatz an korrekten Antworten für Nebenschlüssel aufweist als die beiden anderen.
Als nächstes zeichnen wir die richtige Antwortrate für jeden Schlüssel mit jeder Methode unter Verwendung eines Box-Whisker-Diagramms.
Die minimale korrekte Antwortrate für alle Methoden beträgt 70% oder höher. Es kann jedoch gelesen werden, dass die Variation (Bereich) der Genauigkeit der logistischen Regression kleiner ist als die anderer Methoden. LightGBM war in jedem Index die Spitze, aber Sie können sehen, dass der Bereich ziemlich ungleichmäßig ist.
Übrigens hatten alle Methoden in Bezug auf die korrekte Antwortrate von fp-Daten eine korrekte Antwortrate von etwa 80/90 Songs. Die meisten Fehler waren parallel (andere waren transponierte Songs usw.).
Um diesmal den Schlüssel zu bestimmen, werden wir das Problemdesign unter Verwendung von Domänenwissen ändern.
Es gibt 24 Arten von Schlüsseln, die Sie unterscheiden möchten, aber nicht alle 24 Typen haben völlig unterschiedliche Eigenschaften. Für jede Taste gibt es nur eine Taste mit ähnlichen Eigenschaften (insbesondere dieselbe Melodie und ähnliche verwendete Klänge und Akkorde). Dies wird als [parallel] bezeichnet (https://music-school-theory.com/menukey/parallelkey/). Zum Beispiel ist die parallele Tonart von C (C-Dur) Am (h-Moll). Es gibt immer eine Entsprechung zwischen Dur und Moll. Schauen wir uns das Akkorddiagramm an.
Wie wär es damit? Der verwendete Code ist ziemlich ähnlich, nicht wahr? Von den 24 Schlüsseltypen gibt es 12 Arten solcher Tastenkombinationen.
Auf der Grundlage des Vorstehenden wird das Urteil wie folgt gefällt.
Es ist schwer zu verstehen, wenn Sie ein Beispiel geben
Das Bild ist, dass die Unterscheidung in zwei Teile wie diesen unterteilt ist. Beide Modelle verwenden LightGBM.
model_1 = lgbm.LGBMClassifier(class_weight='balanced')
model_2 = lgbm.LGBMClassifier(class_weight='balanced')
key_answer = df['key']
diatonic_answer = df['diatonic_type']
type_answer = df['key_type']
X = df[num_cols]
y1 = df['diatonic_type_int']
for seed in [1, 4, 9, 16, 25]:
#12 Klassenklassifikation (parallele Klassifikation)
X_train, X_test, y1_train, y1_test = train_test_split(X, y1, random_state=seed)
model_1.fit(X_train, y1_train)
y1_pred = model_1.predict(X_test)
#Zeichenkette (C._Major@A_Rückkehr zum Moll)
y1_pred_str = le_d.inverse_transform(y1_pred)
#Binäre Klassifizierung mit denselben Daten (Haupt- oder Nebenfach)
train_index = y1_train.index
test_index = y1_test.index
y2_train = type_answer[train_index]
y2_test = type_answer[test_index]
model_2.fit(X_train, y2_train)
y2_pred = model_2.predict(X_test)
#Integrieren Sie die Ergebnisse der 12-Klassen-Klassifizierung und der binären Klassifizierung
y_pred = []
for y1_, y2_ in zip(y1_pred_str, y2_pred):
if y2_ == 1:
ans = y1_.split('@')[0]
else:
ans = y1_.split('@')[1]
y_pred.append(ans)
y_test = key_answer[test_index]
5 mal Durchschnitt Richtige Antwortrate: 0,839 Makrorückruf: 0,826 Makro F1 Punktzahl: 0,812
fp Daten Richtige Antwortrate: 0,867
Schlüssel | Richtige Antwortrate (Rückrufrate) |
---|---|
C_Major | 0.848 |
C_minor | 0.843 |
C#/D♭_Major | 0.858 |
C#/D♭_minor | 0.853 |
D_Major | 0.83 |
D_minor | 0.825 |
D#/E♭_Major | 0.84 |
D#/E♭_minor | 0.836 |
E_Major | 0.82 |
E_minor | 0.815 |
F_Major | 0.797 |
F_minor | 0.787 |
F#/G♭_Major | 0.811 |
F#/G♭_minor | 0.803 |
G_Major | 0.746 |
G_minor | 0.686 |
G#/A♭_Major | 0.775 |
G#/A♭_minor | 0.764 |
A_Major | 0.884 |
A_minor | 0.875 |
A#/B♭_Major | 0.909 |
A#/B♭_minor | 0.89 |
B_Major | 0.869 |
B_minor | 0.864 |
Das Ergebnis des 5-fachen Durchschnitts ist etwas niedriger als das Ergebnis von LightGBM mit 24 Klassifizierungen. Die Vorhersagegenauigkeit der ersten Stufe (12 parallel zusammengefasste Klassenklassifikationen) war mit etwa 93% gut, aber die insgesamt korrekte Antwortrate hat in der zweiten Stufe in Dur oder Moll abgenommen. Bei den fp-Daten war die Fehlklassifizierung des parallelen Tons für die meisten Daten verantwortlich. Es gab jedoch einige Songs, bei denen ich in der 24-Klassen-Klassifizierung nicht viele Fehler gemacht habe.
Ich habe verschiedene Dinge ausprobiert, aber das Ergebnis war, dass es besser war, es gehorsam mit LightGBM als 24-Klassen-Klassifizierung vorherzusagen. Immerhin ist Light GBM unglaublich. Bei LightGBM geht es nicht nur um Genauigkeit. ** Die Lerngeschwindigkeit ist ohne Probleme schnell **. Daher halte ich es für einen großen Vorteil, dass die Anzahl der Versuche im Vergleich zu anderen Modellen wie der Parameteranpassung erhöht werden kann.
Es ist nicht so, dass andere Methoden als LightGBM schlecht sind. In Regelbasis 1 ist beispielsweise der Prozentsatz der richtigen Antworten in Moll hoch, und es wurde festgestellt, dass der häufigste Code für die Klassifizierung von Moll nützlich ist. Regelbasis 2 bestätigte die Gültigkeit meiner Hypothese. Bei der logistischen Regression wurde festgestellt, dass die Variation der richtigen Antwortrate für jede Klasse gering war. Auf dem Support-Vektor-Computer ist noch Platz für die Parametereinstellung, sodass sich die richtige Antwortrate je nach Einstellung erhöhen kann. Die letzte zweistufige Vorhersage mit einem anderen Problemdesign kann je nach Modell und Parametern zu guten Ergebnissen führen.
Gegenwärtig werde ich LightGBM verwenden, das leicht eine hohe Genauigkeit erzeugen kann, aber ich werde mir Zeit nehmen, um die Parameter anzupassen. Zu diesem Zeitpunkt werde ich den Artikel erneut schreiben. Es war ein kindischer Satz, aber danke, dass Sie ihn gelesen haben.
Recommended Posts