|
|
4 months ago | |
|---|---|---|
| .. | ||
| solution | 6 months ago | |
| README.md | 4 months ago | |
| assignment.md | 6 months ago | |
| notebook.ipynb | 11 months ago | |
README.md
Побудова регресійної моделі з використанням Scikit-learn: регресія чотирма способами
Примітка для початківців
Лінійна регресія використовується, коли ми хочемо передбачити числове значення (наприклад, ціну будинку, температуру або продажі).
Вона працює, знаходячи пряму, яка найкраще відображає зв’язок між вхідними ознаками й виходом.
У цьому уроці ми зосереджуємося на розумінні концепції перед тим, як вивчати більш просунуті методи регресії.

Інфографіка від Dasani Madipalli
Перевірка знань перед лекцією
Цей урок доступний на R!
Вступ
До цього моменту ви досліджували, що таке регресія, на прикладі даних про ціни на гарбузи, які ми використаємо протягом цього уроку. Ви також візуалізували дані за допомогою Matplotlib.
Тепер ви готові заглибитися в регресію для машинного навчання (ML). Візуалізація допомагає зрозуміти дані, але справжня сила машинного навчання полягає у навчанні моделей. Моделі тренуються на історичних даних, щоб автоматично вловлювати залежності в даних і дозволяють робити прогнози для нових даних, які модель раніше не бачила.
У цьому уроці ви дізнаєтесь більше про два типи регресії: базова лінійна регресія та поліноміальна регресія, а також про математику, що лежить в основі цих методів. Ці моделі дозволять нам передбачати ціни на гарбузи залежно від різних вхідних даних.
🎥 Натисніть на зображення вище, щоб переглянути коротке відеоогляд лінійної регресії.
Протягом цього курсу ми припускаємо мінімальні знання математики і прагнемо зробити матеріал доступним для студентів з різних галузей, тому звертайте увагу на примітки, 🧮 позначки, діаграми та інші інструменти навчання, які допоможуть зрозуміти матеріал.
Вимоги
Ви вже знайомі зі структурою даних про гарбузи, які ми досліджуємо. Ви можете знайти їх завантаженими та попередньо очищеними у файлі цього уроку notebook.ipynb. У файлі ціна гарбуза відображається за бушель у новому фреймі даних. Переконайтеся, що ви можете запускати ці ноутбуки у Visual Studio Code.
Підготовка
Нагадаємо, ви завантажуєте ці дані, щоб ставити питання.
- Коли найкращий час купувати гарбузи?
- Яку ціну можна очікувати за коробку мініатюрних гарбузів?
- Чи варто купувати їх у кошиках на півбушеля, чи в коробках на 1 1/9 бушеля?
Продовжимо копатися в цих даних.
У попередньому уроці ви створили Pandas DataFrame і заповнили його частиною оригінального набору даних, стандартизуючи ціни за бушель. Проте таким чином вдалося зібрати лише близько 400 точок даних і тільки за осінні місяці.
Ознайомтеся з даними, які ми завантажили у супровідному ноутбуці цього уроку. Дані завантажені, і початковий розсіювальний графік відображає дані за місяцями. Можливо, ми зможемо дізнатися більше про природу даних, очистивши їх більш ретельно.
Лінійна регресійна лінія
Як ви дізналися в уроці 1, мета лінійної регресійної вправи — побудувати лінію, щоб:
- Показати залежності змінних. Відобразити зв’язок між змінними
- Зробити прогнози. Робити точні прогнози про те, де нова точка даних розміститься відносно цієї лінії
Зазвичай для цього використовується регресія найменших квадратів (Least-Squares Regression). Термін «найменших квадратів» означає процес мінімізації загальної похибки в нашій моделі. Для кожної точки даних ми вимірюємо вертикальну відстань (результат, який називається залишком) між фактичною точкою та нашою регресійною лінією.
Ми підносимо ці відстані у квадрат з двох основних причин:
-
Величина важливіша за напрямок: Хочемо, щоб похибка -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, наприклад, день року (число днів від початку року)?
У наведеному нижче коді ми припускаємо, що дані були очищені і отримано DataFrame з назвою 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 — розмір набору даних.
Далі потрібно розділити дані на навчальний (train) та тестовий (test) набори, щоб можна було перевірити модель після навчання:
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)
Поліноміальна регресія
Інший тип лінійної регресії — це поліноміальна регресія. Хоча іноді між змінними існує лінійний зв’язок — чим більша гарбуз за обсягом, тим вища ціна — іноді такі зв’язки не можна відобразити у вигляді площини чи прямої лінії.
✅ Ось декілька інших прикладів даних, які можуть потребувати поліноміальної регресії.
Подивіться ще раз на зв’язок між датою та ціною. Чи цього розсіювання досить, щоб його обов’язково слід аналізувати прямою лінією? А чи не можуть ціни коливатися? У такому разі можна спробувати поліноміальну регресію.
✅ Поліноми — це математичні вирази, які можуть складатися з однієї чи кількох змінних і коефіцієнтів.
Поліноміальна регресія створює криву лінію, щоб краще підходити нелінійним даним. У нашому випадку, якщо включити змінну 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 = 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 техніки. Хорошим курсом для поглибленого вивчення є Stanford Statistical Learning course
Завдання
Відмова від відповідальності: Цей документ було перекладено за допомогою сервісу автоматичного перекладу Co-op Translator. Хоча ми прагнемо до точності, будь ласка, майте на увазі, що автоматичні переклади можуть містити помилки або неточності. Оригінальний документ рідною мовою слід вважати авторитетним джерелом. Для критичної інформації рекомендується професійний людський переклад. Ми не несемо відповідальності за будь-які непорозуміння або неправильні тлумачення, що виникли внаслідок використання цього перекладу.





