From 9182fb2ff61cf1e592b1e356de6de13140f68d90 Mon Sep 17 00:00:00 2001 From: Katana Date: Sat, 26 Oct 2024 15:34:44 +0300 Subject: [PATCH 1/2] lab2 is done(?) --- .gitignore | 4 + lab_2/lab2.ipynb | 961 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 965 insertions(+) create mode 100644 lab_2/lab2.ipynb diff --git a/.gitignore b/.gitignore index 207d123..60b5e88 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,7 @@ ipython_config.py # Remove previous ipynb_checkpoints # git rm -r .ipynb_checkpoints/ + +/aimenv + +/static \ No newline at end of file diff --git a/lab_2/lab2.ipynb b/lab_2/lab2.ipynb new file mode 100644 index 0000000..5ac0c9e --- /dev/null +++ b/lab_2/lab2.ipynb @@ -0,0 +1,961 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Начало лабораторной работы\n", + "\n", + "https://www.kaggle.com/datasets/sid321axn/gold-price-prediction-dataset\n", + "\n", + "https://www.kaggle.com/datasets/uciml/pima-indians-diabetes-database\n", + "\n", + "https://www.kaggle.com/datasets/fedesoriano/stroke-prediction-dataset" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 1. Цены на золото\n", + "\n", + "Исторически золото использовалось как форма валюты в различных частях мира, включая США. В настоящее время драгоценные металлы, такие как золото, хранятся в центральных банках всех стран для гарантии выплаты внешних долгов, а также для контроля инфляции, что отражает финансовую устойчивость страны. В последнее время развивающиеся мировые экономики, такие как Китай, Россия и Индия, стали крупными покупателями золота, в то время как США, Южная Африка и Австралия относятся к крупнейшим продавцам золота.\n", + "\n", + "Прогнозирование роста и падения ежедневных цен на золото может помочь инвесторам решать, когда покупать (или продавать) этот актив. Однако цены на золото зависят от множества факторов, таких как цены на другие драгоценные металлы, цены на нефть, динамика фондового рынка, цены на облигации, валютные курсы и т.д.\n", + "\n", + "Задача этого проекта — точно предсказать будущую скорректированную цену закрытия Gold ETF на заданный период времени в будущем. Проблема является задачей регрессии, поскольку выходное значение, скорректированная цена закрытия в этом проекте, является непрерывной переменной.\n", + "\n", + "Объект исследования - данные о торгах золотом на биржах\n", + "\n", + "Проблемная область - прогнозирование цен на золото" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "количество колонок: 81\n", + "колонки: Date, Open, High, Low, Close, Adj Close, Volume, SP_open, SP_high, SP_low, SP_close, SP_Ajclose, SP_volume, DJ_open, DJ_high, DJ_low, DJ_close, DJ_Ajclose, DJ_volume, EG_open, EG_high, EG_low, EG_close, EG_Ajclose, EG_volume, EU_Price, EU_open, EU_high, EU_low, EU_Trend, OF_Price, OF_Open, OF_High, OF_Low, OF_Volume, OF_Trend, OS_Price, OS_Open, OS_High, OS_Low, OS_Trend, SF_Price, SF_Open, SF_High, SF_Low, SF_Volume, SF_Trend, USB_Price, USB_Open, USB_High, USB_Low, USB_Trend, PLT_Price, PLT_Open, PLT_High, PLT_Low, PLT_Trend, PLD_Price, PLD_Open, PLD_High, PLD_Low, PLD_Trend, RHO_PRICE, USDI_Price, USDI_Open, USDI_High, USDI_Low, USDI_Volume, USDI_Trend, GDX_Open, GDX_High, GDX_Low, GDX_Close, GDX_Adj Close, GDX_Volume, USO_Open, USO_High, USO_Low, USO_Close, USO_Adj Close, USO_Volume\n" + ] + } + ], + "source": [ + "import pandas as pd;\n", + "data_gold = pd.read_csv(\"..//static//csv//gold.csv\", sep=\",\")\n", + "print('количество колонок: ' + str(data_gold.columns.size))\n", + "print('колонки: ' + ', '.join(data_gold.columns))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "\n", + "Получение сведений о пропущенных данных\n", + "\n", + "Типы пропущенных данных:\n", + "\n", + " None - представление пустых данных в Python\n", + " NaN - представление пустых данных в Pandas\n", + " '' - пустая строка" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Date 0\n", + "Open 0\n", + "High 0\n", + "Low 0\n", + "Close 0\n", + " ..\n", + "USO_High 0\n", + "USO_Low 0\n", + "USO_Close 0\n", + "USO_Adj Close 0\n", + "USO_Volume 0\n", + "Length: 81, dtype: int64\n", + "\n", + "Date False\n", + "Open False\n", + "High False\n", + "Low False\n", + "Close False\n", + " ... \n", + "USO_High False\n", + "USO_Low False\n", + "USO_Close False\n", + "USO_Adj Close False\n", + "USO_Volume False\n", + "Length: 81, dtype: bool\n", + "\n" + ] + } + ], + "source": [ + "# Количество пустых значений признаков\n", + "print(data_gold.isnull().sum())\n", + "\n", + "print()\n", + "\n", + "# Есть ли пустые значения признаков\n", + "print(data_gold.isnull().any())\n", + "\n", + "print()\n", + "\n", + "# Процент пустых значений признаков\n", + "for i in data_gold.columns:\n", + " null_rate = data_gold[i].isnull().sum() / len(data_gold) * 100\n", + " if null_rate > 0:\n", + " print(f\"{i} процент пустых значений: %{null_rate:.2f}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Итог: пропущеных значений нет\n", + "\n", + "Количество столбцов слишком большое, оставим только самые необходимые\n", + "\n", + " Date: Уникальный идентификатор для каждого торгового дня.\n", + " Close: Цена закрытия золота на соответствующую дату.\n", + " Volume: Объем торгов золотом на соответствующую дату.\n", + " Open: Цена открытия золота на соответствующую дату.\n", + " High: Самая высокая зафиксированная цена золота в течение торгового дня.\n", + " Low: Самая низкая зафиксированная цена золота в течение торгового дня." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
DateCloseVolumeOpenHighLow
02011-12-15152.33000221521900154.740005154.949997151.710007
12011-12-16155.22999618124300154.309998155.369995153.899994
22011-12-19154.86999512547200155.479996155.860001154.360001
32011-12-20156.9799969136300156.820007157.429993156.580002
42011-12-21157.16000411996100156.979996157.529999156.130005
\n", + "
" + ], + "text/plain": [ + " Date Close Volume Open High Low\n", + "0 2011-12-15 152.330002 21521900 154.740005 154.949997 151.710007\n", + "1 2011-12-16 155.229996 18124300 154.309998 155.369995 153.899994\n", + "2 2011-12-19 154.869995 12547200 155.479996 155.860001 154.360001\n", + "3 2011-12-20 156.979996 9136300 156.820007 157.429993 156.580002\n", + "4 2011-12-21 157.160004 11996100 156.979996 157.529999 156.130005" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data_gold_reduced = data_gold[['Date', 'Close', 'Volume', 'Open', 'High', 'Low']]\n", + "\n", + "data_gold_reduced.head()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Аномальное рапределение будем искать по z-индексу. Z-индекс показывает, насколько далеко значение находится от среднего в стандартных отклонениях. Значения Z-индекса больше 3 или меньше -3 обычно считаются аномальными." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Аномалии в наборе данных gold:\n", + "В атрибуте 'Volume' обнаружены аномалии: [28957700, 23355300, 44149000, 28822100, 27399400, 28336900, 23995000, 25148400, 23374100, 30924000, 55601800, 93804200, 25975200, 28872100, 24780000, 24374800, 28341200, 49139000, 26635000, 35782900, 26459600, 24372700, 26810900]\n" + ] + } + ], + "source": [ + "from scipy import stats\n", + "# Вычисляем Z-индексы только для числовых столбцов\n", + "gold_zscores = data_gold_reduced.select_dtypes(include=['float64', 'int64']).apply(stats.zscore, nan_policy='omit')\n", + "\n", + "# Устанавливаем порог для поиска аномалий\n", + "threshold = 3\n", + "\n", + "def find_anomalies(zscores, df):\n", + " for column in zscores.columns:\n", + " # Проверяем, есть ли аномалии в Z-индексах\n", + " anomalies = df[column][(zscores[column].abs() > threshold)]\n", + " if not anomalies.empty:\n", + " print(f\"В атрибуте '{column}' обнаружены аномалии: {anomalies.tolist()}\")\n", + "\n", + "# Находим аномалии\n", + "try:\n", + " print(\"Аномалии в наборе данных gold:\")\n", + " find_anomalies(gold_zscores, data_gold_reduced)\n", + "\n", + "except Exception as e:\n", + " print(f\"Произошла ошибка: {e}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Теперь выполним 10 пункт, разобьем данные на выборки" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Набор данных gold:\n", + "Обучающая выборка:\n", + "Close\n", + "122.209999 0.002911\n", + "114.769997 0.002911\n", + "116.769997 0.002911\n", + "115.779999 0.002911\n", + "115.379997 0.002183\n", + " ... \n", + "160.779999 0.000728\n", + "161.600006 0.000728\n", + "118.180000 0.000728\n", + "104.019997 0.000728\n", + "118.589996 0.000728\n", + "Name: proportion, Length: 1151, dtype: float64\n", + "\n", + "Контрольная выборка:\n", + "Close\n", + "119.180000 0.011628\n", + "121.580002 0.011628\n", + "122.419998 0.011628\n", + "115.800003 0.011628\n", + "122.820000 0.011628\n", + " ... \n", + "107.339996 0.005814\n", + "125.459999 0.005814\n", + "159.570007 0.005814\n", + "128.990005 0.005814\n", + "136.419998 0.005814\n", + "Name: proportion, Length: 166, dtype: float64\n", + "\n", + "Тестовая выборка:\n", + "Close\n", + "113.419998 0.011628\n", + "159.570007 0.005814\n", + "156.990005 0.005814\n", + "159.429993 0.005814\n", + "173.610001 0.005814\n", + " ... \n", + "118.820000 0.005814\n", + "119.500000 0.005814\n", + "164.419998 0.005814\n", + "122.320000 0.005814\n", + "169.309998 0.005814\n", + "Name: proportion, Length: 171, dtype: float64\n" + ] + } + ], + "source": [ + "from sklearn.model_selection import train_test_split\n", + "def split_data(df, target_column, test_size=0.2, random_state=42):\n", + " # Разделяем данные на обучающую и временную выборки\n", + " X_train, X_temp, y_train, y_temp = train_test_split(df.drop(columns=[target_column]), \n", + " df[target_column], \n", + " test_size=test_size, \n", + " random_state=random_state)\n", + " # Делим временную выборку на контрольную и тестовую\n", + " X_val, X_test, y_val, y_test = train_test_split(X_temp, y_temp, \n", + " test_size=0.5, \n", + " random_state=random_state)\n", + " \n", + " return X_train, X_val, X_test, y_train, y_val, y_test\n", + "\n", + "gold_train, gold_val, gold_test, gold_train_labels, gold_val_labels, gold_test_labels = split_data(data_gold_reduced, 'Close')\n", + "\n", + "def check_balance(y_train, y_val, y_test):\n", + " print(\"Обучающая выборка:\")\n", + " print(y_train.value_counts(normalize=True))\n", + " print(\"\\nКонтрольная выборка:\")\n", + " print(y_val.value_counts(normalize=True))\n", + " print(\"\\nТестовая выборка:\")\n", + " print(y_test.value_counts(normalize=True))\n", + "\n", + "print(\"Набор данных gold:\")\n", + "check_balance(gold_train_labels, gold_val_labels, gold_test_labels)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Как мы видим, данные не требуется аугментировать, т.к. пропорции классов сбалансированы.\n", + "\n", + "Для этого набора данных не надо использовать преращение данных так как задача не на классификацию." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 2. Диабет у женщин Пима" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Этот набор данных изначально был получен из Национального института диабета, заболеваний пищеварительной системы и почек. Целью набора данных является диагностическое прогнозирование наличия или отсутствия у пациента диабета на основе определенных диагностических измерений, включенных в набор данных. На выбор этих случаев из более крупной базы данных налагалось несколько ограничений. В частности, все пациенты здесь — женщины в возрасте не менее 21 года индейского происхождения пима.\n", + "\n", + "Проблемная область - предсказание диабета" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "количество колонок: 9\n", + "колонки: Pregnancies, Glucose, BloodPressure, SkinThickness, Insulin, BMI, DiabetesPedigreeFunction, Age, Outcome\n" + ] + } + ], + "source": [ + "diabetes = pd.read_csv(\"..//static//csv//diabetes.csv\", sep=\",\")\n", + "print('количество колонок: ' + str(diabetes.columns.size))\n", + "print('колонки: ' + ', '.join(diabetes.columns))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Получение сведений о пропущенных данных\n", + "\n", + "Типы пропущенных данных:\n", + "\n", + " None - представление пустых данных в Python\n", + " NaN - представление пустых данных в Pandas\n", + " '' - пустая строка" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Pregnancies 0\n", + "Glucose 0\n", + "BloodPressure 0\n", + "SkinThickness 0\n", + "Insulin 0\n", + "BMI 0\n", + "DiabetesPedigreeFunction 0\n", + "Age 0\n", + "Outcome 0\n", + "dtype: int64\n", + "\n", + "Pregnancies False\n", + "Glucose False\n", + "BloodPressure False\n", + "SkinThickness False\n", + "Insulin False\n", + "BMI False\n", + "DiabetesPedigreeFunction False\n", + "Age False\n", + "Outcome False\n", + "dtype: bool\n", + "\n" + ] + } + ], + "source": [ + "# Количество пустых значений признаков\n", + "print(diabetes.isnull().sum())\n", + "\n", + "print()\n", + "\n", + "# Есть ли пустые значения признаков\n", + "print(diabetes.isnull().any())\n", + "\n", + "print()\n", + "\n", + "# Процент пустых значений признаков\n", + "for i in diabetes.columns:\n", + " null_rate = diabetes[i].isnull().sum() / len(diabetes) * 100\n", + " if null_rate > 0:\n", + " print(f\"{i} процент пустых значений: %{null_rate:.2f}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Итог: пропущенных данных нет" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Pregnancies Glucose BloodPressure SkinThickness Insulin \\\n", + "count 768.000000 768.000000 768.000000 768.000000 768.000000 \n", + "mean 3.845052 120.894531 69.105469 20.536458 79.799479 \n", + "std 3.369578 31.972618 19.355807 15.952218 115.244002 \n", + "min 0.000000 0.000000 0.000000 0.000000 0.000000 \n", + "25% 1.000000 99.000000 62.000000 0.000000 0.000000 \n", + "50% 3.000000 117.000000 72.000000 23.000000 30.500000 \n", + "75% 6.000000 140.250000 80.000000 32.000000 127.250000 \n", + "max 17.000000 199.000000 122.000000 99.000000 846.000000 \n", + "\n", + " BMI DiabetesPedigreeFunction Age Outcome \n", + "count 768.000000 768.000000 768.000000 768.000000 \n", + "mean 31.992578 0.471876 33.240885 0.348958 \n", + "std 7.884160 0.331329 11.760232 0.476951 \n", + "min 0.000000 0.078000 21.000000 0.000000 \n", + "25% 27.300000 0.243750 24.000000 0.000000 \n", + "50% 32.000000 0.372500 29.000000 0.000000 \n", + "75% 36.600000 0.626250 41.000000 1.000000 \n", + "max 67.100000 2.420000 81.000000 1.000000 \n" + ] + } + ], + "source": [ + "print(diabetes.describe())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Теперь проверим данные на аномалии" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Аномалии в наборе данных diabetes:\n", + "В атрибуте 'Pregnancies' обнаружены аномалии: [15, 17, 14, 14]\n", + "В атрибуте 'Glucose' обнаружены аномалии: [0, 0, 0, 0, 0]\n", + "В атрибуте 'BloodPressure' обнаружены аномалии: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n", + "В атрибуте 'SkinThickness' обнаружены аномалии: [99]\n", + "В атрибуте 'Insulin' обнаружены аномалии: [543, 846, 495, 485, 495, 478, 744, 680, 545, 465, 579, 474, 480, 600, 440, 540, 480, 510]\n", + "В атрибуте 'BMI' обнаружены аномалии: [0.0, 0.0, 0.0, 0.0, 0.0, 67.1, 0.0, 0.0, 59.4, 0.0, 0.0, 57.3, 0.0, 0.0]\n", + "В атрибуте 'DiabetesPedigreeFunction' обнаружены аномалии: [2.288, 1.893, 1.781, 2.329, 1.476, 2.137, 1.731, 1.6, 2.42, 1.699, 1.698]\n", + "В атрибуте 'Age' обнаружены аномалии: [69, 72, 81, 70, 69]\n" + ] + } + ], + "source": [ + "# Вычисляем Z-индексы только для числовых столбцов\n", + "diabetes_zscores = diabetes.select_dtypes(include=['float64', 'int64']).apply(stats.zscore, nan_policy='omit')\n", + "\n", + "# Устанавливаем порог для поиска аномалий\n", + "threshold = 3\n", + "\n", + "# Находим аномалии\n", + "try:\n", + " print(\"Аномалии в наборе данных diabetes:\")\n", + " find_anomalies(diabetes_zscores, diabetes)\n", + "\n", + "except Exception as e:\n", + " print(f\"Произошла ошибка: {e}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Теперь выполним разбиение данных" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Обучающая выборка:\n", + "Outcome\n", + "0 0.653094\n", + "1 0.346906\n", + "Name: proportion, dtype: float64\n", + "\n", + "Контрольная выборка:\n", + "Outcome\n", + "0 0.675325\n", + "1 0.324675\n", + "Name: proportion, dtype: float64\n", + "\n", + "Тестовая выборка:\n", + "Outcome\n", + "0 0.61039\n", + "1 0.38961\n", + "Name: proportion, dtype: float64\n" + ] + } + ], + "source": [ + "diabetes_train, diabetes_val, diabetes_test, diabetes_train_labels, diabetes_val_labels, diabetes_test_labels = split_data(diabetes, 'Outcome')\n", + "\n", + "check_balance(diabetes_train_labels, diabetes_val_labels, diabetes_test_labels)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "В этом наборе данных наблюдается дисбаланс, 0 тип составляет около 65%, а 1 тип около 35%. В этом случае лучше использовать метод oversampling." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Oversampling для Diabetes:\n", + "Outcome\n", + "1 500\n", + "0 500\n", + "Name: count, dtype: int64\n" + ] + } + ], + "source": [ + "from imblearn.over_sampling import RandomOverSampler\n", + "\n", + "X_diabetes = diabetes.drop('Outcome', axis=1)\n", + "y_diabetes = diabetes['Outcome']\n", + "\n", + "# Oversampling\n", + "ros_diabetes = RandomOverSampler(random_state=42)\n", + "X_diabetes_resampled, y_diabetes_resampled = ros_diabetes.fit_resample(X_diabetes, y_diabetes)\n", + "diabetes_resampled = pd.DataFrame(X_diabetes_resampled, columns=X_diabetes.columns)\n", + "diabetes_resampled['Outcome'] = y_diabetes_resampled\n", + "\n", + "print(\"\\nOversampling для Diabetes:\")\n", + "print(diabetes_resampled['Outcome'].value_counts())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 3. Индикаторы инсульта" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "По данным Всемирной организации здравоохранения (ВОЗ), инсульт является второй по значимости причиной смертности во всем мире, на его долю приходится примерно 11% от общего числа смертей. Этот набор данных используется для прогнозирования вероятности инсульта у пациента на основе таких входных параметров, как пол, возраст, различные заболевания и статус курильщика. Каждая строка данных содержит соответствующую информацию о пациенте.\n", + "\n", + "Объект исследования - реальные данные о пациентах\n", + "\n", + "Проблемная область - предсказание инсульта" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "количество колонок: 12\n", + "колонки: id, gender, age, hypertension, heart_disease, ever_married, work_type, Residence_type, avg_glucose_level, bmi, smoking_status, stroke\n" + ] + } + ], + "source": [ + "healthcare = pd.read_csv(\"..//static//csv//healthcare-dataset-stroke-data.csv\", sep=\",\")\n", + "print('количество колонок: ' + str(healthcare.columns.size))\n", + "print('колонки: ' + ', '.join(healthcare.columns))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Получение сведений о пропущенных данных\n", + "\n", + "Типы пропущенных данных:\n", + "\n", + " None - представление пустых данных в Python\n", + " NaN - представление пустых данных в Pandas\n", + " '' - пустая строка" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "id 0\n", + "gender 0\n", + "age 0\n", + "hypertension 0\n", + "heart_disease 0\n", + "ever_married 0\n", + "work_type 0\n", + "Residence_type 0\n", + "avg_glucose_level 0\n", + "bmi 201\n", + "smoking_status 0\n", + "stroke 0\n", + "dtype: int64\n", + "\n", + "id False\n", + "gender False\n", + "age False\n", + "hypertension False\n", + "heart_disease False\n", + "ever_married False\n", + "work_type False\n", + "Residence_type False\n", + "avg_glucose_level False\n", + "bmi True\n", + "smoking_status False\n", + "stroke False\n", + "dtype: bool\n", + "\n", + "bmi процент пустых значений: %3.93\n" + ] + } + ], + "source": [ + "# Количество пустых значений признаков\n", + "print(healthcare.isnull().sum())\n", + "\n", + "print()\n", + "\n", + "# Есть ли пустые значения признаков\n", + "print(healthcare.isnull().any())\n", + "\n", + "print()\n", + "\n", + "# Процент пустых значений признаков\n", + "for i in healthcare.columns:\n", + " null_rate = healthcare[i].isnull().sum() / len(healthcare) * 100\n", + " if null_rate > 0:\n", + " print(f\"{i} процент пустых значений: %{null_rate:.2f}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Для столбца bmi используем заполнение данных на \"Unknown\" для пустых значений." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " id age hypertension heart_disease \\\n", + "count 5110.000000 5110.000000 5110.000000 5110.000000 \n", + "mean 36517.829354 43.226614 0.097456 0.054012 \n", + "std 21161.721625 22.612647 0.296607 0.226063 \n", + "min 67.000000 0.080000 0.000000 0.000000 \n", + "25% 17741.250000 25.000000 0.000000 0.000000 \n", + "50% 36932.000000 45.000000 0.000000 0.000000 \n", + "75% 54682.000000 61.000000 0.000000 0.000000 \n", + "max 72940.000000 82.000000 1.000000 1.000000 \n", + "\n", + " avg_glucose_level stroke \n", + "count 5110.000000 5110.000000 \n", + "mean 106.147677 0.048728 \n", + "std 45.283560 0.215320 \n", + "min 55.120000 0.000000 \n", + "25% 77.245000 0.000000 \n", + "50% 91.885000 0.000000 \n", + "75% 114.090000 0.000000 \n", + "max 271.740000 1.000000 \n" + ] + } + ], + "source": [ + "healthcare['bmi'] = healthcare['bmi'].fillna('Unknown')\n", + "\n", + "print(healthcare.describe())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Проверим данные на аномалии" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Аномалии в наборе данных Healthcare:\n", + "В атрибуте 'hypertension' обнаружены аномалии: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]\n", + "В атрибуте 'heart_disease' обнаружены аномалии: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]\n", + "В атрибуте 'avg_glucose_level' обнаружены аномалии: [252.72, 243.58, 259.63, 249.31, 263.32, 271.74, 242.52, 250.89, 247.51, 243.53, 242.3, 243.5, 251.6, 247.69, 250.2, 254.6, 254.63, 246.34, 251.46, 267.76, 246.53, 244.28, 251.99, 253.16, 242.84, 249.29, 242.94, 247.48, 266.59, 243.73, 243.59, 250.8, 255.17, 267.61, 260.85, 248.37, 263.56, 247.97, 248.24, 253.93, 254.95, 247.87, 261.67, 256.74, 244.3, 242.62, 243.52, 267.6, 253.86]\n", + "В атрибуте 'stroke' обнаружены аномалии: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]\n" + ] + } + ], + "source": [ + "healthcare_zscores = healthcare.select_dtypes(include=['float64', 'int64']).apply(stats.zscore, nan_policy='omit')\n", + "\n", + "# Устанавливаем порог для поиска аномалий\n", + "threshold = 3\n", + "# Находим аномалии\n", + "try:\n", + " print(\"\\nАномалии в наборе данных healthcare:\")\n", + " find_anomalies(healthcare_zscores, healthcare)\n", + "\n", + "except Exception as e:\n", + " print(f\"Произошла ошибка: {e}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Теперь выполним разбиение данных" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Обучающая выборка:\n", + "stroke\n", + "0 0.954256\n", + "1 0.045744\n", + "Name: proportion, dtype: float64\n", + "\n", + "Контрольная выборка:\n", + "stroke\n", + "0 0.939335\n", + "1 0.060665\n", + "Name: proportion, dtype: float64\n", + "\n", + "Тестовая выборка:\n", + "stroke\n", + "0 0.939335\n", + "1 0.060665\n", + "Name: proportion, dtype: float64\n" + ] + } + ], + "source": [ + "\n", + "healthcare_train, healthcare_val, healthcare_test, healthcare_train_labels, healthcare_val_labels, healthcare_test_labels = split_data(healthcare, 'stroke')\n", + "\n", + "\n", + "check_balance(healthcare_train_labels, healthcare_val_labels, healthcare_test_labels)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "В этом наборе данных данные совсем несбалансированы, из-за чего аугментация данных необходима для более точного обучения. В этом наборе используем undersampling." + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Undersampling для Healthcare:\n", + "stroke\n", + "0 249\n", + "1 249\n", + "Name: count, dtype: int64\n" + ] + } + ], + "source": [ + "from imblearn.under_sampling import RandomUnderSampler\n", + "\n", + "X_healthcare = healthcare.drop('stroke', axis=1)\n", + "y_healthcare = healthcare['stroke']\n", + "\n", + "rus_healthcare = RandomUnderSampler(random_state=42)\n", + "X_healthcare_resampled_under, y_healthcare_resampled_under = rus_healthcare.fit_resample(X_healthcare, y_healthcare)\n", + "healthcare_resampled_under = pd.DataFrame(X_healthcare_resampled_under, columns=X_healthcare.columns)\n", + "healthcare_resampled_under['stroke'] = y_healthcare_resampled_under\n", + "\n", + "print(\"\\nUndersampling для Healthcare:\")\n", + "print(healthcare_resampled_under['stroke'].value_counts())" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "aimenv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 6c5847dff1daf27e2d151fd2a519ea57c8922f14 Mon Sep 17 00:00:00 2001 From: Katana Date: Tue, 29 Oct 2024 21:49:55 +0300 Subject: [PATCH 2/2] fixed --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 60b5e88..cd6c856 100644 --- a/.gitignore +++ b/.gitignore @@ -12,7 +12,6 @@ ipython_config.py # Remove previous ipynb_checkpoints # git rm -r .ipynb_checkpoints/ - /aimenv /static \ No newline at end of file