23 KiB
Vytvoření regresního modelu pomocí Scikit-learn: čtyři způsoby regresí
Infografika od Dasani Madipalli
Kvíz před lekcí
Tato lekce je dostupná v R!
Úvod
Doposud jste prozkoumali, co je regrese, na vzorových datech získaných z datasetu cen dýní, který budeme používat v celé této lekci. Také jste ji vizualizovali pomocí Matplotlibu.
Nyní jste připraveni ponořit se hlouběji do regresí pro strojové učení. Zatímco vizualizace vám umožňuje pochopit data, skutečná síla strojového učení spočívá v trénování modelů. Modely jsou trénovány na historických datech, aby automaticky zachytily závislosti mezi daty, a umožňují vám předpovídat výsledky pro nová data, která model dosud neviděl.
V této lekci se dozvíte více o dvou typech regresí: základní lineární regrese a polynomiální regrese, spolu s některými matematickými základy těchto technik. Tyto modely nám umožní předpovídat ceny dýní na základě různých vstupních dat.
🎥 Klikněte na obrázek výše pro krátký video přehled o lineární regresi.
V celém tomto kurzu předpokládáme minimální znalosti matematiky a snažíme se ji zpřístupnit studentům z jiných oborů, takže sledujte poznámky, 🧮 výpočty, diagramy a další učební nástroje, které vám pomohou s pochopením.
Předpoklady
Nyní byste měli být obeznámeni se strukturou dat o dýních, která zkoumáme. Najdete je předem načtená a předem vyčištěná v souboru notebook.ipynb této lekce. V souboru je cena dýní zobrazena za bušl v novém datovém rámci. Ujistěte se, že můžete tyto notebooky spustit v jádrech ve Visual Studio Code.
Příprava
Připomeňme si, že tato data načítáte, abyste si mohli klást otázky:
- Kdy je nejlepší čas na nákup dýní?
- Jakou cenu mohu očekávat za balení mini dýní?
- Mám je koupit v polovičních bušlových koších nebo v krabici o velikosti 1 1/9 bušlu? Pokračujme v prozkoumávání těchto dat.
V předchozí lekci jste vytvořili datový rámec Pandas a naplnili jej částí původního datasetu, standardizovali ceny podle bušlu. Tímto způsobem jste však byli schopni shromáždit pouze asi 400 datových bodů a pouze pro podzimní měsíce.
Podívejte se na data, která jsme předem načetli v doprovodném notebooku této lekce. Data jsou předem načtena a počáteční bodový graf je vytvořen, aby ukázal data podle měsíců. Možná můžeme získat trochu více detailů o povaze dat jejich dalším čištěním.
Lineární regresní přímka
Jak jste se naučili v lekci 1, cílem cvičení lineární regrese je být schopen vykreslit přímku, která:
- Ukazuje vztahy mezi proměnnými. Ukazuje vztah mezi proměnnými
- Dělá předpovědi. Umožňuje přesně předpovědět, kde by nový datový bod spadal ve vztahu k této přímce.
Je typické pro regresi metodou nejmenších čtverců, že se kreslí tento typ přímky. Termín 'nejmenší čtverce' znamená, že všechny datové body obklopující regresní přímku jsou umocněny na druhou a poté sečteny. Ideálně je tento konečný součet co nejmenší, protože chceme nízký počet chyb, tedy nejmenší čtverce
.
Děláme to proto, že chceme modelovat přímku, která má nejmenší kumulativní vzdálenost od všech našich datových bodů. Také umocňujeme hodnoty na druhou před jejich sečtením, protože nás zajímá jejich velikost, nikoli směr.
🧮 Ukažte mi matematiku
Tato přímka, nazývaná přímka nejlepšího přizpůsobení, může být vyjádřena rovnicí:
Y = a + bX
X
je 'vysvětlující proměnná'.Y
je 'závislá proměnná'. Sklon přímky jeb
aa
je průsečík s osou Y, což odkazuje na hodnotuY
, kdyžX = 0
.Nejprve vypočítejte sklon
b
. Infografika od Jen LooperJinými slovy, a odkazujíc na původní otázku o datech dýní: "předpovězte cenu dýně za bušl podle měsíce",
X
by odkazovalo na cenu aY
by odkazovalo na měsíc prodeje.Vypočítejte hodnotu Y. Pokud platíte kolem $4, musí být duben! Infografika od Jen Looper
Matematika, která vypočítává přímku, musí ukázat sklon přímky, který také závisí na průsečíku, tedy na tom, kde se
Y
nachází, kdyžX = 0
.Metodu výpočtu těchto hodnot můžete pozorovat na webu Math is Fun. Navštivte také tento kalkulátor nejmenších čtverců, abyste viděli, jak hodnoty čísel ovlivňují přímku.
Korelace
Ještě jeden termín, který je třeba pochopit, je koeficient korelace mezi danými proměnnými X a Y. Pomocí bodového grafu můžete rychle vizualizovat tento koeficient. Graf s datovými body rozptýlenými v úhledné přímce má vysokou korelaci, ale graf s datovými body rozptýlenými všude mezi X a Y má nízkou korelaci.
Dobrý model lineární regrese bude takový, který má vysoký (blíže k 1 než k 0) koeficient korelace pomocí metody nejmenších čtverců s regresní přímkou.
✅ Spusťte notebook doprovázející tuto lekci a podívejte se na bodový graf Měsíc vs. Cena. Zdá se, že data spojující Měsíc s Cenou za prodej dýní mají podle vašeho vizuálního hodnocení bodového grafu vysokou nebo nízkou korelaci? Změní se to, pokud použijete jemnější měřítko místo Měsíc
, např. den v roce (tj. počet dní od začátku roku)?
V níže uvedeném kódu předpokládáme, že jsme data vyčistili a získali datový rámec nazvaný new_pumpkins
, podobný následujícímu:
ID | Měsíc | DenVRoce | Druh | Město | Balení | Nízká cena | Vysoká cena | Cena |
---|---|---|---|---|---|---|---|---|
70 | 9 | 267 | PIE TYPE | BALTIMORE | 1 1/9 bushel cartons | 15.0 | 15.0 | 13.636364 |
71 | 9 | 267 | PIE TYPE | BALTIMORE | 1 1/9 bushel cartons | 18.0 | 18.0 | 16.363636 |
72 | 10 | 274 | PIE TYPE | BALTIMORE | 1 1/9 bushel cartons | 18.0 | 18.0 | 16.363636 |
73 | 10 | 274 | PIE TYPE | BALTIMORE | 1 1/9 bushel cartons | 17.0 | 17.0 | 15.454545 |
74 | 10 | 281 | PIE TYPE | BALTIMORE | 1 1/9 bushel cartons | 15.0 | 15.0 | 13.636364 |
Kód pro čištění dat je dostupný v
notebook.ipynb
. Provedli jsme stejné kroky čištění jako v předchozí lekci a vypočítali sloupecDenVRoce
pomocí následujícího výrazu:
day_of_year = pd.to_datetime(pumpkins['Date']).apply(lambda dt: (dt-datetime(dt.year,1,1)).days)
Nyní, když máte pochopení matematiky za lineární regresí, vytvořme regresní model, abychom zjistili, zda můžeme předpovědět, které balení dýní bude mít nejlepší ceny dýní. Někdo, kdo kupuje dýně pro sváteční dýňovou zahradu, by mohl chtít tyto informace, aby mohl optimalizovat své nákupy balení dýní pro zahradu.
Hledání korelace
🎥 Klikněte na obrázek výše pro krátký video přehled o korelaci.
Z předchozí lekce jste pravděpodobně viděli, že průměrná cena pro různé měsíce vypadá takto:

To naznačuje, že by měla existovat nějaká korelace, a můžeme zkusit trénovat model lineární regrese, abychom předpověděli vztah mezi Měsíc
a Cena
, nebo mezi DenVRoce
a Cena
. Zde je bodový graf, který ukazuje druhý vztah:

Podívejme se, zda existuje korelace pomocí funkce corr
:
print(new_pumpkins['Month'].corr(new_pumpkins['Price']))
print(new_pumpkins['DayOfYear'].corr(new_pumpkins['Price']))
Zdá se, že korelace je poměrně malá, -0.15 podle Měsíc
a -0.17 podle DenVRoce
, ale mohlo by existovat jiné důležité spojení. Zdá se, že existují různé shluky cen odpovídající různým druhům dýní. Abychom tuto hypotézu potvrdili, vykresleme každou kategorii dýní pomocí jiné barvy. Předáním parametru ax
funkci pro vykreslení bodového grafu můžeme vykreslit všechny body na stejný graf:
ax=None
colors = ['red','blue','green','yellow']
for i,var in enumerate(new_pumpkins['Variety'].unique()):
df = new_pumpkins[new_pumpkins['Variety']==var]
ax = df.plot.scatter('DayOfYear','Price',ax=ax,c=colors[i],label=var)

Naše zkoumání naznačuje, že druh má větší vliv na celkovou cenu než skutečné datum prodeje. Můžeme to vidět na sloupcovém grafu:
new_pumpkins.groupby('Variety')['Price'].mean().plot(kind='bar')

Zaměřme se nyní pouze na jeden druh dýní, 'pie type', a podívejme se, jaký vliv má datum na cenu:
pie_pumpkins = new_pumpkins[new_pumpkins['Variety']=='PIE TYPE']
pie_pumpkins.plot.scatter('DayOfYear','Price')

Pokud nyní vypočítáme korelaci mezi Cena
a DenVRoce
pomocí funkce corr
, dostaneme něco jako -0.27
- což znamená, že trénování prediktivního modelu má smysl.
Před trénováním modelu lineární regrese je důležité zajistit, že naše data jsou čistá. Lineární regrese nefunguje dobře s chybějícími hodnotami, proto má smysl zbavit se všech prázdných buněk:
pie_pumpkins.dropna(inplace=True)
pie_pumpkins.info()
Dalším přístupem by bylo vyplnit tyto prázdné hodnoty průměrnými hodnotami z odpovídajícího sloupce.
Jednoduchá lineární regrese
🎥 Klikněte na obrázek výše pro krátký video přehled o lineární a polynomiální regresi.
Pro trénování našeho modelu lineární regrese použijeme knihovnu Scikit-learn.
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split
Začneme oddělením vstupních hodnot (features) a očekávaného výstupu (label) do samostatných numpy polí:
X = pie_pumpkins['DayOfYear'].to_numpy().reshape(-1,1)
y = pie_pumpkins['Price']
Všimněte si, že jsme museli provést
reshape
na vstupních datech, aby je balíček lineární regrese správně pochopil. Lineární regrese očekává 2D pole jako vstup, kde každý řádek pole odpovídá vektoru vstupních vlastností. V našem případě, protože máme pouze jeden vstup, potřebujeme pole s tvarem N×1, kde N je velikost datasetu.
Poté musíme data rozdělit na trénovací a testovací dataset, abychom mohli po trénování ověřit náš model:
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
Nakonec samotné trénování modelu lineární regrese zabere pouze dva řádky kódu. Definujeme objekt LinearRegression
a přizpůsobíme ho našim datům pomocí metody fit
:
lin_reg = LinearRegression()
lin_reg.fit(X_train,y_train)
Objekt LinearRegression
po přizpůsobení obsahuje všechny koeficienty regrese, které lze získat pomocí vlastnosti .coef_
. V našem případě je pouze jeden koeficient, který by měl být kolem -0.017
. To znamená, že ceny se zdají s časem mírně klesat, ale ne příliš, asi o 2 centy za den. Průsečík regrese s osou Y můžeme také získat pomocí lin_reg.intercept_
- bude kolem 21
v našem případě, což naznačuje cenu na začátku roku.
Abychom viděli, jak přesný je náš model, můžeme předpovědět ceny na testovacím datasetu a poté změřit, jak blízko jsou naše předpovědi očekávaným hodnotám. To lze provést pomocí metriky střední kvadratické chyby (MSE), což je průměr všech kvadratických rozdílů mezi očekávanou a předpovězenou hodnotou.
pred = lin_reg.predict(X_test)
mse = np.sqrt(mean_squared_error(y_test,pred))
print(f'Mean error: {mse:3.3} ({mse/np.mean(pred)*100:3.3}%)')
Naše chyba se zdá být kolem 2 bodů, což je ~17 %. Nic moc. Dalším ukazatelem kvality modelu je koeficient determinace, který lze získat takto:
score = lin_reg.score(X_train,y_train)
print('Model determination: ', score)
Pokud je hodnota 0, znamená to, že model nebere v úvahu vstupní data a funguje jako nejhorší lineární prediktor, což je jednoduše průměrná hodnota výsledku. Hodnota 1 znamená, že můžeme dokonale předpovědět všechny očekávané výstupy. V našem případě je koeficient kolem 0,06, což je poměrně nízké.
Můžeme také vykreslit testovací data spolu s regresní přímkou, abychom lépe viděli, jak regresní analýza v našem případě funguje:
plt.scatter(X_test,y_test)
plt.plot(X_test,pred)

Polynomická regrese
Dalším typem lineární regrese je polynomická regrese. Zatímco někdy existuje lineární vztah mezi proměnnými – čím větší je objem dýně, tím vyšší je cena – někdy tyto vztahy nelze vykreslit jako rovinu nebo přímku.
✅ Zde jsou některé další příklady dat, která by mohla využít polynomickou regresi.
Podívejte se znovu na vztah mezi datem a cenou. Zdá se, že tento bodový graf by měl být nutně analyzován přímkou? Nemohou ceny kolísat? V tomto případě můžete zkusit polynomickou regresi.
✅ Polynomy jsou matematické výrazy, které mohou obsahovat jednu nebo více proměnných a koeficientů.
Polynomická regrese vytváří zakřivenou čáru, která lépe odpovídá nelineárním datům. V našem případě, pokud do vstupních dat zahrneme kvadratickou proměnnou DayOfYear
, měli bychom být schopni přizpůsobit naše data parabolické křivce, která bude mít minimum v určitém bodě během roku.
Scikit-learn obsahuje užitečné API pipeline pro kombinaci různých kroků zpracování dat dohromady. Pipeline je řetězec odhadovačů. V našem případě vytvoříme pipeline, která nejprve přidá polynomické prvky do našeho modelu a poté provede trénink regrese:
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import make_pipeline
pipeline = make_pipeline(PolynomialFeatures(2), LinearRegression())
pipeline.fit(X_train,y_train)
Použití PolynomialFeatures(2)
znamená, že zahrneme všechny polynomy druhého stupně ze vstupních dat. V našem případě to bude jednoduše DayOfYear
2, ale pokud máme dvě vstupní proměnné X a Y, přidá to X2, XY a Y2. Můžeme také použít polynomy vyššího stupně, pokud chceme.
Pipeline lze použít stejným způsobem jako původní objekt LinearRegression
, tj. můžeme pipeline fit
a poté použít predict
k získání výsledků predikce. Zde je graf zobrazující testovací data a aproximační křivku:

Použitím polynomické regrese můžeme dosáhnout mírně nižší MSE a vyšší determinace, ale ne výrazně. Musíme vzít v úvahu další prvky!
Vidíte, že minimální ceny dýní jsou pozorovány někde kolem Halloweenu. Jak to můžete vysvětlit?
🎃 Gratulujeme, právě jste vytvořili model, který může pomoci předpovědět cenu dýní na koláče. Pravděpodobně můžete stejný postup zopakovat pro všechny typy dýní, ale to by bylo zdlouhavé. Naučme se nyní, jak vzít do úvahy odrůdu dýní v našem modelu!
Kategorické prvky
V ideálním světě bychom chtěli být schopni předpovědět ceny pro různé odrůdy dýní pomocí stejného modelu. Sloupec Variety
je však poněkud odlišný od sloupců jako Month
, protože obsahuje nenumerické hodnoty. Takové sloupce se nazývají kategorické.
🎥 Klikněte na obrázek výše pro krátký přehled o použití kategorických prvků.
Zde můžete vidět, jak průměrná cena závisí na odrůdě:

Abychom vzali odrůdu v úvahu, musíme ji nejprve převést na číselnou formu, nebo ji zakódovat. Existuje několik způsobů, jak to udělat:
- Jednoduché číselné kódování vytvoří tabulku různých odrůd a poté nahradí název odrůdy indexem v této tabulce. To není nejlepší nápad pro lineární regresi, protože lineární regrese bere skutečnou číselnou hodnotu indexu a přidává ji k výsledku, násobí ji nějakým koeficientem. V našem případě je vztah mezi číslem indexu a cenou zjevně nelineární, i když zajistíme, že indexy budou seřazeny nějakým specifickým způsobem.
- One-hot kódování nahradí sloupec
Variety
čtyřmi různými sloupci, jeden pro každou odrůdu. Každý sloupec bude obsahovat1
, pokud odpovídající řádek patří dané odrůdě, a0
jinak. To znamená, že v lineární regresi budou čtyři koeficienty, jeden pro každou odrůdu dýní, odpovědné za "výchozí cenu" (nebo spíše "dodatečnou cenu") pro danou odrůdu.
Níže uvedený kód ukazuje, jak můžeme provést one-hot kódování odrůdy:
pd.get_dummies(new_pumpkins['Variety'])
ID | FAIRYTALE | MINIATURE | MIXED HEIRLOOM VARIETIES | PIE TYPE |
---|---|---|---|---|
70 | 0 | 0 | 0 | 1 |
71 | 0 | 0 | 0 | 1 |
... | ... | ... | ... | ... |
1738 | 0 | 1 | 0 | 0 |
1739 | 0 | 1 | 0 | 0 |
1740 | 0 | 1 | 0 | 0 |
1741 | 0 | 1 | 0 | 0 |
1742 | 0 | 1 | 0 | 0 |
Abychom provedli trénink lineární regrese s použitím one-hot kódované odrůdy jako vstupu, stačí správně inicializovat data X
a y
:
X = pd.get_dummies(new_pumpkins['Variety'])
y = new_pumpkins['Price']
Zbytek kódu je stejný jako ten, který jsme použili výše pro trénink lineární regrese. Pokud to vyzkoušíte, uvidíte, že střední kvadratická chyba je přibližně stejná, ale získáme mnohem vyšší koeficient determinace (~77 %). Pro ještě přesnější predikce můžeme vzít v úvahu více kategorických prvků, stejně jako numerické prvky, jako Month
nebo DayOfYear
. Abychom získali jedno velké pole prvků, můžeme použít join
:
X = pd.get_dummies(new_pumpkins['Variety']) \
.join(new_pumpkins['Month']) \
.join(pd.get_dummies(new_pumpkins['City'])) \
.join(pd.get_dummies(new_pumpkins['Package']))
y = new_pumpkins['Price']
Zde také bereme v úvahu City
a typ balení Package
, což nám dává MSE 2,84 (10 %) a determinaci 0,94!
Spojení všeho dohromady
Abychom vytvořili nejlepší model, můžeme použít kombinovaná data (one-hot kódované kategorické + numerické) z výše uvedeného příkladu spolu s polynomickou regresí. Zde je kompletní kód pro vaše pohodlí:
# set up training data
X = pd.get_dummies(new_pumpkins['Variety']) \
.join(new_pumpkins['Month']) \
.join(pd.get_dummies(new_pumpkins['City'])) \
.join(pd.get_dummies(new_pumpkins['Package']))
y = new_pumpkins['Price']
# make train-test split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
# setup and train the pipeline
pipeline = make_pipeline(PolynomialFeatures(2), LinearRegression())
pipeline.fit(X_train,y_train)
# predict results for test data
pred = pipeline.predict(X_test)
# calculate MSE and determination
mse = np.sqrt(mean_squared_error(y_test,pred))
print(f'Mean error: {mse:3.3} ({mse/np.mean(pred)*100:3.3}%)')
score = pipeline.score(X_train,y_train)
print('Model determination: ', score)
To by nám mělo dát nejlepší koeficient determinace téměř 97 % a MSE=2,23 (~8 % chybovost predikce).
Model | MSE | Determinace |
---|---|---|
DayOfYear Lineární |
2,77 (17,2 %) | 0,07 |
DayOfYear Polynomická |
2,73 (17,0 %) | 0,08 |
Variety Lineární |
5,24 (19,7 %) | 0,77 |
Všechny prvky Lineární | 2,84 (10,5 %) | 0,94 |
Všechny prvky Polynomická | 2,23 (8,25 %) | 0,97 |
🏆 Skvělá práce! Vytvořili jste čtyři regresní modely v jedné lekci a zlepšili kvalitu modelu na 97 %. V poslední části o regresi se naučíte o logistické regresi pro určení kategorií.
🚀Výzva
Otestujte několik různých proměnných v tomto notebooku a zjistěte, jak korelace odpovídá přesnosti modelu.
Kvíz po přednášce
Přehled & Samostudium
V této lekci jsme se naučili o lineární regresi. Existují další důležité typy regrese. Přečtěte si o technikách Stepwise, Ridge, Lasso a Elasticnet. Dobrou možností pro další studium je kurz statistického učení Stanfordu.
Úkol
Prohlášení:
Tento dokument byl přeložen pomocí služby pro automatický překlad Co-op Translator. Ačkoli se snažíme o přesnost, mějte prosím na paměti, že automatické překlady mohou obsahovat chyby nebo nepřesnosti. Původní dokument v jeho původním jazyce by měl být považován za autoritativní zdroj. Pro důležité informace se doporučuje profesionální lidský překlad. Neodpovídáme za žádné nedorozumění nebo nesprávné interpretace vyplývající z použití tohoto překladu.