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/uk/2-Regression/3-Linear
localizeflow[bot] d493273e8e
chore(i18n): sync translations with latest source changes (chunk 1/1, 12 changes)
4 months ago
..
solution chore(i18n): sync translations with latest source changes (chunk 1/1, 300 changes) 6 months ago
README.md chore(i18n): sync translations with latest source changes (chunk 1/1, 12 changes) 4 months ago
assignment.md chore(i18n): sync translations with latest source changes (chunk 1/1, 300 changes) 6 months ago
notebook.ipynb 🌐 Update translations via Co-op Translator 11 months ago

README.md

Побудова регресійної моделі з використанням Scikit-learn: регресія чотирма способами

Примітка для початківців

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

У цьому уроці ми зосереджуємося на розумінні концепції перед тим, як вивчати більш просунуті методи регресії.
Linear vs polynomial regression infographic

Інфографіка від Dasani Madipalli

Перевірка знань перед лекцією

Цей урок доступний на R!

Вступ

До цього моменту ви досліджували, що таке регресія, на прикладі даних про ціни на гарбузи, які ми використаємо протягом цього уроку. Ви також візуалізували дані за допомогою Matplotlib.

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

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

ML for beginners - Understanding Linear Regression

🎥 Натисніть на зображення вище, щоб переглянути коротке відеоогляд лінійної регресії.

Протягом цього курсу ми припускаємо мінімальні знання математики і прагнемо зробити матеріал доступним для студентів з різних галузей, тому звертайте увагу на примітки, 🧮 позначки, діаграми та інші інструменти навчання, які допоможуть зрозуміти матеріал.

Вимоги

Ви вже знайомі зі структурою даних про гарбузи, які ми досліджуємо. Ви можете знайти їх завантаженими та попередньо очищеними у файлі цього уроку notebook.ipynb. У файлі ціна гарбуза відображається за бушель у новому фреймі даних. Переконайтеся, що ви можете запускати ці ноутбуки у Visual Studio Code.

Підготовка

Нагадаємо, ви завантажуєте ці дані, щоб ставити питання.

  • Коли найкращий час купувати гарбузи?
  • Яку ціну можна очікувати за коробку мініатюрних гарбузів?
  • Чи варто купувати їх у кошиках на півбушеля, чи в коробках на 1 1/9 бушеля?

Продовжимо копатися в цих даних.

У попередньому уроці ви створили Pandas DataFrame і заповнили його частиною оригінального набору даних, стандартизуючи ціни за бушель. Проте таким чином вдалося зібрати лише близько 400 точок даних і тільки за осінні місяці.

Ознайомтеся з даними, які ми завантажили у супровідному ноутбуці цього уроку. Дані завантажені, і початковий розсіювальний графік відображає дані за місяцями. Можливо, ми зможемо дізнатися більше про природу даних, очистивши їх більш ретельно.

Лінійна регресійна лінія

Як ви дізналися в уроці 1, мета лінійної регресійної вправи — побудувати лінію, щоб:

  • Показати залежності змінних. Відобразити зв’язок між змінними
  • Зробити прогнози. Робити точні прогнози про те, де нова точка даних розміститься відносно цієї лінії

Зазвичай для цього використовується регресія найменших квадратів (Least-Squares Regression). Термін «найменших квадратів» означає процес мінімізації загальної похибки в нашій моделі. Для кожної точки даних ми вимірюємо вертикальну відстань (результат, який називається залишком) між фактичною точкою та нашою регресійною лінією.

Ми підносимо ці відстані у квадрат з двох основних причин:

  1. Величина важливіша за напрямок: Хочемо, щоб похибка -5 розглядалася так само, як і +5. Квадрат робить всі значення позитивними.

  2. Штрафування викидів: Квадрат надає більшу вагу великим похибкам, що змушує лінію ближче підходити до точок, які розташовані далеко.

Потім ми складаємо всі ці квадрати. Наша мета — знайти лінію, де ця сума квадратичних відхилень буде найменшою (мінімальною) — звідси й назва «найменших квадратів».

🧮 Покажіть мені математику
Цю лінію, яку називають лінією найкращого прилягання, можна подати за допомогою рівняння:

Y = a + bX

X — 'пояснювальна змінна', Y — 'залежна змінна'. Кут нахилу лінії — b, а a — це перетин з віссю Y, тобто значення Y, коли X = 0.

calculate the slope

Спершу обчислюємо нахил b. Інфографіка від Jen Looper

Іншими словами, у нашому прикладі з гарбузами, де треба "передбачити ціну гарбуза за бушель залежно від місяця", X — це ціна, а Y — місяць продажу.

complete the equation

Обчисліть значення 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)

Тепер, коли ви маєте уявлення про математику лінійної регресії, давайте створимо регресійну модель, щоб побачити, чи можемо ми передбачити, яка упаковка гарбузів матиме найкращі ціни. Хтось, хто купує гарбузи для осіннього ярмарку, може хотіти цю інформацію, щоб оптимізувати свої покупки.

Пошук кореляції

ML for beginners - Looking for Correlation: The Key to Linear Regression

🎥 Натисніть на зображення вище, щоб переглянути коротке відео про кореляцію.

Із попереднього уроку ви, мабуть, бачили, що середня ціна по місяцях виглядає так:

Average price by month

Це підказує, що повинна бути певна кореляція, і ми можемо спробувати навчити модель лінійної регресії для прогнозу зв’язку між Month і Price, або між DayOfYear і Price. Ось розсіювальний графік для останнього зв’язку:

Scatter plot of Price vs. Day of Year

Поглянемо, чи є кореляція, використовуючи функцію 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 of Price vs. Day of Year

Наше дослідження свідчить про те, що сорт має більший вплив на загальну ціну, ніж фактична дата продажу. Це можна бачити на стовпчиковій діаграмі:

new_pumpkins.groupby('Variety')['Price'].mean().plot(kind='bar')
Bar graph of price vs variety

Зараз зосередимося лише на одному сорті гарбуза, 'pie type', і подивимось, який вплив має дата на ціну:

pie_pumpkins = new_pumpkins[new_pumpkins['Variety']=='PIE TYPE']
pie_pumpkins.plot.scatter('DayOfYear','Price') 
Scatter plot of Price vs. Day of Year

Якщо тепер порахувати кореляцію між Price і DayOfYear за допомогою функції corr, отримаємо приблизно -0.27 — це означає, що навчання прогнозної моделі має сенс.

Перед тим, як навчати лінійну регресійну модель, важливо переконатися, що дані чисті. Лінійна регресія погано працює з пропущеними значеннями, тому має сенс позбутися порожніх клітинок:

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

Іншим підходом може бути заповнення порожніх значень середніми значеннями стовпця.

Проста лінійна регресія

ML for beginners - Linear and Polynomial Regression using 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 до вхідних даних, щоб пакет лінійної регресії правильно їх сприйняв. Лінійна регресія очікує 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)
Linear regression

Поліноміальна регресія

Інший тип лінійної регресії — це поліноміальна регресія. Хоча іноді між змінними існує лінійний зв’язок — чим більша гарбуз за обсягом, тим вища ціна — іноді такі зв’язки не можна відобразити у вигляді площини чи прямої лінії.

Ось декілька інших прикладів даних, які можуть потребувати поліноміальної регресії.

Подивіться ще раз на зв’язок між датою та ціною. Чи цього розсіювання досить, щоб його обов’язково слід аналізувати прямою лінією? А чи не можуть ціни коливатися? У такому разі можна спробувати поліноміальну регресію.

Поліноми — це математичні вирази, які можуть складатися з однієї чи кількох змінних і коефіцієнтів.

Поліноміальна регресія створює криву лінію, щоб краще підходити нелінійним даним. У нашому випадку, якщо включити змінну 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 для отримання прогнозів. Ось графік, що показує тестові дані та криву апроксимації:

Polynomial regression

За допомогою поліноміальної регресії ми можемо отримати дещо нижче MSE та вищий коефіцієнт детермінації, але не суттєво. Потрібно враховувати інші ознаки!

Ви бачите, що мінімальні ціни на гарбузи спостерігаються десь біля Геловіну. Як це можна пояснити?

🎃 Вітаємо, ви щойно створили модель, яка може допомогти передбачити ціну гарбузів для пирогів. Ймовірно, ви можете повторити цю процедуру для всіх типів гарбузів, але це було б нудно. Давайте навчимося враховувати сорт гарбуза в нашій моделі!

Категоріальні ознаки

В ідеальному світі ми хочемо передбачати ціни для різних сортів гарбузів за допомогою однієї моделі. Однак стовпець Variety дещо відрізняється від стовпців на кшталт Month, тому що містить нечислові значення. Такі стовпці називаються категоріальними.

ML для початківців - передбачення з категоріальними ознаками за допомогою лінійної регресії

🎥 Натисніть на зображення вище для короткого відеоогляду використання категоріальних ознак.

Тут ви бачите, як середня ціна залежить від сорту:

Average price by variety

Щоб врахувати сорт, спочатку потрібно перетворити його у числову форму, або закодувати. Є кілька способів це зробити:

  • Просте числове кодування створює таблицю різних сортів, а потім замінює назву сорту індексом у цій таблиці. Це не найкраща ідея для лінійної регресії, оскільки регресія бере фактичне числове значення індексу і додає його до результату, множачи на коефіцієнт. У нашому випадку залежність між номером індексу і ціною очевидно нелінійна, навіть якщо впорядкувати індекси певним чином.
  • 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. Хоча ми прагнемо до точності, будь ласка, майте на увазі, що автоматичні переклади можуть містити помилки або неточності. Оригінальний документ рідною мовою слід вважати авторитетним джерелом. Для критичної інформації рекомендується професійний людський переклад. Ми не несемо відповідальності за будь-які непорозуміння або неправильні тлумачення, що виникли внаслідок використання цього перекладу.