Cet article est une série. Cliquez ici pour d'autres articles ↓ 0. Design (Qu'est-ce que l'IA pour déterminer la clé?) 1. Collecte de données (exploration) 2. Mise en forme des données (grattage) 4. Développement d'applications Web à l'aide de Django
Cela fait 3-4 mois depuis le développement. Au moment du développement, l'objectif était de déployer, et je n'ai pas passé beaucoup de temps à choisir le modèle essentiel.
Alors cette fois, j'aimerais essayer différentes approches et comparer la précision. J'essaierai également de trouver une précision basée sur des règles sans utiliser l'apprentissage automatique.
La tâche cette fois est de déterminer la tonalité à partir de la progression d'accords de la chanson. Progression du code? Clé? Veuillez consulter l'article ci-dessous pour plus d'informations.
J'ai gratté le nombre de fois où les accords sont apparus et la clé du site de publication de tableaux d'accords appelé J-Total Music. Parmi les chansons affichées, il y a des données pour les chansons (20848 chansons) pour lesquelles la clé pourrait être obtenue.
Cependant, certaines chansons ont peu de codes. Exemple: https://music.j-total.net/data/012si/071_shinohara_tomoe/001.html Étant donné que ces morceaux ne conviennent pas aux données d'entraînement, les données avec un nombre total d'accords apparaissant 20 fois ou moins dans le morceau seront supprimées. En outre, en tant que suppression des valeurs aberrantes, les données avec un nombre total d'accords apparaissant dans la chanson de 250 ou plus sont également supprimées. Dans ce qui suit, nous ferons diverses choses en fonction des ** 20481 données de morceau ** </ u> restantes.
C'est comme ça. «key» est la variable expliquée et à droite de «key» la variable explicative. Pour plonger dans le modèle de machine learning, encodez en libellé la clé et changez-la de 0 à 23. D'autres sont utilisés tels quels.
Il existe 24 types de clés en tout, mais bien sûr, le nombre de données n'est pas pair. Il y a une différence de près de 10 fois entre le plus de touches et le moins de touches. Ce n'est pas autant que des données dites déséquilibrées, mais c'est un peu inquiétant. À propos, le rapport entre la touche majeure et la touche mineure est de ** 149 55: 5526 **, et 73% est la chanson principale </ u>. Si vous regardez le graphique ci-dessus, vous pouvez voir que les mineurs sont regroupés en bas.
Essayez différentes approches pour voir à quel point elles sont précises.
Les indicateurs d'évaluation pour la classification multi-classes sont décrits en détail dans les pages suivantes. https://analysis-navi.com/?p=553
Calculez les trois valeurs suivantes et le taux de réponse correct pour chaque classe.
En ce qui concerne les données de test, «train_test_split» de sklearn prépare 25% du total des données (environ 5000 chansons). La valeur de la moyenne de 5 fois est calculée en tenant compte de la variation de précision en fonction des données. Aussi, comme autre donnée de test, vérifiez le taux de réponse correct avec 90 chansons de flumpool postées sur U-fret. C'est parce que j'aime flumpool et que je connais les clés de toutes les chansons. Ci-après, ces données sont appelées données fp.
Comme ce sera long, je vais d'abord résumer les résultats.
indice | Base de règles 1 | Base de règles 2 | Retour logistique | Machine de vecteur de soutien | LightGBM | LGBM × LGBM |
---|---|---|---|---|---|---|
Taux de réponse correct | 0.528 | 0.613 | 0.843 | 0.854 | 0.857 | 0.839 |
Rappel de macro | 0.566 | 0.626 | 0.836 | 0.832 | 0.836 | 0.826 |
Score Macro F1 | 0.567 | 0.581 | 0.82 | 0.827 | 0.833 | 0.812 |
Taux de réponse correct des données fp | 0.178 | 0.611 | 0.889 | 0.889 | 0.911 | 0.867 |
LightGBM est le plus précis!
Au moment du développement, j'utilisais l'apprentissage automatique parce que ma motivation était "Je veux faire quelque chose avec l'apprentissage automatique pour le moment!", Mais c'est peut-être un problème qui peut être résolu sur une base de règles en premier lieu. Essayez les deux suivants. 1-1. [L'accord le plus fréquemment utilisé dans le morceau (ci-après désigné comme l'accord le plus fréquemment utilisé) est utilisé comme tonalité](## 1-1. L'accord le plus fréquemment utilisé est utilisé comme tonalité) 1-2. [Calculez le nombre total de codes diatoniques pour chaque touche et sortez la clé la plus populaire](## 1-2. Calculez le nombre total de codes diatoniques pour chaque touche)
Disons que l'accord le plus utilisé dans la chanson est la clé. Par exemple, si "Dm" est utilisé le plus souvent dans un morceau, la clé de ce morceau est identifiée comme Dm. C'est simple. S'il y a plusieurs codes les plus fréquents, je déciderai de la clé au hasard.
<détails> 5 fois la moyenne
Taux de réponse correcte: 0,528
Rappel de macro: 0,556
Score Macro F1: 0,567 données fp
Taux de réponse correcte: 0,178 <détails> En regardant chaque classe, nous pouvons voir que le pourcentage de bonnes réponses en mineur est supérieur à celui en majeur. Si vous le comparez avec votre propre connaissance du domaine, vous pouvez en quelque sorte le comprendre.
Les données fp sont inutiles, n'est-ce pas? .. .. C'est probablement parce qu'il y a beaucoup de chansons en major. Comme je l'ai écrit dans Article précédent, lorsque je détermine la clé à partir du tableau d'accords En regardant le code utilisé, il est déterminé que «c'est cette clé parce que le code diatonique de cette clé est souvent utilisé». Implémentons cette méthode. Plus précisément, le flux est le suivant. Étant donné que l'instruction for est tournée 24 fois (le nombre de touches) sur chaque ligne, le processus prend un temps considérable. Il a fallu environ 20 minutes au total pour calculer la moyenne de 5 fois. .. .. <détails> 5 fois la moyenne
Taux de réponse correcte: 0,613
Taux de réponses correctes moyen pour chaque classe: 0,626
Valeur F: 0,581 données fp
Taux de réponse correcte: 0,611 <détails> La précision moyenne est supérieure à la discrimination par le code le plus fréquent. La valeur maximale du taux de réponse correcte est d'environ 70%, ce qui est à peu près la même pour les deux méthodes, mais il existe une différence considérable dans la valeur minimale. Le taux de réponse correcte le plus bas pour le code le plus fréquent était de 38%, mais cette méthode est de 50%. De plus, comme auparavant, la précision de classification des chansons en mineur est élevée. Jetons un coup d'œil à la matrice de confusion ici.
Curieusement, certaines clés sont mal classées d'environ 20% pour chaque clé. Ceci est parallèle, qui est une clé avec presque le même code utilisé. Puisque cette méthode de discrimination utilise le nombre de fois où le code a été utilisé, je pense qu'il est naturel de le classer à tort comme une clé parallèle. Le taux de réponse correcte pour les données fp a considérablement augmenté par rapport à la fois précédente, mais il est d'environ 60%. J'ai examiné les données de classification erronée, mais la plupart d'entre elles ont été mal classées en parallèle. Il s'avère que cette méthode ne fonctionne pas pour la classification des tons parallèles. Maintenant que vous connaissez la précision basée sur des règles, il est temps d'essayer l'apprentissage automatique. J'essaierai ici aussi quelques méthodes.
2-1. [Discriminate as 24 class classification](## 2-1.24 Class classification)
2-2. [Utiliser la connaissance du domaine pour modifier la conception du problème](## 2-2. Utiliser la connaissance du domaine pour modifier la conception du problème) Il est traité comme un problème de classification de 24 classes avec obéissance. La méthode est la ** régression logistique ** en tant que représentant de l'algorithme de séparation linéaire classique, ** la machine vectorielle de support ** en tant que représentant de l'algorithme de séparation non linéaire, et est la plus puissante en termes de haute précision, de vitesse d'apprentissage élevée et de peu de prétraitement. Utilisez le ** LightGBM ** haut de gamme. Je veux comparer les méthodes, je m'abstiendrai donc d'ajuster les paramètres flashy. Divisez les données avec Pour le moment, j'ai essayé de jouer avec les paramètres du terme de régularisation, mais comme il n'y avait pas de grande différence, je m'entraîne par défaut.
<détails> En guise de test, j'ai entraîné la fonction du noyau avec le noyau rbf, méthode de classification one-to-other. Cependant, il a fallu près d'une heure pour apprendre et la précision était décevante, avec une moyenne d'environ 30%.
Puisqu'il est préférable pour les machines vectorielles de support de standardiser les variables, nous avons décidé de mesurer la précision avec <détails> LightGBM
Je l'ai exécuté avec les paramètres par défaut. <détails> Bien qu'il n'y ait pas de grande différence de précision, le résultat est que LightGBM est le plus précis.
Cependant, du point de vue du temps d'exécution, c'était comme Ensuite, regardons le pourcentage de réponses correctes pour chaque classe. <détails> On peut voir que la régression logistique a un pourcentage de réponses correctes plus élevé pour les clés mineures que les deux autres. Ensuite, traçons le taux de réponse correct pour chaque clé avec chaque méthode à l'aide d'un diagramme de moustaches. Le taux minimum de réponse correcte pour toutes les méthodes est de 70% ou plus. Cependant, on peut lire que la variation (gamme) de précision de la régression logistique est plus petite que celle des autres méthodes.
LightGBM était le meilleur de chaque index, mais vous pouvez voir que la plage est assez inégale. À propos, en ce qui concerne le taux de réponse correct des données fp, toutes les méthodes avaient un taux de réponse correcte d'environ 80/90 chansons. La plupart des erreurs étaient en parallèle (d'autres étaient des chansons transposées, etc.). Dans le but de "déterminer la clé" cette fois, nous modifierons la conception du problème en utilisant la connaissance du domaine. Il existe 24 types de touches que vous souhaitez distinguer, mais les 24 types n'ont pas tous des caractéristiques complètement différentes. Pour chaque touche, il n'y a qu'une seule touche avec des caractéristiques similaires (en particulier, la même mélodie et des sons et accords similaires utilisés). Cela s'appelle parallel.
Par exemple, la clé parallèle de do (do majeur) est Am (si mineur). Il y a toujours une correspondance entre majeur et mineur. Regardons en fait le tableau des accords. Et ça? Le code utilisé est assez similaire, n'est-ce pas? Parmi les 24 types de touches, il existe 12 types de telles combinaisons de touches. Sur la base de ce qui précède, le jugement est rendu comme suit. C'est difficile à comprendre, donc si vous donnez un exemple L'image est que la discrimination est divisée en deux parties comme celle-ci. Les deux modèles utilisent LightGBM. <détails> 5 fois la moyenne
Taux de réponse correcte: 0,839
Rappel de macro: 0,826
Note Macro F1: 0,812 données fp
Taux de réponse correcte: 0,867 Le résultat de la moyenne 5 fois est un peu inférieur au résultat de LightGBM avec 24 classifications.
La précision de prédiction de la première étape (12 classifications de classes résumées en parallèle) était bonne à environ 93%, mais le taux global de réponse correcte a diminué dans la deuxième étape en majeur ou mineur.
En ce qui concerne les données fp, la classification erronée de la tonalité parallèle représentait la plupart des données. Cependant, il y avait des chansons sur lesquelles je n'ai pas fait beaucoup d'erreurs dans le classement des 24 classes. J'ai essayé diverses choses, mais le résultat était qu'il valait mieux le prédire comme une classification de 24 classes docilement avec LightGBM. Après tout, Light GBM est incroyable.
LightGBM n'est pas qu'une question de précision. ** La vitesse d'apprentissage est rapide sans aucun problème **. Par conséquent, je pense que c'est un gros avantage que le nombre d'essais puisse être augmenté par rapport à d'autres modèles tels que l'ajustement des paramètres. Ce n'est pas que les méthodes autres que LightGBM soient mauvaises. Par exemple, la base de règles 1 a un pourcentage élevé de réponses correctes en mineur, et nous avons constaté que le code le plus fréquent est utile pour classer les mineurs. La règle de base 2 a confirmé la validité de mon hypothèse. Dans la régression logistique, il a été constaté que la variation du taux de réponse correcte pour chaque classe était faible. Il y a encore de la place pour le réglage des paramètres sur la machine à vecteurs de support, de sorte que le taux de réponse correct peut augmenter en fonction du réglage. La dernière prédiction en deux étapes avec une conception de problème différente peut donner de bons résultats selon le modèle et les paramètres. Donc, pour le moment, j'aimerais utiliser LightGBM, qui peut facilement produire une grande précision, mais je prendrai le temps d'ajuster les paramètres. À ce moment-là, j'écrirai à nouveau l'article.
C'était une phrase enfantine, mais merci de l'avoir lue.
Recommended Posts
import random
def mode_pred(data):
#Trouvez le code le plus fréquent et enregistrez le nom du code
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)
#S'il y a plusieurs codes les plus fréquents, sélectionnez-les au hasard
if len(ans) == 1:
return ans[0]
else:
return random.choice(ans)
df['mode_pred'] = df.apply(mode_pred, axis=1)
résultat
Clé
Taux de réponse correct (taux de rappel)
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
1-2. Calculez le nombre total de codes diatoniques pour chaque touche
def diatonic_pred(data):
tmp_max = -1
#Trouvez le nombre total d'occurrences du code diatonique pour chaque touche
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)
#La discrimination
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)
résultat
Clé
Taux de réponse correct (taux de rappel)
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
2. Classification par apprentissage automatique
Classement 2-1. 24
train_test_split
et plongez-les dans le modèle tel quel.
Il n'ajuste pas les hyper paramètres, mais il est défini sur class_weight = balancé
. En faisant cela, il sera pondéré par «nombre d'échantillons de la classe correspondante / (nombre de classes * nombre total d'échantillons)».Retour logistique
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)
Machine de vecteur de soutien
la standardisation des variables + noyau rbf + 1 par rapport à une autre méthode de classification
. En normalisant, le temps d'exécution est devenu des ordres de grandeur plus rapides, et j'ai été impressionné. Cependant, un apprentissage prend environ 2-3 minutes, donc le temps d'exécution est plus lent que les deux autres.from sklearn.svm import SVC
from sklearn.multiclass import OneVsRestClassifier
from sklearn.preprocessing import StandardScaler
#1 vs autre classification
svc = SVC(kernel='rbf', class_weight='balanced', verbose=True)
ovr = OneVsRestClassifier(svc)
#Standardisation
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)
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)
résultat
Retour logistique
Machine de vecteur de soutien
LightGBM
Taux de réponse correct
0.843
0.854
0.857
Rappel de macro
0.836
0.832
0.836
Score Macro F1
0.820
0.827
0.833
LightGBM >> Régression logistique >>> Support vector machine
. Le temps requis pour 5 apprentissages était inférieur à 1 minute pour LightGBM, alors qu'il a fallu environ 10 minutes pour la machine vectorielle de support. Il faut du temps pour apprendre une fois, donc je sens que je ne peux pas facilement ajuster les paramètres.
Clé
Retour logistique
Machine de vecteur de soutien
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
2-2. Modifier la conception du problème en utilisant la connaissance du domaine
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]:
#Classification en 12 classes (classification parallèle)
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)
#Chaîne de caractères (C_Major@A_retour au mineur)
y1_pred_str = le_d.inverse_transform(y1_pred)
#Classification binaire avec les mêmes données (majeures ou mineures)
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)
#Intégrer les résultats de la classification en 12 classes et de la classification binaire
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]
résultat
Taux de réponse correct pour chaque classe summary>
Clé
Taux de réponse correct (taux de rappel)
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
Résumé