[PYTHON] Ich habe versucht, Pferderennen vorherzusagen, indem ich alles von der Datenerfassung bis zum tiefen Lernen getan habe

Überblick

Ich bin ein Student mit Schwerpunkt Informationssysteme an einer bestimmten T-Universität. Als ich mir verschiedene Artikel über Qiita angesehen habe, habe ich diesen Artikel gefunden.

In Bezug auf das Erreichen einer Wiederherstellungsrate von 100% in diesem Artikel weiß ich nicht, ob die Anzahl der für den Kauf simulierten Wettkarten in anderen Zeiträumen festgelegt wird. Der Quellcode wird ebenfalls berechnet, daher weiß ich nicht genau, wie es geht. Ich dachte jedoch, es wäre interessant, Pferderennen selbst vorherzusagen, also versuchte ich es tatsächlich mit der Absicht zu studieren.

Es wird eine großartige Lernerfahrung sein, da Sie die gesamte Datenerfassung, -analyse und -prognose durchführen.

Warum Pferderennen?

Es bestand der Wunsch, dass es Geld sein könnte, aber Pferderennen scheinen einen hohen Abzugssatz zu haben, so dass ich nicht viel erwarten kann. Der Hauptgrund ist, dass es in letzter Zeit ein heißes Thema war und ich versuchen wollte, tief zu lernen.

Ein weiterer Grund für die Wahl von Pferderennen ist

――Das Rennergebnis wird von den Zuschauern weniger beeinflusst

Das wird erwähnt.

Es scheint gut, das Thema Aktien zu behandeln, aber da der Preis in Abhängigkeit von den Entscheidungen vieler Menschen schwankt, ist es schwierig, dies mit guter Genauigkeit vorherzusagen, wenn nicht Informationen wie Nachrichten, die Händler häufig sehen, einbezogen werden. Korrekt. Darüber hinaus erteilen viele institutionelle Anleger automatisch Aufträge gemäß dem Algorithmus, der wahrscheinlich davon abhängt.

Aus dem oben Gesagten dachte ich, dass es mit der aktuellen Technologie nicht einfach sein würde, also dachte ich, dass Pferderennen besser für tiefes Lernen geeignet ist.

Die Anzahl der Pferde, die im Pferderennen laufen, variiert von Rennen zu Rennen, aber es scheint, dass die Anzahl der Athleten, die am Bootsrennen teilnehmen, konstant ist. Es scheint, dass maschinelles Lernen einfacher sein wird, wenn detaillierte Daten erhalten werden können.

Erklärung für diejenigen, die neu im Pferderennen sind

"Pferderennen (Keiba, Englisch: Pferderennen) ist ein Wettkampf, bei dem Pferde, auf denen Pferde reiten, und ein Glücksspiel, das die Reihenfolge der Ankunft vorhersagt" (Zitat: [Pferderennen - Wikipedia](https: // ja.wikipedia.org/wiki/horse Racing)).

Ich hatte wenig Wissen über Pferderennen, bis ich diese Daten analysierte, daher werde ich das Wissen zusammenfassen, das ich für notwendig hielt, um diesen Artikel zu lesen.

Lassen Sie uns zunächst die Arten von Wettscheinen als Grundkenntnisse kennen. Es ist in Ordnung, nur einen einzelnen Gewinn oder einen doppelten Gewinn zu lesen. Referenz: [Art des Wettscheins: JRA für Erstnutzer](https://www.google.com/url?sa=t&rct=j&q½esrc=s&source=web&cd=1&ved=2ahUKEwjj9cC71eHlAhXgy4sBHXKtA0QQFtJAlQ jra.go.jp% 2Fkouza% 2Fbeginner% 2Fbaken% 2F & usg = AOvVaw12f8T5GSlozZG9tnRspGtC)

Weitere Begriffe finden Sie im Folgenden

Referenz: Pferderennen Glossar JRA

Ich bin nicht so vertraut damit, also lass es mich wissen, wenn du einen Fehler machst ...

Domänenwissen soll beim maschinellen Lernen wichtig sein, daher ist es notwendig, sich mit Pferderennen vertraut zu machen, um die Vorhersagegenauigkeit zu verbessern.

Grobe Prozedur

Selbst wenn Sie Vorhersagen über Pferderennen treffen, gibt es viele Dinge, über die Sie nachdenken und die Sie tun müssen. Das Verfahren kann grob wie folgt unterteilt werden.

  1. Datenerfassung (Crawlen und Scraping)
  2. Datenformatierung (Pandas, SQL usw.)
  3. Modellierung (maschinelles Lernen)

Das erste große Problem für diejenigen, die Pferderennen vorhersagen möchten, ist die Datenerfassung und -formung. In Wettbewerben wie Kaggle ist es ziemlich einfach, da der Datensatz von Anfang an angegeben wird, aber diesmal müssen wir zunächst die Daten sammeln.

Es ist auch schwierig, ein Modell zu erstellen, da verschiedene Methoden in Betracht gezogen werden können. Heutzutage können Sie Gradienten-Boosting, Deep Learning usw. in der Bibliothek problemlos verwenden. Sie müssen jedoch verschiedene Methoden ausprobieren, um die Vorhersagegenauigkeit zu verbessern.

Vorausgesetztes Wissen

Zusammenfassung der Ergebnisse

Nutzungsdaten

Ergebnis

Als Anfänger habe ich ein Modell mit höherer Genauigkeit als ich selbst gebaut

Beginnen wir mit der Datenerfassung

Maschinelles Lernen ist nicht plötzlich möglich, obwohl keine Daten vorliegen. Lass uns kriechen und kratzen.

Erhalten Sie zuerst die Ergebnisse der vergangenen Rennen und Informationen zum Pferd von der Zielstelle.

Die hier erhaltenen Daten sollten so nah wie möglich an den Rohdaten liegen, und die Daten werden später für das Training formatiert.

Zielseite

Es ist die größte Informationsseite für Pferderennen in Japan. Von früheren Renndaten bis hin zu Informationen zum Stammbaum von Pferden können Sie kostenlos detaillierte Daten erhalten.

Es scheint, dass detailliertere Daten erhalten werden können, wenn Sie ein bezahltes Mitglied werden. Dies ist effektiv, wenn Sie die Genauigkeit des Modells verbessern möchten.

Gesammelte Daten

Dieses Mal haben wir beschlossen, Daten zu sammeln, die sich auf die Rennergebnisse auf der zentralen Rennbahn konzentrieren, die über eine große Menge an Informationen und ein einheitliches System verfügt.

Da es viele Daten gibt, können Sie ein gutes Modell erstellen, indem Sie verschiedene Daten sammeln und verwenden. Es ist jedoch ziemlich mühsam, Stammbauminformationen und Daten wie Besitzer und Trainer zu sammeln, daher habe ich mich diesmal entschieden, dies nicht zu tun. Es scheint, dass sich die Vorhersagegenauigkeit verbessert, wenn Sie hier Daten hinzufügen.

Holen Sie sich zuerst die URL zu allen Rennen

Verwenden Sie im Detaillierten Rennsuchbildschirm auf der Website Selenium, um alle URLs zu den Rennergebnissen abzurufen.

Der Grund für die Nichtverwendung von Anforderungen und Beautiful Soup, die häufig beim Crawlen und Scraping in Python verwendet werden, besteht darin, dass sowohl die Such-URL als auch die Suchergebnis-URL [https://db.netkeiba.com/?pid=race_search_detail](https :: //db.netkeiba.com/?pid=race_search_detail) hat sich nicht geändert.

Wenn der Bildschirm dynamisch von JavaScript oder PHP generiert wird, können Sie die gewünschten Daten nicht durch einfaches Herunterladen des HTML-Codes abrufen.

Mit Selenium können Bildschirmübergänge durch tatsächliche Browseroperationen ausgeführt werden, sodass das Webcrawlen auch auf Websites durchgeführt werden kann, auf denen sich die Anzeige durch Klicken auf eine solche Schaltfläche oder auf Websites, für die eine Anmeldung erforderlich ist, ändert. (Bitte beachten Sie, dass das Crawlen für Websites, für die aufgrund von Mitgliedschaftsvereinbarungen usw. eine Anmeldung erforderlich ist, häufig verboten ist.)

Bereiten Sie zunächst vor, was Sie brauchen

import time

from selenium import webdriver
from selenium.webdriver.support.ui import Select,WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options

options = Options()
options.add_argument('--headless')    #Im kopflosen Modus
driver = webdriver.Chrome(chrome_options=options) 
wait = WebDriverWait(driver,10)

Füllen Sie die Formulareingabe aus

Füllen Sie die erforderlichen Felder im Formular aus. Warten Sie nach dem Senden, bis die Suchergebnisse angezeigt werden. スクリーンショット 2019-11-18 18.09.14.png

URL = "https://db.netkeiba.com/?pid=race_search_detail"
driver.get(URL)
time.sleep(1)
wait.until(EC.presence_of_all_elements_located)

#Suche nach Monat
year = 2019
month = 1

#Wählen Sie einen Zeitraum aus
start_year_element = driver.find_element_by_name('start_year')
start_year_select = Select(start_year_element)
start_year_select.select_by_value(str(year))
start_mon_element = driver.find_element_by_name('start_mon')
start_mon_select = Select(start_mon_element)
start_mon_select.select_by_value(str(month))
end_year_element = driver.find_element_by_name('end_year')
end_year_select = Select(end_year_element)
end_year_select.select_by_value(str(year))
end_mon_element = driver.find_element_by_name('end_mon')
end_mon_select = Select(end_mon_element)
end_mon_select.select_by_value(str(month))

#Schauen Sie sich die zentrale Rennbahn an
for i in range(1,11):
    terms = driver.find_element_by_id("check_Jyo_"+ str(i).zfill(2))
    terms.click()
        
#Wählen Sie die Nummer aus, die angezeigt werden soll(20,50,Von 100 bis maximal 100)
list_element = driver.find_element_by_name('list')
list_select = Select(list_element)
list_select.select_by_value("100")

#Formular abschicken
frm = driver.find_element_by_css_selector("#db_search_detail_form > form")
frm.submit()
time.sleep(5)
wait.until(EC.presence_of_all_elements_located)

Der Einfachheit halber versuche ich, die URL für Januar 2019 zu erhalten. Wenn Sie einen größeren Datenbereich wünschen, führen Sie einen der folgenden Schritte aus:

(Im Github-Code versuchen wir, Renndaten zu sammeln, die seit 2008 nicht mehr erfasst wurden.)

Wenn Sie die Auswahl der Rennstrecke nicht eingeben, werden die Daten der im Ausland ausgetragenen Rennen berücksichtigt. Lassen Sie uns 10 zentrale Rennstrecken richtig überprüfen.

Ich habe beschlossen, diesmal keine anderen Daten als die zentrale Rennbahn zu verwenden, da möglicherweise nur wenige Pferde laufen oder die Daten unvollständig sind.

Speichern Sie die URL während der Paginierung

Klicken Sie in Selen auf die Schaltfläche und speichern Sie die angezeigten URLs für jeweils 100 Elemente. スクリーンショット 2019-11-18 18.11.48.png

with open(str(year)+"-"+str(month)+".txt", mode='w') as f:
    while True:
        time.sleep(5)
        wait.until(EC.presence_of_all_elements_located)
        all_rows = driver.find_element_by_class_name('race_table_01').find_elements_by_tag_name("tr")
        for row in range(1, len(all_rows)):
            race_href=all_rows[row].find_elements_by_tag_name("td")[4].find_element_by_tag_name("a").get_attribute("href")
            f.write(race_href+"\n")
        try:
            target = driver.find_elements_by_link_text("Nächster")[0]
            driver.execute_script("arguments[0].click();", target) #Klicken Sie auf Verarbeitung mit Javascript
        except IndexError:
            break

Öffnen Sie die Datei und schreiben Sie die erhaltene URL Zeile für Zeile. Die Race-URL befindet sich in der 5. Spalte der Tabelle. Wählen Sie in Python, wo die Elemente des Arrays bei 0 beginnen, "find_elements_by_tag_name (" td ") [4]" aus und so weiter.

Das Paging erfolgt in einer while-Schleife. Ich benutze "try", um die Ausnahme abzufangen, da ich nicht auf die letzte Seite klicken kann.

Der driver.execute_script (" Argumente [0] .click (); ", Ziel) Teil des Versuchs, aber wenn Sie es zu einem einfachen target.click () machen, erhalten Sie eine ElementClickInterceptedException im kopflosen Modus. Es ist aufgetreten. Anscheinend wurde erkannt, dass sich die Elemente überlappten und ich nicht gut darauf klicken konnte. Es gab eine Lösung in hier, aber ich konnte dies tun, indem ich wie oben mit JavaScript klickte.

Holen Sie sich HTML basierend auf der erhaltenen URL

Das HTML, das ich zuvor erhalten habe, scheint PHP oder JavaScript nicht viel zu verwenden, um die Seite anzuzeigen, daher werde ich hier endlich Anfragen verwenden. Basierend auf den Informationen in der obigen URL erhalte ich das HTML und speichere es, aber es dauert einige Sekunden, bis jede Seite abgerufen ist, daher dauert es sehr lange.

import os
import requests

save_dir = "html"+"/"+str(year)+"/"+str(month)
if not os.path.isdir(save_dir):
    os.makedirs(save_dir)
        
with open(str(year)+"-"+str(month)+".txt", "r") as f:
    urls = f.read().splitlines()
    for url in urls:
        list = url.split("/")
        race_id = list[-2]
        save_file_path = save_dir+"/"+race_id+'.html'
        response = requests.get(url)
        response.encoding = response.apparent_encoding
        html = response.text
        time.sleep(5)
        with open(save_file_path, 'w') as file:
            file.write(html)

Aufgrund des Zeichencodes kann es verstümmelt sein, wenn Sie es gehorsam erhalten. Ich habe es mit response.encoding = response.apparent_encoding gemacht und es hat funktioniert. Referenz: Korrigieren Sie verstümmelte Zeichen beim Umgang mit Japanisch in Anfragen

Analysieren Sie HTML und erstellen Sie CSV

Details zum Rennen ・ Informationen zu jedem Läufer werden in csv gespeichert. Ich habe beschlossen, eine CSV mit dem folgenden Format zu erstellen.

Es gibt andere Informationen, die erhalten werden können. Es scheint, dass bezahlte Mitglieder auch einen sogenannten Geschwindigkeitsindex erhalten können.

import numpy as np
import pandas as pd
from bs4 import BeautifulSoup

CSV_DIR = "csv"
if not os.path.isdir(CSV_DIR):
    os.makedirs(CSV_DIR)
save_race_csv = CSV_DIR+"/race-"+str(year)+"-"+str(month)+".csv"
horse_race_csv = CSV_DIR+"/horse-"+str(year)+"-"+str(month)+".csv"

# race_data_columns, horse_data_Spalten werden lang sein, also weglassen
race_df = pd.DataFrame(columns=race_data_columns )
horse_df = pd.DataFrame(columns=horse_data_columns )

html_dir = "html"+"/"+str(year)+"/"+str(month)
if os.path.isdir(html_dir):
    file_list = os.listdir(html_dir)
    for file_name in file_list:
        with open(html_dir+"/"+file_name, "r") as f:
            html = f.read()
            list = file_name.split(".")
            race_id = list[-2]
            race_list, horse_list_list = get_rade_and_horse_data_by_html(race_id, html) #Ausgelassen, weil es lange dauern wird
            for horse_list in horse_list_list:
                horse_se = pd.Series( horse_list, index=horse_df.columns)
                horse_df = horse_df.append(horse_se, ignore_index=True)
            race_se = pd.Series(race_list, index=race_df.columns )
            race_df = race_df.append(race_se, ignore_index=True )
            
race_df.to_csv(save_race_csv, header=True, index=False)
horse_df.to_csv(horse_race_csv, header=True, index=False)

Fügen Sie für jedes Rennen die Details des Rennens, Informationen zu jedem Läufer usw. zur Liste hinzu und fügen Sie dem Pandas-Datenrahmen eine Zeile hinzu.

Die Funktionen get_rade_and_horse_data_by_html, race_data_columns und Horse_data_columns sind kompliziert und werden hier nicht berücksichtigt. Um es kurz zu erklären, ist die Funktion get_rade_and_horse_data_by_html eine Funktion, die BeautifulSoup verwendet, um die gewünschten Daten aus HTML aufzulisten und zurückzugeben. Race_Data_columns und Horse_Data_columns sind die Spaltennamen der zu erfassenden Daten.

Weitere Hinweise

Stellen Sie beim Crawlen sicher, dass Sie Zeit haben, um darauf zuzugreifen, damit der Server nicht angegriffen wird.

Es gibt andere Personen, die detaillierte rechtliche Vorsichtsmaßnahmen zusammengefasst haben. Wenn Sie dies also tatsächlich tun, Liste der Vorsichtsmaßnahmen für das Web-Scraping - Qiita ) Usw., siehe.

Sobald die Daten vorliegen, werden wir die Formgebung und Analyse durchführen.

Nachdem wir die Daten im CSV-Format haben, bereinigen wir sie, damit sie einfach zu handhaben sind.

Überlegen Sie sich als Nächstes, welche Art von Modell erstellt werden soll, während Sie den Status der Daten betrachten. Danach erstellen wir Zugdaten gemäß dem Modell, das Sie erstellen möchten.

Formatieren Sie Daten so, dass sie einfach zu handhaben sind

Formatieren wir die Daten so, dass sie einfach zu handhaben sind.

Konvertieren Sie beispielsweise Datumsdaten oder Zahlen in einer Zeichenfolge in ein Datum / Uhrzeit-Objekt oder int. Da es in Zukunft einfacher sein wird, wenn die Daten in einer Spalte so einfach wie möglich sind, werden Geschlecht und Alter in zwei Spalten unterteilt. Es ist noch viel zu tun; Es sind viele Dinge zu erledigen.

Es wäre vielleicht besser gewesen, es gleichzeitig mit dem Scraping zu machen, aber da der Scraping-Code kompliziert zu sein schien, habe ich beschlossen, es diesmal separat zu machen.

Nachfolgend einige davon.

#Extrahieren Sie Zeitinformationen und kombinieren Sie sie mit Datumsinformationen. Machen Sie es zu einem Datum / Uhrzeit-Typ
race_df["time"] = race_df["time"].str.replace('Start: (\d\d):(\d\d)(.|\n)*', r'\1 Uhr\2 Minuten')
race_df["date"] = race_df["date"] + race_df["time"]
race_df["date"] = pd.to_datetime(race_df['date'], format='%Y Jahr%m Monat%d Tag%Uhr%M Minuten')
#Die ursprüngliche Zeit ist nicht erforderlich. Löschen Sie sie daher
race_df.drop(['time'], axis=1, inplace=True)

#Entfernen Sie zusätzliches R, Leerzeichen und Zeilenumbrüche in einigen runden Spalten
race_df['race_round'] = race_df['race_round'].str.strip('R \n')

Datenanalyse

Wir werden die formatierten Daten analysieren und grob prüfen, welche Art von Verteilung sie haben. Wenn Sie ein Modell erstellen, müssen Sie es so trainieren, dass die Daten nicht so stark wie möglich verzerrt werden. Daher ist dies auch wichtig für die Problemstellung des Modells.

Die Datenanalyse ist auch wichtig, wenn Sie überlegen, wie Features erstellt werden sollen. Im Fall von Deep Learning usw. scheint es nicht notwendig zu sein, sich so sehr an das Feature-Quantity-Engineering zu halten, aber wenn gewöhnliches nicht-tiefes maschinelles Lernen wie Gradienten-Boosting wie LightGBM durchgeführt wird, muss sorgfältig überlegt werden, wie hoch das Feature-Quantity sein sollte. es gibt.

Selbst mit Kaggle scheint die Möglichkeit, in die oberen Ränge zu gelangen, zu steigen, wenn Sie eine gute Anzahl an Features finden.

Zugdaten erstellen

Nachdem Sie unter Bezugnahme auf die zuvor erwähnte Datenanalyse entschieden haben, welche Art von Modell erstellt werden soll, erstellen wir Zugdaten.

Obwohl es sich um Eingabedaten handelt, ist es ungefähr wie folgt.

Die Gewinnchancen für das Rennen, das Sie vorhersagen möchten, schwanken bis kurz vor dem Spiel, sodass wir sie nicht in die Daten aufnehmen.

Endlich Modellbildung (Deep Learning)

Zunächst werde ich einen Überblick geben, diesmal werde ich tief mit Keras lernen. Verwenden von Daten von einem Pferd als Eingabe

Ich habe zwei davon gemacht.

Wie man das Modell entscheidet

Es muss überlegt werden, ob das Klassifizierungsproblem oder das Regressionsproblem gelöst werden soll.

Im Falle des Regressionsproblems denke ich, dass es vorhersagen wird, wie viel das Pferd sein wird (es wird so etwas wie 1,2 erlauben) und wie viel Zeit es haben wird.

Im Falle eines Klassifizierungsproblems werden Sie gebeten, vorherzusagen, wie viele Pferde es sein wird (dies wird durch natürliche Zahlen von 1 bis 16 klassifiziert), ob es zuerst sein wird, ob es oben sein wird usw. ..

Die Zeiten und Geschwindigkeiten variieren stark je nach Rennstrecke und Strecke. Daher ist es schwierig, wenn Sie sie nicht separat vorhersagen. Dieses Mal werden wir einfach als Klassifizierungsproblem vorhersagen, ob wir oben sein sollen oder nicht.

Was wir bei der Modellerstellung gemacht haben und wie wir mit Überlernen umgehen sollen

Ich werde über verschiedene Dinge schreiben, die ich beim Erstellen des Modells versucht habe.

Selbst wenn Sie ein Modell erstellen, ist es unabdingbar, einen Weg zu finden, um Überlernen zu verhindern und zu überprüfen, ob es überlernt ist. Selbst wenn Sie maschinell lernen und mit den vorliegenden Daten gute Ergebnisse erzielen, bedeutet dies nicht, dass das Modell andere Daten mit guter Genauigkeit vorhersagen kann.

Teilen Sie den Datensatz für Training und Test auf

Zunächst von den Grundlagen. Es macht keinen Sinn, ein Modell zu erstellen, es sei denn, Sie können bewerten, ob es gut ist oder nicht.

80% der gesammelten und formatierten Daten wurden als Trainingsdaten und 20% als Testdaten verwendet. Mit anderen Worten

Es ist in Form von. Diese Testdaten werden für die zu Beginn geschriebene korrekte Antwortrate verwendet.

Zum Zeitpunkt des Trainings wurden die Trainingsdaten weiter in einen für den Zug und einen für die Validierung unterteilt.

Gewichtsregulierung und Ausfall

Gewichtsregulierung und Aussetzer sind einige der Mittel, um Überlernen zu verhindern, und Keras macht sie einfach zu bedienen.

Das Hinzufügen von Kosten entsprechend dem Gewicht zur Verlustfunktion des Netzwerks ist die Regularisierung des Gewichts, und der Ausfall besteht darin, die Merkmalsmenge von der Schicht während des Trainings zufällig zu reduzieren (fallen zu lassen).

Wir haben die L2-Regularisierung zur Gewichtsregulierung verwendet.

Referenz: Erfahren Sie mehr über Über- und Unterlernen | TensorFlow Core


model = tf.keras.Sequential([
        tf.keras.layers.Dense(300, kernel_regularizer=tf.keras.regularizers.l2(0.001), activation=tf.nn.relu, input_dim=df_columns_len), #l2 Regularisierte Schicht
        tf.keras.layers.Dropout(0.2), #Aussteigen
        tf.keras.layers.Dense(100, kernel_regularizer=tf.keras.regularizers.l2(0.001), activation=tf.nn.relu), #l2 Regularisierte Schicht
        tf.keras.layers.Dropout(0.2), #Aussteigen
        tf.keras.layers.Dense(1, activation=tf.nn.sigmoid) 
    ])

Kreuzvalidierung

Eine einfache Holdout-Validierung, die nur einen bestimmten Zeitraum verwendet, kann überstrapaziert sein, um in diesem Zeitraum gute Ergebnisse zu erzielen.

Lassen Sie uns überprüfen, ob das Modell mit den vorliegenden Daten gut ist, da die Kreuzvalidierung in Wettbewerben wie Kaggle erfolgt.

Das Problem ist, dass es sich um Zeitreihendaten handelt, sodass Sie KFold nicht einfach zum Teilen der Daten verwenden können. Wenn bei der Eingabe von Zeitreihendaten zukünftige Informationen auf Training und vergangene Informationen auf Validierung eingestellt sind, ist das Ergebnis möglicherweise besser als es sein sollte. Eigentlich habe ich zuerst einen Fehler gemacht und durch Eingabe zukünftiger Daten trainiert, aber die Vorhersagewahrscheinlichkeit eines doppelten Gewinns lag über 70%.

Daher habe ich dieses Mal die Split-Methode verwendet, die für die Kreuzvalidierung von Zeitreihendaten verwendet wird (sklearns TimeSeries Split. html)).

Grob gesagt wird der Datensatz, wie in der folgenden Abbildung gezeigt, durch Hinzufügen von Zeitreihen unterteilt und ein Teil davon wird als Verifizierungsdaten verwendet.

プレゼンテーション1のコピー.png

In dieser Abbildung lernen Sie dreimal. Einige Trainingsdaten werden jedoch reduziert. Wenn also die Anzahl der Daten gering ist, ist ein einfaches Halten möglicherweise besser.

tscv = TimeSeriesSplit(n_splits=3)
for train_index, val_index in tscv.split(X_train,Y_train):
    train_data=X_train[train_index]
    train_label=Y_train[train_index]
    val_data=X_train[val_index]
    val_label=Y_train[val_index]
    model = train_model(train_data,train_label,val_data,val_label,target_name)

Hyper-Parameter-Tuning

Hyperparameter beim maschinellen Lernen sind wichtig. Zum Beispiel ist es beim Deep Learning umso einfacher, über den Fuß zu treten, je größer die dazwischen liegende Schicht ist, je mehr Zwischenvariablen vorhanden sind und je weniger Trainingsdaten vorhanden sind. Wenn es jedoch klein ist, ist es möglicherweise nicht flexibel genug, um richtig zu lernen, selbst wenn die Datenmenge ausreicht.

Es wird viele Kontroversen darüber geben, wie es geht. Dies scheint von Person zu Person unterschiedlich zu sein.

Dieses Mal gab es eine Bibliothek namens hyperas, die die Parametereinstellung von Keras automatisch anpasst, also habe ich mich für die Verwendung entschieden. Es war relativ intuitiv und leicht zu verstehen.

Übergeben Sie zur einfachen Verwendung einfach die Datenvorbereitungsfunktion und die Funktion, die den Wert zurückgibt, den Sie minimieren möchten, indem Sie auf "optim.minimize" trainieren.

Geben Sie die Breite an, die Sie mit "Auswahl" für ganzzahlige Werte und "einheitlich" für reelle Zahlen anpassen möchten.

Weitere Informationen finden Sie hier: https://github.com/maxpumperla/hyperas

import keras
from keras.callbacks import EarlyStopping
from keras.callbacks import CSVLogger
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation

from hyperopt import Trials, STATUS_OK, tpe
from hyperas import optim
from hyperas.distributions import choice, uniform
def prepare_data_is_hukusyo():
    """
Ich werde hier verschiedene Daten vorbereiten
    """
    return X_train, Y_train, X_test, Y_test

def create_model_is_hukusyo(X_train, Y_train, X_test, Y_test):
    train_size = int(len(Y_train) * 0.8)
    train_data = X_train[0:train_size]
    train_label = Y_train[0:train_size]
    val_data = X_train[train_size:len(Y_train)]
    val_label = Y_train[train_size:len(Y_train)]

    callbacks = []
    callbacks.append(EarlyStopping(monitor='val_loss', patience=2))

    model = Sequential()
    model.add(Dense({{choice([512,1024])}}, kernel_regularizer=keras.regularizers.l2(0.001), activation="relu", input_dim=train_data.shape[1]))
    model.add(Dropout({{uniform(0, 0.3)}}))
    model.add(Dense({{choice([128, 256, 512])}}, kernel_regularizer=keras.regularizers.l2(0.001), activation="relu"))
    model.add(Dropout({{uniform(0, 0.5)}}))

    if {{choice(['three', 'four'])}} == 'three':
        pass
    elif {{choice(['three', 'four'])}} == 'four':
        model.add(Dense(8, kernel_regularizer=keras.regularizers.l2(0.001), activation="relu"))
        model.add(Dropout({{uniform(0, 0.5)}}))

    model.add(Dense(1, activation="sigmoid"))

    model.compile(
        loss='binary_crossentropy',
        optimizer=keras.optimizers.Adam(),
        metrics=['accuracy'])

    history = model.fit(train_data,
        train_label,
        validation_data=(val_data, val_label),
        epochs=30,
        batch_size=256,
        callbacks=callbacks)

    val_loss, val_acc = model.evaluate(X_test, Y_test, verbose=0)
    print('Best validation loss of epoch:', val_loss)
    return {'loss': val_loss, 'status': STATUS_OK, 'model': model}

#Eigentlich mit Hyperas einstellen
best_run, best_model = optim.minimize(model=create_model_is_hukusyo,
                                     data=prepare_data_is_hukusyo,
                                     algo=tpe.suggest,
                                     max_evals=15,
                                     trials=Trials())

Mischen Sie das Ergebnis

Möglicherweise können Sie genauere Vorhersagen treffen, indem Sie die Ausgaben verschiedener Modelle mischen.

Durch Mittelung der Vorhersage für den 1. Platz und der Vorhersage für den 3. Platz und darüber konnten wir einen Wert erhalten, der geringfügig höher als der ursprüngliche Vorhersagewert war.

Die Eigenschaften von Pferden, die wahrscheinlich an erster Stelle stehen, und die Eigenschaften von Pferden, die wahrscheinlich an erster Stelle stehen, können geringfügig voneinander abweichen, und es wird angenommen, dass eine genauere Vorhersage durch Mischen der beiden möglich ist. Ich werde.

Zum Beispiel scheint es, dass die Eigenschaften eines Pferdes, das auf Platz 1 steht, es aber nicht übertreibt, wenn es mitten im Rennen zu versagen scheint und ein Pferd, das stabil in die Spitze eintritt, leicht unterschiedlich ist.

Ergebnis

Am Ende habe ich ein Modell mit höherer Genauigkeit gemacht als ich selbst, der ein Anfänger im Pferderennen ist.

Es gibt noch mehr Informationen, die im Pferderennen wichtig zu sein scheinen, daher scheint es Raum für Verbesserungen zu geben.

Der Saldo, wenn ich weiterhin den 1. Platz bei einem Gewinn kaufe, ist wie folgt. Ich habe es mit Pandas richtig geplottet.

image.png

Beim Doppelsieg wurde es wie folgt.

image.png

Es ist ein großes Defizit. Es ist etwas besser, wenn Sie nur diejenigen mit hohen Vorhersagen kaufen und nicht diejenigen mit niedrigen Gewinnchancen.

Andere Tipps

Bei dieser Vorhersage für Pferderennen werde ich einige der Dinge belassen, die ich versucht habe und die nichts mit der Hauptlinie zu tun haben.

Verwenden Sie GCP

Das GCP-Guthaben lief Ende November aus, daher war mein zweites Ziel, es zu konsumieren.

Sie können das Programm vor dem Schlafengehen werfen und es überprüfen, wenn Sie morgens aufwachen.

Bitte seien Sie vorsichtig, wenn Sie GCP verwenden, da die kostenlose Instanz nicht über genügend Speicher zum Erstellen von CSV und Deep Learning verfügt.

Mit LINE benachrichtigen Benachrichtigen

In Bezug auf GCP habe ich LINE Notify gesendet, wenn das Programm beendet wurde oder ein Fehler aufgetreten ist.

Sobald ich fertig war, konnte ich die Ergebnisse sehen und das nächste Programm ausführen, was eine Menge Arbeit war.

Einige am Ende

Es ist eine geeignete Unterhaltung für Studenten. Wenn Sie damit vertraut sind, gibt es meiner Meinung nach viele Dinge zu tun. Wenn Sie einen Fehler machen, wird dies eine Lernerfahrung sein. Ich wäre Ihnen dankbar, wenn Sie in den Kommentaren oder auf Twitter darauf hinweisen könnten.

Twitter ID (ich twittere nicht zu viel): @ 634kami

Quellcode

Es wird auf Github veröffentlicht. Ich wollte etwas machen, das vorerst funktioniert, also können die Leute es nicht sehen, aber bitte sehen Sie nur diejenigen, die sagen, dass es in Ordnung ist.

Der Code auf Qiita wurde teilweise geändert, um das Lesen zu erleichtern.

Wo Sie sich verbessern können / was Sie tun möchten

Andere Links, auf die ich verwiesen habe oder die ich wahrscheinlich bin

Nachtrag

Ich habe Folgendes hinzugefügt, weil ich Folgendes getan habe.

Unten sind die Ergebnisse.

total: 8, random tansyo accuracy:0.125, hukusyo accuracy:0.375
tansyo accuracy: 0.3497536945812808
hukusyo accuracy: 0.7044334975369458

total: 9, random tansyo accuracy:0.1111111111111111, hukusyo accuracy:0.3333333333333333
tansyo accuracy: 0.2693726937269373
hukusyo accuracy: 0.6568265682656826

total: 10, random tansyo accuracy:0.1, hukusyo accuracy:0.3
tansyo accuracy: 0.30563002680965146
hukusyo accuracy: 0.6407506702412868

total: 11, random tansyo accuracy:0.09090909090909091, hukusyo accuracy:0.2727272727272727
tansyo accuracy: 0.2582278481012658
hukusyo accuracy: 0.5468354430379747

total: 12, random tansyo accuracy:0.08333333333333333, hukusyo accuracy:0.25
tansyo accuracy: 0.2600806451612903
hukusyo accuracy: 0.5826612903225806

total: 13, random tansyo accuracy:0.07692307692307693, hukusyo accuracy:0.23076923076923078
tansyo accuracy: 0.2894736842105263
hukusyo accuracy: 0.5855263157894737

total: 14, random tansyo accuracy:0.07142857142857142, hukusyo accuracy:0.21428571428571427
tansyo accuracy: 0.23014586709886548
hukusyo accuracy: 0.5380875202593193

total: 15, random tansyo accuracy:0.06666666666666667, hukusyo accuracy:0.2
tansyo accuracy: 0.2525399129172714
hukusyo accuracy: 0.532656023222061

In jedem Fall war die Genauigkeitsrate besser als die vollständig zufällige Auswahlmethode.

Recommended Posts

Ich habe versucht, Pferderennen vorherzusagen, indem ich alles von der Datenerfassung bis zum tiefen Lernen getan habe
Ich habe versucht, Dropout zu erklären
Ich habe versucht, Perceptron Teil 1 [Deep Learning von Grund auf neu] zu implementieren.
[Deep Learning von Grund auf neu] Ich habe versucht, Sigmoid Layer und Relu Layer zu implementieren
Ich habe versucht, Oba Hanana und Otani Emiri durch tiefes Lernen zu klassifizieren
Ich habe die übliche Geschichte ausprobiert, Deep Learning zu verwenden, um den Nikkei-Durchschnitt vorherzusagen
Ich habe versucht, tief zu lernen
Ich habe versucht, die Strichzeichnung mit Deep Learning aus dem Bild zu extrahieren
Ich habe versucht, das Vorhandensein oder Nichtvorhandensein von Schnee durch maschinelles Lernen vorherzusagen.
Ich habe versucht, die Veränderung der Schneemenge für 2 Jahre durch maschinelles Lernen vorherzusagen
Ich habe versucht, Hanana Oba und Emiri Otani durch tiefes Lernen zu klassifizieren (Teil 2)
Ich habe versucht, das Spiel in der J League vorherzusagen (Datenanalyse)
"Deep Learning from Grund" Memo zum Selbststudium (Nr. 16) Ich habe versucht, SimpleConvNet mit Keras zu erstellen
"Deep Learning from Grund" Memo zum Selbststudium (Nr. 17) Ich habe versucht, DeepConvNet mit Keras zu erstellen
[Pferderennen] Ich habe versucht, die Stärke des Rennpferdes zu quantifizieren
Ich habe versucht, die Erkennung von Anomalien durch spärliches Strukturlernen zu implementieren
[Einführung in Pandas] Ich habe versucht, die Austauschdaten durch Dateninterpolation zu erhöhen ♬
Erstellen Sie eine KI, die Zuckerbergs Gesicht mit tiefem Lernen identifiziert learning (Datenlernen)
Ich habe versucht, in einem tief erlernten Sprachmodell zu schreiben
Ich habe versucht, mit pypyodbc schnell Daten von AS / 400 abzurufen
[Deep Learning von Grund auf neu] Ich habe versucht, die Gradientenbestätigung auf leicht verständliche Weise zu erklären.
Ich habe versucht, Othello AI zu machen, dass ich 7,2 Millionen Hände durch tiefes Lernen mit Chainer gelernt habe
Ich habe versucht, Deep VQE zu implementieren
Verwendung der offenen Daten von Data City Sabae zur Vorhersage des Werts des Wasserstandsmessers durch maschinelles Lernen Teil 2
Ich habe versucht, mit Pandas eine Pferderenn-Datenbank zu erstellen
Ich habe versucht, Deep Learning mit Spark × Keras × Docker skalierbar zu machen
Ich ließ RNN Sin Wave lernen und versuchte vorherzusagen
Ich habe versucht, mit Theano tief zu lernen
Ich habe versucht, mit pypyodbc Preparation 1 schnell Daten von AS / 400 abzurufen
[Data Science-Grundlagen] Ich habe versucht, mit Python von CSV auf MySQL zu speichern
Ich habe versucht, Deep Learning zu implementieren, das nicht nur mit NumPy tiefgreifend ist
Ich habe versucht, Kanas handschriftliche Zeichenerkennung durchzuführen. Teil 2/3 Datenerstellung und Lernen
Ich habe versucht, die Anzahl der Mnisten durch unbeaufsichtigtes Lernen zu klassifizieren [PCA, t-SNE, k-means]
Ich habe versucht, Konversationsdaten von ASKfm zu kratzen
Verbessertes Lernen, um von null bis tief zu lernen
Bildausrichtung: von SIFT bis Deep Learning
[Python] [Verarbeitung natürlicher Sprache] Ich habe Deep Learning ausprobiert (auf Japanisch von Grund auf neu erstellt)
[Python] Deep Learning: Ich habe versucht, Deep Learning (DBN, SDA) ohne Verwendung einer Bibliothek zu implementieren.
Ein Anfänger des maschinellen Lernens versuchte, mit Python ein Vorhersagemodell für Pferderennen zu erstellen
Ich habe versucht, die 100-Yen-Lagerstätte von Rakuten-Pferderennen (Python / Selen) zu automatisieren.
Ich habe versucht, das Bild zu verarbeiten und zu transformieren und die Daten für maschinelles Lernen zu erweitern
Ich habe versucht, die Daten des Laptops durch Booten unter Ubuntu zu retten
Ich habe versucht, Cifar10 mit der SONY Deep Learning Library NNabla [Nippon Hurra] zu implementieren.
Ich habe versucht, den G-Test und die E-Qualifikation durch Training ab 50 zu bestehen
Ich habe versucht, Deep Learning mit Spark × Keras × Docker 2 Multi-Host-Edition skalierbar zu machen
Ich habe versucht, nächstes Jahr mit AI vorherzusagen
Ich habe eine Funktion zum Abrufen von Daten aus der Datenbank spaltenweise mithilfe von SQL mit SQLite3 von Python [SQLite3, SQL, Pandas] erstellt.
Ich habe versucht, durch Schaben ein Bild zu bekommen
Ich habe versucht, die Daten mit Zwietracht zu speichern
Ich habe versucht, CloudWatch-Daten mit Python abzurufen
So kratzen Sie Pferderenndaten mit Beautiful Soup
Ich habe versucht, das Überleben der Titanic mit PyCaret vorherzusagen
Ich habe versucht, Drachenkugeln nach Adalin zu klassifizieren
[Keras] Ich habe versucht, das Problem der Klassifizierung des Donut-Typ-Bereichs durch maschinelles Lernen zu lösen. [Studie]
[Erste Datenwissenschaft ⑤] Ich habe versucht, meinem Freund zu helfen, die erste Eigenschaft durch Datenanalyse zu finden
Ich habe versucht, die Laufdaten des Rennspiels (Assetto Corsa) mit Plotly zu visualisieren
Ich habe versucht, Stückpreisdaten nach Sprache mit Real Gachi von Python zu aggregieren und zu vergleichen