Регресията е един от методите, прилагани от специалистите в областта на машинното обучение за решаване на конкретни бизнес задачи. В зависимост от начина на използване, можем да разделим задачите в 2 категории:
- изследване на връзката на всяка от отделните характеристики с целевата променлива
- прогнозиране на непрекъснати числови стойности (например заплата, цена, тегло и др.) на база на вече известни данни.
В тази статия с практически пример ще разгледаме решение на регресионна задача за прогнозиране на цени на автомобили. Ще използваме езика за програмиране Python и неговите библиотеки за анализ на данни и машинно обучение.
С какви данни ще работим?
Данните съдържат 4041 реда и 74 колони и включват обяви за продажба на автомобили от различни български сайтове. Извлечени са на 01.07.2021г.
5 случайно избрани реда изглеждат по следния начин:
brand | model | month_prod | year_prod | color | engine_type | hp | gearbox | category | mileage | gps | adaptive_fl | antiblock_sys | airbags_back | airbags_front | tire_pressure_control | parktronic | isofix | auto_start_stop | dvd_tv | step_tip | no_key_ignition | usb_av_inaux_outputs | diff_blockage | boardcomp | light_sensor | el_mirrors | el_susp_adj | climatronic | mf_steering_wheel | sw_heating | 7seats | buy_back | barter | gas_sys | lb | saved_sold | sb | leasing | methane_sys | parts | new_import | credit | service_book | tuning | 2_3_doors | xenon_lights | alloy_wheels | metalic | heated_wipers | rollbar | towbar | halogen_lights | moving_roof | offroad | alarm | armored | casco | winch | reinforced_glass_windows | suede | right_sw | taxi | date_created | time_created | day | month | year | views | dealer | city | region | price | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
526 | Mercedes-Benz | ML | февруари | 2015 | Червен | Бензинов | 333 | Автоматична | Джип | 67000 | Да | Не | Не | Не | Не | Не | Не | Не | Да | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Да | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | 26 април 2021 | 18:03 | 26 | април | 2021 | 11923 | Автокъща | Пловдив | Южен централен | 49950 |
1049 | Audi | A3 | ноември | 2013 | Сив | Бензинов | 140 | Автоматична | Седан | 190000 | Да | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Да | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | 15 юни 2021 | 22:14 | 15 | юни | 2021 | 183 | Автокъща | Дупница | Югозападен | 23500 |
649 | Porsche | Panamera | септември | 2012 | Черен | Бензинов | 400 | Автоматична | Хечбек | 187000 | Да | Не | Не | Не | Не | Не | Не | Не | Да | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Да | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | 11 юни 2021 | 16:42 | 11 | юни | 2021 | 2469 | Автокъща | Пловдив | Южен централен | 54000 |
974 | Audi | A3 | февруари | 2006 | Сребърен | Дизелов | 105 | Ръчна | Хечбек | 186000 | Не | Не | Да | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Да | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | 17 юни 2021 | 21:01 | 17 | юни | 2021 | 17 | Автокъща | Русе | Северен централен | 7500 |
920 | Audi | A3 | май | 2003 | Черен | Дизелов | 101 | Ръчна | Хечбек | 200000 | Не | Не | Да | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Да | Да | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Да | Не | Не | Не | Не | Не | Не | Да | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | 10 юни 2021 | 15:44 | 10 | юни | 2021 | 691 | Автокъща | София | Югозападен | 4500 |
Преглед на данните
За да добием представа за данните, с които разполагаме, ще създадем няколко визуализации. Те ще ни помогнат да намерим отговор на следните въпроси:
- Кои марки и модели са най-предлагани?
- В кои части на България има най-много обяви и на какви цени са автомобилите?
- Какъв е процентът на обявите от Частно лице и Автокъща според типа двигател?
- Какво е разпределението на променливите?
- Кои марки и модели са най-предлагани?
Най-предлаганото превозно средство е Audi A4, като има 324 обяви за този автомобил. На 10-то място е Mercedes-Benz C с 81 обяви.
Най-предлаганите превозни средства са на марките Audi и BMW, съответно 1029 и 633 на брой обяви. На 10-то място е марката Ford с 62 обяви.
- В кои части на България има най-много обяви и на какви цени са автомобилите?
Изчислена е средната претеглена стойност на броя обяви за всеки регион, като теглата са броя население на градовете в съответния регион. Има най-много обяви в Югозападния регион на България – 1526 обяви средно, а най-малко в Северен централен – 85. Има и 1 единствена обява за автомобил, който се намира извън България.
Тук отново е изчислена средна претеглена стойност, но този път за цената на автомобилите. Най-висока е средната цена на автомобил в Югозападния регион – 28389.80 лв. При Североизточния, Югоизточния и Южен централен са близки като стойности. За единствената обява извън България, цената на автомобила е 8900 лв.
- Какъв е процентът на обявите от частно лице и автокъща според типа двигател?
За обявите на автомобили от Автокъща най-предлагани са превозни средства с дизелов двигател – 2170 на брой обяви (69.6%), а най-малко с електрически – 13 обяви или 0.42%.
От частни лица се предлагат също най-много автомобили с дизелов двигател – 578 обяви или 62.6%. Има само 1 обява за автомобил с електрически двигател.
- Какво е разпределението на променливите?
Хистограмите представят разпределенията на числовите променливи в извадката, като с червената пунктирана вертикална линия е означена средната стойност, а със зелената е медианата.
Следната таблица представя средните и медианните стойности за всяка от числовите променливи.
Variable | Mean | Median | |
---|---|---|---|
0 | year_prod | 2009.52 | 2009.00 |
1 | age | 11.48 | 12.00 |
2 | hp | 194.22 | 170.00 |
3 | mileage | 175794.17 | 179890.00 |
4 | price | 22942.49 | 12999.00 |
5 | views | 2841.96 | 581.00 |
Някои изводи:
- Разпределенията на годините на производство и възрастта на автомобила са близки до нормалното. При тях медианата и средната стойност са почти равни – 2009 и 2009.52.
- При конските сили и пробега също няма толкова голяма разлика между средната стойност и медианата.
- По-големи разлики се забелязват при цената и броя преглеждания на обявите. Двете разпределения не са нормално разпределени, а са асиметрични и дясно изтеглени.
Тъй като променливите цена (price) и брой преглеждания (views) не са нормално разпределени, ще ги трансформираме чрез логаритмичната функция, предоставена от библиотеката NumPy. В противен случай можем да получим подвеждащи резултати от регресионните модели.
# Прилагане на трансформация с логаритъм върху 2-те променливи
df['price'] = np.log(df['price'])
df['views'] = np.log(df['views'])
Тъй като имаме много на брой бинарни променливи в извадката, ще разгледаме разпределението само на някои от тях. За да определим точно на кои, ще използваме класът Variance Threshold на библиотеката Scikit-learn, за да премахнем тези бинарни променливи, при които едната категория заема над 75% от данните.
# Откриване на бинарните променливи
df_b = df.loc[:,df.replace({'Да':1, 'Не':0}).isin([0,1]).all()]
# Прилагане на VarianceThreshold
vt = VarianceThreshold(threshold=0.75 * (1 - 0.75))
vt.fit(df_b.replace({'Да':1, 'Не':0}))
gps | auto_start_stop | xenon_lights | metalic | |
---|---|---|---|---|
253 | Не | Не | Не | Не |
822 | Не | Не | Не | Не |
558 | Не | Да | Да | Не |
352 | Да | Не | Не | Да |
3809 | Не | Не | Не | Не |
След прилагане на VarianceThreshold, оставаме с 4 бинарни променливи – наличие на GPS, наличие на Auto Start Stop функционалност, дали превозното средство има ксенонови фарове и дали е в цвят металик. На стълбовидните диаграми по-надолу, можете да видите тяхното разпределение.
Обявите, на които стойността на променливите е Не, са повече.
Кодиране на категорийни променливи и стандартизация на данните
Необходимо е категорийните променливи да ги превърнем в числови, тъй като регресионните модели изискват входните данни да са числа. Нужно е също така те да бъдат и мащабирани, тъй като при използване на регресионните модели, които изчисляват коефициенти, можем да получим резултати с голяма грешка.
# Отделяне на характеристиките и целевата променлива
X = df.drop(['price'], axis=1)
y = df[['price']]
# Отделяне на числовите променливи и създаване на StandartScaler обект
numeric_features = ['year_prod', 'hp', 'mileage', 'views']
numeric_transformer = StandardScaler()
# Отделяне на категорийните променливи и създаване на OneHotEncoder обект
categorical_features = df.select_dtypes('object').columns
categorical_transformer = OneHotEncoder(drop='first')
# Кодиране на нечисловите променливи и стандартизация на данните
preprocessor = ColumnTransformer(
transformers=[
('scaler', numeric_transformer, numeric_features),
('onehot', categorical_transformer, categorical_features),
('col_keep', 'passthrough', ['gps', 'auto_start_stop', 'xenon_lights', 'metalic'])])
# Прилагане на обработките
X_transformed = preprocessor.fit_transform(X).toarray()
# Създаване на списък с колоните
cols_list = [preprocessor.transformers_[0][2],
preprocessor.transformers_[1][1].get_feature_names(categorical_features),
preprocessor.transformers_[2][2]]
cols = list(itertools.chain.from_iterable(cols_list))
# Запазване на данните в нов DataFrame
X_coded = pd.DataFrame(X_transformed, columns=cols)
След обработката на данните, колоните в извадката ни стават 510 на брой. Следващата стъпка е да открием дали има аномалии в данните и кои са по-важните характеристики, които да използваме при изграждане на моделите за машинно обучение.
Обработка на отличителни стойности и избор на по-важни характеристики
За откриване на аномалии ще използваме методът k най-близки съседи (KNN) на библиотеката PyOD.
# Създаване на KNN обект с 5 съседа и метрика 'евклидово разстояние'
alg = KNN(n_neighbors=5, metric='euclidean')
# Прилагане на алгоритъма KNN
knn = alg.fit(X_coded)
X_coded['outlier'] = knn.labels_
Алгоритъмът KNN e открил 404 обяви, в които се срещат аномалии. Тях ще ги премахнем от извадката, тъй като може да повлияят негативно на моделите за машинно обучение.
Следващата стъпка е да използваме класа SelectKBest на библиотеката Scikit-learn, за да открием 5-те характеристики, които оказват най-голямо влияние при при определяне на цената. Той получава като параметър статистически тест. В нашия случай това е f_regression, който първо открива корелацията между всяка характеристика и целевата променлива и конвентира получените резултати в F score и p-value. Накрая се извеждат тези променливи, получили най-добри оценки от теста.
# Откриване на 5-те най-значими характеристики чрез SelectKBest
importances = fs.select_k_best(X_coded, y, 5)
# Визуализация на резултатите
fs.plot_best_features(importances)
SelectKBest e определил година на производство, конски сили, това дали превозното средство е с ръчна скоростна кутия, дали има ксенонови фарове и Auto Start Stop функционалност като най-важните променливи, определящи цената.
На следващата графика можете да видите корелационна матрица, която ни показва колко е силна зависимостта между отделните характеристики.
# Откриване на корелация между независимите характеристики
X_coded = X_coded[importances.features.values]
corr = X_coded.corr()
Премахваме променливите наличие на Auto Start Stop функционалност и ръчна скоростна кутия, тъй като между първата и година на производство има 60% положителна корелация, а между втората и променливата конски сили има 59% отрицателна корелация.
Изграждане на модели за машинно обучение с параметри по подразбиране
По време на тази стъпка ще създадем модели за машинно обучение, използващи различни регресионни алгоритми, като ще оставим параметрите, които са им зададени по подразбиране.
Първо е необходимо да разделим извадката на 2 части – 70% от данните ще са за обучение на моделите, а 30% за тест. Ще използваме train_test_split на библиотеката Scikit-learn.
# Разделяне на извадката
X_train, X_test, y_train, y_test = train_test_split(X_coded,
y,
test_size=0.3,
random_state=17)
След като сме разделили данните, трябва да създадем и обучим моделите. Ще използваме 12 различни регресионни алгоритми при изграждане на моделите, след което ще тестваме до колко добре те прогнозират стойностите на целевата променлива.
# Създаване на модели с параметри по подразбиране
knn = KNeighborsRegressor()
lr = LinearRegression()
sgd = SGDRegressor()
hr = HuberRegressor()
ridge = Ridge()
br = BayesianRidge()
omp = OrthogonalMatchingPursuit()
et = ExtraTreesRegressor()
gbr = GradientBoostingRegressor()
ab = AdaBoostRegressor()
rf = RandomForestRegressor()
dt = DecisionTreeRegressor()
# Запазване на моделите в списък
regressors = [knn, lr, sgd, hr, ridge, br, omp, et, gbr, ab, rf, dt]
# Обучение на моделите
for regressor in regressors:
regressor.fit(X_train, y_train)
# Създаване на празен списък за резултатите
predictions = []
# Прогнозиране на стойности и запазване на резултатите с списъка
for name, regressor in zip(names,regressors):
locals()['y_pred_' + str(name)] = np.exp(regressor.predict(X_test))
predictions.append(locals()['y_pred_' + str(name)])
Получените прогнозирани стойности е необходимо да бъдат съпоставени с действителните. За тази цел ще разгледаме някои често използвани метрики за оценка на регресионни алгоритми. Това ще ни позволи да добием представа до колко добре моделите с параметри по подразбиране са прогнозирали цените на превозните средства.
Метриките, които ще разгледаме са:
- R-квадрат (R-squared) и Изравнен R-квадрат (Adjusted R-squared)
- Средна абсолютна грешка (MAE) и Средна абсолютна процентна грешка (MAPE)
- Средна квадратична грешка (Mean Squared Error) & Корен от средната квадратична грешка (Root Mean Squared Error)
Model | R2_score | Adj R2 | MSE | RMSE | MAE | MAPE | |
---|---|---|---|---|---|---|---|
7 | ExtraTreesRegressor | 0.88 | 0.88 | 123842231.55 | 11128.44 | 4694.38 | 22.86 |
10 | RandomForestRegressor | 0.88 | 0.88 | 124523408.57 | 11159.01 | 4787.34 | 22.39 |
11 | DecisionTreeRegressor | 0.88 | 0.88 | 120830168.14 | 10992.28 | 4789.53 | 24.04 |
8 | GradientBoostingRegressor | 0.88 | 0.88 | 123208997.36 | 11099.95 | 5015.91 | 22.27 |
0 | KNeighborsRegressor | 0.84 | 0.84 | 163466018.58 | 12785.38 | 5425.23 | 23.23 |
2 | SGDRegressor | 0.71 | 0.71 | 294067408.72 | 17148.39 | 6255.44 | 24.45 |
4 | Ridge | 0.68 | 0.68 | 323521437.05 | 17986.70 | 6331.09 | 24.58 |
5 | BayesianRidge | 0.68 | 0.68 | 323748351.97 | 17993.01 | 6331.51 | 24.58 |
1 | LinearRegression | 0.68 | 0.68 | 324008977.92 | 18000.25 | 6331.99 | 24.58 |
3 | HuberRegressor | 0.65 | 0.65 | 350406954.54 | 18719.16 | 6412.73 | 24.87 |
9 | AdaBoostRegressor | 0.69 | 0.69 | 305244621.77 | 17471.25 | 7002.41 | 27.06 |
6 | OrthogonalMatchingPursuit | 0.44 | 0.44 | 556220119.71 | 23584.32 | 10120.78 | 42.96 |
Алгоритмите използващи дървете на решенията се справят най-добре от всички модели, като коефициентите им на детерминация са 0.88. ExtraTreesRegressor е на първо място според средна абсолютна грешка, а GradientBoostingRegressor е с най-нисък резултат за средна абсолютна процентна грешка – 22.27%, но стойностите на останалите грешки са по-високи. Най-лошо се е справил OrthogonalMatchingPursuit с 0.44 коефициент на детерминация и много високи грешки.
Избор на модел и откриване на оптимални параметри
Ще изберем модела, използващ алгоритъма ExtraTreesRegressor, защото като цяло даде най-добри резултати при теста с параметри по подразбиране. В тази стъпка ще използваме библиотеката Hyperopt, за да открием оптималните параметри за модела, при които средната абсолютна процентна грешка е най-ниска.
Първо ще зададем какво да бъде пространството от параметри, след което ще създадем и приложим целева фукнция.
# Създаване на пространство от параметри
params = {'criterion': hp.choice('criterion', ['mae', 'mse']),
'max_depth': hp.quniform('max_depth', 1, 100, 1),
'max_features': hp.choice('max_features', ['sqrt','log2', None]),
'min_samples_leaf': hp.choice('min_samples_leaf', [2, 5, 10, 14]),
'min_samples_split' : hp.choice ('min_samples_split', [2, 4, 6, 8, 10]),
'n_estimators' : hp.choice('n_estimators', [200, 500, 800])
}
# Създаване на целева функция
def objective(params):
et_new = ExtraTreesRegressor(criterion = params['criterion'], max_depth = params['max_depth'],
max_features = params['max_features'],
min_samples_leaf = params['min_samples_leaf'],
min_samples_split = params['min_samples_split'],
n_estimators = params['n_estimators'],
)
mape = cross_val_score(et_new, X_train, y_train, scoring=neg_mean_absolute_error, cv = 5).mean()
return {'loss': -mape, 'status': STATUS_OK }
Тъй като целевата променлива е преминала през трансформация с логаритъм, откриването на оптималните параметри е на база стойността на MAPE, а не MAE.
# Прилагане на целевата функция
trials = Trials()
best = fmin(fn= objective,
space= params,
algo= tpe.suggest,
max_evals = 80,
trials= trials)
Оптималните параметри, които е открихме чрез функцията fmin(), са следните:
Hyperparameter | Value |
---|---|
criterion | MAE |
max_depth | 53 |
max_features | None |
min_samples_leaf | 2 |
min_samples_split | 6 |
n_estimators | 200 |
След като вече имаме оптималните параметри, е необходимо да тестваме до колко добре моделът ще прогнозира стойностите на целевата променлива.
# Създаване на нов модел с оптималните параметри
et_optimised = ExtraTreesRegressor(criterion = criterion[best['criterion']],
max_depth = best['max_depth'],
max_features = m_features[best['max_features']],
min_samples_leaf = leaf[best['min_samples_leaf']],
min_samples_split = split[best['min_samples_split']],
n_estimators = n_est[best['n_estimators']])
# Обучение на оптимизирания модел
et_optimised.fit(X_train, y_train)
# Прогнозиране на стойности
et_new_pred = np.exp(et_optimised.predict(X_test))
Получените резултати от модела са следните:
Metrics | Scores | |
---|---|---|
0 | R2_score | 0.84 |
1 | Adj R2 | 0.84 |
2 | MSE | 162523237.78 |
3 | RMSE | 12748.46 |
4 | MAE | 5093.31 |
5 | MAPE | 22.15 |
Резултатите са малко по-лоши от тези, получени при модела с параметрите по подразбиране по отношение на всички метрики освен средна абсолютна процентна грешка, но това е, защото търсихме оптимални параметри, при които тя да е най-ниска. Също така моделът не е обучен върху цялата обучаваща извадка наведнъж, а при оптимизиране на параметрите се използва кръстосана валидация и моделът се обучава и тества всеки път върху различни по-малки части от данните. Това позволява генерализация и ни помага да избегнем преобучение на модела (проблем, който би довел до лоши резултати при постъпване на нови данни).
Средната цена на превозно средство е 23383.51 лв, така че средна абсолютна грешка от 5093.31 лв можем да кажем, че е приемлива. Моделът може допълнително да се оптимизира, за да се намали тази грешка, като се добавят още стойности в пространството от параметри и чрез Hyperopt (или някоя друга библиотека за избор на оптимални параметри) да се открият по-подходящи стойности за параметрите на модела. Всичко е въпрос на множество експерименти докато се достигне до оптимално решение.
Коефициентът на детерминация е 0.84, което означава, че 84% от дисперсията на цената се обяснява от стойностите на независимите променливи.
Средната абсолютна процентна грешка е 22.15%, което я прави приемлива според интерпретацията на C. D. Lewis в книгата Industrial and business forecasting methods: a practical guide to exponential smoothing and curve fitting.
Следната графика съпоставя пронозираните и действителните стойности и ни позволява да видим до колко те се разминават като стойности.
В сравнение с предишната графика, тази диаграма на разсейването ни показва точно колко са разликите между пронозираните и действителните стойности. Когато те са с отрицателен знак, тогава моделът е поставил по-ниска цена за автомобила от действителната, а когато е с положителен знак, е поставил по-висока цена.
Запазване на модела и тест върху нови данни
Ще използваме библиотеката joblib, за да съхраним както модела, така и функцията с предварителната обработка на данните в отделни файлове, които да можем след това да използваме директно върху новите данни и да правим прогнози.
joblib.dump(et_optimised, './model/et_model.pickle')
joblib.dump(preprocessor,'./model/preprocessor.pickle')
След като сме съхранили файловете, ще приложим модела върху извадка с данни, които той не е виждал до този момент. Тя съдържа 473 реда с обяви за превозни средства, на които липсва поставена цена.
Първо е необходимо данните да преминат през съответната предварителна обработка, за да може да бъдат използвани от модела за машинно обучение.
# Прилагане на предварителна обработка върху новите данни
df_coded = p.preprocess_data(df)
5 случайни реда от данните след прилагане на предварителната обработка изглеждат по следния начин:
year_prod | xenon_lights | hp | |
---|---|---|---|
11 | -0.246323 | 0 | 0.0636255 |
127 | -1.27892 | 0 | -0.738607 |
119 | -0.418422 | 0 | 0.14162 |
218 | -0.246323 | 1 | -0.827744 |
165 | -1.79521 | 0 | 0.319894 |
# Зареждане на модела за машинно обучение
predictor = joblib.load(f'./model/et_model.pickle')
# Прогнозиране на стойности
y_pred = np.exp(predictor.predict(df_coded))
Следната таблица представя 5 реда от новите данни, но вече с прогнозираните от модела цени.
brand | model | month_prod | year_prod | age | color | engine_type | hp | gearbox | category | mileage | gps | adaptive_fl | antiblock_sys | airbags_back | airbags_front | tire_pressure_control | parktronic | isofix | auto_start_stop | dvd_tv | step_tip | no_key_ignition | usb_av_inaux_outputs | diff_blockage | boardcomp | light_sensor | el_mirrors | el_susp_adj | climatronic | mf_steering_wheel | sw_heating | 7seats | buy_back | barter | gas_sys | lb | saved_sold | sb | leasing | methane_sys | parts | new_import | credit | service_book | tuning | 2_3_doors | xenon_lights | alloy_wheels | metalic | heated_wipers | rollbar | towbar | halogen_lights | moving_roof | offroad | alarm | armored | casco | winch | reinforced_glass_windows | suede | right_sw | taxi | date_created | time_created | day | month | year | views | dealer | city | region | price | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
427 | VW | Scirocco | декември | 1990 | 31 | Тъмно син мет. | Бензинов | 112 | Ръчна | Купе | 223445 | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Да | Не | Не | Не | Не | Да | Не | Не | Не | Не | Не | Не | Не | Не | 1 юли 2021 | 9:31 | 1 | юли | 2021 | 25 | Частно лице | Русе | Северен централен | 9100 |
118 | Toyota | Corolla | февруари | 2006 | 15 | Тъмно син мет. | Дизелов | 116 | Ръчна | Ван | 172000 | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Да | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | 1 юли 2021 | 11:23 | 1 | юли | 2021 | 15 | Автокъща | Варна | Североизточен | 9250.36 |
346 | BMW | 535 | юни | 2014 | 7 | Металик | Бензинов | 306 | Автоматична | Седан | 128500 | Да | Не | Не | Не | Не | Не | Не | Не | Да | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Да | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | 1 юли 2021 | 10:06 | 1 | юли | 2021 | 11 | Частно лице | София | Югозападен | 78271.8 |
2 | Nissan | X-trail | септември | 2005 | 16 | Сив | Дизелов | 136 | Ръчна | Джип | 184000 | Не | Не | Не | Да | Не | Не | Не | Не | Не | Не | Да | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Да | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | 1 юли 2021 | 11:57 | 1 | юли | 2021 | 124 | Частно лице | Русе | Северен централен | 11352.8 |
106 | Skoda | Superb | юни | 2018 | 3 | Бял | Дизелов | 190 | Автоматична | Комби | 167000 | Да | Не | Не | Не | Не | Не | Не | Не | Да | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Да | Не | Не | Не | Да | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | Не | 1 юли 2021 | 11:27 | 1 | юли | 2021 | 89 | Автокъща | Варна | Североизточен | 28540.2 |
Извод
В този практически пример успяхме да изградим модел, който да прогнозира цени на превозни средства. Това обаче не означава, че те трябва да са напременно такива, каквито моделът е определил, тъй като той прави прогнози с известна грешка. Резултатите могат винаги да бъдат подобрени след допълнителни по-задълбочени анализи, експериментиране с различни параметри и прилагане на допълнителни обработки върху данните.
Цялостният пример можете да изтеглите от тук.
Ако искате да научите повече за метриките за оценка на регресионни модели, можете да прочетете в статията Machine Learning: Метрики за оценка на регресионни модели.
Искате да научите повече за машинното обучение?
Включете се в курса по машинно обучение и анализ на данни с Python.
Автор: Десислава Христова