396 KiB
Лабораторная 3
Информация о диабете индейцев Пима
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
df = pd.read_csv(".//scv//diabetes.csv")
print(df.columns)
Столбцы на русском: 'Pregnancies' - количество беременностей 'Glucose' - уровень глюкозы 'BloodPressure'- кровяное давление 'SkinThickness' - толщина кожи 'Insulin' - уровень инсулина 'BMI' - ИМТ 'DiabetesPedigreeFunction' - функция родословной диабета 'Age' - возраст 'Outcome' - исход
df.info()
df.head()
Объект наблюдения - здоровье пациентов
Атрибуты - содержит набор информации об обучении, такие как: количество беременностей, глюкоза, кровяное давление, толщина кожи, ИМТ, возраст и другие атрибуты
plt.figure(figsize=(10, 6))
plt.scatter(df['Age'], df['DiabetesPedigreeFunction'], c=df['Age'], alpha=0.6)
plt.title("Диаграмма 1")
plt.ylabel("Функция родословной диабета")
plt.xlabel("Возраст")
plt.grid(visible='true')
plt.show()
df_dependence = df.groupby('Age')['BMI'].mean().reset_index()
plt.figure(figsize=(12, 6))
plt.plot(df_dependence['Age'], df_dependence['BMI'], marker='.')
plt.title("Диаграмма 2")
plt.xlabel("Возраст")
plt.ylabel("ИМТ")
plt.show()
Присутствует связь между атрибутами, возраст влияет на многие атрибуты в данном датасете. Для примера на первом графике приведена связь между функцией родословной диабета и возрастом. На втором графике показана связь возраста и ИМТ Примеры бизнес целей
1.Прогнозирование шанса диабета на основе функции и возраста.
2.Улучшение диагностики диабета.
Эффект для бизнеса: снижение затрат на лечение, улучшение качества обслуживания. Цели технического проекта
Для первой цели:
Вход: возраст Целевой признак: Наличие диабета.
Для второй цели:
Вход: глюкоза, давление Целевой признак: Наличие диабета.
Проверка на выбросы
null_values = df.isnull().sum()
print("Пропущенные значения по столбцам:")
print(null_values)
stat_summary = df.describe()
print("\nСтатистический обзор данных:")
print(stat_summary)
На основе данных выше можно выделить что нулевых данных нет Также проверим данные на выбросы и дубликаты:
for column in df.select_dtypes(include=[np.number]).columns:
skewness = df[column].skew()
print(f"\nКоэффициент асимметрии для столбца '{column}': {skewness}")
duplicates = df.duplicated().sum()
print(f"\nКоличество дубликатов: {duplicates}")
На основе данных выше можно сказать, что для столбцов выбросы незначительны. Дупликатов нет
Очистка данных от шумов:
plt.figure(figsize=(10, 6))
plt.scatter(df['DiabetesPedigreeFunction'], df['Age'])
plt.xlabel('Функция родословной диабета')
plt.ylabel('Возраст')
plt.title('Диаграмма рассеивания перед чисткой')
plt.show()
Q1 = df["DiabetesPedigreeFunction"].quantile(0.25)
Q3 = df["DiabetesPedigreeFunction"].quantile(0.75)
IQR = Q3 - Q1
threshold = 1.5 * IQR
lower_bound = Q1 - threshold
upper_bound = Q3 + threshold
outliers = (df["DiabetesPedigreeFunction"] < lower_bound) | (df["DiabetesPedigreeFunction"] > upper_bound)
# Вывод выбросов
print("Выбросы в датасете:")
print(df[outliers])
# Заменяем выбросы на медианные значения
median_score = df["DiabetesPedigreeFunction"].median()
df.loc[outliers, "DiabetesPedigreeFunction"] = median_score
# Визуализация данных после обработки
plt.figure(figsize=(10, 6))
plt.scatter(df['DiabetesPedigreeFunction'], df['Age'])
plt.xlabel('Функция родословной диабета')
plt.ylabel('Возраст')
plt.title('Диаграмма рассеивания после чистки')
plt.show()
Разбиение набора данных на обучающую, контрольную и тестовую выборки
from sklearn.model_selection import train_test_split
train_df, test_df = train_test_split(df, test_size=0.2, random_state=42)
train_df, val_df = train_test_split(train_df, test_size=0.25, random_state=42)
print("Размер обучающей выборки:", len(train_df))
print("Размер контрольной выборки:", len(val_df))
print("Размер тестовой выборки:", len(test_df))
def check_balance(df, name):
counts = df['DiabetesPedigreeFunction'].value_counts()
print(f"Распределение функции родословной диабета в {name}:")
print(counts)
print()
check_balance(train_df, "обучающей выборке")
check_balance(val_df, "контрольной выборке")
check_balance(test_df, "тестовой выборке")
В датасете нет категориальных данных, hot-encoding не требуется
Используем дискретизацию
list_age = ["young", "middle-aged", "old"]
bins = np.linspace(0, 100, 4)
train_df['Age_Category'] = pd.cut(train_df['Age'], bins=bins, labels=list_age)
val_df['Age_Category'] = pd.cut(val_df['Age'], bins=bins, labels=list_age)
test_df['Age_Category'] = pd.cut(test_df['Age'], bins=bins, labels=list_age)
print("Обучающая выборка:\n",train_df.head(), "\n")
print("Контрольная выборка:\n",val_df.head(), "\n")
print("Тестовая выборка:\n",test_df.head())
Используем Ручной синтез, создадим новый столбец который будет говорить об опасности диабета при уровне сахара >=11
train_df['Glucose_Warning'] = [1 if i >= 200 else 0 for i in train_df["Glucose"]]
val_df['Glucose_Warning'] = [1 if i >= 200 else 0 for i in val_df["Glucose"]]
test_df['Glucose_Warning'] =[1 if i >= 200 else 0 for i in test_df["Glucose"]]
print("Обучающая выборка:\n",train_df.head(), "\n")
print("Контрольная выборка:\n",val_df.head(), "\n")
print("Тестовая выборка:\n",test_df.head())
Используем масштабирование
from sklearn.preprocessing import StandardScaler, MinMaxScaler
# Пример масштабирования числовых признаков
numerical_features = ['Glucose', 'BloodPressure', 'DiabetesPedigreeFunction', 'Age']
scaler = StandardScaler()
train_df[numerical_features] = scaler.fit_transform(train_df[numerical_features])
val_df[numerical_features] = scaler.transform(val_df[numerical_features])
test_df[numerical_features] = scaler.transform(test_df[numerical_features])
Используем Featuretools
import featuretools as ft
df['id'] = df.index
es = ft.EntitySet(id='diabet_data')
es = es.add_dataframe(dataframe_name='diabet', dataframe=df, index='id', make_index=False)
features, feature_defs = ft.dfs(entityset=es,
target_dataframe_name='diabet',
agg_primitives=['count', 'mean', 'sum'],
verbose=True)
val_feature_matrix = ft.calculate_feature_matrix(features=feature_defs, entityset=es, instance_ids=val_df.index)
test_feature_matrix = ft.calculate_feature_matrix(features=feature_defs, entityset=es, instance_ids=test_df.index)
print(features.head())
import time
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
# Разделение данных на обучающую и валидационную выборки. Удаляем целевую переменную
X = features.drop('Outcome', axis=1)
y = features['Outcome']
# One-hot encoding для категориальных переменных (преобразование категориальных объектов в числовые)
X = pd.get_dummies(X, drop_first=True)
# Проверяем, есть ли пропущенные значения, и заполняем их медианой или другим подходящим значением
X.fillna(X.median(), inplace=True)
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)
# Обучение модели
model = LinearRegression()
# Начинаем отсчет времени
start_time = time.time()
model.fit(X_train, y_train)
# Время обучения модели
train_time = time.time() - start_time
# Предсказания и оценка модели и вычисляем среднеквадратичную ошибку
predictions = model.predict(X_val)
mse = mean_squared_error(y_val, predictions)
print(f'Время обучения модели: {train_time:.2f} секунд')
print(f'Среднеквадратичная ошибка: {mse:.2f}')
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import r2_score, mean_absolute_error
from sklearn.model_selection import cross_val_score
# Удаление строк с NaN
feature_matrix = features.dropna()
val_feature_matrix = val_feature_matrix.dropna()
test_feature_matrix = test_feature_matrix.dropna()
# Разделение данных на обучающую и тестовую выборки
X_train = feature_matrix.drop('Outcome', axis=1)
y_train = feature_matrix['Outcome']
X_val = val_feature_matrix.drop('Outcome', axis=1)
y_val = val_feature_matrix['Outcome']
X_test = test_feature_matrix.drop('Outcome', axis=1)
y_test = test_feature_matrix['Outcome']
X_test = X_test.reindex(columns=X_train.columns, fill_value=0)
# Кодирования категориальных переменных с использованием одноразового кодирования
X = pd.get_dummies(X, drop_first=True)
# Разобьём тренировочный тест и примерку модели
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Выбор модели
model = RandomForestRegressor(random_state=42)
# Обучение модели
model.fit(X_train, y_train)
# Предсказание и оценка
y_pred = model.predict(X_test)
rmse = mean_squared_error(y_test, y_pred, squared=False)
r2 = r2_score(y_test, y_pred)
mae = mean_absolute_error(y_test, y_pred)
print()
print(f"RMSE: {rmse}")
print(f"R²: {r2}")
print(f"MAE: {mae} \n")
# Кросс-валидация
scores = cross_val_score(model, X_train, y_train, cv=5, scoring='neg_mean_squared_error')
rmse_cv = (-scores.mean())**0.5
print(f"Кросс-валидация RMSE: {rmse_cv} \n")
# Анализ важности признаков
feature_importances = model.feature_importances_
feature_names = X_train.columns
# Проверка на переобучение
y_train_pred = model.predict(X_train)
rmse_train = mean_squared_error(y_train, y_train_pred, squared=False)
r2_train = r2_score(y_train, y_train_pred)
mae_train = mean_absolute_error(y_train, y_train_pred)
print(f"Train RMSE: {rmse_train}")
print(f"Train R²: {r2_train}")
print(f"Train MAE: {mae_train}")
print()