33 KiB
Lab2 PIbd-31 Yakovlev¶
Загрузим три датасета
import pandas as pd
df = pd.read_csv("datasets/laptop.csv")
df2 = pd.read_csv("datasets/coffee.csv")
df3 = pd.read_csv("datasets/car_price_prediction.csv")
df.info()
df2.info()
df3.info()
Проблемная область¶
Первый датасет позволяет проанализировать данные, и понять какие ноутбуки имеют превосходство на рынке техники, и какие чаще всего выбирают пользователи. Второй датасет позволяет при помощи данных акций за последние 25 лет спрогнозировать будущие показатели акций кофейни Starbucks Третий датасет позволяет проанализировать данные, и спрогнозировать категорию цены для машины, по ее комплектующим.
Анализ набора данных¶
Объекты наблюдения - игровые ноутбуки, акции, машины Атрибуты -
- Имя бренда, цена, рейтинг, поколение процессора, марка процессора, сегмент процессора, специальная метка, производительность процессора, видеокарта, видеопамять, номер видеокарты, кол-во потоков видеокарты, размер дисплея, оперативная память, тип оперативной памяти, ОС, SSD.
- Дата, начальная цена за день, максимальная цена, минимальная цена, цена на момент закрытия продаж, скорректированая цена на момент закрытия, объем торговли акций за день.
- Цена обслуживания, производитель, модель, год выпуска, категория, кожанный салон, тип топлива, объем двигателя. Связи между объектами - нет
Бизнес-цели¶
- Какие модели игровых ноутбуков более выгодно продавать магазинам техники. Какие комплектующие наиболее популярны у производителей и покупателей, для дальнейшего увеличения производства данных комплектующих.
- Прогноз цен, для дальнешей покупки, продажи акций. Прогнозирование, для предотвращения упадка.
- Для составления списка лучших моделей автомобилей. Определения наилучшего буджетного автомобиля, который не будет часто ломаться и приносить убытки.
Примеры целей технического проекта. Что поступает на вход, что является целевым признаком.¶
На входе всегда датасет, целевые признаки:
- Рейтинг ноутбука
- Максимальная цена за день
- Цена обслуживания
Проблемы набора данных и их решения¶
- Возможны устаревшие данные. Для решения данной проблемы требуется удаление самых старых записей, и добавление более новых.
- Возможны выбросы. Решить эту проблему помогает удаление таких выбросов. В маленькой выборке не рекомендуется удалять выбросы. В большой выборке выбросы усредняются.
Качество набора данных¶
Наборы данных содержат достаточно примеров и признаков для обучения модели. Учтены различные ситуации проблемной области. Данные соответствуют данным, которые будут подаваться в производственной среде. Все метки согласованы.
Поиск аномалий¶
print(df.describe())
print(df2.describe())
print(df3.describe())
При просмотре вывода не было замечено аномалий в столбцах датасетов.
Проблема пропущенных данных¶
print("DATASET 1")
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("DATASET 2")
for i in df2.columns:
null_rate = df2[i].isnull().sum() / len(df2)*100
if null_rate > 0:
print(f"{i} процент пустых значений: %{null_rate:.2f}")
print("DATASET 3")
for i in df3.columns:
null_rate = df3[i].isnull().sum() / len(df3)*100
if null_rate > 0:
print(f"{i} процент пустых значений: %{null_rate:.2f}")
В первом датасете были поля с пустыми значениями, в остальных пустых значений не найдено.
df = df.fillna(0) #Замена пустых значений на 0
print(df.isnull().any())
df.tail()
Разбиение на выборки¶
Для разбиения на выборке для начала уменьшим количество уникальных значений в столбцах с целевыми признаками, путем добавления новых столбцов с малым количеством уникальных значений.
#У первого дата сета добавим новый столбец с рейтингом от 1 до 5 на основе столбца от 1 до 100.
df['new_rating'] = pd.cut(df['rating'], bins=[0,20,40,60,80,100], labels=[1,2,3,4,5], include_lowest=True)
#У второго добавим столбец с наибольшей ценой от 1 до 10, на основе столбца от 1 до 127.
df2['new_high'] = pd.cut(df2['High'], bins=[0,13,26,39,52,65,78,91,104,117,130], labels=[1,2,3,4,5,6,7,8,9,10], include_lowest=True)
#У третьего удалим слишком большие значения обслуживания и слишком маленькие и добавим новый столбец с категориями цен от 1 до 5.
df3_filtered = df3[df3['Price'] >= 10000]
df3_filtered = df3_filtered[df3_filtered['Price'] <= 100000]
df3_filtered['new_price'] = pd.cut(df3_filtered['Price'], bins=[10000,28000,46000,64000,82000,100000], labels=[1,2,3,4,5], include_lowest=True)
from sklearn.model_selection import train_test_split
def split_stratified_into_train_val_test(
df_input,
stratify_colname="y",
frac_train=0.6,
frac_val=0.15,
frac_test=0.25,
random_state=None,
):
if frac_train + frac_val + frac_test != 1.0:
raise ValueError(
"fractions %f, %f, %f do not add up to 1.0"
% (frac_train, frac_val, frac_test)
)
if stratify_colname not in df_input.columns:
raise ValueError("%s is not a column in the dataframe" % (stratify_colname))
X = df_input # Contains all columns.
y = df_input[
[stratify_colname]
] # Dataframe of just the column on which to stratify.
# Split original dataframe into train and temp dataframes.
df_train, df_temp, y_train, y_temp = train_test_split(
X, y, stratify=y, test_size=(1.0 - frac_train), random_state=random_state
)
# Split the temp dataframe into val and test dataframes.
relative_frac_test = frac_test / (frac_val + frac_test)
df_val, df_test, y_val, y_test = train_test_split(
df_temp,
y_temp,
stratify=y_temp,
test_size=relative_frac_test,
random_state=random_state,
)
assert len(df_input) == len(df_train) + len(df_val) + len(df_test)
return df_train, df_val, df_test
Выборки датасетов¶
df_train1, df_val1, df_test1 = split_stratified_into_train_val_test(
df, stratify_colname="new_rating", frac_train=0.60, frac_val=0.20, frac_test=0.20
)
df_train2, df_val2, df_test2 = split_stratified_into_train_val_test(
df2, stratify_colname="new_high", frac_train=0.60, frac_val=0.20, frac_test=0.20
)
df_train3, df_val3, df_test3 = split_stratified_into_train_val_test(
df3_filtered, stratify_colname="new_price", frac_train=0.60, frac_val=0.20, frac_test=0.20
)
print(f"train df: {df_train1.shape}, Val df: {df_val1.shape}, Test df:{df_test1.shape}")
print(f"train df2: {df_train2.shape}, Val df2: {df_val2.shape}, Test df2:{df_test2.shape}")
print(f"train df3_filtered: {df_train3.shape}, Val df3_filtered: {df_val3.shape}, Test df3_filtered:{df_test3.shape}")
Было сделано разбиение на три выборки: 60%, 20% и 20% при помощи библиотеки scikit-learn и функции train_test_split. На взгляд сбалансированные
Приращение методами выборки с избытком (oversampling) и выборки с недостатком (undersampling)¶
from imblearn.over_sampling import ADASYN
from imblearn.under_sampling import RandomUnderSampler
df_train1 = df_train1[['price', 'rating', 'threads', 'ram_storage', 'operating_system', 'new_rating']].copy()
ada = ADASYN()
undersampler = RandomUnderSampler(random_state=42)
print("Выборка до oversampling и undersampling:", df_train1.shape)
print(df_train1.new_rating.value_counts())
X_resampled, y_resampled = ada.fit_resample(df_train1, df_train1['new_rating'])
df_train1_adasyn = pd.DataFrame(X_resampled)
print("Выборка после oversampling: ", df_train1_adasyn.shape)
print(df_train1_adasyn.new_rating.value_counts())
X_resampled_under, y_resampled_under = undersampler.fit_resample(df_train1, df_train1['new_rating'])
print("Выборка после undersampling: ", pd.DataFrame(X_resampled_under).shape)
print(pd.DataFrame(X_resampled_under).new_rating.value_counts())
df_train2 = df_train2[['Open', 'High', 'new_high', 'Low', 'Close', 'Adj Close', 'Volume']].copy()
print("Выборка до oversampling и undersampling:", df_train2.shape)
print(df_train2.new_high.value_counts())
X_resampled, y_resampled = ada.fit_resample(df_train2, df_train2['new_high'])
df_train2_adasyn = pd.DataFrame(X_resampled)
print("Выборка после oversampling: ", df_train2_adasyn.shape)
print(df_train2_adasyn.new_high.value_counts())
X_resampled_under2, y_resampled_under2 = undersampler.fit_resample(df_train2, df_train2['new_high'])
print("Выборка после undersampling: ", pd.DataFrame(X_resampled_under2).shape)
print(pd.DataFrame(X_resampled_under2).new_high.value_counts())
from imblearn.over_sampling import SMOTE
df_train3 = df_train3[['Price', 'new_price','Prod. year' ,'Cylinders' ,'Airbags']].copy()
smote = SMOTE(random_state=42)
print("Выборка до oversampling и undersampling:", df_train3.shape)
print(df_train3.new_price.value_counts())
X_resampled, y_resampled = smote.fit_resample(df_train3, df_train3['new_price'])
df_train3_smote = pd.DataFrame(X_resampled)
print("Выборка после oversampling: ", df_train3_smote.shape)
print(df_train3_smote.new_price.value_counts())
X_resampled_under3, y_resampled_under3 = undersampler.fit_resample(df_train3, df_train3['new_price'])
print("Выборка после undersampling: ", pd.DataFrame(X_resampled_under3).shape)
print(pd.DataFrame(X_resampled_under3).new_price.value_counts())