You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ML-For-Beginners/translations/sr/2-Regression/3-Linear/README.md

36 KiB

Направите регресиони модел користећи Scikit-learn: регресија на четири начина

Напомена за почетнике

Линеарна регресија се користи када желимо да предвидимо намерну вредност (на пример, цену куће, температуру или продају). Ради тако што пронађе праву линију која најбоље представља зависност између улазних карактеристика и излаза.

У овој лекцији се фокусирамо на разумевање концепта пре него што истражимо напредније регресионе технике. Линеарна насупрот полиномијалној регресији инфографика

Инфографика од Дасани Мадипали

Квиз пре предавања

Ова лекција је доступна у R!

Увод

До сада сте истражили шта је регресија помоћу узорних података скупљених из сета података о ценама бундеве који ћемо користити током ове лекције. Такође сте визуализовали те податке користећи Matplotlib.

Сада сте спремни да дубље зароните у регресију за машинско учење. Док визуализација омогућава да разумете податке, права моћ машинског учења долази из тренинга модела. Модели се обучавају на историјским подацима да аутоматски ухвате зависности у подацима и омогућавају вам да предвидите резултате за нове податке које модел раније није видео.

У овој лекцији научићете више о две врсте регресије: основна линеарна регресија и полиномијална регресија, заједно са неком математиком која стоји иза ових техника. Ови модели ће нам омогућити да предвидимо цене бундева у зависности од различитих улазних података.

Машинско учење за почетнике - Разумевање линеарне регресије

🎥 Кликните слику изнад за кратак видео преглед линеарне регресије.

Током целог овог курикулума претпостављамо минимално знање из математике, и настојимо да буде приступачно студентима који долазе из других области, па обратите пажњу на напомене, 🧮 илустрације, дијаграме и друге алате за учење који помажу у разумевању.

Предуслов

Сада би требало да сте упознати са структуром података о бундевама које посматрамо. Можете их пронаћи претходно учитане и очишћене у фајлу notebook.ipynb који прати ову лекцију. У том фајлу, цена бундеве је приказана по бушелу у новом дате фрејму. Обавезно проверите да можете покренути ове нотебоок-ове у Visual Studio Code окружењу.

Припрема

Као подсетник, учитавате ове податке да бисте могли да поставите питања у вези са њима.

  • Када је најбоље време за куповину бундева?
  • Коју цену могу очекивати за кутију минијатурних бундева?
  • Да ли треба да их купим у корпама за пола бушела или у кутијама од 1 1/9 бушела? Хајде да наставимо да прегледамо ове податке.

У претходној лекцији, направили сте Pandas дате фрејм и попунили га делом оригиналног скупа података, стандардујући цене по бушелу. Међутим, тиме сте успели да сакупите око 400 тачака података и само за јесење месеце.

Погледајте податке које смо претходно учитали у приложеном нотебоок-у ове лекције. Податак је претходно учитан и направљен је почетни scatterplot (распршени графикон) који приказује месец. Можда можемо добити више детаља о природи података ажурирањем и додатним чишћењем.

Линеарна регресиона линија

Као што сте научили у Лекцији 1, циљ линеарне регресије је да буде могуће нацртати линију која:

  • Приказује везе између променљивих. Прикажи однос између променљивих
  • Прави предвиђања. Тачно предвиђа где ће нова тачка података пасти у односу на ту линију.

Типично је за регресију најмањих квадрата да повуче ову врсту линије. Термин "најмањи квадрати" се односи на процес минимизирања укупне грешке у нашем моделу. За сваку тачку података меримо вертикалну удаљеност (која се назива резидуал) између стварне тачке и наше регресионе линије.

Ове удаљености квадратимо из два главна разлога:

  1. Величина уместо смера: Желимо да грешка од -5 буде третирана исто као грешка од +5. Квадрирање све вредности чини позитивним.

  2. Казњавање одступања: Квадрирање даје већу тежину већим грешкама, приморавајући линију да остане ближе тачкама које су удаљене.

Затим сабирамо све ове вредности квадрате заједно. Наш циљ је да пронађемо специфичну линију код које је ова укупна сума најмања (најмања могућа вредност)—отуда и назив "најмањи квадрати".

🧮 Покажи ми математику

Ова линија, названа линија најбољег прилагођавања може се изразити једначином:

Y = a + bX

X је 'објашњавајућа променљива'. Y је 'зависна променљива'. Нагиб линије је b, док је a y-пресек, што представља вредност Y када је X = 0.

израчун нагиба

Прво израчунај нагиб b. Инфографика од Џен Лупер

Другим речима, и осврћући се на наше оригинално питање у вези цена бундеве: "предвидети цену бундеве по бушелу по месецу", X би се односило на цену, а Y на месец продаје.

заврши једначину

Израчунај вредност Y. Ако плаћате око $4, мора да је април! Инфографика од Џен Лупер

Математика која израчунава линију мора показати нагиб линије, који такође зависи од пресека, односно где се Y налази када је X = 0.

Метод рачунања ових вредности можете видети на Math is Fun сајту. Посетите и овај калкулатор најмањих квадрата да бисте приметили како вредности бројева утичу на линију.

Корелација

Још један термин који треба разумети је коефицијент корелације између датих X и Y променљивих. Коришћењем scatterplot-а, можете брзо визуализовати овај коефицијент. На графикону са тачкама распршеним у прелепој линији корелација је висока, док је на графикону са тачкама распршеним на све стране између X и Y корелација ниска.

Добар модел линеарне регресије ће имати висок (ближе 1 него 0) коефицијент корелације користећи метод најмањих квадрата с линијом регресије.

Покрените нотебоок који прати ову лекцију и погледајте scatterplot Месец у односу на цену. Да ли подаци који повезују месец и цену за продају бундеве изгледају као да имају високу или ниску корелацију, према вашој визуелној интерпретацији scatterplot-а? Да ли се то мења ако користите прецизнију меру уместо Month, на пример дан у години (број дана од почетка године)?

У доњем коду претпоставићемо да смо очистили податке и добили дате фрејм назван new_pumpkins, сличан следећем:

ID Month DayOfYear Variety City Package Low Price High Price Price
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

Код за чишћење података налази се у notebook.ipynb. Извршили смо исте кораке чишћења као у претходној лекцији и израчунали колону DayOfYear користећи следећи израз:

day_of_year = pd.to_datetime(pumpkins['Date']).apply(lambda dt: (dt-datetime(dt.year,1,1)).days)

Сада када имате разумевање математике иза линеарне регресије, хајде да направимо регресиони модел да видимо можемо ли предвидети који пакет бундева ће имати најбоље цене. Неко ко купује бундеве за хладњачу можда жели ове информације како би оптимизовао куповине пакета бундева за хладњачу.

Тражење корелације

Машинско учење за почетнике - Тражење корелације: Кључ линеарне регресије

🎥 Кликните слику изнад за кратак видео преглед корелације.

Из претходне лекције сте вероватно видели да просечна цена за различите месеце изгледа овако:

Просечна цена по месецу

Ово указује да би требало да постоји нека корелација, и да можемо покушати обуку модела линеарне регресије да предвидимо однос између Month и Price или између DayOfYear и Price. Ево scatter plot-а који показује овај други однос:

Scatter plot цена у односу на дан у години

Хајде да видимо да ли постоји корелација коришћењем corr функције:

print(new_pumpkins['Month'].corr(new_pumpkins['Price']))
print(new_pumpkins['DayOfYear'].corr(new_pumpkins['Price']))

Изгледа да је корелација прилично мала, -0.15 по Month и -0.17 по DayOfMonth, али може бити још неки важан однос. Изгледа као да постоје различити кластери цена који одговарају различитим врстама бундева. Да бисмо потврдили ову хипотезу, хајде да свака категорија бундеве буде приказана различитом бојом. Прослеђујући ax параметар scatter функцији за цртање можемо приказати све тачке на истом графикону:

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)
Scatter plot цена у односу на дан у години, са бојама

Наша истрага сугерише да врста има већег утицаја на цену од стварног датума продаје. Ово можемо видети уз помоћ графикона:

new_pumpkins.groupby('Variety')['Price'].mean().plot(kind='bar')
Графикон цена по врсти

Хајде сад да се фокусирамо само на једну врсту бундеве, 'тип за пите', и видимо каквог утицаја има датум на цену:

pie_pumpkins = new_pumpkins[new_pumpkins['Variety']=='PIE TYPE']
pie_pumpkins.plot.scatter('DayOfYear','Price') 
Scatter plot цена у односу на дан у години за тип за пите

Ако сада израчунамо корелацију између Price и DayOfYear користећи corr функцију, добићемо нешто као -0.27 - што значи да има смисла тренирати предиктивни модел.

Пре тренирања линеарног регресионог модела, важно је осигурати да су наши подаци чисти. Линеарна регресија не ради добро са недостајућим вредностима, па има смисла уклонити све празне ћелије:

pie_pumpkins.dropna(inplace=True)
pie_pumpkins.info()

Други приступ би био да се празне вредности попуне просечним вредностима из одговарајуће колоне.

Једноставна линеарна регресија

Машинско учење за почетнике - Линеарна и полиномијална регресија користећи Scikit-learn

🎥 Кликните слику изнад за кратак видео преглед линеарне и полиномијалне регресије.

За обуку нашег модела линеарне регресије користићемо библиотеку Scikit-learn.

from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split

Почињемо раздвајањем улазних вредности (карактеристика) и очекиваног излаза (ознаке) у одвојене numpy низове:

X = pie_pumpkins['DayOfYear'].to_numpy().reshape(-1,1)
y = pie_pumpkins['Price']

Имајте у виду да смо морали да извршимо reshape улазних података да би Linear Regression пакет исправно разумео. Линеарна регресија очекује 2Д низ као улаз, где сваки ред одговара вектору улазних карактеристика. У нашем случају, пошто имамо само један улаз, потребан нам је низ са обликом N×1, где је N величина скупа података.

Затим, морамо поделити податке на тренирајући и тестни скуп, како бисмо могли да валидамо наш модел након тренинга:

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)

Коначно, тренирање самог модела линеарне регресије траје само две линије кода. Дефинишемо LinearRegression објекат и прилагођавамо га нашим подацима користећи fit методу:

lin_reg = LinearRegression()
lin_reg.fit(X_train,y_train)

Објект LinearRegression након fit-овања садржи све коефицијенте регресије, до којих се може приступити коришћењем .coef_ својства. У нашем случају, постоји само један коефицијент, који би требао бити око -0.017. То значи да цене изгледа да благо падају са временом, али не превише, око 2 цента дневно. Такође можемо приступити тачки пресека регресије са Y осом користећи lin_reg.intercept_ - она ће у нашем случају бити око 21, што указује на цену на почетку године.

Да видимо колико је наш модел прецизан, можемо предвидети цене на тест скупу података, а затим мерити колико су наша предвиђања блиска очекиваним вредностима. Ово се може урадити коришћењем метрике корен средње квадратичне грешке (RMSE), која је корен средине свих квадратних разлика између очекиване и предвиђене вредности.

pred = lin_reg.predict(X_test)

rmse = np.sqrt(mean_squared_error(y_test,pred))
print(f'RMSE: {rmse:3.3} ({rmse/np.mean(pred)*100:3.3}%)')

Чини се да је наша грешка око 2 поена, што је ~17%. Није баш добро. Још један показатељ квалитета модела је коефицијент детерминације, који се добија овако:

score = lin_reg.score(X_train,y_train)
print('Model determination: ', score)

Ако је вредност 0, то значи да модел не узима у обзир улазне податке и понаша се као најгории линеарни предиктор, што је једноставно просечна вредност резултата. Вредност 1 значи да можемо савршено предвидети све очекиване излазе. У нашем случају, коефицијент је око 0.06, што је прилично ниско.

Такође можемо приказати тест податке заједно са регресионом линијом да боље видимо како регресија ради у нашем случају:

plt.scatter(X_test,y_test)
plt.plot(X_test,pred)
Linear regression

Полиномијална регресија

Још један тип линеарне регресије је полиномијална регресија. Иако понекад постоји линеарна веза између променљивих - што је тиква већа у обиму, то је цена виша - понекад се те везе не могу приказати као раван или права линија.

Ево неколико додатних примера података који би могли користити полиномијалну регресију

Погледајте још једном однос између Датума и Цене. Да ли овај распоред тачака делује као нешто што нужно треба анализирати правом линијом? Зар цене не могу флуктуирати? У овом случају, можете покушати полиномијалну регресију.

Полиноми су математички изрази који могу садржати једну или више променљивих и коефицијената

Полиномијална регресија прави закривљену линију да боље прилагоди нелинеарне податке. У нашем случају, ако укључимо квадратну променљиву DayOfYear у улазне податке, требало би да можемо прилагодити наше податке параболичном кривом, која ће имати минимум у одређеној тачки током године.

Scikit-learn укључује користан pipeline API за комбиновање различитих корака обраде података заједно. Pipeline је ланац estimatora. У нашем случају, направићемо pipeline који прво додаје полиномијалне особине нашем моделу, а затим тренира регресију:

from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import make_pipeline

pipeline = make_pipeline(PolynomialFeatures(2), LinearRegression())

pipeline.fit(X_train,y_train)

Користећи PolynomialFeatures(2) значи да ћемо укључити све другостепене полиноме из улазних података. У нашем случају то ће значити само DayOfYear2, али с обзиром на две улазне променљиве X и Y, ово ће додати X2, XY и Y2. Такође можемо користити и полиноме виших степени ако желимо.

Pipeline-ови се могу користити на исти начин као и оригинални објекат LinearRegression, односно можемо fit-овати pipeline, а затим користити predict за добијање резултата предвиђања. Ево графикона који показује тест податке и криву апроксимације:

Polynomial regression

Коришћењем полиномијалне регресије можемо добити мало мању МСЕ и већи коефицијент детерминације, али не значајно. Потребно је узети у обзир и друге карактеристике!

Можете приметити да се минималне цене тиквића појављују негде око Ноћи вештица. Како бисте то објаснили?

🎃 Честитамо, управо сте направили модел који може помоћи у предвиђању цене пит тиквица. Вероватно можете поновити исти поступак за све типове тиквица, али то би било заморно. Сада ћемо научити како да узмемо у обзир сорту тикве у нашем моделу!

Категоријалне карактеристике

У идеалном свету, желимо да можемо предвидети цене за различите сорте тикви користећи исти модел. Међутим, колона Variety је нешто другачија од колона као што је Month, јер садржи не-нумеричке вредности. Такве колоне се зову категоријалне.

ML за почетнике - предвиђања категоријалних особина са линеарном регресијом

🎥 Кликните на слику изнад за кратак видео преглед коришћења категоријалних особина.

Овде можете видети како просечна цена зависи од сорте:

Average price by variety

Да бисмо узели у обзир сорту, прво морамо да је претворимо у нумерички облик, односно да је енкодирају. Постоји неколико начина како то можемо урадити:

  • Једноставно нумеричко кодирање ће направити табелу различитих сорти, а затим заменити име сорте индексом у тој табели. Ово није најбоља идеја за линеарну регресију, јер линеарна регресија узима стварну нумеричку вредност индекса и додаје је резултату помноженом неким коефицијентом. У нашем случају, веза између броја индекса и цене је јасно нелинеарна, чак и ако осигурамо да су индекси уређени на одређени начин.
  • One-hot кодирање ће заменити колону Variety четири различите колоне, по једну за сваки тип. Свака колона ће садржати 1 ако је одговарајући ред тог типа, и 0 у супротном. Ово значи да ће у линеарној регресији постојати четири коефицијента, по један за сваку сортутіквице, који ће бити одговорни за „почетну цену“ (или боље речено „додатну цену“) за ту одређену сорту.

Код у наставку показује како можемо да извршимо one-hot кодирање сорте:

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

Да бисмо тренирали линеарну регресију користећи one-hot кодирање сорте као улаз, само треба исправно иницијализовати податке X и y:

X = pd.get_dummies(new_pumpkins['Variety'])
y = new_pumpkins['Price']

Остатак кода је исти као што смо користили горе за тренирање линеарне регресије. Ако пробате, видећете да је средња квадратична грешка отприлике иста, али добијамо знатно већи коефицијент детерминације (~77%). Да бисмо добили још прецизнија предвиђања, можемо узети у обзир више категоријалних особина, као и нумеричких, као што су Month или DayOfYear. Да бисмо добили једну велику матрицу особина, можемо користити 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']

Овде такође узимамо у обзир City и тип Package, што нам даје МСЕ 2.84 (10%), и коефицијент детерминације 0.94!

Све заједно

Да бисмо направили најбољи модел, можемо користити комбиноване (one-hot кодиране категоријалне + нумеричке) податке из горњег примера заједно са полиномијалном регресијом. Ево комплетног кода ради ваше погодности:

# подеси податке за тренинг
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']

# направи подјелу на тренинг и тест
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)

# подеси и обучи цјевовод
pipeline = make_pipeline(PolynomialFeatures(2), LinearRegression())
pipeline.fit(X_train,y_train)

# предвиди резултате за тест податке
pred = pipeline.predict(X_test)

# израчунај MSE и коефицијент детерминације
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)

Ово би нам требало дати најбољи коефицијент детерминације од скоро 97%, и МСЕ=2.23 (~8% грешке предвиђања).

Модел МСЕ Детерминација
Линеарна DayOfYear 2.77 (17.2%) 0.07
Полиномијална DayOfYear 2.73 (17.0%) 0.08
Линеарна Variety 5.24 (19.7%) 0.77
Линеарна све особине 2.84 (10.5%) 0.94
Полиномијална све особине 2.23 (8.25%) 0.97

🏆 Браво! Направили сте четири модела регресије у једном часу и побољшали квалитет модела на 97%. У завршном делу о регресији научићете о логистичкој регресији за категоризацију.


🚀 Изазов

Испробајте неколико различитих променљивих у овом notebook-у да видите како корелација одговара тачности модела.

Квиз након предавања

Преглед и Самосталан рад

У овом часу смо научили о линеарној регресији. Постоје и други важни типови регресије. Прочитајте о Stepwise, Ridge, Lasso и Elasticnet техникама. Добар курс за учење више је Stanford Statistical Learning курс

Задатак

Направи модел


Изјава о одрицању одговорности:
Овај документ је преведен уз помоћ AI сервиса за превођење Co-op Translator. Иако тежимо тачности, имајте у виду да аутоматски преводи могу садржати грешке или нетачности. Оригинални документ на изворном језику треба сматрати ауторитетним извором. За критичне информације препоручује се професионални људски превод. Не сносимо одговорност за било каква неспоразуми или погрешна тумачења настала коришћењем овог превода.