51 KiB
51 KiB
In [26]:
import pandas as pd
df = pd.read_csv("..//static//csv//ds_salaries.csv")
df.head()
Out[26]:
Бизнес-цели
Задача регрессии: Построить модель для прогноза зарплаты в USD используя атрибуты.Задача классификации: Определение уровня опыта сотрудника (experience_level) на основе других характеристик, таких как job_title, salary_in_usd, и employment_type.
Проведем обработку данных и сделаем выборки
In [27]:
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
# Удаление выбросов из столбца `salary_in_usd` с использованием IQR
Q1 = df['salary_in_usd'].quantile(0.25)
Q3 = df['salary_in_usd'].quantile(0.75)
IQR = Q3 - Q1
df = df[(df['salary_in_usd'] >= Q1 - 1.5 * IQR) & (df['salary_in_usd'] <= Q3 + 1.5 * IQR)]
# Преобразование категориальных данных в числовые (если потребуется)
if 'remote_ratio' in df.columns:
df['remote_ratio'] = df['remote_ratio'].astype(int)
# Удаление дубликатов
df.drop_duplicates(inplace=True)
# Определение целевой переменной и признаков
X = df.drop(columns=['salary_in_usd', 'salary_currency', 'job_title']) # Признаки
y = df['salary_in_usd'] # Целевая переменная для регрессии
# Определение числовых и категориальных признаков
numeric_features = ['work_year', 'remote_ratio']
categorical_features = ['experience_level', 'employment_type',
'employee_residence', 'company_location', 'company_size']
# Обработка числовых данных
numeric_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='median')), # Заполнение пропусков медианой
('scaler', StandardScaler()) # Нормализация данных
])
# Обработка категориальных данных
categorical_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='most_frequent')), # Заполнение пропусков модой
('onehot', OneHotEncoder(handle_unknown='ignore')) # Преобразование в One-Hot Encoding
])
# Комбинированный трансформер
preprocessor = ColumnTransformer(
transformers=[
('num', numeric_transformer, numeric_features), # Применяем числовую обработку
('cat', categorical_transformer, categorical_features) # Применяем категориальную обработку
]
)
# Разделение данных на обучающую и тестовую выборки
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Применение пайплайна
X_train_transformed = preprocessor.fit_transform(X_train)
X_test_transformed = preprocessor.transform(X_test)
# Проверка результата трансформации
print(f"Transformed feature shape (train): {X_train_transformed.shape}")
print(f"Transformed feature shape (test): {X_test_transformed.shape}")
Выведим результаты
In [28]:
# Получим имена категориальных признаков после OneHotEncoder
categorical_feature_names = preprocessor.named_transformers_['cat']['onehot'].get_feature_names_out(categorical_features)
# Объединим их с именами числовых признаков
feature_names = list(numeric_features) + list(categorical_feature_names)
# Создадим DataFrame для преобразованных данных
X_train_transformed_df = pd.DataFrame(X_train_transformed.toarray() if hasattr(X_train_transformed, 'toarray') else X_train_transformed, columns=feature_names)
# Выведем первые 5 строк обработанного набора данных
X_train_transformed_df.head()
Out[28]:
Обучим три модели
In [29]:
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.ensemble import RandomForestRegressor
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.model_selection import RandomizedSearchCV
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
# Задание случайного состояния
random_state = 42
# Модели и параметры
models_regression = {
"LinearRegression": LinearRegression(),
"RandomForestRegressor": RandomForestRegressor(random_state=random_state),
"GradientBoostingRegressor": GradientBoostingRegressor(random_state=random_state)
}
param_grids_regression = {
"LinearRegression": {},
"RandomForestRegressor": {
'model__n_estimators': [50, 100, 200],
'model__max_depth': [None, 10, 20],
'model__min_samples_split': [2, 5, 10]
},
"GradientBoostingRegressor": {
'model__n_estimators': [50, 100, 200],
'model__learning_rate': [0.01, 0.1, 0.2],
'model__max_depth': [3, 5, 10]
}
}
# Результаты
results_regression = {}
# Перебор моделей
for name, model in models_regression.items():
print(f"Training {name}...")
# Создание пайплайна
pipeline = Pipeline(steps=[
('preprocessor', preprocessor), # Используем уже созданный preprocessor
('model', model)
])
# Определение параметров для RandomizedSearchCV
param_grid = param_grids_regression[name]
search = RandomizedSearchCV(pipeline, param_distributions=param_grid,
cv=5, scoring='neg_mean_absolute_error',
n_jobs=-1, random_state=random_state, n_iter=20)
search.fit(X_train, y_train)
# Лучшая модель
best_model = search.best_estimator_
y_pred = best_model.predict(X_test)
# Метрики
mae = mean_absolute_error(y_test, y_pred)
rmse = np.sqrt(mean_squared_error(y_test, y_pred))
r2 = r2_score(y_test, y_pred)
# Сохранение результатов
results_regression[name] = {
"Best Params": search.best_params_,
"MAE": mae,
"RMSE": rmse,
"R2": r2
}
# Печать результатов
for name, metrics in results_regression.items():
print(f"\nModel: {name}")
for metric, value in metrics.items():
print(f"{metric}: {value}")
In [30]:
# Формирование таблицы метрик из результатов регрессионных моделей
reg_metrics = pd.DataFrame.from_dict(results_regression, orient="index")[
["MAE", "RMSE", "R2"]
]
# Визуализация результатов с помощью стилизации
styled_metrics = (
reg_metrics.sort_values(by="RMSE")
.style.background_gradient(cmap="viridis", low=1, high=0.3, subset=["RMSE", "MAE"])
.background_gradient(cmap="plasma", low=0.3, high=1, subset=["R2"])
)
# Отобразим таблицу
styled_metrics
Out[30]:
Чтото слабоватые модели получились. Даже 50% нет, нужно попробовать улучшить данные.
In [38]:
# Функция для приведения выбросов к среднему значению
def handle_outliers(df, column):
Q1 = df[column].quantile(0.25)
Q3 = df[column].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
mean_value = df[column].mean()
df[column] = np.where((df[column] < lower_bound) | (df[column] > upper_bound), mean_value, df[column])
return df
# Приведение выбросов в столбце `salary_in_usd` к среднему значению
df = handle_outliers(df, 'salary_in_usd')
# Преобразование категориальных данных в строковые для корректной обработки
if 'remote_ratio' in df.columns:
df['remote_ratio'] = df['remote_ratio'].astype(str)
# Удаление дубликатов
df.drop_duplicates(inplace=True)
# Определение целевой переменной и признаков
X = df.drop(columns=['salary_in_usd', 'salary_currency', 'job_title']) # Признаки
y = df['salary_in_usd'] # Целевая переменная для регрессии
# Определение числовых и категориальных признаков
numeric_features = ['work_year'] # Убрали 'remote_ratio', так как это категориальный признак
categorical_features = ['experience_level', 'employment_type',
'employee_residence', 'company_location', 'company_size', 'remote_ratio']
# Обработка числовых данных
numeric_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='median')), # Заполнение пропусков медианой
('scaler', StandardScaler()) # Нормализация данных
])
# Обработка категориальных данных
categorical_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='most_frequent')), # Заполнение пропусков модой
('onehot', OneHotEncoder(handle_unknown='ignore')) # Преобразование в One-Hot Encoding
])
# Комбинированный трансформер
preprocessor = ColumnTransformer(
transformers=[
('num', numeric_transformer, numeric_features), # Применяем числовую обработку
('cat', categorical_transformer, categorical_features) # Применяем категориальную обработку
]
)
# Разделение данных на обучающую и тестовую выборки
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Применение пайплайна
X_train_transformed = preprocessor.fit_transform(X_train)
X_test_transformed = preprocessor.transform(X_test)
# Проверка результата трансформации
print(f"Transformed feature shape (train): {X_train_transformed.shape}")
print(f"Transformed feature shape (test): {X_test_transformed.shape}")
# Определение моделей и их параметров
models = {
"LinearRegression": LinearRegression(),
"RandomForestRegressor": RandomForestRegressor(random_state=42),
"GradientBoostingRegressor": GradientBoostingRegressor(random_state=42)
}
param_grids = {
"LinearRegression": {},
"RandomForestRegressor": {
'model__n_estimators': [100, 200, 300],
'model__max_depth': [10, 20, None],
'model__min_samples_split': [2, 5, 10]
},
"GradientBoostingRegressor": {
'model__n_estimators': [100, 200, 300],
'model__learning_rate': [0.01, 0.1, 0.2],
'model__max_depth': [3, 5, 7]
}
}
# Результаты
results = {}
# Обучение моделей с подбором гиперпараметров
for name, model in models.items():
print(f"Training {name}...")
pipeline = Pipeline(steps=[
('preprocessor', preprocessor),
('model', model)
])
param_grid = param_grids[name]
search = RandomizedSearchCV(pipeline, param_distributions=param_grid, cv=5,
scoring='neg_mean_absolute_error', n_jobs=-1,
random_state=42, n_iter=20)
search.fit(X_train, y_train)
# Лучшая модель
best_model = search.best_estimator_
y_pred = best_model.predict(X_test)
# Метрики
mae = mean_absolute_error(y_test, y_pred)
rmse = np.sqrt(mean_squared_error(y_test, y_pred))
r2 = r2_score(y_test, y_pred)
# Сохранение результатов
results[name] = {
"Best Params": search.best_params_,
"MAE": mae,
"RMSE": rmse,
"R2": r2
}
# Печать результатов
for name, metrics in results.items():
print(f"\nModel: {name}")
for metric, value in metrics.items():
print(f"{metric}: {value}")
# Формирование таблицы метрик из результатов регрессионных моделей
reg_metrics = pd.DataFrame.from_dict(results, orient="index")[
["MAE", "RMSE", "R2"]
]
# Визуализация результатов с помощью стилизации
styled_metrics = (
reg_metrics.sort_values(by="RMSE")
.style.background_gradient(cmap="viridis", low=1, high=0.3, subset=["RMSE", "MAE"])
.background_gradient(cmap="plasma", low=0.3, high=1, subset=["R2"])
)
# Отобразим таблицу
styled_metrics
Out[38]:
Переписал не много код, стало чуть лучше, но не намного. Думаю для моей первой работы подойдет
Приступим к задаче классификации
In [39]:
import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split, RandomizedSearchCV
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.metrics import accuracy_score, confusion_matrix, f1_score
# Преобразование целевой переменной для классификации
y_class = df['Leather interior'].map({'Yes': 1, 'No': 0}) # Преобразуем в 0/1
X = df.drop(columns=['Leather interior', 'ID']) # Признаки
# Определение числовых и категориальных признаков
numeric_features = ['work_year'] # Пример числового признака
categorical_features = ['experience_level', 'employment_type', 'employee_residence',
'company_location', 'company_size', 'remote_ratio']
# Обработка числовых данных
numeric_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='median')),
('scaler', StandardScaler())
])
# Обработка категориальных данных
categorical_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='most_frequent')),
('onehot', OneHotEncoder(handle_unknown='ignore'))
])
# Комбинированный трансформер
preprocessor = ColumnTransformer(
transformers=[
('num', numeric_transformer, numeric_features),
('cat', categorical_transformer, categorical_features)
]
)
# Разделение данных на обучающую и тестовую выборки
X_train_clf, X_test_clf, y_train_clf, y_test_clf = train_test_split(X, y_class, test_size=0.2, random_state=42)
# Определение моделей и их гиперпараметров
models_classification = {
"LogisticRegression": LogisticRegression(max_iter=1000),
"RandomForestClassifier": RandomForestClassifier(random_state=42),
"KNN": KNeighborsClassifier()
}
param_grids_classification = {
"LogisticRegression": {
'model__C': [0.1, 1, 10]
},
"RandomForestClassifier": {
"model__n_estimators": [100, 200, 300],
"model__max_features": ["sqrt", "log2", None],
"model__max_depth": [5, 10, 15, None],
"model__criterion": ["gini", "entropy"]
},
"KNN": {
'model__n_neighbors': [3, 5, 7, 9],
'model__weights': ['uniform', 'distance']
}
}
# Результаты
results_classification = {}
# Перебор моделей
for name, model in models_classification.items():
print(f"Training {name}...")
pipeline = Pipeline(steps=[
('preprocessor', preprocessor),
('model', model)
])
param_grid = param_grids_classification[name]
grid_search = RandomizedSearchCV(pipeline, param_distributions=param_grid, cv=5, scoring='f1', n_jobs=-1, random_state=42)
grid_search.fit(X_train_clf, y_train_clf)
# Лучшая модель
best_model = grid_search.best_estimator_
y_pred = best_model.predict(X_test_clf)
# Метрики
acc = accuracy_score(y_test_clf, y_pred)
f1 = f1_score(y_test_clf, y_pred)
# Вычисление матрицы ошибок
c_matrix = confusion_matrix(y_test_clf, y_pred)
# Сохранение результатов
results_classification[name] = {
"Best Params": grid_search.best_params_,
"Accuracy": acc,
"F1 Score": f1,
"Confusion_matrix": c_matrix
}
# Печать результатов
for name, metrics in results_classification.items():
print(f"\nModel: {name}")
for metric, value in metrics.items():
print(f"{metric}: {value}")