Dies ist die Serie "Yugio DS (Data Science)", die verschiedene Yugioh-Kartendaten mit Python analysiert. Der Artikel wird insgesamt viermal gehalten, und schließlich werden wir ein Programm implementieren, das offensive und defensive Attribute aus dem Kartennamen durch Verarbeitung natürlicher Sprache + maschinelles Lernen vorhersagt. Darüber hinaus hat das Wissen des Autors über Yugioh bei etwa E ・ HERO aufgehört. Es tut mir leid, dass sowohl Karten als auch Data Science Amateure sind, aber bitte bleiben Sie in Kontakt.
No. | Artikelüberschrift | Keyword | |
---|---|---|---|
0 | Holen Sie sich Karteninformationen aus der Yugioh-Datenbank-Yugioh DS 0.Schaben | beautifulsoup | |
1 | Visualisieren Sie Yugioh-Kartendaten mit Python-Yugioh Data Science 1.EDA-Ausgabe | pandas, seaborn | |
2 | Verarbeiten Sie den Namen der Yugioh-Karte in natürlicher Sprache-Yugioh Data Science 2.NLP-Ausgabe | wordcloud, word2vec, doc2vec, t-SNE | Dieser Beitrag! |
3 | Sagen Sie offensive und defensive Attribute anhand des Yugioh-Kartennamens voraus-Yugioh Data Science 3.Maschinelles Lernen | lightgbm etc. |
In Vorheriger Artikel ist der Vektor, der durch Konvertieren des Kartennamens mit Doc2Vec erhalten wird, der Funktionsbetrag und andere Elemente der Karte (Angriffskraft, Verteidigungskraft, Attribut, Rasse, Stufe). ) Wird als Label verwendet und ein Modell implementiert, das durch maschinelles Lernen offensive und defensive Attribute aus dem Kartennamen vorhersagt. Darüber hinaus führen wir unter Verwendung des erlernten Modells eine Vorhersageaufgabe aus, die dem entsprechenden ursprünglichen Kartennamen offensive und defensive Attribute verleiht. Ich möchte überprüfen, wie stark das ursprüngliche Monster, an das ich dachte, im Lichte des maschinellen Lernens beurteilt wurde.
Python==3.7.4
In diesem Artikel wird handgefertigter Code aus Yugio OCG Card Database als Originaldaten verwendet. .. Es ist spätestens ab Juni 2020. Außerdem wird angenommen, dass die Eingabedaten des maschinellen Lernens die Originaldaten sind, die von der NLP-Edition verarbeitet werden. 。
Wie oben erwähnt, wird diesmal nur der Kartenname (vektorisiert) als Merkmalsbetrag verwendet. Es gibt 5 Labels, Angriffskraft, Verteidigungskraft, Attribut, Rasse und Level. Bereiten Sie also auch 5 Modelle vor. Obwohl es sich um eine Art Modell handelt, wird Deep Learning aufgrund der Spezifikationen der verwendeten Maschine nicht verwendet. Verwenden Sie vorerst "LightGBM", das genaueste der Baumprobleme, das sowohl auf Klassifizierungs- als auch auf Regressionsprobleme angewendet werden kann. Stellen Sie vor der Implementierung das Problem jedes Modells (Regressionsmodell / Klassifizierungsmodell) ein und stellen Sie eine Hypothese mit guter Genauigkeit auf.
No. | Voraussichtliches Etikett | Problemstellung | Hypothese |
---|---|---|---|
1 | Attribut | Klassifizierung mehrerer Klassen | 例えばカード名に「天使」と入ってたら光Attributになるなどの傾向はありそうなので、まあまあ精度は高そう |
2 | Rennen | Klassifizierung mehrerer Klassen | No.1と同様。カード名に「ドラゴン」と入っているものはドラゴン族など、Rennenによってはかなり精度が高そう |
3 | Niveau | Klassifizierung mehrerer Klassen | シリーズ物のカードだと同じ単語が入っていてもNiveauがバラバラになったりするので精度は悪そう。また、ラベル自体のデータ数の偏りが影響しそう |
4 | Offensivkraft | Rückkehr | No.Die Genauigkeit scheint aus dem gleichen Grund wie 3 schlecht zu sein |
5 | Verteidigungskraft | Rückkehr | No.Die Genauigkeit scheint aus dem gleichen Grund wie 3 schlecht zu sein |
Importieren Sie die erforderlichen Pakete.
python
from sklearn.metrics import confusion_matrix, plot_confusion_matrix
from sklearn.metrics import mean_squared_error, r2_score
from gensim.models.doc2vec import Doc2Vec
from gensim.models.doc2vec import TaggedDocument
from sklearn.model_selection import train_test_split
import gensim
import lightgbm as lgb
import matplotlib.pyplot as plt
%matplotlib inline
import MeCab
import numpy as np
import pandas as pd
import pickle
import seaborn as sns
sns.set(font="IPAexGothic")
Importieren Sie die zu verwendenden Daten und das Doc2Vec-Modell, das den Kartennamen vektorisiert.
python
model_d2v = pickle.load(open('./input/model_d2v.pickle', 'rb'))
X = pickle.load(open('./input/X.pickle', 'rb'))
y = pickle.load(open('./input/y.pickle', 'rb'))
print("shape")
print("X: {}".format(X.shape))
print("y: {}".format(y.shape))
print("----------------")
print("data")
print("y: ")
print(y.head())
shape
X: (6206, 30)
y: (6206, 7)
----------------
data
y:
rarity attr level species attack defence kind
0 Seltenes Dunkelattribut 5 Vögel und Bestien 1500 2000 Synchro
1 Ultra Rare Darkness 7 Vögel und Bestien 2600 2000 Synchro
2 Ultra Rare Darkness 12 Vögel und Bestien 3000 2000 Synchro
3 Normale Dunkelheit 2 Vögel und Bestien 800 100 Synchro
4 Seltene Dunkelheit 5 Vögel und Bestien 2100 1600-
Das importierte "X" (Funktionsbetrag) und "y" (Etikett) werden wie folgt in Vorheriger Artikel gespeichert. Es ist eine Voraussetzung. Der Vorgang zum einfachen Speichern wird unten beschrieben.
python
#Datenrahmen-Monster, die eine Liste von Wörtern enthalten, die im Kartennamen enthalten sind_Erstellen Sie eine Wortliste
#Kürzung
#Erstellen Sie ein markiertes Dokument für das Doc2Vec-Modell
document = [TaggedDocument(words = wordlist, tags = [monsters_wordlist.name[i]]) for i, wordlist in enumerate(monsters_wordlist.wordlist)]
#Lernen des Doc2Vec-Modells
model_d2v = Doc2Vec(documents = document, dm = 0, vector_size=30, epochs=200)
#Vektorisieren Sie alle Kartennamen mit dem Doc2Vec-Modell
d2v_vecs = np.zeros((monsters_wordlist.name.shape[0],30))
for i, word in enumerate(monsters_wordlist.wordlist):
d2v_vecs[i] = model_d2v.infer_vector(word)
#Speichern Sie den vektorisierten Kartennamen als X und die für das Etikett verwendeten Daten als y
X = d2v_vecs
y = monsters_wordlist[["rarity", "attr", "level", "species", "attack", "defence"]]
#sparen
with open("./input/model_d2v.pickle", "wb") as f:
pickle.dump(model_d2v, f)
with open("./input/X.pickle", "wb") as f:
pickle.dump(X, f)
with open("./input/y.pickle", "wb") as f:
pickle.dump(y, f)
monsters_wordlist
ist der folgende Datenrahmen. Informationen zur Generierungsmethode finden Sie in Vorheriger Artikel.
Implementieren Sie ein Modell, das jedes der fünf Labels trainiert. Wenn Sie Hyperparameter einzeln schreiben oder durch Klassifizierung / Regression teilen, erhöht sich die Codemenge. Implementieren Sie zur Vereinfachung eine Funktion, die diese Prozesse umschließt. Ich werde auch ein wenig über "LightGBM" hinzufügen.
python
#Trainingsdaten / Testdaten in zwei Teile geteilt
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0, test_size=0.2)
#Schließen Sie den Prozess des Erstellens und Lernens eines Klassifizierungs- / Regressionsmodells für mehrere Klassen mit einer Funktion ab
def fit_model(column, mode='Classifier'):
if mode == 'Classifier':
model_lgb = lgb.LGBMClassifier(num_leaves=5,
learning_rate=0.05, n_estimators=720,
max_bin = 55, bagging_fraction = 0.8,
bagging_freq = 5, feature_fraction = 0.2319,
feature_fraction_seed=9, bagging_seed=9,
min_data_in_leaf =6, min_sum_hessian_in_leaf = 11, verbosity=-1)
model_lgb.fit(X_train, y_train[column], eval_set=[(X_test, y_test[column])], eval_metric='multi_logloss', early_stopping_rounds=10)
elif mode == 'Regressor':
model_lgb = lgb.LGBMRegressor(num_leaves=5,
learning_rate=0.05, n_estimators=720,
max_bin = 55, bagging_fraction = 0.8,
bagging_freq = 5, feature_fraction = 0.2319,
feature_fraction_seed=9, bagging_seed=9,
min_data_in_leaf =6, min_sum_hessian_in_leaf = 11, verbosity=-1)
model_lgb.fit(X_train, y_train[column], eval_set=[(X_test, y_test[column])], eval_metric='rmsle', early_stopping_rounds=10)
return model_lgb
#Erstellen Sie für jedes Etikett ein Modell
model_attr = fit_model("attr", mode="Classifier")
model_level = fit_model("level", mode="Classifier")
model_species = fit_model("species", mode="Classifier")
model_attack = fit_model("attack", mode="Regressor")
model_defence = fit_model("defence", mode="Regressor")
Wir werden die Richtigkeit der Lernergebnisse anhand der Testdaten überprüfen.
Überprüfen Sie als Bewertungsindex für die Überprüfung der Genauigkeit die korrekte Antwortrate (Genauigkeit) für Klassifizierungsfragen und den Entscheidungskoeffizienten (R2-Score) für Regressionsfragen.
python
def get_accuracy(column, model):
y_pred = model.predict(X_test)
accuracy = sum(y_test[column] == y_pred) / len(y_test)
return accuracy
def get_r2score(column, model):
y_pred = model.predict(X_test)
r2score = r2_score(y_test[column], y_pred)
return r2score
accuracy_attr = get_accuracy("attr", model_attr)
print("accuracy_attr: {}".format(accuracy_attr))
accuracy_species = get_accuracy("species", model_species)
print("accuracy_species: {}".format(accuracy_species))
accuracy_level = get_accuracy("level", model_level)
print("accuracy_level: {}".format(accuracy_level))
r2score_attack = get_r2score("attack", model_attack)
print("r2score_attack: {}".format(r2score_attack))
r2score_defence = get_r2score("defence", model_defence)
print("r2score_defence: {}".format(r2score_defence))
accuracy_attr: 0.5515297906602254
accuracy_species: 0.4669887278582931
accuracy_level: 0.3413848631239936
r2score_attack: 0.0804399379391485
r2score_defence: 0.04577024081390113
Überprüfen Sie zunächst die korrekte Antwortrate "Genauigkeit". In Anbetracht der korrekten Antwortrate des Modells, das eine völlig zufällige Bezeichnung ergibt, gibt es 7 Arten von Attributbezeichnungen ("attr"), also etwa ** 0,143 **, und 13 Arten von Ebenen ("Ebene") von 0 bis 12. ** 0,077 **, Es gibt 25 Rassen (Arten
), was ** 0,04 ** ist, also scheint das obige Modell so zu lernen, wie es ist. Auf der anderen Seite sind im Fall von Stufe 1925 von 6206 Zielkarten voreingenommene Daten, so dass es Stufe 4 ist. Selbst wenn alle Modelle als Stufe 4 beurteilt werden, beträgt die korrekte Antwortrate etwa ** 0,31 **. Ich werde. Dies ist ein Wert, der sehr nahe an der oben angegebenen korrekten Antwortrate liegt. Daher muss durch gründliches Graben bestätigt werden, ob es tatsächlich ein Modell gibt, das vorhersagt, dass alle Level 4 sind.
Als nächstes kommt der Entscheidungskoeffizient "R2 Score", der verstanden werden kann, je näher er an 1 liegt, desto höher ist die Analysegenauigkeit (die Streuung des Etiketts kann durch die Vorhersageformel durch die Merkmalsmenge erklärt werden). Da der Wert sowohl in der Offensiv- als auch in der Defensivkraft recht niedrig ist, kann gesagt werden, dass der Kartenname kaum Offensiv- und Defensivkraft darstellt (nicht relevant).
Um die Genauigkeit des Klassifizierungsproblems genauer zu sehen, zeichnen Sie eine Verwirrungsmatrix, die die Vorhersagen den ursprünglichen Werten zuordnet.
def make_cm(column, model, normalize="false"):
labels = y[column].unique()
y_pred = model.predict(X_test)
cm = confusion_matrix(y_test[column], y_pred, labels=labels, normalize=normalize)
cm_labeled = pd.DataFrame(cm, columns=labels, index=labels)
f, ax = plt.subplots(figsize = (20, 10))
ax = sns.heatmap(cm_labeled, annot=True, cmap="YlGnBu", fmt=".2f")
ax.set_ylabel("Actual")
ax.set_xlabel("Predicted")
ax.set_title("confusion_matrix: {}".format(column))
make_cm("attr", model_attr, "pred")
plt.savefig('./output/ml4-2-1.png', bbox_inches='tight', pad_inches=0)
make_cm("level", model_level, "pred")
plt.savefig('./output/ml4-2-2.png', bbox_inches='tight', pad_inches=0)
make_cm("level", model_level, "pred")
plt.savefig('./output/ml4-2-3.png', bbox_inches='tight', pad_inches=0)
Die Werte in der Verwirrungsmatrix werden normalisiert, um in Zeilenrichtung 1 zu ergeben. Mit anderen Worten, der Wert ist die Wahrscheinlichkeit, dass das, was als A vorhergesagt wurde, tatsächlich A war (= Präzisionsrate "Präzision"). Beispielsweise sind in der Darstellung des ersten Attributs etwa 58% der vorhergesagten dunklen Attribute tatsächlich dunkle Attribute.
Wenn wir uns die Attribute ansehen, können wir sehen, dass die Feuer- und Wasserattribute relativ genau vorhergesagt werden können, möglicherweise weil der Kartenname dazu neigt, solche Informationen direkt zu enthalten. Bei den Rassen ist auch die Kompatibilitätsrate von Reptilien und Dinosauriern hoch. Auf der anderen Seite kann verstanden werden, dass die Vorhersage des psychischen Stammes dazu neigt, fälschlicherweise vorhergesagt zu werden, selbst für das, was tatsächlich ein mechanischer Stamm war.
Auf den ersten Blick scheint es einige Labels zu geben, die den Pegel genau vorhersagen können. Um jedoch die Bedenken zu überprüfen (das Modell, das den Grad 4 vorhersagt, ist abgeschlossen), muss die Rückrufrate "Rückruf" überprüft werden. .. Der Rückruf ist ein Wert, der den Prozentsatz dessen angibt, was tatsächlich mit A gekennzeichnet ist und der korrekt als A vorhergesagt wird. Das Bild unten ist eine Verwirrungsmatrix, die den Rückruf durch Ändern der Level-Plot-Einstellungen zeigt. Es wurde jedoch auch bestätigt, dass für die meisten Level 4 vorhergesagt wurde.
Bisher haben wir verwirrende Indikatoren wie die richtige Antwortrate "Genauigkeit", die Präzisionsrate "Präzision", die Rückrufrate "Rückruf" erläutert. Einzelheiten finden Sie jedoch unter [Für Anfänger] Erläuterung der Bewertungsindikatoren für Klassifizierungsprobleme beim maschinellen Lernen (korrekte Antwortrate /) (Konformitätsrate, Rückrufrate usw.).
Implementieren Sie den Prozess der Vorhersage offensiver und defensiver Attribute für neue Kartennamen, die nicht im Datensatz enthalten sind. Der neu einzugebende Kartenname wird ebenfalls auf die gleiche Weise wie beim Lernen vorverarbeitet (vektorisiert) und durch Anwendung der Vorhersagemethode jedes Modells vorhergesagt. Die Vorverarbeitungsfunktion "get_vec ()" führt den Prozess der wortmorphologischen Analyse → Vektorisierung durch das doc2vec-Modell durch. Dies entspricht im Wesentlichen dem Vorgang zum Generieren von Feature X in der NLP-Edition.
python
#Funktion, die den Kartennamen vorverarbeitet
def get_vec(rawtext):
m = MeCab.Tagger ("-Ochasen -d /usr/local/lib/mecab/dic/mecab-ipadic-neologd/")
lines = []
text_list = rawtext.split("・")
for text in text_list:
keitaiso = []
m.parse('')
node = m.parseToNode(text)
while node:
#Fügen Sie die Morphologie in das Wörterbuch ein
tmp = {}
tmp['surface'] = node.surface
tmp['base'] = node.feature.split(',')[-3] #Prototyp(base)
tmp['pos'] = node.feature.split(',')[0] #Teil(pos)
tmp['pos1'] = node.feature.split(',')[1] #Neuklassifizierung von Teilwörtern(pos1)
#BOS repräsentiert den Anfang und das Ende eines Satzes/EOS weglassen
if 'BOS/EOS' not in tmp['pos']:
keitaiso.append(tmp)
node = node.next
lines.append(keitaiso)
#Speichern Sie das Oberflächensystem für die Nomenklatur und die Originalform für Verben / Adjektive in der Liste.
word_list = []
for line in lines:
for keitaiso in line:
if (keitaiso['pos'] == 'Substantiv'):
word_list.append(keitaiso['surface'])
elif (keitaiso['pos'] == 'Verb') | (keitaiso['pos'] == 'Adjektiv') :
if not keitaiso['base'] == '*' :
word_list.append(keitaiso['base'])
else:
word_list.append(keitaiso['surface'])
#Kommentar ausschließen, wenn Nomenklatur, Verben und Adjektive enthalten sind
# else:
# word_list.append(keitaiso['surface'])
model_d2v = pickle.load(open('./input/model_d2v.pickle', 'rb'))
vec = model_d2v.infer_vector(word_list).reshape(1,-1)
return vec
#Eine Funktion, die andere Informationen sofort aus dem Kartennamen vorhersagt
def predict_cardinfo(name):
vec=get_vec(name)
print("Attribut:{}".format(model_attr.predict(vec)[0]))
print("Niveau:{}".format(model_level.predict(vec)[0]))
print("Rennen:{}".format(model_species.predict(vec)[0]))
print("Offensivkraft:{}".format(model_attack.predict(vec)[0]))
print("Verteidigungskraft:{}".format(model_defence.predict(vec)[0]))
Lassen Sie uns tatsächlich verschiedene Kartennamen mit der Methode "Predict_cardinfo ()" vorhersagen.
** Blauäugiger weißer Drache **
python
predict_cardinfo("Blauäugiger weißer Drache")
Attribut: Lichtattribut
Level 4
Rasse: Drache
Angriffskraft: 1916.3930197124996
Verteidigungskraft: 1366.9371594605982
** Rotäugiger weißer Drache **
python
predict_cardinfo("Rotäugiger weißer Drache")
Attribut: Erdattribut
Level 4
Rasse: Krieger
Angriffskraft: 1168.203405707642
Verteidigungskraft: 1007.5706886946783
** Roter Magier **
python
predict_cardinfo("Roter Magier")
Attribut: Dunkles Attribut
Level 4
Rasse: Zauberer
Angriffskraft: 1884.3345074514568
Verteidigungskraft: 1733.53872077943
** Ultra Super Chaos Magier **
python
predict_cardinfo("Ultra Super Chaos Magier")
Attribut: Dunkles Attribut
Level 4
Rasse: Zauberer
Angriffskraft: 2129.5019817399634
Verteidigungskraft: 1623.7306977987516
Für Wörter wie "Drache" und "Magier" können wir "Drachenstamm" und "Hexenstamm" fast wie beabsichtigt vorhersagen. Die Offensiv- und Defensivkräfte werden in der Regel von den Daten von Monstern mit niedrigem Level gezogen und haben niedrige Werte. Trotzdem scheinen sie bei Verwendung starker Wörter wie "Chaos" tendenziell etwas zuzunehmen. Wie in der Verwirrungsmatrix bestätigt, wird für das Niveau fast Level 4 vorhergesagt. Diese Funktion kann auch beispiellose Namen vorhersagen, in denen Wörter verwendet werden. Ich denke, es wäre interessant, es dem Namen Pikachu oder anderen Spielen zu entnehmen.
Obwohl die Implementierung dieses Mal weggelassen wird, ist es zweckmäßig, "Optuna" zu verwenden, wenn eine Hyperparameter-Optimierung durchgeführt wird. Es scheint, dass "Optuna" die Sciki-Lernschnittstelle ab Juli 2020 nicht unterstützt, aber das Implementierungsbeispiel unter der Annahme der ursprünglichen Schnittstelle wird als Referenzbeispiel beschrieben.
import optuna.integration.lightgbm as lgb_o
def get_best_params(column, mode, metric):
y_obj = y[column]
X_trainval, X_test, y_trainval, y_test = train_test_split(X, y_obj, test_size=0.2)
X_train, X_valid, y_train, y_valid = train_test_split(X_trainval, y_trainval, test_size=0.1)
#In einen Datensatz für LightGBM konvertieren
train = lgb_o.Dataset(X_train, y_train)
val = lgb_o.Dataset(X_valid, y_valid)
#Hyperparametersuche&Modellbau
if mode == "regression":
params = {'objective': '{}'.format(mode),
'metric': '{}'.format(metric),
'random_seed':0}
elif mode == "multiclass":
params = {'objective': '{}'.format(mode),
'metric': '{}'.format(metric),
'num_class': len(y_obj.unique()),
'random_seed':0}
model_o = lgb_o.train(params,
train,
valid_sets=val,
early_stopping_rounds=10,
verbose_eval=False)
y_trainval_pred = model_o.predict(X_trainval,num_iteration=gbm_o.best_iteration)
y_test_pred = model_o.predict(X_test,num_iteration=gbm_o.best_iteration)
best_params = model_o.params
return best_params
best_params_attack = get_best_params("attack", "regression", "rmse")
Wir haben ein Modell implementiert, das Attribute, Rasse, Level, Offensivkraft und Defensivkraft anhand des Kartennamens von Yugioh vorhersagt. Insbesondere für Attribute und Rennen konnten wir die Vorhersagegenauigkeit wie erwartet bestätigen. Für Todo ist das Umschließen mit maschinellen Lernfunktionen etwas rau, daher besteht die beste Vorgehensweise bei der Pipeline-Konvertierung darin, mit dem Lernen fortzufahren. Wenn Sie zu einem Wettbewerb wie kaggle gehen, sollten Sie die Genauigkeitsbewertung meiner Meinung nach sorgfältiger durchführen. Als weitere Richtung erscheint es interessant, eine Webanwendung mit Django usw. zu erstellen und zu veröffentlichen.
Die Implementierung als Data Science wird die letzte in diesem Artikel sein, aber wenn ich Zeit habe, kann ich einen Artikel über 0 veröffentlichen. Scraping. Daten-Scraping ist ein problematisches Thema, daher werde ich nicht den vollständigen Code bereitstellen, sondern nur die Implementierungstipps.
Recommended Posts