Lekce 3 - Předpověď ceny zlata pomocí lineární regrese v Pythonu
V minulé lekci, Neuronové sítě v Pythonu - Prostředí Jupyter, jsme si představili prostředí Jupyter notebook pro Python.
Vítejte u další lekce, dnes si zkusíme předpovídat data pomocí
lineární regrese a pracovat s .csv
soubory pomocí knihovny
Pandas. Jak víte, než se dostaneme k neuronkám nám ještě chvíli potrvá
Lineární regrese
Určitě se mnozí z vás setkali s tímto vzorečkem:
Je to předpis lineární funkce. Tyto funkce jsou nám lidem velmi blízké a také jednoduché na pochopení.
Jablka
Představme si např. úlohu na sběr jablek v sadu. 1
farmář
sebere 200
jablek za hodinu. x
farmářů sebere
y = ax
jablek za hodinu, v našem případě se
a = 200
. Máme zde jednoduchý lineární vztah mezi x
a y
.
- Koeficient
a
je sklon funkce, čím více jeden formář dokáže jablek sebrat, tím více nám s každým farmářemy
povyroste. b
je tzv. bias (tento výraz rozebereme později u neuronových sítích) a dovoluje funkci posun, aby se lépe přizpůsobila datům. Můžeme např. říci, že ve skladu je již v základub = 500
jablek a výsledek funkce bude vždy o500
jablek vyšší, bez ohledu na hodnotyx
ay
.
Zlato
Přejděme na zajímavější komoditu. Řekněme, že programujeme jednoduchý předpovídač ceny zlata a historická data již máme.
Pro předpověď potřebujeme vytvořit přímku tak, aby prošla co nejvíce body v datasetu (jednoduše soubor dat, který chceme předpovídat) a tedy odpovídala co nejpřesněji tomu, jak cena zlata roste nebo klesá. Právě pomocí lineární regrese zjednodušíme velké množství bodů (cen zlata v daný okamžik) na pouhou přímku, čímž samozřejmě ztratíme určitou přesnost. Této metodě "osekání" nějaké složité funkce na podobnou jednodušší funkci se v matematice obecně říká aproximace.
Abychom lineární funkci přizpůsobili, potřebujeme ji takzvaně
"optimalizovat". To se týká proměnných a
a b
,
jelikož x
je vstup (v tomto případě čas). Ukážeme si 2
způsoby, jak můžeme funkci optimalizovat:
- Dopočítání z dat - Spočítáme sklon
a
a následněb
- Gradientní metoda - U této metody vybereme
a
ab
náhodně a postupně je podle námi definované chybové funkce optimalizujeme, dokud není chyba co nejmenší
Výpočet ceny zlata v Pythonu
Nyní již známe vzorec pro lineární funkci a můžeme si tedy ukázat jednoduchý příklad v Pythonu. Spusťme si prostředí, které jsme si představili v minulé lekci, a dle potřeby si vytvořme nový notebook.
Import knihoven
Nejdříve je potřeba importovat knihovny s kterými budeme pracovat:
from sklearn.linear_model import LinearRegression import numpy as np import matplotlib.pyplot as plt
Zjednodušený příklad
Než se vrhneme na reálné ceny zlata, začneme jednodušším příkladem.
Vstupní a výstupní data
Pro ukázku si definujeme jednoduchý příklad: Chceme výstup o
2
větší než vstup. V tomto případě chceme sklon
a = 1
a bias b = 2
.
Funkci můžeme rychle ověřit při vstupu 3
:
y = 1 * 3 + 2
y = 5
V kódu pro tyto hodnoty definujeme vstupní a výstupní data, čímž nasimulujeme podobný případ jako se zlatem - máme hodnoty před a po změně, ale nevíme vzoreček, jakým změny předpovídat. Budeme se tedy snažit uhádnout naši lineární funkci:
# Definujeme si vstupní data, v tomto případě 1 a 3 x = np.array([[1], [3]]) # Definujeme si výstup, který chceme. # Pokud je vstup 1, chceme výstup 3 # Pokud je vstup 3, chceme výstup 5 y = np.array([[3], [5]])
Regressor
Data jsou připravena, nyní si můžeme vytvořit Regressor
neboli lineární funkci a optimalizovat ji na naše data:
# Vytvoříme regressor neboli lineární funkci reg = LinearRegression() # Optimalizujeme reg.fit(x, y)
Metodě fit()
jednoduše předáme vstupní a výstupní data a
ona zjistí vztah mezi nimi. Jak si funkce vede ověříme pomocí metody
score()
.
reg.score(x, y)
Výsledek:
1
Metoda vrátila výsledek 1
, což znamená, že mezi
x
a y
je vysoká korelace neboli vztah. Když
x
stoupá, y
také stoupá, přesněji o
2
. Zjednodušeně to znamená, že naše funkce protíná všechny
body, jak i uvidíte dále v grafu.
Vytvoříme si tedy graf pro vizualizaci funkce, kterou zjišťujeme, a bodů, které již máme z dat:
# Pomocí funkce plot() se vykreslí čárový graf plt.plot(x, reg.predict(x)) # Pomocí funkce scatter() vykreslíme jednotlivé body v grafu # V tomto případě body [1, 3] a [3, 5] plt.scatter(x, y, c="r") # v parametru c specifikujeme styl bodů, chceme je červené
Vidíme, že metoda predict()
nám zobrazila přímku
odpovídající změně našich dat. Metoda scatter()
na ni pak
dále vykreslila body, v našem případě jen dva.
Zobrazíme si sklon a bias funkce a ověříme si tak, že jsme měli pravdu:
a = reg.coef_ b = reg.intercept_ print("Sklon je {} a bias je {}".format(a, b))
Výsledkem jsou opravdu koeficienty lineární funkce, podle které jsme data vytvořili:
Sklon je [[1.]] a bias je [2.]
Zlato!
Už umíme předpovídat data za pomoci knihovny scikit-learn
,
proto se vrhneme na příklad s reálnými daty o ceně zlata.
Příprava reálných dat
Ještě předtím než začneme, potřebujeme data. Ta můžeme stáhnout
např. zde : https://pkgstore.datahub.io/…thly_csv.csv.
Stažený .csv
soubor přesuneme do složky s aktuálním
.ipynb
notebookem. Pokud nevíte, kde se nachází, přesuňte se
na předchozí záložku v prohlížeči a tam bude běžící notebook označen
zeleně:
Výtečně, soubor monthly_csv.csv
máme v naší pracovní
složce a můžeme se tedy vrhnout na tvorbu předpovídače.
Importy
Importujeme si tedy ještě knihovnu Pandas
pro čtení dat z
.csv
, naše prvotní importy ponecháme:
import pandas as pd
Čtení dat
Přečteme data ze souboru a zobrazíme si hlavičku neboli prvních 5
řádků .csv
souboru:
data = pd.read_csv("monthly_csv.csv")
data.head()
Výsledek:
Date Price 0 1950-01 34.73 1 1950-02 34.73 2 1950-03 34.73 3 1950-04 34.73 4 1950-05 34.73
Jak můžeme vidět, dataset obsahuje 2 vlastnosti: Datum
a
Cenu
. Datum
budeme reprezentovat jako počet měsíců
od 1.1.1950, což je začátek datasetu. V den, kdy jsem tento článek psal, je
maximální index 833
, což je 1.6.2019.
Vstupy a výstupy
Připravíme si tedy opět vstupy a výstupy:
# numpy pole od 0 do 833 ve dne 14.6.2019 x = np.arange(len(data)) # Ceny převedeme na numpy pole y = data["Price"].to_numpy()
Data ještě musíme převést do tvaru, který funkce fit()
požaduje, což je (vzorek, vlastnosti)
. My zatím máme jen
(hodnoty)
.
Představte si vzorek jako člověka a hodnoty jako nějaké jeho vlastnosti,
jako např. výška
a váha
. Vstup by v tomto
případě vypadal takto: [ [173, 71] ]
. Pokud bychom chtěli více
lidí, vypadal by vstup takto: [ [173, 71], [183, 86] ]
.
My tedy potřebujeme převést Cena
a Datum
na
tento tvar, jelikož zatím mají tvar:
[34.73, 34.73, 34.73, 34.73, 34.73]
a
[0, 1, 2, 3 4, 5]
. Náš požadovaný tvar vypadá takto:
[ [34.73], [34.73], [34.73], [34.73], [34.73] ]
a
[ [0], [1], [2], [3], [4], [5] ]
.
Jelikož je knihovna NumPy
dělaná na práci s
n-dimenzionálními poli, toto je jednodušší, než se zdá. Stačí použít
funkci reshape()
a zadat žádaný tvar. Funkci můžeme zadat tvar
například (32, 2)
, pokud velikost pole sedí, tedy je
64 => 32 * 2
. Pokud funkci zadáme (-1, 2)
,
automaticky si dopočítá chybějící dimenzi, takto lze použít pouze na
jednu dimenzi.
Nejdříve si zobrazíme tvar x
před změnou tvaru:
x.shape
Výsledek:
(834,)
Změníme tvar x
a y
:
x = x.reshape(-1, 1) y = y.reshape(-1, 1)
A tvary si vypíšeme:
x.shape, y.shape
Výsledek:
((834, 1), (834, 1))
Lineární regrese
Nyní pojďme zobecnit pohyb ceny zlata na jednoduchou lineární funkci.
Data jsou připravená, vytvoříme si tedy LinearRegression()
a
optimalizujeme funkci pomocí metody fit()
:
reg = LinearRegression() reg.fit(x, y)
Podíváme se, jak si funkce vede pomocí metody score()
.
reg.score(x, y)
Výsledek:
0.6859359867746044
Jak jsme asi tušili, tak jednoduché to nebude Funkce si nevede nějak dobře, to
nám značí, že Cena
není tak moc závislá na
Datum
. Vizualizujeme si vše v grafu, abychom se
přesvědčili:
plt.plot(x, reg.predict(x))
plt.scatter(x, y, c="r")
Výsledek:
I přesto, že funkce není ideální, bude zajímavé zjistit, jakou
předpoví Cenu
pro datum 1.7.2025 oproti dnešku. To je dle mých
výpočtů index 906
. Cena dnes je:
data["Price"][833]
Výsledek:
1358.4879999999998
A cena v roce 2025:
reg.predict([[906]]).item()
Výsledek:
1126.481982068847
Náš jednoduchý předpovídač předpovídá, že zlato rozhodně není vhodná investice. O tom zda je to pravda, se ještě dozvíme u polynomiální regrese, která si s tím dokáže poradit lépe. To vše se brzy dozvíte v následujících lekcích.
V následujícím kvízu, Kvíz - Základy neuronových sítí v Pythonu, si vyzkoušíme nabyté zkušenosti z předchozích lekcí.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 141x (59.61 kB)
Aplikace je včetně zdrojových kódů v jazyce Python