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/bg/2-Regression/3-Linear
localizeflow[bot] 53f59247af
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) 7 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) 7 months ago
notebook.ipynb 🌐 Update translations via Co-op Translator 11 months ago

README.md

Изграждане на регресионен модел с помощта на Scikit-learn: регресия по четири начина

Забележка за начинаещи

Линейната регресия се използва, когато искаме да предскажем числена стойност (например цена на къща, температура или продажби). Тя работи чрез намиране на права линия, която най-добре представя връзката между входните характеристики и изхода.

В този урок се фокусираме върху разбирането на концепцията, преди да разгледаме по-сложни регресионни техники. Линейна срещу полиномиална регресия инфографика

Инфографика от Dasani Madipalli

Предварителен тест

Този урок е наличен и на R!

Въведение

Досега разгледахте какво е регресия чрез примерни данни от набора с цени на тикви, който ще използваме през целия урок. Също така го визуализирахте с помощта на Matplotlib.

Сега сте готови да навлезете по-дълбоко в регресията за ML. Докато визуализацията ви позволява да разберете данните, истинската сила на Машинното обучение идва от обучението на модели. Моделите се обучават върху исторически данни, за да уловят автоматично зависимостите в данните, и ви позволяват да предсказвате резултати за нови данни, които моделът не е виждал досега.

В този урок ще научите повече за два вида регресия: основна линейна регресия и полиномиална регресия, заедно с част от математиката зад тези техники. Тези модели ще ни позволят да предсказваме цените на тиквите в зависимост от различни входни данни.

ML за начинаещи - Разбиране на линейната регресия

🎥 Кликнете върху изображението по-горе за кратко видео с обобщение на линейната регресия.

В целия този учебен план предполагаме минимални знания по математика и се стремим да го направим достъпен за студенти от други области, затова внимавайте за бележки, 🧮 извадки, схеми и други учебни средства, които подпомагат разбирането.

Предварителни умения

До момента трябва да сте запознати със структурата на данните за тиквите, които разглеждаме. Можете да ги намерите предварително заредени и почистени във файла notebook.ipynb за този урок. Във файла цената на тиквите се показва на бушел в нов DataFrame. Уверете се, че можете да стартирате тези тетрадки (notebooks) в ядра (kernels) в Visual Studio Code.

Подготовка

Като напомняне, зареждате тези данни, за да можете да задавате въпроси спрямо тях.

  • Кога е най-доброто време да се купуват тикви?
  • Каква цена мога да очаквам за кутия с мини тикви?
  • Трябва ли да ги купувам в кошници по половин бушел или в кутии по 1 1/9 бушел? Нека продължим да изследваме тези данни.

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

Вижте данните, които предварително заредихме в съпровождащата тетрадка за този урок. Данните са предварително заредени и е начертан първоначален разсейващ (scatter) график за данните по месеци. Може би можем да добавим малко повече детайли за естеството на данните чрез по-добро почистване.

Линия на линейната регресия

Както научихте в Урок 1, целта на упражнение по линейна регресия е да можете да начертаете линия, която да:

  • Показва взаимовръзки между променливи. Показва връзката между променливите
  • Прави прогнози. Прави точни прогнози за това къде нова точка данни би попаднала в съотношение с линията.

Точно такава линия обичайно се чертае с помощта на регресия с минимални квадрати (Least-Squares Regression). Терминът "минимални квадрати" се отнася до процеса на минимизиране на общата грешка в нашия модел. За всяка точка данни измерваме вертикалното разстояние (наречено остатък) между действителната точка и нашата регресионна линия.

Тези разстояния се повдигат на квадрат по две основни причини:

  1. Величина пред посока: Искаме да третираме грешка -5 същo като грешка +5. Квaдратирането превръща всички стойности в положителни.

  2. Накaзване на екстремни стойности: Квaдратирането придава по-голяма тежест на по-големите грешки, принуждавайки линията да стои по-близо до точки, които са далеч.

След това събираме всички тези квадратирани стойности. Целта ни е да намерим конкретна линия, при която тази крайна сума е най-малка (най-малката възможна стойност) — откъдето идва и името "минимални квадрати".

🧮 Покажи ми математиката

Тази линия, наречена линия на най-добро прилягане, може да бъде изразена с уравнение:

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. Използвайки разсейващ (scatter) график, може бързо да визуализирате този коефициент. Графика с точки, подредени в чиста линия, показва висока корелация, докато графика с точки разпръснати навсякъде между X и Y показва ниска корелация.

Добър линейно регресионен модел е този, който има висок (по-близо до 1 отколкото до 0) коефициент на корелация при приложена метода на регресия с минимални квадрати с линия на регресия.

Стартирайте тетрадката, придружаваща този урок, и разгледайте разсейващия график Месец към Цена. Изглежда ли асоциацията между Месец и Цена за продажбата на тикви с висока или ниска корелация според вашата визуална интерпретация на графиката? Променя ли се това, ако използвате по-фина мярка вместо Месец, напр. ден от годината (т.е. брой дни от началото на годината)?

В следващия код ще приемем, че сме почистили данните и сме получили 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)

Сега, когато разбирате математиката зад линейната регресия, нека създадем регресионен модел, за да видим дали можем да предскажем коя опаковка тикви ще има най-добри цени. Някой, който купува тикви за празничен тиквен етикет, може да иска тази информация, за да оптимизира покупките на опаковки тикви за етикета.

Търсене на корелация

ML за начинаещи - Търсене на корелация: Ключът към линейната регресия

🎥 Кликнете върху изображението по-горе за кратко видео с обобщение на корелацията.

От предишния урок вероятно сте видели, че средната цена за различните месеци изглежда така:

Средна цена по месеци

Това предполага, че трябва да има някаква корелация и можем да пробваме да обучим модел на линейна регресия за прогнозиране на връзката между Месец и Цена, или между ДенОтГодината и Цена. Ето разсейващия график, който показва последната връзка:

Scatter plot Цена срещу Ден от година

Нека проверим дали има корелация с функцията corr:

print(new_pumpkins['Month'].corr(new_pumpkins['Price']))
print(new_pumpkins['DayOfYear'].corr(new_pumpkins['Price']))

Изглежда, че корелацията е доста малка, -0.15 за Месец и -0.17 за ДенОтГодината, но може да има друга важна връзка. Изглежда има различни клъстери от цени, съответстващи на различни сортове тикви. За да потвърдим тази хипотеза, нека начертаем всяка категория тикви с различен цвят. Предавайки параметър ax на функцията за разсейващ график, можем да начертаем всички точки на един и същ график:

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_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()

Друг подход би бил да запълним празните стойности със средните стойности от съответните колони.

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

ML за начинаещи - Линейна и полиномиална регресия с 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 е верига от оценители (estimators). В нашия случай ще създадем 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

С помощта на полиномиална регресия можем да получим леко по-ниска средна квадратична грешка и по-висок коефициент на детерминация, но незначително. Трябва да вземем предвид и други характеристики!

Можете да видите, че минималните цени на тиквите се наблюдават някъде около Хелоуин. Как бихте го обяснили?

🎃 Поздравления, току-що създадохте модел, който може да помага за предсказване на цената на тикви за пай. Вероятно можете да повторите същата процедура за всички видове тикви, но това би било досадно. Нека сега научим как да вземем предвид сорта тикви в нашия модел!

Категориални характеристики

В идеалния свят искаме да можем да предсказваме цените за различни сортове тикви, използвайки същия модел. Въпреки това, колоната 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 и коефициент на детерминация
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%. В последната част за регресия ще научите за логистичната регресия за определяне на категории.


🚀Предизвикателство

Тествайте няколко различни променливи в тази тетрадка, за да видите как корелацията съответства на точността на модела.

Викторина след лекцията

Преглед и самообучение

В този урок научихме за линейната регресия. Има и други важни видове регресия. Прочетете за техническите подходи Stepwise, Ridge, Lasso и Elasticnet. Добър курс за по-задълбочено изучаване е Stanford Statistical Learning course

Задача

Изградете модел


Отказ от отговорност:
Този документ е преведен с помощта на AI преводаческа услуга Co-op Translator. Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи могат да съдържат грешки или неточности. Оригиналният документ на неговия език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Не носим отговорност за никакви недоразумения или погрешни тълкувания, произтичащи от използването на този превод.