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

Инфографика од Dasani Madipalli
До сада сте истражили шта је регресија користећи узорке података из скупа података о цени бундеве који ћемо користити током целе ове лекције. Такође сте то визуелизовали помоћу Matplotlib-а.
Сада сте спремни да дубље зароните у регресију за машинско учење. Док вам визуализација омогућава да разумете податке, права снага машинског учења долази из тренирања модела. Модели се тренирају на историјским подацима да би аутоматски ухватили зависности у подацима и омогућавају вам да предвидите исходе за нове податке које модел раније није видео.
У овој лекцији ћете сазнати више о два типа регресије: основна линеарна регресија и полиномијална регресија, заједно са неким математичким основама ових техника. Ови модели ће нам омогућити да предвидимо цене бундеве у зависности од различитих улазних података.
🎥 Кликните на слику изнад за кратак видео преглед линеарне регресије.
Током читавог овог курикулума претпостављамо минимално познавање математике и тежимо да је учинимо приступачном за студенте из других области, па обратите пажњу на напомене, 🧮 илустрације, дијаграме и друге алате за учење који помажу разумевању.
До сада би требало да сте упознати са структуром података о бундеви које испитујемо. Можете их пронаћи учитане и очишћене у notebook.ipynb фајлу ове лекције. У том фајлу, цена бундеве је приказана по бушелу у новом DataFrame-у. Обавезно проверите да можете да покренете ове бележнице у језгру у Visual Studio Code.
Као подсетник, ове податке учитавате да бисте могли да постављате питања у вези са њима.
- Када је најбоље време за куповину бундеве?
- Коју цену могу очекивати за кутију минијатурних бундевa?
- Да ли их треба купити у корпама од пола бушела или у кутији од 1 1/9 бушела?
Хајде да наставимо са анализом ових података.
У претходној лекцији сте направили Pandas DataFrame и попунили га делом оригиналног скупа података, стандардизујући цене по бушелу. Међутим, тиме сте пришли само око 400 података и то само за јесење месеце.
Погледајте податке које смо претходно учитали у бележници која прати ову лекцију. Податци су учитани и приказан је почетни графикон распршености (scatterplot) за приказ месечних података. Можда можемо добити мало више детаља о природи података њиховим додатним чишћењем.
Као што сте научили у Лекцији 1, циљ вежбе линеарне регресије јесте да се нацрта линија која:
- Приказује односе између варијабли. Приказује однос између варијабли
- Прави предвиђања. Прави тачна предвиђања о томе где би нова тачка могла пасти у односу на ту линију.
Типично за регресију најмањих квадрата је цртање овакве линије. Термин „најмањи квадрати“ односи се на процес минимизације укупне грешке у нашем моделу. За сваки податак меримо вертикалну удаљеност (која се зове резидуала) између стварне тачке и наше регресионе линије.
Ове удаљености квадратимо из два главна разлога:
-
Величина изнад Смера: Желимо да грешка од -5 има исту тежину као грешка од +5. Квадрирањем сви износи постају позитивни.
-
Кажњавање одступања: Квадрирањем се већа грешка додатно потенцира, па линија буде ближа удаљенијим тачкама.
Затим саберемо све ове квадрате. Наш циљ је да пронађемо специфичну линију за коју је овај укупни збир најмањи (најмања могућа вредност) – отуда и назив „Најмањи квадрати“.
🧮 Покажи ми математику
Ова линија, названа линија најбољег прилагођавања, може бити изражена једначином:
Y = a + bX
Xје 'објашњавајућа варијабла'.Yје 'зависна варијабла'. Нагиб линије јеb, аaје пресек са Y-оскулом, што указује на вредностYкада јеX = 0.Прво израчунајте нагиб
b. Инфографика од Jen LooperДругим речима, и ослањајући се на наше питање из података о бундеви: „предвидети цену бундеве по бушелу по месецу“,
Xби се односило на цену, аYна месец продаје.Израчунајте вредност Y. Ако плаћате око 4 долара, то мора бити април! Инфографика од Jen Looper
Математика која израчунава линију мора приказати нагиб линије, који такође зависи од пресека, односно где се
Yналази када јеX = 0.Метод за израчунавање ових вредности можете погледати на Math is Fun сајту. Посетите и овaj калкулатор најмањих квадрата да бисте видели како вредности бројева утичу на линију.
Још један термин који треба разумети је Коефицијент корелације између дате X и Y варијабле. Помоћу scatterplot-а можете брзо визуализовати овај коефицијент. График са тачкама распоређеним у прецизној линији има високу корелацију, док график са тачкама расутим на разним местима између X и Y има ниску корелацију.
Добар линеарни регресијски модел имаће висок (ближи 1 него 0) коефицијент корелације користећи методу регресије најмањих квадрата са линијом регресије.
✅ Покрените бележницу која прати ову лекцију и погледајте scatterplot Цена у односу на Месец. Да ли подаци који повезују Месец и Цену у продаји бундеве изгледају да имају високу или ниску корелацију, према Вашој визуелној процени распореда тачака? Да ли се то мења ако користите прецизнију меру уместо Месеца, нпр. дан у години (односно број дана од почетка године)?
У доњем коду претпоставићемо да смо очистили податке и добили DataFrame под називом new_pumpkins, сличан следећем:
| ID | Месец | ДанУгодини | Врста | Град | Паковање | Најнижа цена | Највиша цена | Цена |
|---|---|---|---|---|---|---|---|---|
| 70 | 9 | 267 | ВРСТА ЗА ПИТЕ | БАЛТИМОР | 1 1/9 бушел картонске кутије | 15.0 | 15.0 | 13.636364 |
| 71 | 9 | 267 | ВРСТА ЗА ПИТЕ | БАЛТИМОР | 1 1/9 бушел картонске кутије | 18.0 | 18.0 | 16.363636 |
| 72 | 10 | 274 | ВРСТА ЗА ПИТЕ | БАЛТИМОР | 1 1/9 бушел картонске кутије | 18.0 | 18.0 | 16.363636 |
| 73 | 10 | 274 | ВРСТА ЗА ПИТЕ | БАЛТИМОР | 1 1/9 бушел картонске кутије | 17.0 | 17.0 | 15.454545 |
| 74 | 10 | 281 | ВРСТА ЗА ПИТЕ | БАЛТИМОР | 1 1/9 бушел картонске кутије | 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)Сада када разумете математику иза линеарне регресије, хајде да направимо регресијски модел да видимо да ли можемо предвидети која паковања буњева имају најбоље цене. Неки који купују бундеве за свечани јесењи паркинг можда желе ове информације како би оптимизовали своју куповину пакета бундеве.
🎥 Кликните на слику изнад за кратак видео преглед корелације.
Из претходне лекције вероватно сте видели да просечна цена за различите месеце изгледа овако:
Ово сугерише да треба да постоји нека корелација, и можемо покушати да тренирамо линеарни регресијски модел да предвидимо однос између Месец и Цена, или између ДануГодини и Цена. Ево графикона распршености који приказује овај други однос:
Хајде да проверимо да ли постоји корелација помоћу функције corr:
print(new_pumpkins['Month'].corr(new_pumpkins['Price']))
print(new_pumpkins['DayOfYear'].corr(new_pumpkins['Price']))Чини се да је корелација прилично мала, -0.15 по Месецу и -0.17 по Дану у месецу, али можда постоји неки други важан однос. Изгледа да постоје различити скупови цена који одговарају разним врстама бундеве. Да бисмо потврдили ову хипотезу, хајде да нацртамо сваку категорију бундеве другим бојама. Прослеђивањем 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)Истраживање нам сугерише да врста бундеве има већи утицај на укупну цену од самог датума продаје. Видимо то и помоћу тракастог графика:
new_pumpkins.groupby('Variety')['Price'].mean().plot(kind='bar')За сада се фокусирајмо само на једну врсту бундеве, 'type за питу', и видимо какав утицај датум има на цену:
pie_pumpkins = new_pumpkins[new_pumpkins['Variety']=='PIE TYPE']
pie_pumpkins.plot.scatter('DayOfYear','Price') Ако сада израчунамо корелацију између Цена и ДанУгодини користећи функцију corr, добићемо нешто око -0.27 - што значи да има смисла тренирати предиктивни модел.
Пре тренирања линеарног регресијског модела, важно је да подаци буду чисти. Линеарна регресија не функционише добро са недостајућим вредностима, па има смисла уклонити све празне ћелије:
pie_pumpkins.dropna(inplace=True)
pie_pumpkins.info()Други приступ би био да се те празне вредности попуне просечним вредностима из одговарајуће колоне.
🎥 Кликните на слику изнад за кратак видео преглед линеарне и полиномијалне регресије.
За тренирање нашег Линеарног регресијског модела користићемо 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над улазним подацима како би линерарни регресијски пакет правилно разумео податке. Линеарна регресија очекује 2D низ као улаз, где сваки ред у низу одговара вектору карактеристика улаза. У нашем случају, пошто имамо само један улаз, потребан нам је низ облика 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, што указује на цену на почетку године.
Да бисмо видели колико је наш модел прецизан, можемо предвидети цене на тестном сету података, а затим измерити колико су наша предвиђања блиска очекиваним вредностима. Ово се може урадити помоћу метрике средње квадратичне грешке (MSE), која је просек свих квадратних разлика између очекиваних и предвиђених вредности.
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}%)')Наша грешка изгледа да је око 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)Још један тип линеарне регресије је полиномијална регресија. Иако понекад постоји линеарна веза између променљивих - што је бундева већа по обиму, то је цена виша - понекад ове везе нису могуће приказати као раван или праву линију.
✅ Ево још неких примера података који могу користити полиномијалну регресију
Погледајте поново везу између датума и цене. Да ли овај расејани графикон мора нужно да буде анализиран правом линијом? Зар цене не могу да варирају? У овом случају можете покушати полиномијалну регресију.
✅ Полиноми су математички изрази који могу да се састоје од једне или више променљивих и коефицијената
Полиномијална регресија прави закривљену линију да боље прилагоди нелинеарне податке. У нашем случају, ако у улазне податке укључимо квадрат променљиве DayOfYear, требало би да можемо да прилагодимо податке параболичном кривом, која ће имати минимум на одређеној тачки у току године.
Scikit-learn укључује корисан pipeline API за комбиновaње различитих корака обраде података заједно. Pipeline је ланац ескиматора. У нашем случају креираћемо 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 да добијемо резултате предвиђања. Ево графика који приказује тестне податке и криву апроксимације:
Коришћењем полиномијалне регресије можемо добити благо ниже MSE и више вредности коефицијента детерминације, али не значајно. Потребно је узети у обзир друге карактеристике!
Можете видети да су минималне цене бувеђа примећене негде око ноћи вештица. Како то можете да објасните?
🎃 Честитамо, управо сте креирали модел који може помоћи у предвиђању цене тикви за питу. Вероватно можете поновити исти поступак за све врсте тикви, али то би било заморно. Хајде сада да научимо како да у наш модел укључимо разноликост тикви!
У идеалном свету, желимо да можемо предвидети цене различитих врста тикви користећи исти модел. Међутим, колона Variety се делимично разликује од колона као што је Month, јер садржи не-нумеричке вредности. Те колоне се зову категоријалне.
🎥 Кликните на слику изнад за кратак видео преглед коришћења категоријалних карактеристика.
Овде можете видети како просечна цена зависи од врсте:
Да бисмо узели у обзир врсту, прво морамо да је конвертујемо у нумерички облик, односно да je енкодирајемо. Постоји неколико начина да то урадимо:
- Једноставно нумеричко кодирање ће направити табелу различитих врста, а затим заменити име врсте индексом у тој табели. Ово није најбоља идеја за линеарну регресију, јер линеарна регресија узима стварну нумеричку вредност индекса и додаје је резултату, множећи неким коефицијентом. У нашем случају, веза између броја индекса и цене је очигледно нелинеарна, чак и ако се уверимо да су индекси поређани на одређени начин.
- One-hot кодирање ће заменити колону
Varietyса 4 различите колоне, по једна за сваку врсту. Свака колона ће садржати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, што нам даје MSE 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%, и MSE=2.23 (~8% грешке у предвиђању).
| Модел | MSE | Коэффицијент детерминације |
|---|---|---|
Линеарна 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 course
Резервaција од одговорности: Овај документ је преведен уз помоћ AI услуге за превод Co-op Translator. Иако тежимо тачности, молимо вас да имате у виду да аутоматски преводи могу садржати грешке или нетачности. Изворни документ на свом оригиналном језику треба сматрати ауторитетним извором. За критичне информације препоручује се професионални људски превод. Нисмо одговорни за било каква неспоразуми или погрешне интерпретације проузроковане коришћењем овог превода.












