1.1 MiB
1.1 MiB
In [286]:
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib.ticker import FuncFormatter
df = pd.read_csv(".//csv//Webtoon_Dataset.csv")
print(df.columns)
- Бизнес-цель: Проанализировать предпочтений читателей для создания комикса
- Эффект: успешность комикса
- Техническая цель: определить предпочитаемые жанры аудитории сайта Webtoon
- Входные данные: 'Subscribers', 'Rating', 'Genre'
- Целевой признак: 'Genre'
- Обнаруженные проблемы:
Зашумленность данных. В колонке "число подписчиков" данные имеют строковое представление, есть значения с буквенными обозначениями K и k. Переделаем их в цифровое представление.
Выбросы: есть комиксы с очень большим количеством подписчиков.
In [287]:
# убираем зашумленность
def convert_str_to_float(value):
if isinstance(value, str):
if 'm' in value:
return float(value.replace(',', '').replace('m', '')) * 1000000
elif 'M' in value:
return float(value.replace(',', '').replace('M', '')) * 1000
elif 'k' in value:
return float(value.replace(',', '').replace('k', '')) * 1000
elif 'K' in value:
return float(value.replace(',', '').replace('K', '')) * 1000
elif 'b' in value:
return float(value.replace(',', '').replace('b', '')) * 1000000000
elif 'B' in value:
return float(value.replace(',', '').replace('B', '')) * 1000000000
return value
# чтобы шкала была более наглядная
def thousands(x, pos):
if x >= 1_000_000:
return f'{x / 1_000_000:.1f}M'
else:
return f'{x / 1_000:.1f}K'
df['Subscribers'] = df['Subscribers'].apply(convert_str_to_float)
plt.figure(figsize=(12, 8))
ax = sns.scatterplot(x='Subscribers', y='Rating', hue='Genre', data=df, palette='Set1')
# форматтер для x
ax.xaxis.set_major_formatter(FuncFormatter(thousands))
plt.title('График популярности жанров аудитории Webtoon')
plt.xlabel('Количество подписчиков')
plt.ylabel('Рейтинг')
plt.legend(title='Жанры')
plt.show()
Выводы по графику:
- Есть смещение в сторону меньших значений, это можно исправить при помощи oversampling и undersampling;
In [288]:
Q1 = df['Rating'].quantile(0.25)
Q3 = df['Rating'].quantile(0.75)
IQR = Q3 - Q1
threshold = 1.5 * IQR
outliers = (df['Rating'] < (Q1 - threshold)) | (df['Rating'] > (Q3 + threshold))
median_rating = df['Rating'].median()
df.loc[outliers, 'Rating'] = median_rating
plt.figure(figsize=(12, 8))
ax = sns.scatterplot(x='Subscribers', y='Rating', hue='Genre', data=df, palette='Set1')
# форматтер для x
ax.xaxis.set_major_formatter(FuncFormatter(thousands))
plt.title('График популярности жанров аудитории Webtoon')
plt.xlabel('Количество подписчиков')
plt.ylabel('Рейтинг')
plt.legend(title='Жанры')
plt.show()
- Разбиение на обучающую, контрольную и тестовую выборки.
In [289]:
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))
- Оценка сбалансированности выборок.
In [290]:
def build_graph(df, column_name, title, xlabel):
genre_counts = df[f'{column_name}'].value_counts()
plt.figure(figsize=(16, 4))
sns.barplot(x=genre_counts.index, y=genre_counts.values, palette='viridis')
plt.title(f'{title}')
plt.xlabel(f'{xlabel}')
plt.ylabel('Количество')
plt.show()
def check_balance(df, name):
counts = df['Genre'].value_counts()
print(f"Распределение Genre в {name}:")
print(counts)
print()
check_balance(train_df, "обучающей выборке")
build_graph(train_df, 'Genre', 'Обучающая', 'Жанр')
In [291]:
check_balance(val_df, "контрольной выборке")
build_graph(val_df, 'Genre', 'Контрольная', 'Жанр')
In [292]:
check_balance(test_df, "тестовой выборке")
build_graph(test_df, 'Genre', 'Тестовая', 'Жанр')
Выборки относительно сбалансированы
- Приращение данных с помощью oversampling и undersampling
In [293]:
from imblearn.over_sampling import RandomOverSampler
def oversample(df):
X = df.drop('Genre', axis=1)
y = df['Genre']
oversampler = RandomOverSampler(random_state=42)
X_resampled, y_resampled = oversampler.fit_resample(X, y)
resampled_df = pd.concat([X_resampled, y_resampled], axis=1)
return resampled_df
train_df_oversampled = oversample(train_df)
val_df_oversampled = oversample(val_df)
test_df_oversampled = oversample(test_df)
# Проверка
check_balance(train_df_oversampled, "обучающей выборке после oversampling")
In [294]:
check_balance(val_df_oversampled, "контрольной выборке после oversampling")
In [295]:
check_balance(test_df_oversampled, "тестовой выборке после oversampling")
In [296]:
from imblearn.under_sampling import RandomUnderSampler
def undersample(df):
X = df.drop('Genre', axis=1)
y = df['Genre']
undersampler = RandomUnderSampler(random_state=42)
X_resampled, y_resampled = undersampler.fit_resample(X, y)
resampled_df = pd.concat([X_resampled, y_resampled], axis=1)
return resampled_df
train_df_undersampled = undersample(train_df)
val_df_undersampled = undersample(val_df)
test_df_undersampled = undersample(test_df)
check_balance(train_df_undersampled, "обучающей выборке после undersampling")
In [297]:
check_balance(val_df_undersampled, "контрольной выборке после undersampling")
In [298]:
check_balance(test_df_undersampled, "тестовой выборке после undersampling")
Датасет 2. Использование мобильных телефонов¶
In [299]:
df = pd.read_csv(".//csv//mobile_usage_behavioral_analysis.csv")
print(df.columns)
- Бизнес-цель: для исследовательского журнала определить статистику, сколько человек тратит времени на социальные сети.
- Эффект: увеличение интереса читателей к журналу.
- Техническая цель: разработка модели прогнозирования использования соцсетей в зависимости от возраста
- Входные данные: Social_Media_Usage_Hours
- Целевой признак: Social_Media_Usage_Hours
In [300]:
# преобразование из строки в число и очистка от пустых значений
df['Social_Media_Usage_Hours'] = df['Social_Media_Usage_Hours'].astype(float)
plt.figure(figsize=(7, 8))
plt.subplot
sns.scatterplot(x='Age', y='Social_Media_Usage_Hours', data=df)
plt.title('График зависимости использования соцсетей от возраста')
plt.xlabel('Возраст')
plt.ylabel('Время, потраченное на соцсети, ч')
plt.show()
Набор достаточно сбалансирован, выбросов нет, нулевых значений тоже.
- Разбиение на обучающую, контрольную и тестовую выборки.
In [301]:
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))
- Оценка сбалансированности выборок.
In [302]:
def check_balance(df, name):
counts = df['Social_Media_Usage_Hours'].value_counts()
print(f"Распределение Social_Media_Usage_Hours в {name}:")
print(counts)
print()
check_balance(train_df, "обучающей выборке")
build_graph(train_df, 'Social_Media_Usage_Hours', 'Обучающая', 'Время в соц сетях, ч')
In [303]:
check_balance(val_df, "контрольной выборке")
build_graph(val_df, 'Social_Media_Usage_Hours', 'Контрольная', 'Время в соц сетях, ч')
In [304]:
check_balance(test_df, "тестовой выборке")
build_graph(test_df, 'Social_Media_Usage_Hours', 'Тестовая', 'Время в соц сетях, ч')
- Приращение данных с помощью oversampling и undersampling
In [305]:
from imblearn.over_sampling import RandomOverSampler
def oversample(df):
X = df.drop('Social_Media_Usage_Hours', axis=1)
# метки y должны быть дискретными, а не неприрыными -> конвертируем в целое число
y = df['Social_Media_Usage_Hours'].astype(int)
oversampler = RandomOverSampler(random_state=42)
X_resampled, y_resampled = oversampler.fit_resample(X, y)
resampled_df = pd.concat([X_resampled, y_resampled], axis=1)
return resampled_df
train_df_oversampled = oversample(train_df)
val_df_oversampled = oversample(val_df)
test_df_oversampled = oversample(test_df)
check_balance(train_df_oversampled, "обучающей выборке после oversampling")
In [306]:
check_balance(val_df_oversampled, "контрольной выборке после oversampling")
In [307]:
check_balance(test_df_oversampled, "тестовой выборке после oversampling")
Датасет 3. Факторы, влияющие на успеваемость студентов¶
In [308]:
df = pd.read_csv(".//csv//StudentPerformanceFactors.csv")
print(df.columns)
- Бизнес-цель: повышение успеваемости студентов за счет улучшения факторов, влияющих на успеваемость студентов.
- Эффект: улучшение показателей успеваемости и увеличение конкурентоспособности образовательного учреждения.
- Техническая цель: разработка модели машинного обучения, которая сможет предсказывать успеваемость студента (например, оценки на экзаменах)
- Входные данные: 'Hours_Studied', 'Attendance', 'Extracurricular_Activities', 'Sleep_Hours'
- Целевой признак: 'Exam_Score'
In [309]:
plt.figure(figsize=(12, 8))
sns.scatterplot(x='Attendance', y='Hours_Studied', hue='Exam_Score', data=df, palette='viridis')
# форматтер для x
plt.title('Зависимость оценки за экзамен от посещаемости и часов учёбы в неделю')
plt.xlabel('Посещаемость')
plt.ylabel('Количество часов, потраченных на учёбу в неделю')
plt.legend(title='Оценка за экзамен')
plt.show()
- Обнаруженные проблемы:
- Точки расположены относительно равномерно, значит, зашумленности нет.
- Точки распределены относительно равномерно по осям X и Y, смещениея нет
- На графике есть выбросы, но они не критичны
- Разбиение на обучающую, контрольную и тестовую выборки.
In [310]:
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))
- Оценка сбалансированности выборок.
In [311]:
def check_balance(df, name):
counts = df['Exam_Score'].value_counts()
print(f"Распределение Exam_Score в {name}:")
print(counts)
print()
check_balance(train_df, "обучающей выборке")
build_graph(train_df, 'Exam_Score', 'Обучающая', 'Оценка за экзамен')
In [312]:
check_balance(val_df, "контрольной выборке")
build_graph(test_df, 'Exam_Score', 'Контрольная', 'Оценка за экзамен')
In [313]:
check_balance(test_df, "тестовой выборке")
build_graph(test_df, 'Exam_Score', 'Тестовая', 'Оценка за экзамен')
- Приращение данных с помощью oversampling и undersampling
In [314]:
from imblearn.over_sampling import RandomOverSampler
def oversample(df):
X = df.drop('Exam_Score', axis=1)
y = df['Exam_Score']
oversampler = RandomOverSampler(random_state=42)
X_resampled, y_resampled = oversampler.fit_resample(X, y)
resampled_df = pd.concat([X_resampled, y_resampled], axis=1)
return resampled_df
train_df_oversampled = oversample(train_df)
val_df_oversampled = oversample(val_df)
test_df_oversampled = oversample(test_df)
check_balance(train_df_oversampled, "обучающей выборке после oversampling")
In [315]:
check_balance(val_df_oversampled, "контрольной выборке после oversampling")
In [316]:
check_balance(test_df_oversampled, "тестовой выборке после oversampling")