Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

_RSOD_2

.pdf
Скачиваний:
1
Добавлен:
28.11.2024
Размер:
628.57 Кб
Скачать

МИНОБРНАУКИ РОССИИ САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ ЭЛЕКТРОТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ «ЛЭТИ» ИМ. В.И. УЛЬЯНОВА (ЛЕНИНА) Кафедра информационной безопасности

ОТЧЕТ по лабораторной работе №2

по дисциплине «Распределенные системы обработки данных» Тема: Реализация алгоритма MOSS с использованием PySpark для обнаружения плагиата в исходном коде

Студент гр. 1363

 

Соловьев М.И.

Преподаватель

 

 

Троценко В.В

Санкт-Петербург

2024

Цель работы.

Реализовать алгоритм MOSS для обнаружения плагиата в исходном коде.

Основные теоретические положения.

Основы RDD и DataFrame

RDD (Resilient Distributed Dataset) — это низкоуровневый объект в Spark,

представляющий распределённые данные без строгой схемы. В RDD нет информации о структуре данных, поэтому он подходит для неструктурированных данных и сложных вычислений. RDD позволяет выполнять базовые операции (map, filter, foreach), но не поддерживает оптимизации Catalyst.

DataFrame — это структурированное расширение RDD, где данные представлены в виде таблицы с колонками и типами данных (схемой). DataFrame

предоставляет SQL-подобные операции и автоматическую оптимизацию через

Catalyst, делая его удобным для табличных данных и аналитических запросов.

Трансформации и Действия

Spark использует ленивые трансформации, такие как filter, map, join,

которые не запускают вычислений, а лишь добавляют шаги в граф выполнения

(DAG). Чтобы граф был выполнен, необходимо вызвать действие (например, count или collect). Действия запускают выполнение всех накопленных трансформаций, что делает их "неленивыми" операциями.

Добавление колонок в DataFrame можно выполнить с помощью метода withColumn, который возвращает новый DataFrame с добавленной колонкой.

Catalyst Optimizer

Catalyst — это встроенный оптимизатор в Spark, работающий на уровне

DataFrame и SQL, но не на уровне RDD. Catalyst использует схему данных для улучшения плана выполнения (DAG), что помогает ускорить выполнение операций. Catalyst нельзя "выключить" — он не замедляет работу, а наоборот,

оптимизирует её.

2

Catalyst не поддерживает RDD, поскольку у RDD нет схемы, и их операции выполняются без оптимизации.

Взаимодействие между RDD и DataFrame

DataFrame можно преобразовать в RDD (с помощью .rdd) и обратно (с

помощью .toDF()), что полезно при переходе между высокоуровневой и низкоуровневой обработкой данных. Преобразование в RDD полезно для использования методов, недоступных в DataFrame API, однако это приводит к потере схемы и оптимизаций Catalyst.

Нагрузка на кластер и производительность

Создание множества DataFrame не увеличивает нагрузку на кластер, пока не выполняются действия, так как трансформации ленивы. Spark API и SQL

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

Количество драйверов и воркеров в Spark-программе: минимально один драйвер, и любое количество воркеров в зависимости от конфигурации кластера.

Драйвер управляет задачами, а воркеры выполняют вычисления на отдельных узлах кластера.

Пользовательские функции (UDF) и сериализация

Spark требует сериализации функций для передачи между узлами, так как работает в распределённой среде. UDF (User-Defined Functions) обеспечивают механизм для создания пользовательской логики, но требуют обёрток и сериализации для совместимости со Spark. Случайные функции Python

напрямую не поддерживаются, так как Spark использует UDF для передачи функций в сериализованном виде.

3

Экспериментальные результаты.

Работа была разделена на следующие этапы:

1.Удаление пробелов из кода программ

2.Разбиение кода на подстроки длины 5

3.Нахождение хэшей этих подстрок

4.Поиск общих хэшей

5.Нахождение коэффициента сходства

Удаление пробелов из кода программ

Этот этап выполняется посредством применения UDF-функции clean_data

к исходному коду программ.

def clean_data(inp: str) -> str: return "".join(inp.split())

inp = common.read_data()

df = inp. withColumn('content',clean_data_udf(col('content')))

Рисунок 1 – Датафрейм df

Разбиение кода на подстроки длины 5

Выполняется при помощи применения UDF-функции split_content к

отформатированному ранее тексту.

def split_content(cont, n=5):

return [cont[i:i+n] for i in range(0, len(cont)-n)]

splited_df = df.withColumn('substrings',split_content_udf(col('content')))

Рисунок 2 – Датафрейм splited_df

4

Нахождение хэшей этих подстрок

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

splited_df = splited_df.withColumn('substrings',explode(col('substrings'))

)

def get_hash(cont):

return crc32(cont.encode() hashed_df =

splited_df.withColumn('hash',hash_udf2(col('substrings'))) hashed_df =

hashed_df.groupBy('author').agg(collect_set('hash').alias('hashes'

))

Рисунок 3 – Датафрейм hashed_df

Поиск общих хэшей

Создадим датафрейм df_joined, который будет состоять из всевозможных

пар файлов и их хэшей.

df_joined

=

hashed_df.alias('df1').join(hashed_df.alias('df2'),

col('df1.author') != col('df2.author'))

Рисунок 4 – Датафрейм df_joined

5

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

df_template = df_joined.select(col('df1.author').alias('_lhs_author'), col('df2.author').alias('_rhs_author'),\

size(col('df1.hashes')).alias('total'), lit(0.0).alias('match'))

Рисунок 5 – Датафрейм df_template

Для подсчета совпадающих хэшей создадим датафрейм df_with_common_count, в котором создадим все возможные пары значений хэшей и отфильтруем их при несовпадении.

df_with_common_count = df_joined.select(df_joined['df1.author'], explode(col('df1.hashes')).alias('df1_expl'),df_joined['df2.author'],\ explode(col('df2.hashes')).alias('df2_expl')).filter('df1_expl = df2_expl')

6

Рисунок 6 – Датафрейм df_with_common_count

Нахождение коэффициента сходства

Для нахождения числа совпадающих хэшей для каждой пары файлов сгруппируем записи датафрейма из предыдущего этапа по левому и правому автору и применим функцию “count” к записям.

df_with_common_count = df_with_common_count.groupBy( col('df1.author').alias('lhs_author'), \ col('df2.author').alias('rhs_author')

).agg(count('df1_expl').alias('common')).orderBy(col('common').desc())

Рисунок 7 – Датафрейм df_with_common_count

7

Создадим датафрейм df_total_and_common для расчета коэффициента совпадения хэшей, используя правый JOIN для df_with_common_count и df_template по столбцам “lhs_author” и “rhs_author”. Также удалим столбцы,

содержащие избыточную информацию.

to_drop = ['rhs_author', 'lhs_author'] df_total_and_common =

df_with_common_count.alias('main').join(df_template,\ (df_template._lhs_author == df_with_common_count.lhs_author) & \

(df_template._rhs_author==df_with_common_count.rhs_author),'right'). drop(*to_drop)

При выполнении операции JOIN в столбце “common”, содержащем число совпадающих хэшей между файлами, образовались значения “NULL”, в случаях если между файлами не существует общих хэшей. Заменим эти значения на 0.

df_total_and_common = df_total_and_common.na.fill(value = 0)

Найдем коэффициент сходства, поделив значения столбца “common” на

“total”.

df_total_and_common = df_total_and_common.withColumn('match',col('common')

/ col('total')).orderBy(col('match').desc())

Рисунок 8 – Датафрейм df_total_and_common

Для прохождения тестов сформируем финальный датафрейм result_df и

вернем его из функции.

8

result_df = df_total_and_common.select( col('_lhs_author').alias('lhs_author'), col('_rhs_author').alias('rhs_author'), col('match')

).orderBy(col('match').desc()) return result_df

Запустим проверку программы. Как можно заметить по рисунку 9, тесты были успешно пройдены

Рисунок 9 – Результат прохождения тестов

Выводы.

В ходе выполнения лабораторной работы была написана программа,

реализующая алгоритм MOSS для обнаружения плагиата в исходном коде.

9

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]