Линейна регресия
Накратко: Линейната регресия предсказва число с права y = w · x + b, а средният квадрат на грешките (MSE) казва с едно число колко добре правата пасва на данните.
Проблем
Двама колеги, две прави
Складът иска да обещава часове, не дни. Ето 10 минали поръчки: разстоянието и за колко часа пристигнаха.
# минали поръчки: разстояние в km и часове до доставкатаKM = [30, 50, 80, 100, 130, 160, 200, 240, 270, 300]HOURS = [10, 11, 17, 17, 23, 24, 31, 33, 40, 44]Двама колеги гледат точките и предлагат правило:
- права A: всеки километър добавя 0,08 часа, плюс 12 часа в склада;
- права B: всеки километър добавя 0,12 часа, плюс 6 часа в склада.
На графиката и двете изглеждат прилично. Колегите спорят цял следобед. Спорът няма да свърши, докато нямат едно число, което казва колко е добра правата.
Идеята
Правата като модел
Двете предложения са от един вид: часове = w · km + b.
- w е наклонът: колко часа добавя всеки километър;
- b е отместването: часовете при 0 km, тоест обработката в склада.
Модел, който предсказва число с права, се казва линейна регресия. Да научиш модела значи да избереш w и b.
# правата: часове = w · km + bdef predict(w, b, km): return w * km + bЗа разлика от k най-близки съседи, правата не пази поръчките. Тя е две числа, а прогнозата е едно умножение и едно събиране. И продължава наклона си: за 500 km казва 0,12 · 500 + 6 = 66 часа, докато съседите на 500 km са поръчките от 300 km.
Идеята
Грешката на всяка поръчка
За всяка поръчка правата казва някакво число. Грешката е разликата: колко казва правата минус колко е било наистина. Положителна е, когато правата обещава повече, отрицателна, когато обещава по-малко.
Права B, поръчка по поръчка:
w, b = 0.12, 6for km, hours in zip(KM, HOURS): guess = predict(w, b, km) print(f"{km} km: истина {hours} ч, правата {guess:.2f} ч, грешка {guess - hours:.2f}")print(f"MSE: {mse(w, b):.2f}")30 km: истина 10 ч, правата 9.60 ч, грешка -0.4050 km: истина 11 ч, правата 12.00 ч, грешка 1.0080 km: истина 17 ч, правата 15.60 ч, грешка -1.40100 km: истина 17 ч, правата 18.00 ч, грешка 1.00130 km: истина 23 ч, правата 21.60 ч, грешка -1.40160 km: истина 24 ч, правата 25.20 ч, грешка 1.20200 km: истина 31 ч, правата 30.00 ч, грешка -1.00240 km: истина 33 ч, правата 34.80 ч, грешка 1.80270 km: истина 40 ч, правата 38.40 ч, грешка -1.60300 km: истина 44 ч, правата 42.00 ч, грешка -2.00MSE: 1.83Десет грешки, част с плюс, част с минус. Трябва ни едно число за цялата права.
Идеята
Едно число: средният квадрат
Всяка грешка се повдига на квадрат, квадратите се събират и се делят на броя на поръчките. Това е средният квадрат на грешките, MSE (mean squared error). Число, което казва колко е лош моделът, се казва функция на грешката (loss). По-малко е по-добре, а 0 значи, че правата минава през всяка точка.
# средният квадрат на грешките (MSE)def mse(w, b): total = 0 for km, hours in zip(KM, HOURS): error = predict(w, b, km) - hours total += error * error return total / len(KM)zip(KM, HOURS) върви по двата списъка едновременно: на всяка стъпка дава една двойка km и часове.Защо квадрат? Сравни трите прави. C е хоризонталната права през средното, 25 часа за всяка поръчка:
# средната грешка без квадратdef mean_error(w, b): total = 0 for km, hours in zip(KM, HOURS): total += predict(w, b, km) - hours return total / len(KM)lines = {"A": (0.08, 12), "B": (0.12, 6), "C": (0, 25)}for name, (w, b) in lines.items(): print(f"права {name}: MSE {mse(w, b):.2f}, средна грешка {mean_error(w, b):.2f}")права A: MSE 17.35, средна грешка -0.52права B: MSE 1.83, средна грешка -0.28права C: MSE 124.00, средна грешка 0.00Без квадрата права C има средна грешка 0,00: колкото е над точките, толкова е под тях, и плюсовете унищожават минусите. Най-лошата права „печели“. С квадрата нищо не се унищожава: C е 124, A е 17,35, а B е 1,83. Колегата с права B печели спора.
Квадратът прави и още нещо: голямата грешка тежи повече. Грешка от 4 часа дава 16, а две грешки по 2 часа дават общо 8. Правата, която греши малко навсякъде, е по-добра от тази, която е точна на половината поръчки и греши много на другата половина.
Виж го
Грешките като квадрати
def predict(w, b, km): return w * km + b
def mse(w, b): total = 0 for km, hours in zip(KM, HOURS): error = predict(w, b, km) - hours total += error * error return total / len(KM)Стъпка по стъпка, с думи
- 10 минали поръчки: колко km и за колко часа пристигнаха.
- Права A: 0,08 часа на km плюс 12 часа.
- Грешката на всяка поръчка: колко казва правата минус колко беше. Едни точки са над правата, други под нея.
- Всяка грешка на квадрат е квадрат със страна грешката. Средната им площ е MSE: 17,35.
- Права B: 0,12 часа на km плюс 6 часа. Правата се завърта, а квадратите се свиват.
- MSE на B е 1,83 срещу 17,35 на A.
- Правата с по-малка MSE е по-близо до точките. Едно число вместо спор.
Всеки квадрат е една грешка на квадрат: страната му е разстоянието от точката до правата. MSE е средната им площ. Права B е по-добра, защото квадратите ѝ са по-малки, не защото някой така е преценил.
Пробвай
Предвиди изхода
Куриерът взима 2 € на килограм. Три пратки от 1, 2 и 3 kg са стрували 3, 5 и 7 €. Какво ще отпечата програмата?
kg = [1, 2, 3]price = [3, 5, 7]total = 0for x, y in zip(kg, price): error = 2 * x - y total += error * errorprint(f"{total / 3:.2f}")Правата 2 · kg дава 2, 4 и 6 €, а истината е 3, 5 и 7 €. Всяка грешка е −1, а квадратът ѝ е 1. Средното на 1, 1 и 1 е 1,00. MSE не може да е отрицателна.
Пробвай
Попълни
Какво се добавя към сумата за всяка поръчка?
error = predict(w, b, km) - hours
total += Квадратът на грешката: error * error. Умножението е по-ясно и по-бързо от степенуване, а резултатът е същият.
Пробвай
Намери грешката
Колега пише функцията на грешката и сравнява правите. Неговата програма казва, че най-добрата е хоризонталната права C. На кой ред е грешката?
Избери реда с грешката.
Грешката се добавя без квадрат. Плюсовете и минусите се унищожават, и правата през средното излиза с грешка 0. Трябва error * error.
Идеята
Кога правата лъже
Правата е най-простият модел и често е достатъчна. Но:
- Светът не е прав. Ако след 300 km поръчката минава през друг склад и чака още ден, точките правят стъпало. Правата минава между двете части и греши и на двете.
- Една странна точка. Поръчка, изгубена за седмица, е грешка от стотици часове, а квадратът ѝ тежи колкото всички останали заедно. Правата се накланя към нея и започва да лъже за нормалните поръчки. Такива точки се проверяват и махат или се мери със средната абсолютна грешка.
- Далеч извън данните. Поръчките са до 300 km. За 2 000 km правата казва 246 часа, но никой не е проверил дали изобщо има такава доставка.
- Връзка не значи причина. Правата казва, че по-далечните поръчки пътуват по-дълго. Тя не казва защо. Ако по-далечните градове просто се обслужват от по-бавен куриер, по-бърз куриер там ще счупи правата.
Правата, която колегите избраха на око, е само едно от безбройните w и b. Коя е най-добрата и как да я намериш без да гадаеш, е в урока за градиентното спускане.
По-точно, за любопитните
Формулата за най-добрата права. За една права има точна формула (метод на най-малките квадрати). w е колко се движат заедно km и часовете, делено на колко се движат самите km. b е такова, че правата минава през средната точка:
w = Σ (km − средно km) · (часове − средно часове) / Σ (km − средно km)², b = средно часове − w · средно km.
n = len(KM)mean_km = 0mean_hours = 0for km, hours in zip(KM, HOURS): mean_km += km mean_hours += hoursmean_km /= nmean_hours /= ntop = 0bottom = 0for km, hours in zip(KM, HOURS): top += (km - mean_km) * (hours - mean_hours) bottom += (km - mean_km) * (km - mean_km)w = top / bottomb = mean_hours - w * mean_kmprint(f"най-добрата права: {w:.4f} ч/km, {b:.2f} ч")print(f"MSE: {mse(w, b):.2f}")най-добрата права: 0.1241 ч/km, 5.64 чMSE: 1.62Най-добрата права е малко по-добра от B (1,62 срещу 1,83). Колегата е преценил добре.
Защо не винаги формулата? Тя е за правата с квадратна грешка. При много признаци, при друга функция на грешката и при невронните мрежи точна формула няма или е твърде бавна. Затова се ползва градиентното спускане.
Повече признаци. Правата може да има по едно w за всеки признак: часове = w₁ · km + w₂ · kg + w₃ · пратки + b. Идеята и MSE са същите.
Средната абсолютна грешка (MAE) събира |грешка| вместо квадрата. Тя не наказва толкова голямата грешка и е по-спокойна към странни точки. MSE е по-гладка и затова по-удобна за градиентното спускане.
В библиотеките: LinearRegression в scikit-learn смята точно тази формула. В ML.NET е Sdca или Ols регресия.
Упражнение
Цената на куриера
Реши задачата в редактора си.
Куриерът не публикува ценоразписа си, но магазинът пази колко е платил за осем пратки:
# пратки: тегло в kg и цена на куриера в €KG = [0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 5.0, 6.0]EUR = [4.10, 4.60, 5.00, 5.60, 6.40, 7.50, 8.30, 9.40]Колегите предлагат три прави за цената: A е 0,90 € на kg плюс 3,80 €, B е 1,10 € на kg плюс 3,20 €, C е 0,70 € на kg плюс 4,60 €. Напиши функцията на грешката (MSE), отпечатай я за трите и кажи коя е най-добра.
права A (0.90 €/kg + 3.80 €): MSE 0.0144права B (1.10 €/kg + 3.20 €): MSE 0.0769права C (0.70 €/kg + 4.60 €): MSE 0.2869най-малка MSE: права AОще задачи
- Средната абсолютна грешка. Смени квадрата с абсолютна стойност. Сменя ли се победителят?
- Формулата. Сметни най-добрата права с формулата от „По-точно“. Колко е по-добра от A?
Тест
Провери се
Свързани уроци
Раздел „Свързани уроци“- Нужно отпреди: Функции · Параметри и return · Общото за всички: атрибути на класа · Какво е машинно учене
- Продължава в: Градиентно спускане · Класификация: измама или не · Преобучение: моделът, който наизустява · Неврон
- Задачи по темата: Как учи модел