Лінійна регресія використовується, коли ми хочемо передбачити числове значення (наприклад, ціну будинку, температуру або обсяг продажів). Вона працює, знаходячи пряму лінію, яка найкраще відображає зв’язок між вхідними ознаками та виходом.
У цьому уроці ми зосереджуємося на розумінні концепції перед тим, як дослідити більш просунуті методи регресії.

Інфографіка від Dasani Madipalli
До цього моменту ви досліджували, що таке регресія, використовуючи вибіркові дані з набору даних про ціни на гарбузи, який ми використовуватимемо протягом усього цього уроку. Ви також візуалізували ці дані за допомогою Matplotlib.
Тепер ви готові зануритися глибше у регресію в машинному навчанні. Хоча візуалізація допомагає зрозуміти дані, справжня сила машинного навчання полягає в навчанні моделей. Моделі навчаються на історичних даних, щоб автоматично виявляти залежності в даних, і дозволяють прогнозувати результати для нових даних, яких модель раніше не бачила.
У цьому уроці ви детальніше дізнаєтесь про два типи регресії: базова лінійна регресія та поліноміальна регресія, а також про математику, що лежить в основі цих методів. Ці моделі дозволять нам прогнозувати ціни на гарбузи залежно від різних вхідних даних.
🎥 Натисніть на зображення вище, щоб переглянути короткий відеоогляд лінійної регресії.
Протягом цього курсу ми передбачаємо мінімальні знання математики і намагаємося зробити її доступною для студентів з інших галузей, тому звертайте увагу на примітки, 🧮 підказки, діаграми та інші інструменти для полегшення розуміння.
До цього часу ви вже маєте ознайомлення зі структурою даних про гарбузи, які ми досліджуємо. Ви можете знайти їх завантаженими та попередньо очищеними у файлі notebook.ipynb цього уроку. У файлі ціна на гарбуз подана за бушель у новому датафреймі. Переконайтесь, що ви можете запускати ці ноутбуки в ядрах у Visual Studio Code.
Як нагадування, ви завантажуєте ці дані, щоб ставити до них запитання.
- Коли найкращий час купувати гарбузи?
- Яку ціну можна очікувати за коробку мініатюрних гарбузів?
- Чи варто купувати їх у корзинах на півбушеля або у коробках на 1 1/9 бушеля? Продовжимо досліджувати ці дані.
У попередньому уроці ви створили датафрейм Pandas і наповнили його частиною оригінального набору даних, стандартизувавши ціни за бушель. Проте при цьому ви змогли зібрати лише близько 400 точок даних і лише для осінніх місяців.
Погляньте на дані, які ми заздалегідь завантажили у супровідному ноутбуці цього уроку. Дані завантажено, і побудовано початковий графік розсіювання для показу даних по місяцях. Можливо, ми зможемо отримати трохи більше інформації про природу цих даних, очистивши їх ще більше.
Як ви дізнались у Уроці 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. Також відвідайте цей калькулятор найменших квадратів, щоб побачити, як значення чисел впливають на лінію.
Ще один термін, який потрібно зрозуміти, – це коефіцієнт кореляції між заданими змінними X та Y. За допомогою графіка розсіювання ви швидко можете візуалізувати цей коефіцієнт. Якщо точки на графіку розташовані акуратно по лінії — кореляція висока, якщо розкидані по всьому графіку — кореляція низька.
Добра модель лінійної регресії матиме високий (ближчий до 1, ніж до 0) коефіцієнт кореляції, визначений методом найменших квадратів із регресійною лінією.
✅ Запустіть ноутбук, який супроводжує цей урок, і подивіться на графік розсіювання місяця продажу до ціни. Чи є у даних про продажі гарбузів за місяцями висока чи низька кореляція згідно з вашим візуальним тлумаченням графіка? Чи зміниться це, якщо використати більш тонкий показник замість 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. Ось графік розсіювання, який показує останній зв’язок:
Перевіримо, чи існує кореляція, використовуючи функцію 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)Наше дослідження свідчить, що сорт має більший вплив на загальну ціну, ніж фактична дата продажу. Ми можемо підкріпити це стовпчиковою діаграмою:
new_pumpkins.groupby('Variety')['Price'].mean().plot(kind='bar')Наразі зосередимося лише на одному сорті гарбузів, "pie type", і подивимось, як дата впливає на ціну:
pie_pumpkins = new_pumpkins[new_pumpkins['Variety']=='PIE TYPE']
pie_pumpkins.plot.scatter('DayOfYear','Price') Якщо тепер обчислити кореляцію між Price і DayOfYear за допомогою функції 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, щоб поєднати різні кроки обробки даних. 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, бо він містить нечислові значення. Такі стовпці називаються категоріальними.
🎥 Натисніть на зображення вище для короткого відеоогляду використання категоріальних ознак.
Тут ви можете побачити, як середня ціна залежить від сорту:
Щоб врахувати сорт, спочатку нам потрібно перетворити його у числову форму, або закодувати його. Є кілька способів зробити це:
- Просте числове кодування побудує таблицю різних сортів, а потім замінить назву сорту на індекс у цій таблиці. Це не найкраща ідея для лінійної регресії, бо лінійна регресія бере фактичне числове значення індексу і додає його до результату, множачи на якийсь коефіцієнт. У нашому випадку залежність між номером індексу та ціною явно нелінійна, навіть якщо ми впевнемося, що індекси впорядковані в певний спосіб.
- 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%. У фінальному розділі про регресію ви дізнаєтесь про логістичну регресію для визначення категорій.
Перевірте декілька різних змінних у цій нотатці, щоб побачити, як кореляція відповідає точності моделі.
У цьому уроці ми дізнались про лінійну регресію. Існують також інші важливі типи регресії. Прочитайте про покрокові, Ridge, Lasso та Elasticnet методи. Хорошим курсом для подальшого вивчення є курс Стенфордського університету зі статистичного навчання
Відмова від відповідальності:
Цей документ було перекладено за допомогою сервісу автоматичного перекладу Co-op Translator. Хоча ми прагнемо до точності, просимо враховувати, що автоматичні переклади можуть містити помилки або неточності. Оригінальний документ рідною мовою слід вважати авторитетним джерелом. Для критично важливої інформації рекомендується звертатися до професійного людського перекладу. Ми не несемо відповідальності за будь-які непорозуміння або неправильні тлумачення, що виникли внаслідок використання цього перекладу.












