English translation is not available yet. Showing Russian content.

Настройка data augmentation для кода (переименование переменных, перестановка функций)

ТЕХНИЧЕСКОЕ ЗАДАНИЕ: Настройка data augmentation для кода (переименование переменных, перестановка функций)

1. Цель задачи

Разработать пайплайн аугментации исходного кода на Python, который автоматически переименовывает переменные и переставляет функции в файлах, сохраняя синтаксическую корректность. Цель — проверить и повысить устойчивость моделей машинного обучения (например, CodeBERT, GPT для кода) к таким поверхностным изменениям, не меняющим семантику программы. Ключевой результат Реализованный модуль augment_code.py, способный генерировать версии кода с переименованными переменными и переставленными функциями, и отчёт о влиянии аугментации на предсказания предобученной code-модели (метрика accuracy/EM не ухудшается более чем на 5%).

2. Исходные данные

Что нужноОткуда взять
Набор Python-файловРепозиторий из 10–20 небольших скриптов (например, из CodeSearchNet или собственные примеры)
Предобученная модельHugging Face: microsoft/codebert-base или Salesforce/codegen-350M-mono
Датасет для оценки50 пар (исходный код, вопрос/метка) в формате JSONL (можно синтезировать)

Если нет реального инструмента — симулируем:

  1. Создать папку sample_code/ с 5–10 Python-файлами (каждый 20–80 строк), содержащими минимум 2 функции и 3–5 переменных.
  2. Сгенерировать тестовые пары: взять 10 вопросов из HumanEval (или выдумать), для каждого написать эталонное решение (функция) и 10 вариантов с переименованием/перестановкой вручную.
  3. Использовать Docker-образ с Python 3.10+ и torch.

3. Технологический стек

КомпонентИнструментыНазначение
Язык и средаPython 3.10+, Jupyter NotebookРазработка и прототипирование
Парсинг кодаast (stdlib), black (форматирование)Анализ и модификация синтаксиса
Аугментацияrandom, libcst (для безопасных замен)Переименование переменных, перестановка
Модель и оценкаtransformers, torch, datasetsЗагрузка code-модели, вычисление метрик
Тестированиеpytest, unittestПроверка валидности аугментированного кода
ВерсионированиеGitФиксация версий

4. Этапы выполнения

Этап 1: Подготовка окружения и данных (2 ч)

Действия

  1. Создать виртуальное окружение и установить зависимости: pip install transformers torch datasets libcst black.
  2. Организовать структуру папок:
    project/
    ├── data/
    │   ├── original/            # Исходные Python-файлы (10 шт.)
    │   └── augmented/           # Сгенерированные варианты
    ├── augment.py               # Модуль аугментации
    ├── evaluate.py              # Скрипт оценки модели
    └── report.md                # Отчёт
    
  3. Поместить 10 Python-файлов из выбранного репозитория в data/original/. Если репозиторий недоступен — создать скрипт generate_samples.py, который сгенерирует 10 файлов с функциями (например, калькулятор, сортировка, работа со строками).
  4. Проверить, что каждый файл синтаксически корректен: python -m py_compile file.py.

Ожидаемый результат этапа Работающее окружение и папка data/original/ с 10 валидными Python-скриптами.

Этап 2: Реализация аугментации — переименование переменных (3 ч)

Действия

  1. Написать функцию rename_variables(source_code: str, p_rename: float = 0.3):
    • Использовать libcst для обхода AST.
    • Собрать все имена переменных (ast.Name, исключая встроенные функции и self).
    • Для каждой переменной с вероятностью p_rename заменить на новое случайное имя (например, var_{uuid_short} или из списка ['x','y','tmp_val','res']).
    • Гарантировать, что новое имя не конфликтует с существующими именами.
    • Вернуть изменённый код (строка).
  2. Написать функцию rename_variables_ast(source_code: str) — упрощённая версия с ast и ast.NodeTransformer:
    • Использовать ast.parse, затем трансформер, меняющий ast.Name.id (сохранять контекст, чтобы не переименовывать определение функции).
    • После модификации: ast.unparse(modified_tree), отформатировать black.
  3. Протестировать на простом скрипте:
    def add(a, b):
        c = a + b
        return c
    
    Ожидаемый вывод (пример):
    def add(x, y):
        z = x + y
        return z
    
  4. Написать unit-тест, проверяющий, что после переименования код остаётся синтаксически валидным и выполняет ту же логику (для этого прогнать на тестовом наборе входов).

Ожидаемый результат этапа Рабочая функция rename_variables, протестированная на 5 примерах, и модульный тест (test_rename.py).

Этап 3: Реализация аугментации — перестановка функций (2 ч)

Действия

  1. Написать функцию shuffle_functions(source_code: str, p_shuffle: float = 0.5):
    • Использовать ast.parse для извлечения всех определений функций верхнего уровня (ast.FunctionDef).
    • Если количество функций >= 2, с вероятностью p_shuffle перемешать их порядок (не перемешивать классы и глобальный код).
    • Сохранить все остальные узлы (импорты, глобальные переменные) в исходном порядке, вставив функции в новом порядке между ними.
    • Восстановить код через ast.unparse и отформатировать black.
  2. Написать функцию shuffle_functions_libcst(source_code: str) — альтернатива с libcst, которая проще сохраняет лишние пробелы, но сложнее в реализации. Можно отдать предпочтение ast.
  3. Протестировать на файле с тремя функциями:
    def foo(): ...
    def bar(): ...
    def baz(): ...
    
    После аугментации порядок может стать, например, bar, baz, foo. Убедиться, что импорт и глобальный код не затронуты.
  4. Дополнительно: написать юнит-тест, проверяющий, что перестановка не меняет количество функций и их сигнатуры.

Ожидаемый результат этапа Функция shuffle_functions с тестами.

Этап 4: Интеграция и генерация датасета (2 ч)

Действия

  1. Создать класс CodeAugmenter или скрипт augment.py, который:
    • Принимает список файлов из data/original/.
    • Для каждого файла применяет обе аугментации (можно последовательно) с заданной вероятностью.
    • Сохраняет аугментированные копии в data/augmented/ с суффиксом _augN.py.
    • Формирует CSV-файл mapping.csv с колонками: original_file, augmented_file, transformations_applied.
  2. Параметры аугментации (p_rename=0.4, p_shuffle=0.3) вынести в конфигурационный словарь.
  3. Запустить генерацию: python augment.py — получить 50–100 аугментированных файлов (по 5–10 вариантов на оригинал).
  4. Проверить, что все сгенерированные файлы синтаксически корректны (прогнать compile()).

Ожидаемый результат этапа Папка data/augmented/ с аугментированными файлами и mapping.csv.

Этап 5: Оценка устойчивости модели (2 ч)

Действия

  1. Выбрать задачу: code clone detection или code summarization. Для простоты возьмём code classification (например, определить, содержит ли функция ошибку). Создать синтетический датасет из 10 пар (баг/не баг).
  2. Загрузить модель microsoft/codebert-base через transformers:
    from transformers import AutoTokenizer, AutoModelForSequenceClassification
    tokenizer = AutoTokenizer.from_pretrained("microsoft/codebert-base")
    model = AutoModelForSequenceClassification.from_pretrained("microsoft/codebert-base", num_labels=2)
    
  3. Для каждого из 10 оригинальных файлов извлечь тестовый вход (например, тело функции), получить предсказание модели. Затем подать соответствующие аугментированные версии (по 3 на каждый оригинал).
  4. Вычислить метрику стабильности: доля предсказаний, совпадающих с предсказанием по оригиналу. Зафиксировать в отчёте.
  5. Дополнительно: провести fine-tuning на небольшом датасете, добавив аугментированные примеры, и сравнить метрики до/после.

Ожидаемый результат этапа Скрипт evaluate.py, выдающий численный отчёт об устойчивости (таблица). Вывод: "модель устойчива, accuracy падает не более чем на 2%".

5. Критерии приемки (Definition of Done)

  • Реализованы функции rename_variables и shuffle_functions, каждая с unit-тестами (минимум 3 теста).
  • Аугментированный код всегда синтаксически корректен и выполняется без ошибок (проверено на 100 сгенерированных файлах).
  • Параметры аугментации конфигурируемы, по умолчанию: переименование 40% переменных, перестановка 30% файлов.
  • Скрипт augment.py успешно генерирует минимум 50 вариантов из 10 исходных файлов.
  • Скрипт evaluate.py вычисляет метрику стабильности и выводит её в формате JSON.
  • Отчёт (report.md) включает описание подхода, результаты оценки и вывод о влиянии аугментации на модель.
  • Все зависимости зафиксированы в requirements.txt.
  • Код соответствует стандартам PEP8 (проверка через flake8).

6. Ожидаемый результат

Основной артефакт Репозиторий с папкой project/, содержащей:

  • augment.py — модуль аугментации с классами/функциями.
  • evaluate.py — скрипт оценки устойчивости.
  • data/original/ и data/augmented/ — исходные и сгенерированные файлы.
  • tests/ — юнит-тесты.
  • report.md — отчёт в формате markdown с таблицами и выводами.

Содержание отчёта описание методов, статистика (сколько файлов преобразовано, доля синтаксически корректных), результаты стабильности модели (до/после аугментации), анализ влияния каждой операции отдельно.

Опциональные результаты Fine-tuned модель с улучшенной устойчивостью (на 10% больше совпадений после дообучения на аугментированных данных).

7. Возможные сложности и их решение

СложностьРешение
При переименовании переменных случайно меняем имена функцийИспользовать ast.Name и проверять, что родительский узел не FunctionDef и не ClassDef. В libcst использовать visit_Name, игнорируя имена, определённые как Assign target? Тщательно фильтровать контекст.
После перестановки функций нарушается логика (если функции не pure)Для оценки устойчивости использовать только функции без глобального состояния или фиксацию входных аргументов.
Аугментированный код не проходит форматирование blackПрименять black после каждой модификации, либо использовать libcst с сохранением структуры.
Модель даёт разные предсказания из-за шума токенизацииУвеличить размер выборки и усреднять метрику. Также можно использовать усреднение по семплам с фиксированным seed.
Слишком много сгенерированных файловОграничить количество вариантов на файл до 5 и управлять seed.

8. Бюджет времени (оценка)

ЭтапВремя (часы)
Подготовка окружения и данных2
Реализация переименования3
Реализация перестановки2
Интеграция и генерация2
Оценка устойчивости2
Итого11

Примечание для первого раза: при отсутствии опыта работы с libcst или ast – заложить дополнительно 2-3 часа на изучение. Возможна замена на ast+astor для упрощения.

9. Связанные вопросы из базы знаний

ВопросТема
45Основы AST в Python
112Data augmentation для NLP
187Fine-tuning CodeBERT на кастомном датасете
234Оценка устойчивости моделей (robustness evaluation)
301Работа с libcst для трансформации кода
456Синтез данных для code summarization
512Генерация adversarial-примеров для кода
678Бенчмарк HumanEval и его модификации
720Black formatter и интеграция в пайплайн
891Метрики стабильности (consistency score)

10. Чек-лист самопроверки

  • Я убедился, что все сгенерированные файлы синтаксически валидны (python -c "compile(open('file').read())").
  • Я проверил, что переименование не затрагивает имена функций и классов, только переменные.
  • Я протестировал аугментацию на файлах с разным количеством функций (1 шт., 5 шт.) и убедился, что при единственной функции порядок не меняется.
  • Я выполнил замер стабильности минимум на 30 парах (оригинал-аугментация) и зафиксировал метрику.
  • Я написал юнит-тесты, которые покрывают граничные случаи (пустой файл, файл без переменных, только импорты).