Простое руководство для новичков: как самому генерировать данные для анализа и тестирования

Представьте: вы только что написали модель машинного обучения и вам нужно протестировать её работу в конкретном сценарии. Или вы собираетесь опубликовать научную статью о пользовательском решении в области Data Science, но имеющиеся датасеты нельзя использовать из-за юридических ограничений. А может быть, в рамках проекта машинного обучения вы занимаетесь отладкой и исправлением ошибок и вам нужны данные, чтобы идентифицировать и устранить проблемы.

В этих, да и во многих других ситуациях могут пригодиться синтетические данные. Реальные данные часто недоступны: уже кому-то принадлежат или дорого стоят. Так что умение создавать синтетические данные — важный навык для дата-сайентистов.

В этой статье я расскажу, с помощью каких приёмов и методов можно с нуля создать в Python синтетические данные, игрушечные датасеты и фиктивные значения. В некоторых решениях применяются методы из библиотек Python, в других — приёмы, основанные на встроенных функциях Python.

Все методы, о которых я рассказываю, пригодились мне при обучении или тестировании моделей, а также для исследовательских задач и научных статей. В конце статьи приведён notebook — вы можете воспользоваться им как руководством к действию или сохранить на будущее.

1. Используем NumPy

NumPy — самая известная библиотека Python. Она поддерживает операции линейной алгебры и численные вычисления, а также полезна при генерировании данных.

Генерирование линейных данных

В этом примере я покажу, как создать датасет с шумом в данных, характеризующимся линейной взаимосвязью между входными и выходными переменными. Этот приём может пригодиться для тестирования моделей линейной регрессии.

# Importing modules (импорт модулей)
from matplotlib import pyplot as plt
import numpy as np

def create_data(N, w):
 """
 Creates a dataset with noise having a linear relationship with the target values.
 N: number of samples
 w: target values
(Создаёт датасет, где есть шум с линейной взаимосвязью между входными и выходными переменными.
N: количество примеров
w: значения выходных переменных)
 """
 # Feature matrix with random data (создание матрицы со случайными значениями)
 X = np.random.rand(N, 1) * 10
 # Target values with noise normally distributed (значения нормально распределённых данных)
 y = w[0] * X + w[1] + np.random.randn(N, 1)
 return X, y

# Visualize the data (визуализация данных)
X, y = create_data(200, [2, 1])

plt.figure(figsize=(10, 6))
plt.title('Simulated Linear Data')
plt.xlabel('X')
plt.ylabel('y')
plt.scatter(X, y)
plt.show()
Синтетические линейные данные (изображение автора)
Синтетические линейные данные (изображение автора)

Данные временных рядов

В этом примере с помощью NumPy я сгенерирую синтетические данные временных рядов с линейным трендом и компонентом сезонности. Пример подойдёт для финансового моделирования и прогнозов фондового рынка.

def create_time_series(N, w):
 """
 Creates a time series data with a linear trend and a seasonal component.
 N: number of samples
 w: target values
(Создаёт временной ряд данных с линейным трендом и сезонной составляющей.
N: количество примеров
w: значения выходных переменных)
 """
 # Time values (заданный период)
 time = np.arange(0,N)
 # Linear trend (линейный тренд)
 trend = time * w[0]
 # Seasonal component (сезонная составляющая)
 seasonal = np.sin(time * w[1])
 # Noise (шум)
 noise = np.random.randn(N)
 # Target values (значения выходных переменных)
 y = trend + seasonal + noise
 return time, y

# Visualize the data (визуализация данных)
time, y = create_time_series(100, [0.25, 0.2])

plt.figure(figsize=(10, 6))
plt.title('Simulated Time Series Data')
plt.xlabel('Time')
plt.ylabel('y')

plt.plot(time, y)
plt.show()
Синтетические данные временных рядов
Синтетические данные временных рядов

Особые данные

Иногда возникает необходимость в данных с особыми характеристиками. Например, для снижения размерности нужен многомерный набор данных всего с несколькими информативными признаками. В примере ниже показан адекватный метод генерирования таких датасетов.

# Create simulated data for analysis (создание синтетических данных для анализа)
np.random.seed(42)
# Generate a low-dimensional signal (​​снижение размерности данных)
low_dim_data = np.random.randn(100, 3)

# Create a random projection matrix to project into higher dimensions (создание случайной проекции данных)
projection_matrix = np.random.randn(3, 6)

# Project the low-dimensional data to higher dimensions (проекция массива данных низкой размерности на массив данных высокой размерности)
high_dim_data = np.dot(low_dim_data, projection_matrix)

# Add some noise to the high-dimensional data (добавление шума на массив данных высокой размерности)
noise = np.random.normal(loc=0, scale=0.5, size=(100, 6))
data_with_noise = high_dim_data + noise
  
X = data_with_noise

Этот фрагмент кода создаёт датасет со 100 наблюдениями и 6 признаками на базе массива данных низкой размерности (всего с тремя размерностями).

2. Используем scikit-learn

Помимо моделей машинного обучения, в scikit-learn есть генераторы данных, которые могут создавать искусственные датасеты контролируемого размера и сложности.

Метод make classification

С помощью метода make_classification можно создать рандомный датасет с n классами. Этот метод позволяет создавать датасеты с выбранным количеством наблюдений, признаков и классов.

Он подходит для тестирования и отладки моделей классификации, таких как машины опорных векторов, деревья решений и наивные байесовские классификаторы.

X, y = make_classification(n_samples=1000, n_features=5, n_classes=2)

#Visualize the first rows of the synthetic dataset (визуализация первых строк синтетического набора данных)
import pandas as pd
df = pd.DataFrame(X, columns=['feature1', 'feature2', 'feature3', 'feature4', 'feature5'])
df['target'] = y
df.head()
Первые строки датасета (изображение автора)
Первые строки датасета (изображение автора)

Метод make regression

Аналогичным образом с помощью метода make_regression можно создать датасеты для регрессионного анализа. Он позволяет задавать количество наблюдений, признаков, предвзятость и шум датасета.

from sklearn.datasets import make_regression

X,y, coef = make_regression(n_samples=100, # number of observations (количество наблюдений)
                           n_features=1, # number of features (количество признаков)
                           bias=10, # bias term (алгоритмическая предвзятость)
                           noise=50, # noise level (шум в данных)
                           n_targets=1, # number of target values (количество значений выходных переменных)
                           random_state=0, # random seed (начальное значение генератора)
                           coef=True # return coefficients (извлечение коэффициентов)
                           )
Синтетические данные, созданные с помощью метода make_regression (изображение автора)
Синтетические данные, созданные с помощью метода make_regression (изображение автора)

Метод make blobs

Метод make_blobs позволяет создавать искусственные blob-объекты с данными, которые подходят для задач кластеризации. В нём можно указать общее число точек данных в датасете, количество кластеров и стандартное отклонение внутри кластера.

from sklearn.datasets import make_blobs

X,y = make_blobs(n_samples=300, # number of observations (число точек данных в датасете)
               n_features=2, # number of features (количество признаков)
               centers=3, # number of clusters (количество кластеров)
               cluster_std=0.5, # standard deviation of the clusters (стандартное отклонение внутри кластера)
               random_state=0)
Синтетические данные в кластерах (изображение автора)
Синтетические данные в кластерах (изображение автора)

3. Используем SciPy

Библиотека SciPy (аббревиатура от Scientific Python) считается одним из лучших инструментов для численных вычислений, оптимизации, статистического анализа и других математических задач. Статистическая модель SciPy может создавать синтетические данные из разных статистических распределений — например, из нормального, биномиального или экспоненциального.

from scipy.stats import norm, binom, expon
# Normal distribution (нормальное распределение)
norm_data = norm.rvs(size=1000)
Изображение автора
Изображение автора
# Binomial distribution (биномиальное распределение)
binom_data = binom.rvs(n=50, p=0.8, size=1000)
Изображение автора
Изображение автора
# Exponential distribution (экспоненциальное распределение)
exp_data = expon.rvs(scale=.2, size=10000)
Изображение автора
Изображение автора

4. Используем Faker

А как насчёт нечисловых данных? Ведь зачастую нам нужно обучать модели на нечисловых или пользовательских данных, таких как имя, адрес и электронная почта. Для создания реалистичных данных, похожих на персональную информацию, подходит библиотека Faker.

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

from faker import Faker

def create_fake_data(N):
 """
 Creates a dataset with fake data.
 N: number of samples
 (Создаёт датасет с фейковыми данными
 N — количество примеров)
 """
 fake = Faker()
 names = [fake.name() for _ in range(N)]
 addresses = [fake.address() for _ in range(N)]
 emails = [fake.email() for _ in range(N)]
 phone_numbers = [fake.phone_number() for _ in range(N)]
 fake_df = pd.DataFrame({'Name': names, 'Address': addresses, 'Email': emails, 'Phone Number': phone_numbers})
 return fake_df

fake_users = create_fake_data(100)
fake_users.head()
Фейковые пользовательские данные, созданные в Faker (изображение автора)
Фейковые пользовательские данные, созданные в Faker (изображение автора)

5. Используем Synthetic Data Vault (SDV)

А что, если в датасете не хватает наблюдений или вам нужно больше данных, похожих на имеющийся датасет, чтобы дополнить обучение ML-модели? Synthetic Data Vault (SDV) — библиотека Python, в которой можно создавать синтетические датасеты с помощью статистических моделей.

В примере ниже мы используем SDV, чтобы расширить демонстрационный датасет:

from sdv.datasets.demo import download_demo

# Load the 'adult' dataset (загружаем датасет с данными по взрослым)
adult_data, metadata = download_demo(dataset_name='adult', modality='single_table')
adult_data.head()
Демонстрационный датасет с информацией по взрослому населению
Демонстрационный датасет с информацией по взрослому населению
from sdv.single_table import GaussianCopulaSynthesizer
# Use GaussianCopulaSynthesizer to train on the data (используем моделирование гауссовыми копулами для обучения модели на основе данных)
model = GaussianCopulaSynthesizer(metadata)
model.fit(adult_data)

# Generate Synthetic data (генерируем синтетические данные)
simulated_data = model.sample(100)
simulated_data.head()
Синтетические выборки (изображение автора)
Синтетические выборки (изображение автора)

Эти синтетические данные очень похожи на исходный датасет.

Что со всем этим делать

В статье я привёл пять способов создания синтетических датасетов, которые можно применять для машинного обучения, статистического моделирования и других задач, подразумевающих манипуляции с данными. Это простые примеры, которые нетрудно повторить. Советую изучить код, прочитать необходимую документацию и освоить методы генерирования данных, подходящие для других задач.

Синтетические датасеты могут пригодиться дата-сайентистам, специалистам в области машинного обучения и разработчикам: с помощью этих датасетов можно повышать эффективность модели и снижать затраты на производство и тестирование приложений.

Как обещал — notebook со всеми методами из статьи.


Чтобы расти, нужно выйти из привычной зоны и сделать шаг к переменам. Можно изучить новое, начав с бесплатных занятий:

Или открыть перспективы с профессиональным обучением и переподготовкой:

Комментарии (0)