Lineare Regression - Länge der Daten y_test & predictions stimmen nicht überein

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
vitellinho
User
Beiträge: 13
Registriert: Dienstag 7. März 2023, 11:05

Hallo zusammen,

aus Trainingszwecken habe ich angefangen ein KI-Model zur Vorhersage des zukünftigen Bitcoin Kurses zu bauen. Dieser basiert auf dem LinearRegression Model aus sk-learn. Mir ist im ersten Zuge nur wichtig, dass Trainings- und Testphase fehlerfrei durchlaufen. Die Genauigkeit der Vorhersage und ein evtl. besseres Modell (zB. basierend auf ein KNN) würde ich im Anschluss aufarbeiten. Hier erstmal mein Code:

Code: Alles auswählen

import pandas as pd
import numpy as np
import yfinance as yf
import sklearn as sk
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import MinMaxScaler
import matplotlib.pyplot as plt

# Erstellung DataFrame
start = "2019-01-01"
end = "2021-01-01"
test_days = 60
bitcoin = yf.download("BTC-USD", start=start, end=end)
bitcoin = bitcoin[["Adj Close"]]
bitcoin_data = bitcoin.values

# Skalierung Daten (0 bis 1)
scaler = MinMaxScaler(feature_range=(0, 1))
scaled_data = scaler.fit_transform(bitcoin)

# Aufteilung Trainings-Set / Test-Set (um Länge zu prüfen: len() nutzen!)
training_len = int(len(scaled_data) * 0.8)
train_data = scaled_data[:training_len]
test_data = scaled_data[training_len:]

# Trennung train_data in x (Features) und y (Labels) + Befüllung
x_train = []
y_train = []
for i in range(test_days, len(train_data)):
    x_train.append(train_data[i - test_days:i])
    y_train.append(train_data[i])

# Falls nötig: reshape der testdaten zur Vorbereitung auf das Model (reshape geht nur bei arrays, deswegen Umwandlung mit np.array)
x_train, y_train = np.array(x_train), np.array(y_train)
x_train = x_train.reshape((len(x_train), -1))

# Trennung test_data in x (Features) und y (Labels) + Befüllung
x_test = []
y_test = []
for i in range(test_days, len(test_data)):
    x_test.append(test_data[i - test_days:i])
    y_test.append(test_data[i])

# Falls nötig: reshape der testdaten zur Vorbereitung auf das Model (reshape geht nur bei arrays, deswegen Umwandlung mit np.array)
x_test, y_test = np.array(x_test), np.array(y_test)
x_test = x_test.reshape((len(x_test), -1))

# Auswahl Model + Training
model = LinearRegression()
model.fit(x_train, y_train)

# Testen des Models + Rückskalierung der predictions und label (y_test)
predictions = model.predict(x_test)
predictions = scaler.inverse_transform(predictions)
y_test = scaler.inverse_transform(y_test)

# Berechnung root mean squared error (gibt die durchschnittliche Abweichung zwischen Vorhersage und Label wieder)
rmse = np.sqrt(np.mean(predictions- y_test)**2)
#print(rmse)

# Definition aller Variablen für Visualisierung (historische Daten (train), labeldaten (valid #1) und Vorhersage des Models (valid #2)
train = bitcoin[: training_len]
valid = bitcoin[training_len :] #1
valid["Predictions"] = predictions[-len(y_test):] #2

# Visualisierung der prediction vs. labeldaten
plt.figure(figsize=(16,8))
plt.title("Model")
plt.ylabel("BTC in $")
plt.xlabel("Date")
plt.plot(train["Adj Close"])
plt.plot(valid[["Adj Close", "Predictions"]])
#plt.legend()
plt.show()
Nun bin ich soweit ganz gut klar gekommen, konnte Fehlermeldungen gut beheben usw. Jetzt hänge ich aber ein Schritt vor Vollendung an der folgenden Fehlermeldung fest:

[*********************100%%**********************] 1 of 1 completed
Traceback (most recent call last):
File "/Users/vitellinho/PycharmProjects/Machine_Learning lernen/btc-usd.py", line 64, in <module>
valid["Predictions"] = predictions[-len(y_test):] #2
~~~~~^^^^^^^^^^^^^^^
File "/Users/vitellinho/PycharmProjects/Machine_Learning lernen/venv/lib/python3.11/site-packages/pandas/core/frame.py", line 4091, in __setitem__
self._set_item(key, value)
File "/Users/vitellinho/PycharmProjects/Machine_Learning lernen/venv/lib/python3.11/site-packages/pandas/core/frame.py", line 4300, in _set_item
value, refs = self._sanitize_column(value)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/vitellinho/PycharmProjects/Machine_Learning lernen/venv/lib/python3.11/site-packages/pandas/core/frame.py", line 5039, in _sanitize_column
com.require_length_match(value, self.index)
File "/Users/vitellinho/PycharmProjects/Machine_Learning lernen/venv/lib/python3.11/site-packages/pandas/core/common.py", line 561, in require_length_match
raise ValueError(
ValueError: Length of values (87) does not match length of index (147)

Anscheinend basiert das Problem auf die Codezeile

Code: Alles auswählen

valid["Predictions"] = predictions[-len(y_test):] #2
Ich habe es mit folgenden Alternativen probiert:

Code: Alles auswählen

valid["Predictions"] = predictions[-len(predictions):]

Code: Alles auswählen

valid["Predictions"] = predictions[-len(y_test):]
Fehlermeldung bleibt aber die selbe..


Hat jemand noch ne Idee?

Zusätzliche Infos:

Shape der trainings- und testdaten nach .reshape:

x_train = (524, 60)
y_train = (524, 1)

x_test = (87, 60)
y_test = (87, 1)
vitellinho
User
Beiträge: 13
Registriert: Dienstag 7. März 2023, 11:05

Update:

Habe gerade bisschen rum probiert und bemerkt, dass ich die Länge sowohl der test-, als auch traindaten in der for schleife durch train_days um 60 reduziere. Dementsprechend len() = 87.

Weiter unten habe ich in der Variable valid aber mit dem ursprünglichen Datensatz gearbeitet, weswegen hier folgende Länge vorliegt: len() = 147. Wenn man von dieser die train_days = 60 abzieht, kommt man wieder auf 87. Habe mein Code nun geändert:

Code: Alles auswählen

import pandas as pd
import numpy as np
import yfinance as yf
import sklearn as sk
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import MinMaxScaler
import matplotlib.pyplot as plt

# Erstellung DataFrame
start = "2019-01-01"
end = "2021-01-01"
test_days = 60
bitcoin = yf.download("BTC-USD", start=start, end=end)
bitcoin = bitcoin[["Adj Close"]]
bitcoin_data = bitcoin.values

# Skalierung Daten (0 bis 1)
scaler = MinMaxScaler(feature_range=(0, 1))
scaled_data = scaler.fit_transform(bitcoin)

# Aufteilung Trainings-Set / Test-Set (um Länge zu prüfen: len() nutzen!)
training_len = int(len(scaled_data) * 0.8)
train_data = scaled_data[:training_len]
test_data = scaled_data[training_len:]

print(len(test_data))

# Trennung train_data in x (Features) und y (Labels) + Befüllung
x_train = []
y_train = []
for i in range(test_days, len(train_data)):
    x_train.append(train_data[i - test_days:i])
    y_train.append(train_data[i])

# Falls nötig: reshape der testdaten zur Vorbereitung auf das Model (reshape geht nur bei arrays, deswegen Umwandlung mit np.array)
x_train, y_train = np.array(x_train), np.array(y_train)
x_train = x_train.reshape((len(x_train), -1))

# Trennung test_data in x (Features) und y (Labels) + Befüllung
x_test = []
y_test = []
for i in range(test_days, len(test_data)):
    x_test.append(test_data[i - test_days:i])
    y_test.append(test_data[i])

# Falls nötig: reshape der testdaten zur Vorbereitung auf das Model (reshape geht nur bei arrays, deswegen Umwandlung mit np.array)
x_test, y_test = np.array(x_test), np.array(y_test)
x_test = x_test.reshape((len(x_test), -1))

# Auswahl Model + Training
model = LinearRegression()
model.fit(x_train, y_train)

# Testen des Models + Rückskalierung der predictions und label (y_test)
predictions = model.predict(x_test)
predictions = scaler.inverse_transform(predictions)
y_test = scaler.inverse_transform(y_test)

# Berechnung root mean squared error (gibt die durchschnittliche Abweichung zwischen Vorhersage und Label wieder)
rmse = np.sqrt(np.mean(predictions- y_test)**2)
#print(rmse)

# Definition aller Variablen für Visualisierung (historische Daten (train), labeldaten (valid #1) und Vorhersage des Models (valid #2)
train = bitcoin[: training_len]
valid = bitcoin[training_len : -test_days] #1
valid["Predictions"] = predictions[-len(y_test):] #2

# Visualisierung der prediction vs. labeldaten
plt.figure(figsize=(16,8))
plt.title("Model")
plt.ylabel("BTC in $")
plt.xlabel("Date")
plt.plot(train["Adj Close"])
plt.plot(valid[["Adj Close", "Predictions"]])
#plt.legend()
plt.show()

Kriege nun eine Vorhersage raus :D

Nun noch die Frage, ist meine Vorgehensweise, bzw. der Code vom Grundsatz her richtig? Oder ist mein Vorgehen (insbesondere bzgl. train_days) falsch?
Antworten