2024-10-18 21:30:59 +04:00

16 KiB
Raw Blame History

  1. Были выбраны следующие датасеты:
  1. Данные о автомобилях (17)
  2. Данные о мобильных устройствах (18)
  3. Данные о миллиордерах (19)
In [85]:
import pandas as pd
cars_df = pd.read_csv("./car_price_prediction.csv")
phones_df = pd.read_csv("./mobile phone price prediction.csv")
rich_df = pd.read_csv("./Forbes Billionaires.csv")
  1. Проблемные области: car_price_prediction.csv - цены на автомобили mobile phone price prediction.csv - цены на мобильные телефоны Forbes Billionaires.csv - данные о миллиордерах
  1. Объекты наблюдения car_price_prediction.csv: автомобили; mobile phone price prediction.csv: телефоны; Forbes Billionaires.csv: миллиардеры;

Атрибуты:

In [86]:
print(phones_df.columns)
print(phones_df.columns)
print(rich_df.columns)
Index(['ID', 'Price', 'Levy', 'Manufacturer', 'Model', 'Prod. year',
       'Category', 'Leather interior', 'Fuel type', 'Engine volume', 'Mileage',
       'Cylinders', 'Gear box type', 'Drive wheels', 'Doors', 'Wheel', 'Color',
       'Airbags'],
      dtype='object')
Index(['Unnamed: 0', 'Name', 'Rating', 'Spec_score', 'No_of_sim', 'Ram',
       'Battery', 'Display', 'Camera', 'External_Memory', 'Android_version',
       'Price', 'company', 'Inbuilt_memory', 'fast_charging',
       'Screen_resolution', 'Processor', 'Processor_name'],
      dtype='object')
Index(['Rank ', 'Name', 'Networth', 'Age', 'Country', 'Source', 'Industry'], dtype='object')

Связи между объектами не прослеживаю

  1. car_price_prediction.csv и mobile phone price prediction.csv бизнес-целью будует являться формирование цены, которая будет соответсвовать существующему рынку и атрибутам объекта. Forbes Billionaires.csv - выявление наиболее прибыльных видов бизнеса и проверенных спосов создания капитала

  2. Формирование цены: на вход характеристики продукта; целевой признак - цена Выявление...: на вход вид бизнеса, страна, источники дохода; целевой признак - место в форбс

6, 7. Проблемы наборов данных Зашумленность:

In [87]:
print(cars_df.shape[0])
print(phones_df.shape[0])
print(rich_df.shape[0])
19237
1370
2600

Так как набо дастаточно быльшие (более 1000 строк), то зашкмленность не будет иметь сильного влияние на качество, шумы усреднятся

Смещение данных, актуальность и просачивание данных проверить представляетяс невозможным, так как был взят готовый сет данных

In [88]:
print("было ", phones_df.shape[0])
for column in phones_df.select_dtypes(include=['int', 'float']).columns:
    mean = cars_df[column].mean()
    std_dev = cars_df[column].std()
    print(column, mean, std_dev)
    
    lower_bound = mean - 3 * std_dev
    upper_bound = mean + 3 * std_dev
    
    cars_df = cars_df[(cars_df[column] <= upper_bound) & (cars_df[column] >= lower_bound)]
    
print("стало ", cars_df.shape[0])

print("\n------------------\n")

print("было ", phones_df.shape[0])
for column in phones_df.select_dtypes(include=['int', 'float']).columns:
    mean = phones_df[column].mean()
    std_dev = phones_df[column].std()
    print(column, mean, std_dev)
    
    lower_bound = mean - 3 * std_dev
    upper_bound = mean + 3 * std_dev
    
    phones_df = phones_df[(phones_df[column] <= upper_bound) & (phones_df[column] >= lower_bound)]
    
print("стало ", phones_df.shape[0])

print("\n------------------\n")

print("было ", rich_df.shape[0])
for column in rich_df.select_dtypes(include=['int', 'float']).columns:
    mean = rich_df[column].mean()
    std_dev = rich_df[column].std()
    print(column, mean, std_dev)
    
    lower_bound = mean - 3 * std_dev
    upper_bound = mean + 3 * std_dev
    
    rich_df = rich_df[(rich_df[column] <= upper_bound) & (rich_df[column] >= lower_bound)]
    
print("стало ", rich_df.shape[0])
было  19237
ID 45576535.886104904 936591.4227992407
Price 18581.7495915248 191880.3101852926
Prod. year 2010.9471797575118 5.560374489543753
Cylinders 4.579460150135761 1.1950443346898312
Airbags 6.620695178600032 4.30661786316207
стало  18729

------------------

было  1370
Unnamed: 0 684.5 395.6292456328273
Rating 4.374416058394161 0.2301756924899598
Spec_score 80.23430656934306 8.37392155180379
стало  1359

------------------

было  2600
Rank  1269.5707692307692 728.1463636959434
Networth 4.8607499999999995 10.659670683623453
Age 64.25370226032736 13.195277077997176
стало  2565

Выше были устранены выбросы, которые могли повлиять на качество данных. При этом выбока осталась достаточного размера для работы с ней

  1. На мой взгляд наборы довольно информативные учитывая кол-во строк и атрибутов. Степень покрытия, соответсвие реальным данным и согласованность меток проверить не представляется возможным (но я верю составителям сетов)
  1. Проверка на пропущенные значения:
In [89]:
print(cars_df.isnull().sum().loc[lambda x: x>0])
print("--------------")
print(phones_df.isnull().sum().loc[lambda x: x>0])
print("--------------")
print(rich_df.isnull().sum().loc[lambda x: x>0])
Series([], dtype: int64)
--------------
Android_version      442
Inbuilt_memory        19
fast_charging         82
Screen_resolution      2
Processor             28
dtype: int64
--------------
Series([], dtype: int64)

в датасете с телефонами нашлись пустые значения. Жаль, но они все не числовые, поэтому просто заменим на моду

In [107]:
columns = ["Android_version", "Inbuilt_memory", "fast_charging", "Screen_resolution", "Processor"]
for column in columns:
    mode = phones_df[column].mode()[0]
    phones_df[column].fillna(mode, inplace=True)
    
print(phones_df.isnull().sum().loc[lambda x: x>0])
Series([], dtype: int64)

Не знаю насколько это правильно и как отразиться на качестве данных, но удалять 400+ строк их 1300 явно было бы хуже

  1. Разбиение данных на выборки
In [113]:
from sklearn.model_selection import train_test_split

cars_train_df, cars_temp_df = train_test_split(cars_df, test_size=0.3, random_state=52)
cars_val_df, cars_test_df = train_test_split(cars_temp_df, test_size=0.5, random_state=52)

phones_train_df, phones_temp_df = train_test_split(phones_df, test_size=0.3, random_state=52)
phones_val_df, phones_test_df = train_test_split(phones_temp_df, test_size=0.5, random_state=52)

rich_train_df, rich_temp_df = train_test_split(rich_df, test_size=0.3, random_state=52)
rich_val_df, rich_test_df = train_test_split(rich_temp_df, test_size=0.5, random_state=52)

print(cars_df.shape[0], cars_train_df.shape[0], cars_test_df.shape[0], cars_val_df.shape[0])
print(cars_val_df.shape[0] + cars_test_df.shape[0] + cars_train_df.shape[0])
print('\n', phones_df.shape[0], phones_train_df.shape[0], phones_test_df.shape[0], phones_val_df.shape[0])
print(phones_val_df.shape[0] + phones_test_df.shape[0] + phones_train_df.shape[0])
print('\n', rich_df.shape[0], rich_train_df.shape[0], rich_test_df.shape[0], rich_val_df.shape[0])
print(rich_val_df.shape[0] + rich_test_df.shape[0] + rich_train_df.shape[0])
18729 13110 2810 2809
18729

 1359 951 204 204
1359

 2565 1795 385 385
2565

Данные были разбиты на обучающую, тестовую и контрольную выборки в отношении 70%-15%-15%

  1. Взял проценты из лекции, наверное это сбалансированно
In [135]:
from imblearn.over_sampling import RandomOverSampler
from imblearn.under_sampling import RandomUnderSampler
cars_df['old_type'] = pd.cut(cars_df['Prod. year'], bins=[1900, 2004, 2015, 2025], 
                             labels=['Old', 'Normal', 'New'])

y = cars_df['old_type']
x = cars_df.drop(columns=['Prod. year', 'old_type'])

oversampler = RandomOverSampler(random_state=52)
x_resampled, y_resampled = oversampler.fit_resample(x, y)

undersampler = RandomUnderSampler(random_state=52)
x_resampled_under, y_resampled_under = undersampler.fit_resample(x, y)

print("oversampling:")
print(pd.Series(y_resampled).value_counts())

print("undersampling:")
print(pd.Series(y_resampled_under).value_counts())
oversampling:
old_type
Old       13196
Normal    13196
New       13196
Name: count, dtype: int64
undersampling:
old_type
Old       2285
Normal    2285
New       2285
Name: count, dtype: int64
In [136]:
phones_df['rating_type'] = pd.cut(phones_df['Rating'], bins=[0, 4.0, 4.5, 5.0], 
                             labels=["bad", "normal", "good"])

y = phones_df['rating_type']
x = phones_df.drop(columns=['Rating', 'rating_type'])

oversampler = RandomOverSampler(random_state=42)
x_resampled, y_resampled = oversampler.fit_resample(x, y)

undersampler = RandomUnderSampler(random_state=42)
x_resampled_under, y_resampled_under = undersampler.fit_resample(x, y)

print("oversampling:")
print(pd.Series(y_resampled).value_counts())

print("undersampling:")
print(pd.Series(y_resampled_under).value_counts())
oversampling:
rating_type
bad       838
normal    838
good      838
Name: count, dtype: int64
undersampling:
rating_type
bad       93
normal    93
good      93
Name: count, dtype: int64
In [139]:
rich_df['age_type'] = pd.cut(rich_df['Age'], bins=[0, 20, 60, 100], 
                             labels=["young", "grown", "old"])

y = rich_df['age_type']
x = rich_df.drop(columns=['Age', 'age_type'])

oversampler = RandomOverSampler(random_state=42)
x_resampled, y_resampled = oversampler.fit_resample(x, y)

undersampler = RandomUnderSampler(random_state=42)
x_resampled_under, y_resampled_under = undersampler.fit_resample(x, y)

print("oversampling:")
print(pd.Series(y_resampled).value_counts())

print("undersampling:")
print(pd.Series(y_resampled_under).value_counts())
oversampling:
age_type
grown    1535
old      1535
young       0
Name: count, dtype: int64
undersampling:
age_type
grown    1030
old      1030
young       0
Name: count, dtype: int64