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

Изображение предоставлено редактором.
# Введение
Синтетические данные, как следует из названия, создаются искусственно, а не собираются из реальных источников. Они выглядят как реальные данные, но позволяют избежать проблем с конфиденциальностью и высоких затрат на сбор данных. Это позволяет легко тестировать программное обеспечение и модели, проводя эксперименты по моделированию производительности после выпуска.
Хотя существуют такие библиотеки, как Faker , SDV и SynthCity , и даже большие языковые модели (LLM) широко используются для генерации синтетических данных, в этой статье я сосредоточусь на том, чтобы избежать использования этих внешних библиотек или инструментов ИИ. Вместо этого вы узнаете, как добиться тех же результатов, написав собственные скрипты на Python . Это позволит лучше понять, как формировать набор данных и как вводятся смещения или ошибки. Мы начнем с простых тестовых скриптов, чтобы понять доступные варианты. Как только вы освоите эти основы, вы сможете спокойно перейти к специализированным библиотекам.
# 1. Генерация простых случайных данных
Проще всего начать с таблицы. Например, если вам нужен фиктивный набор данных о клиентах для внутренней демонстрации, вы можете запустить скрипт для генерации данных в формате CSV (значения, разделенные запятыми):
import csv import random from datetime import datetime, timedelta random.seed(42) countries = [«Canada», «UK», «UAE», «Germany», «USA»] plans = [«Free», «Basic», «Pro», «Enterprise»] def random_signup_date(): start = datetime(2024, 1, 1) end = datetime(2026, 1, 1) delta_days = (end — start).days return (start + timedelta(days=random.randint(0, delta_days))).date().isoformat() rows = [] for i in range(1, 1001): age = random.randint(18, 70) country = random.choice(countries) plan = random.choice(plans) monthly_spend = round(random.uniform(0, 500), 2) rows.append({ «customer_id»: f»CUST{i:05d}», «age»: age, «country»: country, «plan»: plan, «monthly_spend»: monthly_spend, «signup_date»: random_signup_date() }) with open(«customers.csv», «w», newline=»», encoding=»utf-8″) as f: writer = csv.DictWriter(f, fieldnames=rows[0].keys()) writer.writeheader() writer.writerows(rows) print(«Saved customers.csv»)
Выход:

Этот скрипт прост: вы определяете поля, выбираете диапазоны и записываете строки. Модуль random поддерживает генерацию целых чисел, значения с плавающей запятой, случайный выбор и выборку. Модуль csv предназначен для чтения и записи табличных данных построчно. Такой набор данных подходит для:
- Демонстрации фронтенда
- Тестирование панели мониторинга
- разработка API
- Изучение языка структурированных запросов (SQL)
- Модульное тестирование входных конвейеров
Однако у этого подхода есть существенный недостаток: всё происходит совершенно случайно. Это часто приводит к тому, что данные выглядят плоскими или неестественными. Корпоративные клиенты могут потратить всего 2 доллара, в то время как пользователи «бесплатной» версии — 400. Более старшие пользователи ведут себя точно так же, как и молодые, потому что отсутствует какая-либо структурная основа.
В реальных условиях данные редко ведут себя подобным образом. Вместо того чтобы генерировать значения независимо друг от друга, мы можем ввести взаимосвязи и правила. Это делает набор данных более реалистичным, оставаясь при этом полностью синтетическим. Например:
- Корпоративные клиенты практически никогда не должны иметь нулевой уровень расходов.
- Диапазон расходов должен зависеть от выбранного тарифного плана.
- Пользователи старшего возраста могут тратить в среднем немного больше.
- Некоторые планы должны быть более распространены, чем другие.
Добавим в скрипт следующие элементы управления:
import csv import random random.seed(42) plans = [«Free», «Basic», «Pro», «Enterprise»] def choose_plan(): roll = random.random() if roll < 0.45: return "Free" if roll < 0.75: return "Basic" if roll < 0.93: return "Pro" return "Enterprise" def generate_spend(age, plan): if plan == "Free": base = random.uniform(0, 10) elif plan == "Basic": base = random.uniform(10, 60) elif plan == "Pro": base = random.uniform(50, 180) else: base = random.uniform(150, 500) if age >= 40: base *= 1.15 return round(base, 2) rows = [] for i in range(1, 1001): age = random.randint(18, 70) plan = choose_plan() spend = generate_spend(age, plan) rows.append({ «customer_id»: f»CUST{i:05d}», «age»: age, «plan»: plan, «monthly_spend»: spend }) with open(«controlled_customers.csv», «w», newline=»», encoding=»utf-8″) as f: writer = csv.DictWriter(f, fieldnames=rows[0].keys()) writer.writeheader() writer.writerows(rows) print(«Saved controlled_customers.csv»)
Выход:

Теперь набор данных сохраняет значимые закономерности. Вместо генерации случайного шума вы имитируете поведение. Эффективные методы контроля могут включать в себя:
- Взвешенный выбор категорий
- Реалистичные минимальные и максимальные диапазоны
- Условная логика между столбцами
- Преднамеренно добавлены редкие нестандартные случаи.
- Пропущенные значения вставляются с низкой частотой.
- Коррелированные признаки вместо независимых
# 2. Моделирование процессов для синтетических данных
Создание реалистичных синтетических наборов данных на основе моделирования — один из лучших способов. Вместо непосредственного заполнения столбцов вы моделируете процесс. Например, рассмотрим небольшой склад, где поступают заказы, запасы уменьшаются, а низкий уровень запасов приводит к отложенным заказам.
import csv import random from datetime import datetime, timedelta random.seed(42) inventory = { «A»: 120, «B»: 80, «C»: 50 } rows = [] current_time = datetime(2026, 1, 1) for day in range(30): for product in inventory: daily_orders = random.randint(0, 12) for _ in range(daily_orders): qty = random.randint(1, 5) before = inventory[product] if inventory[product] >= qty: inventory[product] -= qty status = «fulfilled» else: status = «backorder» rows.append({ «time»: current_time.isoformat(), «product»: product, «qty»: qty, «stock_before»: before, «stock_after»: inventory[product], «status»: status }) if inventory[product] < 20: restock = random.randint(30, 80) inventory[product] += restock rows.append({ "time": current_time.isoformat(), "product": product, "qty": restock, "stock_before": inventory[product] - restock, "stock_after": inventory[product], "status": "restock" }) current_time += timedelta(days=1) with open("warehouse_sim.csv", "w", newline="", encoding="utf-8") as f: writer = csv.DictWriter(f, fieldnames=rows[0].keys()) writer.writeheader() writer.writerows(rows) print("Saved warehouse_sim.csv")
Выход:

Этот метод превосходен, поскольку данные являются побочным продуктом поведения системы, что обычно приводит к более реалистичным взаимосвязям, чем прямая случайная генерация строк. Другие идеи для моделирования включают:
- Очереди в колл-центре
- Запросы на поездки и подбор водителей
- Заявки на кредиты и их одобрение
- Подписки и отток подписчиков
- Процесс записи пациентов на прием
- Трафик и конверсия сайта
# 3. Создание синтетических данных временных рядов
Синтетические данные не ограничиваются только статическими таблицами. Многие системы генерируют последовательности во времени, такие как трафик приложений, показания датчиков, количество заказов в час или время ответа сервера. Вот простой генератор временных рядов для почасовых посещений веб-сайта с учетом будних дней.
import csv import random from datetime import datetime, timedelta random.seed(42) start = datetime(2026, 1, 1, 0, 0, 0) hours = 24 * 30 rows = [] for i in range(hours): ts = start + timedelta(hours=i) weekday = ts.weekday() base = 120 if weekday >= 5: base = 80 hour = ts.hour if 8 <= hour <= 11: base += 60 elif 18 <= hour <= 21: base += 40 elif 0 <= hour <= 5: base -= 30 visits = max(0, int(random.gauss(base, 15))) rows.append({ "timestamp": ts.isoformat(), "visits": visits }) with open("traffic_timeseries.csv", "w", newline="", encoding="utf-8") as f: writer = csv.DictWriter(f, fieldnames=["timestamp", "visits"]) writer.writeheader() writer.writerows(rows) print("Saved traffic_timeseries.csv")
Выход:

Этот подход хорошо работает, потому что он учитывает тенденции, шумы и циклическое поведение, оставаясь при этом простым для объяснения и отладки.
# 4. Создание журналов событий
Журналы событий — еще один полезный тип скриптов, идеально подходящий для анализа продукта и тестирования рабочих процессов. Вместо одной строки на каждого клиента, вы создаете одну строку на каждое действие.
import csv import random from datetime import datetime, timedelta random.seed(42) events = [«signup», «login», «view_page», «add_to_cart», «purchase», «logout»] rows = [] start = datetime(2026, 1, 1) for user_id in range(1, 201): event_count = random.randint(5, 30) current_time = start + timedelta(days=random.randint(0, 10)) for _ in range(event_count): event = random.choice(events) if event == «purchase» and random.random() < 0.6: value = round(random.uniform(10, 300), 2) else: value = 0.0 rows.append({ "user_id": f"USER{user_id:04d}", "event_time": current_time.isoformat(), "event_name": event, "event_value": value }) current_time += timedelta(minutes=random.randint(1, 180)) with open("event_log.csv", "w", newline="", encoding="utf-8") as f: writer = csv.DictWriter(f, fieldnames=rows[0].keys()) writer.writeheader() writer.writerows(rows) print("Saved event_log.csv")
Выход:

Этот формат полезен для:
- Анализ воронки
- тестирование аналитического конвейера
- Панели мониторинга бизнес-аналитики (BI).
- реконструкция сессии
- Эксперименты по обнаружению аномалий
Полезным приемом здесь является привязка событий к предыдущим действиям. Например, покупка, как правило, должна происходить после входа в систему или просмотра страницы, что делает синтетический лог более правдоподобным.
# 5. Генерация синтетических текстовых данных с помощью шаблонов
Синтетические данные также ценны для обработки естественного языка (NLP). Для начала работы не всегда требуется знание языка программирования; можно создавать эффективные текстовые наборы данных, используя шаблоны и контролируемые вариации. Например, можно создать обучающие данные для заявок в службу поддержки:
import json import random random.seed(42) issues = [ («billing», «С меня дважды списали деньги за подписку»), («login», «Я не могу войти в свою учетную запись»), («shipping», «Мой заказ еще не прибыл»), («refund», «Я хочу запросить возврат средств»), ] tones = [«Пожалуйста, помогите», «Это срочно», «Можете проверить это?», «Мне нужна поддержка»] records = [] for _ in range(100): label, message = random.choice(issues) tone = random.choice(tones) text = f»{tone}. {message}.» records.append({ «text»: text, «label»: label }) with open(«support_tickets.jsonl», «w», encoding=»utf-8″) as f: for item in records: f.write(json.dumps(item) + «n») print(«Сохранено support_tickets.jsonl»)
Выход:

Этот подход хорошо подходит для:
- Демонстрации классификации текста
- Обнаружение намерений
- Тестирование чат-бота
- Оперативная оценка
# Заключительные мысли
Скрипты для работы с синтетическими данными — мощные инструменты, но их можно использовать неправильно. Обязательно избегайте следующих распространенных ошибок:
- Придание всем значениям равномерно случайного характера
- Игнорирование зависимостей между полями
- Генерация значений, нарушающих бизнес-логику.
- Предполагается, что синтетические данные по умолчанию являются по своей природе безопасными.
- Создание данных, которые слишком «чистые», чтобы быть полезными для тестирования реальных граничных случаев.
- Использование одного и того же шаблона настолько часто приводит к тому, что набор данных становится предсказуемым и нереалистичным.
Конфиденциальность остается важнейшим фактором. Хотя синтетические данные снижают риск утечки информации из реальных источников, они не лишены рисков. Если генератор данных слишком тесно связан с исходными конфиденциальными данными, утечка все равно может произойти. Именно поэтому методы, обеспечивающие конфиденциальность, такие как синтетические данные с дифференциальной приватностью, крайне важны.
Канвал Мехрин — инженер по машинному обучению и технический писатель, глубоко увлеченная наукой о данных и взаимодействием ИИ с медициной. Она является соавтором электронной книги «Максимизация производительности с помощью ChatGPT». Как стипендиат программы Google Generation Scholar 2022 для Азиатско-Тихоокеанского региона, она выступает за разнообразие и академическое превосходство. Она также является стипендиатом программы Teradata Diversity in Tech Scholar, стипендиатом Mitacs Globalink Research Scholar и стипендиатом Harvard WeCode Scholar. Канвал — убежденная сторонница перемен, основавшая FEMCodes для расширения прав и возможностей женщин в областях STEM (наука, технология, инженерия и математика).
Источник: www.kdnuggets.com





















