[PYTHON] Ich habe versucht, die Veränderung der Schneemenge für 2 Jahre durch maschinelles Lernen vorherzusagen

Dieser Eintrag ist eine Fortsetzung des zuvor geschriebenen Ich habe versucht, das Vorhandensein oder Nichtvorhandensein von Schnee durch maschinelles Lernen vorherzusagen. Zu diesem Zeitpunkt habe ich nur das Vorhandensein oder Fehlen von Schnee vorhergesagt (1 oder 0), aber ich habe ein wenig mehr versucht, die Änderung der Schneemenge vorherzusagen.

Als ich das Ergebnis zuerst aufschrieb, sah es so aus. Die horizontale Achse ist die Anzahl der Tage und die vertikale Achse ist die Schneemenge (cm).

Ergebnis 1 (blau ist die tatsächliche Schneemenge, rote Linie ist die vorhergesagte Schneemenge) スクリーンショット 2016-05-01 17.45.39.png

Ergebnis 2 (blau ist die tatsächliche Schneemenge, rote Linie ist die vorhergesagte Schneemenge) スクリーンショット 2016-05-01 17.59.35.png

Bitte lesen Sie das Folgende, um herauszufinden, was "Ergebnis 1" bzw. "Ergebnis 2" sind.

Was ich machen wollte

Zuvor habe ich versucht, das Vorhandensein oder Nichtvorhandensein von Schneefall mithilfe von "scikit-learn" in Ich habe versucht, das Vorhandensein oder Nichtvorhandensein von Schneefall durch maschinelles Lernen vorherzusagen vorherzusagen. Ich wurde jedoch ein wenig gierig und wollte die tatsächliche Schneemenge (cm) für einen festgelegten Zeitraum vorhersagen, nicht die Anwesenheit oder Abwesenheit.

Insbesondere werden wir meteorologische Daten wie "Schneedecke", "Windgeschwindigkeit", "Temperatur", die von der Meteorologischen Agentur bereitgestellt werden, erfassen und die Daten für die ersten 7500 Tage zum Lernen und die verbleibenden 2 Jahre (365 x 2 =) verwenden Vorhersage von Schneefalländerungen (730 Tage) und Vergleich mit tatsächlichen Schneefalländerungen.

Trainingsdaten sammeln

Die Trainingsdaten werden von den von der Meteorologischen Agentur veröffentlichten Daten bezogen. Insbesondere beziehen Sie sich bitte auf das zuvor geschriebene Ich habe versucht, das Vorhandensein oder Nichtvorhandensein von Schnee durch maschinelles Lernen vorherzusagen.

Die erhaltenen CSV-Daten sehen so aus. Das Ziel war Sakai City in Toyama, wo es viel Schnee gibt.

data_2013_2015.csv


Heruntergeladene Zeit: 2016/03/20 20:31:19

,Sakai,Sakai,Sakai,Sakai,Sakai,Sakai,Sakai,Sakai,Sakai,Sakai,Sakai,Sakai,Sakai,Sakai
Datum (und Uhrzeit,Temperatur(℃),Temperatur(℃),Temperatur(℃),Schneedecke(cm),Schneedecke(cm),Schneedecke(cm),Windgeschwindigkeit(m/s),Windgeschwindigkeit(m/s),Windgeschwindigkeit(m/s),Windgeschwindigkeit(m/s),Windgeschwindigkeit(m/s),Niederschlag(mm),Niederschlag(mm),Niederschlag(mm)
,,,,,,,,,Windrichtung,Windrichtung,,,,
,,Qualitätsinformationen,Homogene Zahl,,Qualitätsinformationen,Homogene Zahl,,Qualitätsinformationen,,Qualitätsinformationen,Homogene Zahl,,Qualitätsinformationen,Homogene Zahl
2013/2/1 1:00:00,-3.3,8,1,3,8,1,0.4,8,Westen,8,1,0.0,8,1
2013/2/1 2:00:00,-3.7,8,1,3,8,1,0.3,8,Norden,8,1,0.0,8,1
2013/2/1 3:00:00,-4.0,8,1,3,8,1,0.2,8,Ruhig,8,1,0.0,8,1
2013/2/1 4:00:00,-4.8,8,1,3,8,1,0.9,8,Süd-Südost,8,1,0.0,8,1
...

grundlegende Denkweise

Die Idee ist, dass diese Art der Vorhersage wahrscheinlich Standard ist, aber wir trainieren das Modell mit einigen Arten von Peripheriedaten und der resultierenden Menge an Schneefall als Satz, und nur die Peripheriedaten werden auf das resultierende Modell angewendet. Es ist zu geben und den vorhergesagten Wert der Schneefallmenge zu erhalten. Dies ist das sogenannte "lehrreiche Lernen" </ b>.

In diesem Fall wurden die folgenden Daten als Peripheriedaten verwendet.

  • Temperatur
  • Windgeschwindigkeit
  • Der Schneefall von gestern
  • Vor 1 Tag Temperatur, vor 2 Tagen Temperatur, vor 3 Tagen Temperatur
  • Windgeschwindigkeit vor 1 Tag, Windgeschwindigkeit vor 2 Tagen, Windgeschwindigkeit vor 3 Tagen

In Bezug auf das Bild sieht es so aus.

[Temperatur,Windgeschwindigkeit,Schneefall von gestern,1日前のTemperatur,2日前のTemperatur,3日前のTemperatur, 1日前のWindgeschwindigkeit, 2日前のWindgeschwindigkeit, 3日前のWindgeschwindigkeit]→ Schneefall am Tag

[Temperatur,Windgeschwindigkeit,Schneefall von gestern,1日前のTemperatur,2日前のTemperatur,3日前のTemperatur, 1日前のWindgeschwindigkeit, 2日前のWindgeschwindigkeit, 3日前のWindgeschwindigkeit]→ Schneefall am Tag

[Temperatur,Windgeschwindigkeit,Schneefall von gestern,1日前のTemperatur,2日前のTemperatur,3日前のTemperatur, 1日前のWindgeschwindigkeit, 2日前のWindgeschwindigkeit, 3日前のWindgeschwindigkeit]→ Schneefall am Tag

....


[Temperatur,Windgeschwindigkeit,Schneefall von gestern,1日前のTemperatur,2日前のTemperatur,3日前のTemperatur, 1日前のWindgeschwindigkeit, 2日前のWindgeschwindigkeit, 3日前のWindgeschwindigkeit]→ Schneefall am Tag

Geben Sie auf dieser Grundlage nur die peripheren Daten an und erhalten Sie den vorhergesagten Wert

[Temperatur,Windgeschwindigkeit,Schneefall von gestern,1日前のTemperatur,2日前のTemperatur,3日前のTemperatur, 1日前のWindgeschwindigkeit, 2日前のWindgeschwindigkeit, 3日前のWindgeschwindigkeit]→ (Voraussichtlicher Schneefall am Tag)

Ich habe es so gemacht. Grundsätzlich werden die Daten des prognostizierten Zieldatums angegeben, aber nur ein "gestriger Schneefall" sind die Daten einen Tag vor dem prognostizierten Zieldatum. Und es schien den größten Einfluss auf die Daten zu haben, die es gab. Nun, wenn Sie darüber nachdenken, ist es natürlich.

Wie ich zu Beginn geschrieben habe, werde ich die Daten aus den Daten der Meteorologischen Agentur für etwa 7500 Tage für das Training verwenden, die Änderung des Schneefalls für die verbleibenden 2 Jahre vorhersagen und sie mit der tatsächlichen Änderung des Schneefalls vergleichen.

Versuchen Sie vorherzusagen

Der eigentliche Code sieht folgendermaßen aus:

snow_forecaster.py



import csv
import numpy as np
from matplotlib import pyplot
from sklearn import linear_model
from sklearn import cross_validation


class SnowForecast:

    def __init__(self):
        u"""Initialisieren Sie jede Instanzvariable"""
        self.model = None    #Generiertes Lernmodell
        self.data = []       #Array von Trainingsdaten
        self.target = []     #Anordnung des tatsächlichen Schneefalls
        self.predicts = []   #Anordnung der vorhergesagten Schneefallwerte
        self.reals = []      #Anordnung des tatsächlichen Schneefalls
        self.day_counts = [] #Anordnung der verstrichenen Daten ab dem Startdatum
        self.date_list = []
        self.record_count = 0

    def load_csv(self):
        u"""Lesen Sie eine CSV-Datei zum Lernen"""
        with open("sample_data/data.csv", "r") as f:
            reader = csv.reader(f)
            accumulation_yesterday0 = 0
            date_yesterday = ""            
            temp_3days = []
            wind_speed_3days = []

            for row in reader:
                if row[4] == "":
                    continue

                daytime = row[0]               # "yyyy/mmdd HH:MM:SS"
                date = daytime.split(" ")[0]   # "yyyy/mm/dd"
                temp = int(float(row[1]))      #Temperatur. Es gibt einen subtilen Effekt
                wind_speed = float(row[7])     #Windgeschwindigkeit. Es gibt einen subtilen Effekt
                precipitation = float(row[12]) #Niederschlag. Kein Effekt
                accumulation = int(row[4])     #Die Schneemenge. Die Menge an Schneefall gestern hat einen großen Einfluss

                if len(wind_speed_3days) == 3:
                    #Trainingsdaten
                    # [Temperatur,Windgeschwindigkeit,Schneefall von gestern,1日前のTemperatur,2日前のTemperatur,3日前のTemperatur, 1日前のWindgeschwindigkeit, 2日前のWindgeschwindigkeit, 3日前のWindgeschwindigkeit]
                    sample = [temp, wind_speed, accumulation_yesterday0]
                    sample.extend(temp_3days)
                    sample.extend(wind_speed_3days)
                    self.data.append(sample)
                    self.target.append(accumulation)

                if date_yesterday != date:
                    accumulation_yesterday0 = accumulation
                    self.date_list.append(date)

                    wind_speed_3days.insert(0, wind_speed)
                    if len(wind_speed_3days) > 3:
                        wind_speed_3days.pop()

                    temp_3days.insert(0, temp)
                    if len(temp_3days) > 3:
                        temp_3days.pop()

                    date_yesterday = date

        self.record_count = len(self.data)
        return self.data

    def train(self):
        u"""Generieren Sie ein Trainingsmodell. Verwenden Sie bis zu 7500 Tage der Originaldaten für Trainingsdaten"""
        x = self.data
        y = self.target
        print(len(x))
        # ElasticNetCV,LassoCV,Wählen Sie Elastic NetCV mit dem kleinsten Fehler von RidgeCV
        model = linear_model.ElasticNetCV(fit_intercept=True)
        model.fit(x[0:self.training_data_count()], y[0:self.training_data_count()])
        self.model = model

    def predict(self):
        u"""Vorhersage mit einem Lernmodell. Machen Sie Vorhersagen für die letzten zwei Jahre"""
        x = self.data
        y = self.target
        model = self.model

        for i, xi in enumerate(x):
            real_val = y[i]

            if i < self.training_data_count() + 1:
                self.predicts.append(0)
                self.reals.append(real_val)
                self.day_counts.append(i)
                continue

            predict_val = int(model.predict([xi])[0])

            #Wenn die Schneefallvorhersage 0 oder weniger beträgt, wird sie auf 0 gesetzt.
            if predict_val < 0:
                predict_val = 0

            self.predicts.append(predict_val)
            self.reals.append(real_val)
            self.day_counts.append(i)

    def show_graph(self):
        u"""Vergleichen Sie vorhergesagte und gemessene Werte mit einem Diagramm"""
        pyplot.plot(self.day_counts[self.predict_start_num():], self.reals[self.predict_start_num():], "b")
        pyplot.plot(self.day_counts[self.predict_start_num():], self.predicts[self.predict_start_num():], "r")
        pyplot.show()

    def check(self):
        u"""Messen Sie den Fehler zwischen Trainingsdaten und Vorhersagedaten"""
        x = np.array(self.data[self.predict_start_num():])
        y = np.array(self.target[self.predict_start_num():])
        model = self.model
        p = np.array(self.predicts[self.predict_start_num():])
        e = p - np.array(self.reals[self.predict_start_num():])
        error = np.sum(e * e)
        rmse_10cv = np.sqrt(error / len(self.data[self.predict_start_num():]))
        print("RMSE(10-fold CV: {})".format(rmse_10cv))

    def training_data_count(self):
        u"""Verlassen Sie die letzten zwei Jahre und verwenden Sie die Daten davor als Trainingsdaten. Gibt die Anzahl der Trainingsdaten zurück"""
        return self.record_count - 365 * 2

    def predict_start_num(self):
        u"""Die letzten zwei Jahre werden vorhergesagt und verwendet, um den Fehler aus dem gemessenen Wert zu messen. Gibt die vorhergesagte Startposition zurück"""
        return self.training_data_count() + 1

if __name__ == "__main__":
    forecaster = SnowForecast()
    forecaster.load_csv()
    forecaster.train()
    forecaster.predict()
    forecaster.check()
    forecaster.show_graph()

Der nervigste Teil war das Erstellen von Trainingsdaten aus Rohdaten wie im vorherigen Kapitel. Trotzdem ist es einfach, weil es Python ist.

Das Ausführungsergebnis lautet also wie folgt (blau ist die tatsächliche Schneemenge, rote Linie ist die vorhergesagte Schneemenge). Dies ist das erste gezeigte "Ergebnis 1". スクリーンショット 2016-05-01 17.45.39.png

Ich sage so etwas voraus.

Zu diesem Zeitpunkt fragte ich mich plötzlich, wie ich das machen sollte. "Aber ich sage voraus, indem ich die Schneemenge vor einem Tag gebe. Wenn ich also tatsächlich versuche, sie für zukünftige Vorhersagen zu verwenden, kann ich die Schneemenge erst morgen vorhersagen ...?" b>

Nein, weißt du Wenn Sie das sagen, sind Temperatur und Windgeschwindigkeit gleich. Aber Sie sehen, es sind Wettervorhersagen ... Gefun Gefun

Geändert, um den Schneefall des nächsten Tages anhand des von mir vorhergesagten Schneefalls von gestern vorherzusagen

Also habe ich den Code sofort so geändert. Es gibt keine besonderen Änderungen am Trainingsteil des Modells. Von den Daten, die bei der Vorhersage der Schneefallmenge angegeben wurden, ersetzen wir "die Schneefallmenge für gestern" durch den "vorhergesagten Wert einen Tag vor dem vorhergesagten Wert" anstelle des tatsächlichen Messwerts.

Der Code lautet wie folgt. Nur die "Vorhersage" -Funktion hat sich geändert.

snow_forecaster.py


import csv
import numpy as np
from matplotlib import pyplot
from sklearn import linear_model
from sklearn import cross_validation


class SnowForecast:

    def __init__(self):
        u"""Initialisieren Sie jede Instanzvariable"""
        self.model = None    #Generiertes Lernmodell
        self.data = []       #Array von Trainingsdaten
        self.target = []     #Anordnung des tatsächlichen Schneefalls
        self.predicts = []   #Anordnung der vorhergesagten Schneefallwerte
        self.reals = []      #Anordnung des tatsächlichen Schneefalls
        self.day_counts = [] #Anordnung der verstrichenen Daten ab dem Startdatum
        self.date_list = []
        self.record_count = 0

    def load_csv(self):
        u"""Lesen Sie eine CSV-Datei zum Lernen"""
        with open("sample_data/data.csv", "r") as f:
            reader = csv.reader(f)
            accumulation_yesterday0 = 0
            date_yesterday = ""            
            temp_3days = []
            wind_speed_3days = []

            for row in reader:
                if row[4] == "":
                    continue

                daytime = row[0]               # "yyyy/mmdd HH:MM:SS"
                date = daytime.split(" ")[0]   # "yyyy/mm/dd"
                temp = int(float(row[1]))      #Temperatur. Es gibt einen subtilen Effekt
                wind_speed = float(row[7])     #Windgeschwindigkeit. Es gibt einen subtilen Effekt
                precipitation = float(row[12]) #Niederschlag. Kein Effekt
                accumulation = int(row[4])     #Die Schneemenge. Die Menge an Schneefall gestern hat einen großen Einfluss

                if len(wind_speed_3days) == 3:
                    #Trainingsdaten
                    # [Temperatur,Windgeschwindigkeit,Schneefall von gestern,1日前のTemperatur,2日前のTemperatur,3日前のTemperatur, 1日前のWindgeschwindigkeit, 2日前のWindgeschwindigkeit, 3日前のWindgeschwindigkeit]
                    sample = [temp, wind_speed, accumulation_yesterday0]
                    sample.extend(temp_3days)
                    sample.extend(wind_speed_3days)
                    self.data.append(sample)
                    self.target.append(accumulation)

                if date_yesterday != date:
                    accumulation_yesterday0 = accumulation
                    self.date_list.append(date)

                    wind_speed_3days.insert(0, wind_speed)
                    if len(wind_speed_3days) > 3:
                        wind_speed_3days.pop()

                    temp_3days.insert(0, temp)
                    if len(temp_3days) > 3:
                        temp_3days.pop()

                    date_yesterday = date

        self.record_count = len(self.data)
        return self.data

    def train(self):
        u"""Generieren Sie ein Trainingsmodell. Verwenden Sie bis zu 7500 Tage der Originaldaten für Trainingsdaten"""
        x = self.data
        y = self.target
        print(len(x))
        # ElasticNetCV,LassoCV,Wählen Sie Elastic NetCV mit dem kleinsten Fehler von RidgeCV
        model = linear_model.ElasticNetCV(fit_intercept=True)
        model.fit(x[0:self.training_data_count()], y[0:self.training_data_count()])
        self.model = model

    def predict(self):
        u"""Prognostizieren Sie die Schneefallmenge mithilfe eines Lernmodells. Machen Sie Vorhersagen für die letzten zwei Jahre"""
        x = self.data
        y = self.target
        model = self.model
        yesterday_predict_val = None #Variable zum Speichern des vorhergesagten Werts von gestern

        for i, xi in enumerate(x):
            real_val = y[i]

            if i < self.training_data_count() + 1:
                self.predicts.append(0)
                self.reals.append(real_val)
                self.day_counts.append(i)
                continue

            #Ersetzen Sie den gestrigen Schneefall durch die gestrige Vorhersage
            if yesterday_predict_val != None:
                xi[2] = yesterday_predict_val

            predict_val = int(model.predict([xi])[0])

            #Wenn die Schneefallvorhersage 0 oder weniger beträgt, wird sie auf 0 gesetzt.
            if predict_val < 0:
                predict_val = 0

            self.predicts.append(predict_val)
            self.reals.append(real_val)
            self.day_counts.append(i)
            yesterday_predict_val = predict_val

    def show_graph(self):
        u"""Vergleichen Sie vorhergesagte und gemessene Werte mit einem Diagramm"""
        pyplot.plot(self.day_counts[self.predict_start_num():], self.reals[self.predict_start_num():], "b")
        pyplot.plot(self.day_counts[self.predict_start_num():], self.predicts[self.predict_start_num():], "r")
        pyplot.show()

    def check(self):
        u"""Messen Sie den Fehler zwischen Trainingsdaten und Vorhersagedaten"""
        x = np.array(self.data[self.predict_start_num():])
        y = np.array(self.target[self.predict_start_num():])
        model = self.model
        p = np.array(self.predicts[self.predict_start_num():])
        e = p - np.array(self.reals[self.predict_start_num():])
        error = np.sum(e * e)
        rmse_10cv = np.sqrt(error / len(self.data[self.predict_start_num():]))
        print("RMSE(10-fold CV: {})".format(rmse_10cv))

    def training_data_count(self):
        u"""Verlassen Sie die letzten zwei Jahre und verwenden Sie die Daten davor als Trainingsdaten. Gibt die Anzahl der Trainingsdaten zurück"""
        return self.record_count - 365 * 2

    def predict_start_num(self):
        u"""Die letzten zwei Jahre werden vorhergesagt und verwendet, um den Fehler aus dem gemessenen Wert zu messen. Gibt die vorhergesagte Startposition zurück"""
        return self.training_data_count() + 1

if __name__ == "__main__":
    forecaster = SnowForecast()
    forecaster.load_csv()
    forecaster.train()
    forecaster.predict()
    forecaster.check()
    forecaster.show_graph()

Das Ergebnis ist wie folgt (blau ist die tatsächliche Schneemenge, rote Linie ist die vorhergesagte Schneemenge). "Ergebnis 2" wird am Anfang angezeigt. スクリーンショット 2016-05-01 17.59.35.png

Hmm. Wie erwartet wurde es ungenauer als gestern, als die tatsächliche Schneemenge angegeben wurde. Es scheint jedoch, dass die Wellenform nicht so durcheinander ist.

Impressionen etc.

Ich habe mich gefragt, ob es eine eher durcheinandergebrachte Vorhersage sein würde, aber ich dachte, ich könnte sie so vorhersagen. Obwohl es von Gefun Gefun auf dem Weg erfolgreich getäuscht wurde, verwenden die bei der Vorhersage angegebene Temperatur und Windgeschwindigkeit die gemessenen Werte des Tages. Wenn Sie jedoch für einen bestimmten Zeitraum in der Zukunft Vorhersagen treffen möchten, haben Sie keine andere Wahl, als die vorhergesagten Werte separat zu verwenden oder diese Werte zunächst nicht mehr zu verwenden. Wenn Sie also die vorhergesagten Werte verwenden, ist die Genauigkeit höher. Es wird untergehen. Außerdem, je mehr die Zukunft. Wenn Sie also so etwas tun möchten, machen Sie eine Vorhersage mit dem vorhergesagten Wert, dann machen Sie eine Vorhersage mit ihm und so weiter. habe gedacht. Also tu dein Bestes (Meteorological Agency)

Recommended Posts