Predicted progress! From awful to just "very bad"
This commit is contained in:
parent
07f60e449b
commit
65dfaec1a5
@ -6,8 +6,8 @@ import os
|
||||
router = APIRouter()
|
||||
|
||||
# Инициализация сервиса
|
||||
MODEL_PATH = os.getenv("MODEL_PATH", "laptop_price_model.pkl")
|
||||
FEATURE_COLUMNS_PATH = os.getenv("FEATURE_COLUMNS_PATH", "feature_columns.pkl")
|
||||
MODEL_PATH = os.getenv("MODEL_PATH", "services/laptop_price_model.pkl")
|
||||
FEATURE_COLUMNS_PATH = os.getenv("FEATURE_COLUMNS_PATH", "services/feature_columns.pkl")
|
||||
laptop_service = LaptopService(model_path=MODEL_PATH, feature_columns_path=FEATURE_COLUMNS_PATH)
|
||||
|
||||
@router.post("/predict_price/", response_model=PredictPriceResponse, summary="Predict laptop price", description="Predict the price of a laptop based on its specifications.", response_description="The predicted price of the laptop.")
|
||||
|
Binary file not shown.
Binary file not shown.
@ -1,12 +1,19 @@
|
||||
from sqlalchemy import Column, Integer, String, Float
|
||||
from sqlalchemy import Column, Integer, Float, String
|
||||
from database import Base
|
||||
|
||||
|
||||
class Laptop(Base):
|
||||
__tablename__ = "laptops"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
brand = Column(String, index=True)
|
||||
processor = Column(String, index=True)
|
||||
ram = Column(Integer)
|
||||
os = Column(String, index=True)
|
||||
ssd = Column(Integer)
|
||||
display = Column(Float)
|
||||
gpu = Column(String, index=True)
|
||||
weight = Column(Float)
|
||||
battery_size = Column(Integer)
|
||||
release_year = Column(Integer)
|
||||
display_type = Column(String, index=True)
|
||||
|
@ -1,9 +1,10 @@
|
||||
fastapi
|
||||
fastapi~=0.115.2
|
||||
uvicorn
|
||||
sqlalchemy
|
||||
sqlalchemy~=2.0.35
|
||||
psycopg2-binary
|
||||
pydantic
|
||||
joblib
|
||||
pandas
|
||||
numpy
|
||||
python-dotenv
|
||||
pydantic~=2.9.2
|
||||
joblib~=1.4.2
|
||||
pandas~=2.2.3
|
||||
numpy~=2.1.2
|
||||
python-dotenv
|
||||
scikit-learn~=1.5.2
|
@ -1,19 +1,32 @@
|
||||
from pydantic import BaseModel
|
||||
from typing import Optional
|
||||
|
||||
class LaptopCreate(BaseModel):
|
||||
brand: str
|
||||
processor: str
|
||||
ram: int
|
||||
os: str
|
||||
ssd: int
|
||||
display: float
|
||||
gpu: str
|
||||
weight: float
|
||||
battery_size: int
|
||||
release_year: int
|
||||
display_type: str
|
||||
|
||||
class LaptopResponse(BaseModel):
|
||||
id: int
|
||||
brand: str
|
||||
processor: str
|
||||
ram: int
|
||||
os: str
|
||||
ssd: int
|
||||
display: float
|
||||
gpu: str
|
||||
weight: float
|
||||
battery_size: int
|
||||
release_year: int
|
||||
display_type: str
|
||||
|
||||
class Config:
|
||||
orm_mode = True
|
||||
|
26
services/ml/feature_importances.py
Normal file
26
services/ml/feature_importances.py
Normal file
@ -0,0 +1,26 @@
|
||||
import matplotlib.pyplot as plt
|
||||
import joblib
|
||||
import numpy as np
|
||||
|
||||
from services.ml.modelBuilder import X_train
|
||||
|
||||
# Загрузка модели и признаков
|
||||
model_rf = joblib.load('laptop_price_model.pkl')
|
||||
feature_columns = joblib.load('feature_columns.pkl')
|
||||
|
||||
# Получение важности признаков
|
||||
importances = model_rf.feature_importances_
|
||||
indices = np.argsort(importances)[::-1]
|
||||
|
||||
# Вывод наиболее важных признаков
|
||||
print("Важность признаков:")
|
||||
for f in range(X_train.shape[1]):
|
||||
print(f"{f + 1}. {feature_columns[indices[f]]} ({importances[indices[f]]})")
|
||||
|
||||
# Визуализация важности признаков
|
||||
plt.figure(figsize=(12, 8))
|
||||
plt.title("Важность признаков (Random Forest)")
|
||||
plt.bar(range(X_train.shape[1]), importances[indices], align='center')
|
||||
plt.xticks(range(X_train.shape[1]), [feature_columns[i] for i in indices], rotation=90)
|
||||
plt.tight_layout()
|
||||
plt.show()
|
204
services/ml/generate_synthetic_data.py
Normal file
204
services/ml/generate_synthetic_data.py
Normal file
@ -0,0 +1,204 @@
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
import random
|
||||
import re
|
||||
from datetime import datetime
|
||||
|
||||
# Установка случайного зерна для воспроизводимости
|
||||
np.random.seed(42)
|
||||
random.seed(42)
|
||||
|
||||
# Определение возможных значений для категориальных признаков
|
||||
brands = ['Dell', 'HP', 'Lenovo', 'Apple', 'Asus', 'Acer', 'MSI', 'Microsoft', 'Samsung', 'Toshiba']
|
||||
processors = [
|
||||
'Intel Core i3 10th Gen', 'Intel Core i5 10th Gen', 'Intel Core i7 10th Gen',
|
||||
'AMD Ryzen 3 4000 Series', 'AMD Ryzen 5 4000 Series', 'AMD Ryzen 7 4000 Series'
|
||||
]
|
||||
oss = ['Windows 10', 'Windows 11', 'macOS', 'Linux']
|
||||
gpus = ['Integrated', 'NVIDIA GeForce GTX 1650', 'NVIDIA GeForce RTX 3060', 'AMD Radeon RX 5600M']
|
||||
display_sizes = [13.3, 14.0, 15.6, 17.3]
|
||||
display_types = ['HD', 'Full HD', '4K', 'OLED']
|
||||
ram_options = [4, 8, 16, 32] # в GB
|
||||
ssd_options = [0, 256, 512, 1024] # в GB
|
||||
weights = [1.2, 1.5, 2.0, 2.5, 3.0] # в кг
|
||||
battery_sizes = [45, 60, 70, 90, 100] # в Вт⋅ч
|
||||
release_years = list(range(2015, datetime.now().year + 1)) # от 2015 до текущего года
|
||||
|
||||
|
||||
# Функции для генерации признаков
|
||||
def generate_brand():
|
||||
return random.choice(brands)
|
||||
|
||||
|
||||
def generate_processor():
|
||||
return random.choice(processors)
|
||||
|
||||
|
||||
def generate_os():
|
||||
return random.choice(oss)
|
||||
|
||||
|
||||
def generate_gpu():
|
||||
return random.choice(gpus)
|
||||
|
||||
|
||||
def generate_display():
|
||||
return random.choice(display_sizes)
|
||||
|
||||
|
||||
def generate_display_type():
|
||||
return random.choice(display_types)
|
||||
|
||||
|
||||
def generate_ram():
|
||||
return random.choice(ram_options)
|
||||
|
||||
|
||||
def generate_ssd():
|
||||
return random.choice(ssd_options)
|
||||
|
||||
|
||||
def generate_weight():
|
||||
return random.choice(weights)
|
||||
|
||||
|
||||
def generate_battery_size():
|
||||
return random.choice(battery_sizes)
|
||||
|
||||
|
||||
def generate_release_year():
|
||||
return random.choice(release_years)
|
||||
|
||||
|
||||
# Функция для расчёта цены
|
||||
def calculate_price(brand, processor, ram, os, ssd, display, gpu, weight, battery_size, release_year, display_type):
|
||||
base_price = 30000 # базовая цена в условных единицах
|
||||
|
||||
# Добавление стоимости в зависимости от бренда
|
||||
brand_premium = {
|
||||
'Apple': 40000,
|
||||
'MSI': 35000,
|
||||
'Dell': 15000,
|
||||
'HP': 12000,
|
||||
'Lenovo': 10000,
|
||||
'Microsoft': 18000,
|
||||
'Asus': 8000,
|
||||
'Acer': 7000,
|
||||
'Samsung': 9000,
|
||||
'Toshiba': 8500
|
||||
}
|
||||
base_price += brand_premium.get(brand, 10000) # дефолтный премиум
|
||||
|
||||
# Добавление стоимости в зависимости от процессора
|
||||
if 'i3' in processor or 'Ryzen 3' in processor:
|
||||
base_price += 5000
|
||||
elif 'i5' in processor or 'Ryzen 5' in processor:
|
||||
base_price += 10000
|
||||
elif 'i7' in processor or 'Ryzen 7' in processor:
|
||||
base_price += 15000
|
||||
|
||||
# Добавление стоимости за RAM
|
||||
base_price += ram * 2000 # 2000 условных единиц за каждый GB RAM
|
||||
|
||||
# Добавление стоимости за ОС
|
||||
if os == 'Windows 11':
|
||||
base_price += 5000
|
||||
elif os == 'macOS':
|
||||
base_price += 15000
|
||||
elif os == 'Linux':
|
||||
base_price += 3000
|
||||
# Windows 10 считается стандартной и не добавляет стоимости
|
||||
|
||||
# Добавление стоимости за SSD
|
||||
if ssd > 0:
|
||||
base_price += ssd * 100 # 100 условных единиц за каждый GB SSD
|
||||
|
||||
# Добавление стоимости за размер дисплея
|
||||
base_price += (display - 13) * 5000 # 5000 условных единиц за каждый дюйм больше 13"
|
||||
|
||||
# Добавление стоимости за тип дисплея
|
||||
display_type_premium = {
|
||||
'HD': 0,
|
||||
'Full HD': 5000,
|
||||
'4K': 15000,
|
||||
'OLED': 20000
|
||||
}
|
||||
base_price += display_type_premium.get(display_type, 0)
|
||||
|
||||
# Добавление стоимости за GPU
|
||||
gpu_premium = {
|
||||
'Integrated': 0,
|
||||
'NVIDIA GeForce GTX 1650': 15000,
|
||||
'NVIDIA GeForce RTX 3060': 25000,
|
||||
'AMD Radeon RX 5600M': 20000
|
||||
}
|
||||
base_price += gpu_premium.get(gpu, 0)
|
||||
|
||||
# Добавление стоимости за вес (легкие ноутбуки дороже)
|
||||
base_price += (3.0 - weight) * 5000 # Чем легче, тем дороже
|
||||
|
||||
# Добавление стоимости за размер батареи
|
||||
base_price += battery_size * 100 # 100 условных единиц за каждый Вт⋅ч батареи
|
||||
|
||||
# Добавление стоимости за год выпуска (новые модели дороже)
|
||||
current_year = datetime.now().year
|
||||
base_price += (current_year - release_year) * 2000 # 2000 условных единиц за каждый год назад
|
||||
|
||||
# Добавление случайного шума для реалистичности
|
||||
noise = np.random.normal(0, 5000) # среднее 0, стандартное отклонение 5000
|
||||
final_price = base_price + noise
|
||||
|
||||
return max(round(final_price, 2), 5000) # минимальная цена 5000 условных единиц
|
||||
|
||||
|
||||
# Функция для генерации синтетических данных
|
||||
def generate_synthetic_data(num_samples=100000):
|
||||
data = []
|
||||
for _ in range(num_samples):
|
||||
brand = generate_brand()
|
||||
processor = generate_processor()
|
||||
os = generate_os()
|
||||
gpu = generate_gpu()
|
||||
display = generate_display()
|
||||
display_type = generate_display_type()
|
||||
ram = generate_ram()
|
||||
ssd = generate_ssd()
|
||||
weight = generate_weight()
|
||||
battery_size = generate_battery_size()
|
||||
release_year = generate_release_year()
|
||||
|
||||
price = calculate_price(
|
||||
brand, processor, ram, os, ssd, display, gpu, weight, battery_size, release_year, display_type
|
||||
)
|
||||
|
||||
data.append({
|
||||
'brand': brand,
|
||||
'processor': processor,
|
||||
'ram': ram,
|
||||
'os': os,
|
||||
'ssd': ssd,
|
||||
'display': display,
|
||||
'gpu': gpu,
|
||||
'weight': weight,
|
||||
'battery_size': battery_size,
|
||||
'release_year': release_year,
|
||||
'display_type': display_type,
|
||||
'price': price
|
||||
})
|
||||
return pd.DataFrame(data)
|
||||
|
||||
|
||||
print("Генерация синтетических данных...")
|
||||
synthetic_df = generate_synthetic_data(num_samples=100000)
|
||||
|
||||
# Просмотр первых нескольких строк
|
||||
print("\nПример данных после генерации:")
|
||||
print(synthetic_df.head())
|
||||
|
||||
# Проверка распределения цен
|
||||
print("\nСтатистика по ценам:")
|
||||
print(synthetic_df['price'].describe())
|
||||
|
||||
# Сохранение в CSV
|
||||
synthetic_df.to_csv('synthetic_laptops.csv', index=False)
|
||||
print("\nСинтетические данные сохранены в 'synthetic_laptops.csv'.")
|
123
services/ml/modelBuilder.py
Normal file
123
services/ml/modelBuilder.py
Normal file
@ -0,0 +1,123 @@
|
||||
import pandas as pd
|
||||
from sklearn.model_selection import train_test_split
|
||||
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor
|
||||
from sklearn.linear_model import LinearRegression
|
||||
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
|
||||
import matplotlib.pyplot as plt
|
||||
import joblib
|
||||
import numpy as np
|
||||
|
||||
# Шаг 1: Загрузка данных
|
||||
df = pd.read_csv('../../datasets/synthetic_laptops.csv') # Убедитесь, что путь к файлу правильный
|
||||
|
||||
# Шаг 2: Проверка и очистка имен столбцов
|
||||
print("Имена столбцов до очистки:")
|
||||
print(df.columns.tolist())
|
||||
|
||||
# Приведение имен столбцов к нижнему регистру и удаление пробелов
|
||||
df.columns = df.columns.str.strip().str.lower()
|
||||
print("\nИмена столбцов после очистки:")
|
||||
print(df.columns.tolist())
|
||||
|
||||
# Шаг 3: Проверка наличия необходимых столбцов
|
||||
required_columns = [
|
||||
'brand', 'processor', 'ram', 'os', 'ssd', 'display',
|
||||
'gpu', 'weight', 'battery_size', 'release_year', 'display_type', 'price'
|
||||
]
|
||||
missing_columns = [col for col in required_columns if col not in df.columns]
|
||||
|
||||
if missing_columns:
|
||||
print(f"\nОтсутствуют следующие столбцы: {missing_columns}")
|
||||
raise Exception(f"Отсутствуют столбцы: {missing_columns}")
|
||||
else:
|
||||
print("\nВсе необходимые столбцы присутствуют.")
|
||||
|
||||
# Шаг 4: Удаление строк с пропущенными значениями
|
||||
df = df.dropna(subset=required_columns)
|
||||
print(f"\nКоличество строк после удаления пропусков: {df.shape[0]}")
|
||||
|
||||
# Шаг 5: Очистка и преобразование колонок
|
||||
|
||||
# Функция для очистки числовых колонок, если они строковые
|
||||
def clean_numeric_column(column, remove_chars=['₹', ',', ' ']):
|
||||
if column.dtype == object:
|
||||
for char in remove_chars:
|
||||
column = column.str.replace(char, '', regex=False)
|
||||
return pd.to_numeric(column, errors='coerce')
|
||||
else:
|
||||
return column
|
||||
|
||||
# Очистка числовых колонок (исключая 'price', если уже числовая)
|
||||
numerical_columns = ['ram', 'ssd', 'display', 'weight', 'battery_size', 'release_year']
|
||||
for col in numerical_columns:
|
||||
df[col] = clean_numeric_column(df[col])
|
||||
|
||||
# Проверка на пропущенные значения после очистки
|
||||
df = df.dropna(subset=['price'] + numerical_columns)
|
||||
print(f"\nКоличество строк после очистки числовых колонок: {df.shape[0]}")
|
||||
|
||||
# Шаг 6: Выбор необходимых столбцов (все уже включены)
|
||||
# df уже содержит все необходимые столбцы
|
||||
|
||||
print("\nПример данных после предобработки:")
|
||||
print(df.head())
|
||||
|
||||
# Шаг 7: Преобразование категориальных переменных с помощью One-Hot Encoding
|
||||
categorical_features = ['brand', 'processor', 'os', 'gpu', 'display_type']
|
||||
df = pd.get_dummies(df, columns=categorical_features, drop_first=True)
|
||||
print("\nИмена колонок после One-Hot Encoding:")
|
||||
print(df.columns.tolist())
|
||||
|
||||
# Шаг 8: Разделение данных на обучающую и тестовую выборки
|
||||
X = df.drop('price', axis=1)
|
||||
y = df['price']
|
||||
|
||||
X_train, X_test, y_train, y_test = train_test_split(
|
||||
X, y, test_size=0.2, random_state=42
|
||||
)
|
||||
|
||||
print(f"\nРазмер обучающей выборки: {X_train.shape}")
|
||||
print(f"Размер тестовой выборки: {X_test.shape}")
|
||||
|
||||
# Шаг 9: Обучение моделей
|
||||
model_rf = RandomForestRegressor(n_estimators=100, random_state=42)
|
||||
model_rf.fit(X_train, y_train)
|
||||
|
||||
print("\nМодели успешно обучены.")
|
||||
|
||||
# Шаг 10: Оценка моделей
|
||||
models = {
|
||||
'Random Forest': model_rf,
|
||||
}
|
||||
|
||||
for name, mdl in models.items():
|
||||
y_pred = mdl.predict(X_test)
|
||||
mae = mean_absolute_error(y_test, y_pred)
|
||||
rmse = mean_squared_error(y_test, y_pred, squared=False)
|
||||
r2 = r2_score(y_test, y_pred)
|
||||
print(f"{name} - MAE: {mae}, RMSE: {rmse}, R²: {r2}")
|
||||
|
||||
# Шаг 11: Сохранение модели и списка признаков
|
||||
joblib.dump(model_rf, 'laptop_price_model.pkl')
|
||||
print("\nМодель Random Forest сохранена как 'laptop_price_model.pkl'.")
|
||||
|
||||
feature_columns = X.columns.tolist()
|
||||
joblib.dump(feature_columns, 'feature_columns.pkl')
|
||||
print("Сохранены названия признаков в 'feature_columns.pkl'.")
|
||||
|
||||
# Получение важности признаков
|
||||
importances = model_rf.feature_importances_
|
||||
indices = np.argsort(importances)[::-1]
|
||||
|
||||
# Вывод наиболее важных признаков
|
||||
print("Важность признаков:")
|
||||
for f in range(X_train.shape[1]):
|
||||
print(f"{f + 1}. {feature_columns[indices[f]]} ({importances[indices[f]]})")
|
||||
|
||||
# Визуализация важности признаков
|
||||
plt.figure(figsize=(12, 8))
|
||||
plt.title("Важность признаков (Random Forest)")
|
||||
plt.bar(range(X_train.shape[1]), importances[indices], align='center')
|
||||
plt.xticks(range(X_train.shape[1]), [feature_columns[i] for i in indices], rotation=90)
|
||||
plt.tight_layout()
|
||||
plt.show()
|
@ -1,143 +0,0 @@
|
||||
import pandas as pd
|
||||
from sklearn.linear_model import LinearRegression
|
||||
from sklearn.model_selection import train_test_split
|
||||
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor
|
||||
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
|
||||
import joblib
|
||||
import re
|
||||
|
||||
# Шаг 1: Загрузка данных
|
||||
df = pd.read_csv('../laptops.csv')
|
||||
|
||||
# Шаг 2: Проверка и очистка имен столбцов
|
||||
print("Имена столбцов до очистки:")
|
||||
print(df.columns.tolist())
|
||||
|
||||
# Приведение имен столбцов к нижнему регистру и удаление пробелов
|
||||
df.columns = df.columns.str.strip().str.lower()
|
||||
print("\nИмена столбцов после очистки:")
|
||||
print(df.columns.tolist())
|
||||
|
||||
# Шаг 3: Переименование столбцов (если необходимо)
|
||||
df = df.rename(columns={
|
||||
'processor': 'processor',
|
||||
'ram': 'ram',
|
||||
'os': 'os',
|
||||
'ssd': 'ssd',
|
||||
'display': 'display',
|
||||
'price': 'price'
|
||||
# Другие столбцы можно оставить без изменений или переименовать по необходимости
|
||||
})
|
||||
|
||||
# Шаг 4: Проверка наличия необходимых столбцов
|
||||
required_columns = ['processor', 'ram', 'os', 'ssd', 'display', 'price']
|
||||
missing_columns = [col for col in required_columns if col not in df.columns]
|
||||
|
||||
if missing_columns:
|
||||
print(f"\nОтсутствуют следующие столбцы: {missing_columns}")
|
||||
# Здесь можно добавить дополнительную обработку или завершить выполнение
|
||||
raise Exception(f"Отсутствуют столбцы: {missing_columns}")
|
||||
else:
|
||||
print("\nВсе необходимые столбцы присутствуют.")
|
||||
|
||||
# Шаг 5: Удаление строк с пропущенными значениями
|
||||
df = df.dropna(subset=required_columns)
|
||||
print(f"\nКоличество строк после удаления пропусков: {df.shape[0]}")
|
||||
|
||||
# Шаг 6: Очистка и преобразование колонок
|
||||
|
||||
# Функция для очистки числовых колонок, содержащих символы
|
||||
def clean_numeric_column(column, remove_chars=['₹', ',', ' ']):
|
||||
for char in remove_chars:
|
||||
column = column.str.replace(char, '', regex=False)
|
||||
return pd.to_numeric(column, errors='coerce')
|
||||
|
||||
# Очистка колонки 'price'
|
||||
df['price'] = clean_numeric_column(df['price'])
|
||||
|
||||
# Очистка колонки 'ram' (например, '16 GB DDR4 RAM' -> 16)
|
||||
def extract_numeric_ram(ram_str):
|
||||
match = re.search(r'(\d+)', ram_str)
|
||||
if match:
|
||||
return int(match.group(1))
|
||||
else:
|
||||
return None
|
||||
|
||||
df['ram'] = df['ram'].apply(extract_numeric_ram)
|
||||
|
||||
# Очистка колонки 'ssd' (например, '512 GB SSD' -> 512)
|
||||
def extract_numeric_ssd(ssd_str):
|
||||
match = re.search(r'(\d+)', ssd_str)
|
||||
if match:
|
||||
return int(match.group(1))
|
||||
else:
|
||||
return None
|
||||
|
||||
df['ssd'] = df['ssd'].apply(extract_numeric_ssd)
|
||||
|
||||
# Очистка колонки 'display' (убираем лишние символы, если есть)
|
||||
def clean_display(display_str):
|
||||
match = re.search(r'([\d.]+)', display_str)
|
||||
if match:
|
||||
return float(match.group(1))
|
||||
else:
|
||||
return None
|
||||
|
||||
df['display'] = df['display'].apply(clean_display)
|
||||
|
||||
# Проверка на пропущенные значения после очистки
|
||||
df = df.dropna(subset=['price', 'ram', 'ssd', 'display'])
|
||||
print(f"\nКоличество строк после очистки числовых колонок: {df.shape[0]}")
|
||||
|
||||
# Шаг 7: Выбор необходимых столбцов
|
||||
df = df[required_columns]
|
||||
print("\nПример данных после предобработки:")
|
||||
print(df.head())
|
||||
|
||||
# Шаг 8: Преобразование категориальных переменных с помощью One-Hot Encoding
|
||||
df = pd.get_dummies(df, columns=['processor', 'os'], drop_first=True)
|
||||
print("\nИмена колонок после One-Hot Encoding:")
|
||||
print(df.columns.tolist())
|
||||
|
||||
# Шаг 9: Разделение данных на обучающую и тестовую выборки
|
||||
X = df.drop('price', axis=1)
|
||||
y = df['price']
|
||||
|
||||
X_train, X_test, y_train, y_test = train_test_split(
|
||||
X, y, test_size=0.2, random_state=42
|
||||
)
|
||||
|
||||
print(f"\nРазмер обучающей выборки: {X_train.shape}")
|
||||
print(f"Размер тестовой выборки: {X_test.shape}")
|
||||
|
||||
# Шаг 10: Обучение модели
|
||||
model = RandomForestRegressor(n_estimators=100, random_state=42)
|
||||
model.fit(X_train, y_train)
|
||||
|
||||
# Обучение моделей
|
||||
gbr = GradientBoostingRegressor(n_estimators=100, random_state=42)
|
||||
gbr.fit(X_train, y_train)
|
||||
|
||||
lr = LinearRegression()
|
||||
lr.fit(X_train, y_train)
|
||||
print("\nМодели успешно обучена.")
|
||||
|
||||
# Оценка моделей
|
||||
|
||||
models = {'Random Forest': model, 'Gradient Boosting': gbr, 'Linear Regression': lr}
|
||||
|
||||
for name, mdl in models.items():
|
||||
y_pred = mdl.predict(X_test)
|
||||
mae = mean_absolute_error(y_test, y_pred)
|
||||
rmse = mean_squared_error(y_test, y_pred, squared=False)
|
||||
r2 = r2_score(y_test, y_pred)
|
||||
print(f"{name} - MAE: {mae}, RMSE: {rmse}, R²: {r2}")
|
||||
|
||||
# Шаг 12: Сохранение модели
|
||||
joblib.dump(model, '../laptop_price_model.pkl')
|
||||
print("\nМодель сохранена как 'laptop_price_model.pkl'.")
|
||||
|
||||
# Дополнительно: Сохранение колонок, полученных после One-Hot Encoding, для использования в бэкенде
|
||||
feature_columns = X.columns.tolist()
|
||||
joblib.dump(feature_columns, '../feature_columns.pkl')
|
||||
print("Сохранены названия признаков в 'feature_columns.pkl'.")
|
Loading…
Reference in New Issue
Block a user