Однією з найважливіших, але часто недооцінених частин робочого процесу машинного навчання є обробка та підготовка даних. Згідно з дослідженнями, спеціалісти з даних витрачають до 80% свого часу на очищення та підготовку даних для аналізу. Це критичний етап, адже якість вхідних даних напряму впливає на ефективність моделі машинного навчання.
"Сміття на вході - сміття на виході" - цей принцип особливо актуальний для машинного навчання, де якість моделі прямо залежить від якості даних, на яких вона навчається.
Навіщо потрібна обробка даних?
Обробка даних перед їх використанням у моделях машинного навчання необхідна з кількох причин:
- Вирішення проблеми пропущених значень: Реальні набори даних рідко бувають повними. Пропущені значення можуть негативно вплинути на продуктивність моделі.
- Стандартизація даних: Різні ознаки можуть мати різні масштаби, що може спричинити проблеми для деяких алгоритмів.
- Видалення викидів: Аномальні значення можуть спотворити модель і призвести до невірних прогнозів.
- Кодування категоріальних змінних: Більшість алгоритмів ML працюють з числовими даними, тому категоріальні змінні потрібно перетворити.
- Зменшення розмірності: Видалення надлишкових або нерелевантних ознак для підвищення ефективності моделі.
Процес обробки даних
Розглянемо основні етапи обробки даних для машинного навчання:
1. Збір та імпорт даних
Перший крок - це отримання даних з різних джерел: бази даних, API, файли CSV/Excel, веб-скрапінг тощо. Після збору даних їх потрібно імпортувати у середовище аналізу.
Приклад імпорту даних у Python з використанням pandas:
import pandas as pd # Імпорт з CSV файлу df = pd.read_csv('dataset.csv') # Імпорт з Excel файлу df = pd.read_excel('dataset.xlsx') # Імпорт з SQL бази даних import sqlite3 conn = sqlite3.connect('database.db') df = pd.read_sql_query("SELECT * FROM table_name", conn)
2. Дослідницький аналіз даних (EDA)
Перед початком обробки важливо зрозуміти структуру та характеристики даних. EDA допомагає виявити закономірності, аномалії та взаємозв'язки між змінними.
Основні кроки EDA:
- Перегляд перших кількох рядків даних
- Аналіз статистичних показників (середнє, медіана, мін, макс, квартилі)
- Перевірка типів даних
- Аналіз пропущених значень
- Візуалізація розподілу даних
# Перегляд перших 5 рядків print(df.head()) # Базова статистика print(df.describe()) # Типи даних print(df.dtypes) # Перевірка пропущених значень print(df.isnull().sum()) # Візуалізація import matplotlib.pyplot as plt import seaborn as sns # Гістограма числової змінної plt.figure(figsize=(10, 6)) sns.histplot(df['numeric_column'], kde=True) plt.title('Розподіл змінної') plt.show() # Матриця кореляції plt.figure(figsize=(12, 10)) correlation_matrix = df.corr() sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm') plt.title('Матриця кореляції') plt.show()
3. Очищення даних
Після розуміння структури даних настає етап їх очищення. Це включає обробку пропущених значень, видалення дублікатів та аномалій.
Обробка пропущених значень:
- Видалення рядків/стовпців з пропущеними значеннями (якщо їх небагато)
- Заповнення середнім, медіаною або модою (для числових даних)
- Заповнення найпоширенішим значенням (для категоріальних даних)
- Використання просунутих методів, таких як k-NN або машинне навчання, для прогнозування пропущених значень
# Видалення рядків з пропущеними значеннями df_cleaned = df.dropna() # Видалення стовпців з багатьма пропущеними значеннями df_cleaned = df.dropna(axis=1, thresh=len(df)*0.7) # Стовпці з менш ніж 70% непропущених значень # Заповнення середнім df['numeric_column'].fillna(df['numeric_column'].mean(), inplace=True) # Заповнення медіаною df['numeric_column'].fillna(df['numeric_column'].median(), inplace=True) # Заповнення найпоширенішим значенням df['categorical_column'].fillna(df['categorical_column'].mode()[0], inplace=True)
Видалення дублікатів:
# Перевірка дублікатів print(df.duplicated().sum()) # Видалення дублікатів df_cleaned = df.drop_duplicates()
Обробка викидів:
# Визначення викидів за допомогою IQR (міжквартильний розмах) Q1 = df['numeric_column'].quantile(0.25) Q3 = df['numeric_column'].quantile(0.75) IQR = Q3 - Q1 # Фільтрація викидів df_filtered = df[(df['numeric_column'] >= Q1 - 1.5 * IQR) & (df['numeric_column'] <= Q3 + 1.5 * IQR)]
4. Перетворення даних
Після очищення даних часто потрібно їх трансформувати для кращої відповідності вимогам алгоритмів машинного навчання.
Нормалізація і стандартизація:
Багато алгоритмів ML (наприклад, нейронні мережі, k-NN, SVM) чутливі до масштабу даних. Нормалізація приводить всі ознаки до одного масштабу.
from sklearn.preprocessing import MinMaxScaler, StandardScaler # Нормалізація (приведення до діапазону [0, 1]) scaler = MinMaxScaler() df_normalized = pd.DataFrame(scaler.fit_transform(df[['feature1', 'feature2']]), columns=['feature1', 'feature2']) # Стандартизація (приведення до середнього 0 і стандартного відхилення 1) scaler = StandardScaler() df_standardized = pd.DataFrame(scaler.fit_transform(df[['feature1', 'feature2']]), columns=['feature1', 'feature2'])
Кодування категоріальних змінних:
Перетворення текстових категорій у числові значення для алгоритмів ML.
# One-Hot Encoding df_encoded = pd.get_dummies(df, columns=['categorical_column']) # Label Encoding from sklearn.preprocessing import LabelEncoder le = LabelEncoder() df['encoded_category'] = le.fit_transform(df['categorical_column'])
Трансформація ознак:
Часто потрібно створювати нові ознаки або трансформувати існуючі для покращення продуктивності моделі.
# Логарифмічна трансформація (для даних з правостороннім перекосом) df['log_feature'] = np.log1p(df['feature']) # log1p для обробки нульових значень # Поліноміальні ознаки from sklearn.preprocessing import PolynomialFeatures poly = PolynomialFeatures(degree=2, include_bias=False) poly_features = poly.fit_transform(df[['feature1', 'feature2']])
5. Відбір ознак
Відбір релевантних ознак може значно покращити продуктивність моделі, зменшити її складність та час навчання.
Методи відбору ознак:
- Фільтрація: Вибір ознак на основі статистичних тестів
- Обгортка: Оцінка різних комбінацій ознак
- Вбудовані методи: Використання алгоритмів, які виконують відбір ознак під час навчання
# Використання SelectKBest для вибору k найкращих ознак from sklearn.feature_selection import SelectKBest, f_classif selector = SelectKBest(f_classif, k=5) # Вибір 5 найкращих ознак X_new = selector.fit_transform(X, y) # Використання рекурсивного виключення ознак (RFE) from sklearn.feature_selection import RFE from sklearn.linear_model import LogisticRegression model = LogisticRegression() rfe = RFE(model, n_features_to_select=5) X_rfe = rfe.fit_transform(X, y) # Використання важливості ознак з RandomForest from sklearn.ensemble import RandomForestClassifier model = RandomForestClassifier() model.fit(X, y) importances = model.feature_importances_
6. Розділення даних
Останній крок перед навчанням моделі - розділення даних на навчальну, валідаційну та тестову вибірки.
from sklearn.model_selection import train_test_split # Розділення на навчальну (70%) і тестову (30%) вибірки X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42) # Додаткове розділення навчальної вибірки для створення валідаційної X_train, X_val, y_train, y_val = train_test_split(X_train, y_train, test_size=0.2, random_state=42)
Автоматизація процесу обробки даних
Для підвищення ефективності та відтворюваності процесу обробки даних рекомендується використовувати конвеєри (pipelines).
from sklearn.pipeline import Pipeline from sklearn.impute import SimpleImputer from sklearn.preprocessing import StandardScaler, OneHotEncoder from sklearn.compose import ColumnTransformer # Визначення конвеєра для числових ознак numeric_features = ['feature1', 'feature2', 'feature3'] numeric_transformer = Pipeline(steps=[ ('imputer', SimpleImputer(strategy='median')), ('scaler', StandardScaler()) ]) # Визначення конвеєра для категоріальних ознак categorical_features = ['categorical_feature1', 'categorical_feature2'] categorical_transformer = Pipeline(steps=[ ('imputer', SimpleImputer(strategy='most_frequent')), ('onehot', OneHotEncoder(handle_unknown='ignore')) ]) # Об'єднання конвеєрів preprocessor = ColumnTransformer( transformers=[ ('num', numeric_transformer, numeric_features), ('cat', categorical_transformer, categorical_features) ]) # Створення повного конвеєра з попередньою обробкою та моделлю from sklearn.ensemble import RandomForestClassifier full_pipeline = Pipeline(steps=[ ('preprocessor', preprocessor), ('classifier', RandomForestClassifier()) ]) # Навчання та оцінка моделі full_pipeline.fit(X_train, y_train) accuracy = full_pipeline.score(X_test, y_test) print(f"Accuracy: {accuracy}")
Типові помилки при обробці даних
- Витік даних (Data Leakage): Ситуація, коли інформація з тестового набору використовується під час навчання, що призводить до завищених оцінок продуктивності.
- Не врахування розбалансованих класів: У задачах класифікації нерівномірний розподіл класів може призвести до упередженої моделі.
- Неправильна обробка часових рядів: Часові дані мають особливу структуру, яку потрібно враховувати при розділенні та валідації.
- Ігнорування викидів: Викиди можуть значно вплинути на модель, їх слід ретельно аналізувати та обробляти.
- Непослідовна обробка: Різні методи обробки для навчальної та тестової вибірок можуть призвести до проблем.
Висновок
Обробка даних є критичним етапом у процесі машинного навчання, який значною мірою визначає успіх кінцевої моделі. Хоча цей процес може здаватися трудомістким і менш привабливим, ніж навчання моделей, інвестиції в якісну обробку даних завжди окупаються через підвищення точності та надійності прогнозів.
Пам'ятайте, що кожен набір даних унікальний і може вимагати специфічних підходів до обробки. Важливо постійно експериментувати, аналізувати результати та коригувати свій підхід в залежності від специфіки даних та поставленої задачі.
"Дані - це нова нафта, але, як і нафта, вони вимагають очищення та переробки, перш ніж можна буде отримати їх реальну цінність."