Prognostizieren Sie Pferderennen mit maschinellem Lernen und streben Sie eine Wiederherstellungsrate von 100% an.
Letztes Mal habe ich ein Modell für maschinelles Lernen erstellt, das die Pferde vorhersagt, die mit LightGBM unter den Top 3 sein werden. Dieses Mal möchte ich "frühere Leistung von Pferden" als Merkmalsmenge hinzufügen, aber wenn ich es tatsächlich versuche, sind Schaben und Datenverarbeitung ziemlich schwierig. Daher möchte ich zusammenfassen, welche Art von Code geschrieben und implementiert werden soll </ font>.
Kratzen Sie zuerst die früheren Ergebnisse aller Pferde, die 2019 von netkeiba.com gelaufen sind. Auf netkeiba.com wird für jedes Pferd die Pferde-ID angegeben, und die Seiten-URL der vergangenen Ergebnisse lautet 「https://db.netkeiba.com/horse/(horse_id)」 Da es die Struktur hat, wird die in Vorheriger Artikel erstellte Funktion scrape_race_results verarbeitet, um die erforderliche Pferde-ID (und auch die Reiter-ID) zu entfernen.
import time
from tqdm.notebook import tqdm
import requests
from bs4 import BeautifulSoup
import re
import pandas as pd
def scrape_race_results(race_id_list, pre_race_results={}):
race_results = pre_race_results
for race_id in tqdm(race_id_list):
if race_id in race_results.keys():
continue
try:
url = "https://db.netkeiba.com/race/" + race_id
df = pd.read_html(url)[0]
# horse_ID und Jockey_Scraping ID
html = requests.get(url)
html.encoding = "EUC-JP"
soup = BeautifulSoup(html.text, "html.parser")
# horse_id
horse_id_list = []
horse_a_list = soup.find("table", attrs={"summary": "Rennergebnis"}).find_all(
"a", attrs={"href": re.compile("^/horse")}
)
for a in horse_a_list:
horse_id = re.findall(r"\d+", a["href"])
#Es wird groß geschrieben, weil es einen Fehler verursacht, wenn Backslash in Qiita verwendet wird.
horse_id_list.append(horse_id[0])
# jockey_id
jockey_id_list = []
jockey_a_list = soup.find("table", attrs={"summary": "Rennergebnis"}).find_all(
"a", attrs={"href": re.compile("^/jockey")}
)
for a in jockey_a_list:
jockey_id = re.findall(r"\d+", a["href"])
jockey_id_list.append(jockey_id[0])
df["horse_id"] = horse_id_list
df["jockey_id"] = jockey_id_list
race_results[race_id] = df
time.sleep(1)
except IndexError:
continue
except Exception as e:
print(e)
break
return race_results
In DataFrame-Typ konvertieren, der auf den vorherigen Artikel verweist. Dadurch erhalten Sie eine Liste der Pferde_IDs, die Sie benötigen.
results = scrape_race_results(race_id_list)
results = pd.concat([results[key] for key in results])
horse_id_list = results['horse_id'].unique()
Dies wird verwendet, um vergangene Leistungsdaten zu kratzen.
def scrape_horse_results(horse_id_list, pre_horse_id=[]):
horse_results = {}
for horse_id in tqdm(horse_id_list):
if horse_id in pre_horse_id:
continue
try:
url = 'https://db.netkeiba.com/horse/' + horse_id
df = pd.read_html(url)[3]
if df.columns[0]=='Preisgeschichte':
df = pd.read_html(url)[4]
horse_results[horse_id] = df
time.sleep(1)
except IndexError:
continue
except Exception as e:
import traceback
traceback.print_exc()
print(e)
break
except:
break
return horse_results
Es dauert lange, aber machen Sie es nach dem Scraping wieder zu einem DataFrame-Typ und speichern Sie es in einer Pickle-Datei.
horse_results = scrape_horse_results(horse_id_list)
for key in horse_results:
horse_results[key].index = [key] * len(horse_results[key])
df = pd.concat([horse_results[key] for key in horse_results])
df.to_pickle('horse_results.pickle')
Erstellen Sie als Nächstes eine Klasse namens HorseResults und implementieren Sie eine Funktion, die die Reihenfolge der Ankunft und den Durchschnitt der Preise zusammenführt.
class HorseResults:
def __init__(self, horse_results):
self.horse_results = horse_results[['Datum', 'Reihenfolge der Ankunft', 'Preis']]
self.preprocessing()
def preprocessing(self):
df = self.horse_results.copy()
#Entfernen Sie Elemente, die nicht numerische Zeichenfolgen in der Reihenfolge ihrer Ankunft enthalten
df['Reihenfolge der Ankunft'] = pd.to_numeric(df['Reihenfolge der Ankunft'], errors='coerce')
df.dropna(subset=['Reihenfolge der Ankunft'], inplace=True)
df['Reihenfolge der Ankunft'] = df['Reihenfolge der Ankunft'].astype(int)
df["date"] = pd.to_datetime(df["Datum"])
df.drop(['Datum'], axis=1, inplace=True)
#Fülle den Preis NaN mit 0
df['Preis'].fillna(0, inplace=True)
self.horse_results = df
def average(self, horse_id_list, date, n_samples='all'):
target_df = self.horse_results.loc[horse_id_list]
#Geben Sie an, wie viele Läufe in der Vergangenheit ausgeführt wurden
if n_samples == 'all':
filtered_df = target_df[target_df['date'] < date]
elif n_samples > 0:
filtered_df = target_df[target_df['date'] < date].\
sort_values('date', ascending=False).groupby(level=0).head(n_samples)
else:
raise Exception('n_samples must be >0')
average = filtered_df.groupby(level=0)[['Reihenfolge der Ankunft', 'Preis']].mean()
return average.rename(columns={'Reihenfolge der Ankunft':'Reihenfolge der Ankunft_{}R'.format(n_samples), 'Preis':'Preis_{}R'.format(n_samples)})
def merge(self, results, date, n_samples='all'):
df = results[results['date']==date]
horse_id_list = df['horse_id']
merged_df = df.merge(self.average(horse_id_list, date, n_samples), left_on='horse_id',
right_index=True, how='left')
return merged_df
def merge_all(self, results, n_samples='all'):
date_list = results['date'].unique()
merged_df = pd.concat([self.merge(results, date, n_samples) for date in tqdm(date_list)])
return merged_df
Wenn Sie beispielsweise die Ergebnisse der letzten 5 Rennen zur Feature-Menge hinzufügen möchten, können Sie Folgendes implementieren.
hr = HorseResults(horse_results)
results_5R = hr.merge_all(results_p, n_samples=5)
Jetzt können Sie sehen, dass die Reihenfolge der Ankunft und der Durchschnitt der letzten 5 Preisrennen zu den beiden Spalten ganz rechts hinzugefügt wurden.
Details werden im Video ↓ erklärt Datenanalyse / maschinelles Lernen beginnend mit der Vorhersage von Pferderennen
Recommended Posts