190 KiB
190 KiB
In [106]:
import pandas as pd;
df = pd.read_csv("data/house_data.csv", sep=",", nrows=10000)
df.columns
Out[106]:
Определение бизнес целей:¶
- Прогнозирование цены недвижимости
- Оценка влияния факторов на цену недвижимости
Определение целей технического проекта:¶
- Построить модель, которая будет прогнозировать стоимость недвижимости на основе данных характеристик.
- Провести анализ данных для выявления факторов, которые больше всего влияют на цену
Проверка данных на пропуски¶
In [107]:
for i in df.columns:
null_rate = df[i].isnull().sum() / len(df) * 100
if null_rate > 0:
print(f'{i} Процент пустых значений: %{null_rate:.2f}')
print(df.isnull().sum())
df.isnull().any()
Out[107]:
Пустых значений нет, номинальных значений тоже.
Проверка выбросов, и их усреднение¶
In [108]:
numeric_columns = ['price']
for column in numeric_columns:
if pd.api.types.is_numeric_dtype(df[column]): # Проверяем, является ли колонка числовой
q1 = df[column].quantile(0.25) # Находим 1-й квартиль (Q1)
q3 = df[column].quantile(0.75) # Находим 3-й квартиль (Q3)
iqr = q3 - q1 # Вычисляем межквартильный размах (IQR)
# Определяем границы для выбросов
lower_bound = q1 - 1.5 * iqr # Нижняя граница
upper_bound = q3 + 1.5 * iqr # Верхняя граница
# Подсчитываем количество выбросов
outliers = df[(df[column] < lower_bound) | (df[column] > upper_bound)]
outlier_count = outliers.shape[0]
# Устраняем выбросы: заменяем значения ниже нижней границы на саму нижнюю границу, а выше верхней — на верхнюю
df[column] = df[column].apply(lambda x: lower_bound if x < lower_bound else upper_bound if x > upper_bound else x)
print(f"Колонка {column}:")
print(f" Есть выбросы: {'Да' if outlier_count > 0 else 'Нет'}")
print(f" Количество выбросов: {outlier_count}")
print(f" Минимальное значение: {df[column].min()}")
print(f" Максимальное значение: {df[column].max()}")
print(df.head())
Создание выборок¶
Так как мы будет предсказывать цену, то и целевым признаком будет параметр цены.
In [109]:
from sklearn.model_selection import train_test_split
#Разделение данных на обучающую и тестовую выборки
train_data, test_data = train_test_split(df, test_size=0.2, random_state=42)
#Разделение обучающей выборки на обучающую и контрольную
train_data, val_data = train_test_split(train_data, test_size=0.2, random_state=42)
print("Размер обучающей выборки:", len(train_data))
print("Размер контрольной выборки:", len(val_data))
print("Размер тестовой выборки:", len(test_data))
Визуализвация цен в выборках¶
In [110]:
import matplotlib.pyplot as plt
import seaborn as sns
def plot_price_dist(data, title):
sns.histplot(data['price'], kde=True)
plt.title(title)
plt.xlabel('Цена')
plt.ylabel('Частота')
plt.show()
plot_price_dist(train_data, 'Распределение цены в обучающей выборке')
plot_price_dist(val_data, 'Распределение цены в контрольной выборке')
plot_price_dist(test_data, 'Распределение цены в тестовой выборке')
print("Средняя цена в обучающей выборке: ", train_data['price'].mean())
print("Средняя цена в контрольной выборке: ", val_data['price'].mean())
print("Средняя цена в тестовой выборке: ", test_data['price'].mean())
Преобразование целевой переменной в категории дискретизацией¶
In [111]:
import numpy as np
labels = ["low", "middle", "high", "very_high"]
num_bins = 4
hist1, bins1 = np.histogram(train_data["price"].fillna(train_data["price"].median()), bins=num_bins)
bins1,hist1
pd.concat([train_data["price"], pd.cut(train_data["price"], list(bins1))], axis=1).head(10)
pd.concat([train_data["price"], pd.cut(train_data["price"], list(bins1), labels=labels)], axis=1).head()
train_data['price_category'] = pd.cut(train_data["price"], list(bins1), labels=labels)
test_data['price_category'] = pd.cut(train_data["price"], list(bins1), labels=labels)
val_data['price_category'] = pd.cut(train_data["price"], list(bins1), labels=labels)
sns.countplot(x=train_data['price_category'])
plt.title('Распределение цены в обучающей выборке')
plt.xlabel('Категория цены')
plt.ylabel('Частота')
plt.show()
Конструирование признаков¶
- Прогнозирование цен недвижимости. Цель технического проекта: Разработка модели машинного обучения для точного прогнозирования рыночной стоимости недвижимости.
- Оценка влияния факторов на цену недвижимости Цель технического проекта: Разработки модели для анализа данных для выявления факторов, которые больше всего влияют на цену
Конструирование признаков¶
Унитарное кодирование - замена категориальных признаков бинарными значениями.
In [112]:
categorical_features = ['price_category']
train_data_encoded = pd.get_dummies(train_data, columns=categorical_features)
val_data_encoded = pd.get_dummies(val_data, columns=categorical_features)
test_data_encoded = pd.get_dummies(test_data, columns=categorical_features)
print("Столбцы train_data_encoded:", train_data_encoded.columns.tolist())
print("Столбцы val_data_encoded:", val_data_encoded.columns.tolist())
print("Столбцы test_data_encoded:", test_data_encoded.columns.tolist())
Ручной синтез¶
Создание новых признаков на основе экспертных знаний и логики предметной области. Новый признак будет - цена недвижимости за фут.
In [113]:
train_data_encoded['price_per_sqft'] = df['price'] / df['sqft_living']
val_data_encoded['price_per_sqft'] = df['price'] / df['sqft_living']
test_data_encoded['price_per_sqft'] = df['price'] / df['sqft_living']
test_data_encoded
Out[113]:
Масштабирование признаков¶
Это процесс изменения диапазона признаков, чтобы равномерно распределить значения.
In [114]:
from sklearn.preprocessing import StandardScaler
numerical_features = ['bedrooms']
scaler = StandardScaler()
train_data_encoded[numerical_features] = scaler.fit_transform(train_data_encoded[numerical_features])
val_data_encoded[numerical_features] = scaler.transform(val_data_encoded[numerical_features])
test_data_encoded[numerical_features] = scaler.transform(test_data_encoded[numerical_features])
Конструирование признаков с применением фреймворка Featuretools¶
In [115]:
import featuretools as ft
# Удаление дубликатов по идентификатору
train_data_encoded = train_data_encoded.drop_duplicates(subset='id', keep='first')
#Создание EntitySet
es = ft.EntitySet(id='house_data')
#Добавление датафрейма в EntitySet
es = es.add_dataframe(dataframe_name='houses', dataframe=train_data_encoded, index='id')
#Генерация признаков
feature_matrix, feature_defs = ft.dfs(entityset=es, target_dataframe_name='houses', max_depth=2)
feature_matrix
Out[115]: