|
2 weeks ago | |
---|---|---|
.. | ||
solution | 2 weeks ago | |
README.md | 2 weeks ago | |
assignment.md | 2 weeks ago | |
notebook.ipynb | 2 weeks ago |
README.md
Създаване на регресионен модел с помощта на Scikit-learn: четири подхода към регресията
Инфографика от Dasani Madipalli
Тест преди лекцията
Този урок е наличен и на R!
Въведение
Досега разгледахте какво представлява регресията с примерни данни, събрани от набора с данни за цените на тиквите, който ще използваме през целия урок. Също така визуализирахте данните с помощта на Matplotlib.
Сега сте готови да се задълбочите в регресията за машинно обучение. Докато визуализацията ви помага да разберете данните, истинската сила на машинното обучение идва от обучението на модели. Моделите се обучават върху исторически данни, за да улавят автоматично зависимостите в данните, и позволяват да се предсказват резултати за нови данни, които моделът не е виждал преди.
В този урок ще научите повече за два типа регресия: основна линейна регресия и полиномиална регресия, заедно с част от математиката, която стои зад тези техники. Тези модели ще ни позволят да предсказваме цените на тиквите в зависимост от различни входни данни.
🎥 Кликнете върху изображението по-горе за кратък видео преглед на линейната регресия.
В този курс предполагаме минимални познания по математика и се стремим да я направим достъпна за студенти от други области, така че следете за бележки, 🧮 обяснения, диаграми и други инструменти за учене, които да подпомогнат разбирането.
Предварителни знания
Трябва вече да сте запознати със структурата на данните за тиквите, които разглеждаме. Те са предварително заредени и почистени в notebook.ipynb файла на този урок. В него цената на тиквите е показана на бушел в нова рамка с данни. Уверете се, че можете да стартирате тези тетрадки в ядра на Visual Studio Code.
Подготовка
Като напомняне, зареждате тези данни, за да задавате въпроси към тях.
- Кога е най-доброто време за купуване на тикви?
- Каква цена мога да очаквам за кутия с миниатюрни тикви?
- Трябва ли да ги купувам в кошници от половин бушел или в кутии от 1 1/9 бушел? Нека продължим да изследваме тези данни.
В предишния урок създадохте рамка с данни с Pandas и я запълнихте с част от оригиналния набор от данни, стандартизирайки цените на бушел. По този начин обаче успяхте да съберете само около 400 точки с данни и само за есенните месеци.
Разгледайте данните, които предварително заредихме в придружаващата тетрадка на този урок. Данните са предварително заредени и е начертан първоначален разпръснат график, за да се покаже информацията за месеците. Може би можем да получим малко повече подробности за естеството на данните, като ги почистим допълнително.
Линия на линейна регресия
Както научихте в Урок 1, целта на упражнението по линейна регресия е да начертаете линия, която:
- Показва връзките между променливите. Показва връзката между променливите.
- Прави прогнози. Прави точни прогнози за това къде нова точка с данни би попаднала спрямо тази линия.
Типично за регресията с най-малки квадрати е да се начертае този тип линия. Терминът "най-малки квадрати" означава, че всички точки с данни около регресионната линия се повдигат на квадрат и след това се събират. Идеално е тази крайна сума да е възможно най-малка, защото искаме малък брой грешки или най-малки квадрати
.
Правим това, защото искаме да моделираме линия, която има най-малкото кумулативно разстояние от всички наши точки с данни. Също така повдигаме на квадрат стойностите преди да ги съберем, защото ни интересува тяхната големина, а не посоката им.
🧮 Покажете ми математиката
Тази линия, наречена линия на най-добро съответствие, може да бъде изразена чрез уравнение:
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. С помощта на разпръснат график можете бързо да визуализирате този коефициент. График с точки, разположени в права линия, има висока корелация, но график с точки, разпръснати навсякъде между X и Y, има ниска корелация.
Добър модел за линейна регресия ще бъде този, който има висок (по-близо до 1, отколкото до 0) коефициент на корелация, използвайки метода на регресия с най-малки квадрати с линия на регресия.
✅ Стартирайте тетрадката, придружаваща този урок, и разгледайте разпръснатия график "Месец към Цена". Според вашата визуална интерпретация на разпръснатия график, изглежда ли, че данните за продажбите на тикви имат висока или ниска корелация? Променя ли се това, ако използвате по-прецизна мярка вместо Месец
, например ден от годината (т.е. брой дни от началото на годината)?
В кода по-долу ще предположим, че сме почистили данните и сме получили рамка с данни, наречена new_pumpkins
, подобна на следната:
ID | Месец | ДенОтГодината | Сорт | Град | Опаковка | Ниска цена | Висока цена | Цена |
---|---|---|---|---|---|---|---|---|
70 | 9 | 267 | PIE TYPE | BALTIMORE | 1 1/9 бушел кашони | 15.0 | 15.0 | 13.636364 |
71 | 9 | 267 | PIE TYPE | BALTIMORE | 1 1/9 бушел кашони | 18.0 | 18.0 | 16.363636 |
72 | 10 | 274 | PIE TYPE | BALTIMORE | 1 1/9 бушел кашони | 18.0 | 18.0 | 16.363636 |
73 | 10 | 274 | PIE TYPE | BALTIMORE | 1 1/9 бушел кашони | 17.0 | 17.0 | 15.454545 |
74 | 10 | 281 | PIE TYPE | BALTIMORE | 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)
Сега, когато разбирате математиката зад линейната регресия, нека създадем регресионен модел, за да видим дали можем да предскажем коя опаковка тикви ще има най-добри цени. Някой, който купува тикви за празнична тиквена градина, може да иска тази информация, за да оптимизира покупките си на тиквени опаковки за градината.
Търсене на корелация
🎥 Кликнете върху изображението по-горе за кратък видео преглед на корелацията.
От предишния урок вероятно сте видели, че средната цена за различните месеци изглежда така:

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

Нека видим дали има корелация, използвайки функцията 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', и да видим какъв ефект има датата върху цената:
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()
Друг подход би бил да запълним тези празни стойности със средни стойности от съответната колона.
Проста линейна регресия
🎥 Кликнете върху изображението по-горе за кратък видео преглед на линейната и полиномиалната регресия.
За да обучим нашия модел за линейна регресия, ще използваме библиотеката 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), която е средната стойност на всички квадратични разлики между очак Нашата грешка изглежда е около 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 включва полезен API за pipeline, който комбинира различни стъпки на обработка на данни. 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)
означава, че ще включим всички полиноми от втори ред от входните данни. В нашия случай това просто означава DayOfYear
2, но при две входни променливи 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
и типа на опаковката, което ни дава MSE 2.84 (10%) и детерминация 0.94!
Събиране на всичко заедно
За да създадем най-добрия модел, можем да използваме комбинирани (one-hot кодирани категориални + числови) данни от горния пример заедно с полиномиална регресия. Ето пълния код за ваше удобство:
# set up training data
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']
# make train-test split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
# setup and train the pipeline
pipeline = make_pipeline(PolynomialFeatures(2), LinearRegression())
pipeline.fit(X_train,y_train)
# predict results for test data
pred = pipeline.predict(X_test)
# calculate MSE and determination
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%. В последния раздел за регресия ще научите за логистичната регресия за определяне на категории.
🚀Предизвикателство
Тествайте няколко различни променливи в този notebook, за да видите как корелацията съответства на точността на модела.
Тест след лекцията
Преглед и самостоятелно обучение
В този урок научихме за линейната регресия. Има и други важни видове регресия. Прочетете за техниките Stepwise, Ridge, Lasso и Elasticnet. Добър курс за изучаване на повече е Статистическият курс на Stanford.
Задача
Отказ от отговорност:
Този документ е преведен с помощта на AI услуга за превод Co-op Translator. Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за недоразумения или погрешни интерпретации, произтичащи от използването на този превод.