- BrainTools - https://www.braintools.ru -
В апреле я уже писала [1]на Хабр о своем дипломном проекте — системе для проверки подлинности источников в научных публикациях. Тогда до защиты оставалось около двух месяцев, проект еще был в состоянии живого прототипа, а я пыталась понять, что из задуманного получится довести до нормального рабочего вида.
С тех пор проект успел заметно измениться.
Во-первых, я защитила диплом. На 5. Работу еще отметили как лучшую в день защиты, так что этот факт я тоже оставлю здесь — не каждый день такое случается.
Во-вторых, сама система стала намного ближе к настоящему инженерному инструменту, а не просто к учебному прототипу. В ней появились OCR, кэширование, offline-режим, корпусная оценка, классификация типов ошибок и отдельные ML-модули для разных задач.
И, пожалуй, самое важное: после защиты стало еще понятнее, что формально диплом закончился, а сама задача — нет. Чем лучше становилась система, тем сильнее проявлялись сложные места: PDF, OCR, плохое оформление, неполные метаданные, русскоязычные источники, внешние API и вечное «источник не найден — это ошибка [2] системы или источника правда не существует?».
Эта статья — не отчет в стиле «я все сделала, можно расходиться». Скорее это попытка спокойно разобрать, что получилось, что пришлось переделать, какие результаты удалось получить и почему проверка библиографии оказалась гораздо менее скучной задачей, чем кажется на первый взгляд.
Тема моей ВКР звучала так:
«Разработка системы автоматической проверки подлинности источников в научных публикациях с использованием методов машинного обучения»
Если перевести с дипломного языка на человеческий, задача была такой: система получает научный [3] документ, находит в нем список литературы, разбирает каждую библиографическую запись, проверяет, существует ли источник, сверяет данные с внешними базами и возвращает не просто «найдено / не найдено», а более полезный результат.
Например:
источник подтвержден;
источник, скорее всего, существует, но данных недостаточно;
источник не удалось подтвердить;
источник найден, но в записи есть ошибки;
запись плохо разобрана и требует ручной проверки.
В начале мне казалось, что основная сложность будет в DOI и URL. Логика [4] выглядела простой: нашли DOI, отправили запрос, получили ответ, сделали вывод.
На практике оказалось, что DOI — это не начало проверки, а где-то середина. До него еще нужно извлечь текст из PDF, найти список литературы, убрать лишние колонтитулы, разделить общий блок на отдельные записи, распарсить авторов, название, год и журнал, а потом еще понять, не исказился ли смысл на этапе извлечения.
Первая версия проекта была довольно линейной:
документ
-> извлечение текста
-> список литературы
-> отдельные записи
-> DOI / URL
-> внешняя проверка
-> статус
Сейчас пайплайн стал подробнее и устойчивее.
Система принимает PDF и DOCX через веб-интерфейс, извлекает текст, использует OCR для страниц без нормального текстового слоя, удаляет повторяющиеся шапки и футеры, ищет библиографический блок не только по очевидным заголовкам вроде «Литература» или References, разбивает список на отдельные записи и нормализует текст.
Отдельная часть работы — обработка шума. В реальных документах DOI может быть разорван переносом строки, URL может сломаться из-за форматирования, а OCR иногда превращает нормальный текст в набор похожих символов. Поэтому система отдельно нормализует DOI, URL, пробелы, кавычки, смешение кириллицы и латиницы, а также пытается учитывать типичные OCR-искажения.
После этого запись разбирается на поля: авторы, название, год, журнал или издатель, том, номер, страницы, DOI, URL и другие идентификаторы.
Дальше начинается проверка. Система использует DOI resolver, проверяет URL, ищет данные в Crossref, OpenAlex, Wikidata, ORCID, PubMed, Google Scholar и через обычный веб-поиск. Чтобы не дергать внешние сервисы бесконечно, появился постоянный SQLite-кэш. Еще добавился offline-режим: в нем система работает только с уже сохраненными результатами и не зависит от доступности внешних API.
Но главное изменение даже не в количестве источников проверки. Главное — система теперь пытается объяснить, что именно не так с записью.
Она выделяет разные типы проблем:
ошибка DOI;
ошибка URL;
несовпадение авторов;
несовпадение названия;
несовпадение года;
несовпадение журнала или издателя;
риск OCR;
риск некорректного парсинга.
Это оказалось важнее, чем я думала в начале. Пользователю мало увидеть красный статус. Ему нужно понять причину: источник не существует, DOI записан с ошибкой, год не совпадает, сервис не ответил или система просто не уверена в результате разбора.
После нескольких месяцев работы я стала намного осторожнее относиться к выводу «DOI не найден — значит источник фейковый».
В реальности это так не работает.
У нормального источника может не быть DOI. DOI может быть указан с ошибкой. Он может быть разорван переносом строки. После OCR он может превратиться во что-то почти похожее, но уже невалидное. URL может не открываться, хотя сама статья существует. Внешний сервис может временно не ответить. А русскоязычные источники часто вообще не вписываются в удобный сценарий «нашли DOI и успокоились».
Поэтому система смотрит не на один признак, а на набор сигналов.
Она проверяет:
есть ли DOI;
резолвится ли DOI;
есть ли URL;
открывается ли URL;
найден ли источник во внешних каталогах;
совпадает ли название;
похожи ли авторы;
не конфликтует ли год;
есть ли устойчивое совпадение по метаданным, даже если идентификатора нет.
Только после этого формируется итоговый статус.
Например, если DOI отсутствует, но источник найден по названию и авторам, это не провал, а скорее likely_verified.
Если URL открывается, но метаданные больше нигде не подтверждаются, это не полноценное подтверждение, а неопределенный случай.
Если источник найден, но год или авторы расходятся с канонической карточкой, система может сказать: источник, вероятно, настоящий, но сама библиографическая запись оформлена с ошибками.
Такой подход мне кажется более честным. Он ближе к тому, как проверяет человек: не по одному признаку, а по совокупности данных.
Итоговый пайплайн можно описать так:
PDF или DOCX
-> извлечение текста
-> OCR для страниц без нормального текстового слоя
-> удаление повторяющихся колонтитулов
-> поиск блока библиографии
-> разбиение на отдельные записи
-> нормализация текста
-> парсинг библиографических полей
-> оценка качества разбора
-> проверка DOI, URL и внешних каталогов
-> сопоставление с канонической записью
-> ML-оценка достоверности
-> классификация рисков
-> HTML-отчет и JSON
В интерфейсе пользователь видит не просто список ссылок. Для каждой записи формируется карточка: исходный текст, выделенные поля, статус проверки, качество разбора, найденные риски, маршрут проверки и причины, по которым система пришла к такому выводу.
Отдельно можно скачать итоговый JSON. Для диплома это было важно: хотелось сделать не только демонстрационный интерфейс, но и результат, который можно использовать дальше — например, в другой системе или в исследовательской обработке.
В первой версии проекта идея машинного обучения [5] звучала довольно широко: ML должен помогать оценивать достоверность источника.
После доработок стало понятно, что одной модели «на все случаи жизни» здесь недостаточно. В итоге я разделила задачу на две части.
Первая модель — source_trust. Она оценивает, насколько источник выглядит достоверным с учетом признаков записи и результатов проверок. В признаки входят наличие ключевых полей, качество парсинга, результаты проверки DOI и URL, количество подтверждений из внешних сервисов, совпадение названия, авторов, года, DOI и другие сигналы.
Вторая модель — reference_match. Она помогает понять, действительно ли найденная во внешнем каталоге карточка соответствует текущей библиографической записи.
Это отдельная проблема. Внешний поиск может вернуть похожую, но не ту публикацию. Особенно если у работы короткое название, много авторов, нет DOI или год отличается на один-два года.
Мне нравится, что ML в этой системе не пытается заменить все правила. Сначала идут понятные инженерные проверки: DOI, URL, внешние каталоги, совпадение полей. Потом из этих проверок собираются признаки. И только после этого модель помогает оценить более сложные или пограничные случаи.
То есть это не подход «нейросеть, разберись сама». Скорее наоборот: система сначала собирает максимум проверяемых фактов, а модель работает уже поверх них.
Мне не хотелось останавливаться на ощущении «вроде работает», поэтому я проверяла систему на нескольких уровнях.
На небольшой ручной разметке из 41 новой библиографической записи сегментация получилась идеальной: precision, recall и F1 равны 1.0. На этом наборе система правильно выделила границы всех записей.
Но такой результат нельзя воспринимать как доказательство, что задача решена. Маленькая ручная выборка показывает, что логика работает на конкретных примерах, но не гарантирует устойчивость на большом и шумном корпусе.
Поэтому я отдельно провела корпусную оценку.
На 500 PDF из PMC Open Access система нашла библиографический блок в 96,8% документов. В эталонных JATS XML было 32 910 ссылок, система извлекла 22 534 записи. Это уже более реалистичная картина: библиографический раздел обычно находится, но извлечь все записи из PDF без потерь все еще сложно.
Еще я проверяла систему на GROBID end-to-end evaluation dataset. Важно: GROBID я не использовала как сервис или модель, только брала датасет для сравнения с JATS/NLM XML.
На первых 100 документах из PMC_sample_1943 система обработала 100 PDF, нашла библиографию в 97% документов, извлекла 3 660 записей при 4 006 эталонных и автоматически сопоставила 3 307. End-to-end recall получился 82,55%, precision — 90,36%, F1 — 86,28%.
ML-часть оценивалась отдельно. Для модели source_trust F1 получился около 0.79. Для модели reference_match — около 0.91. На небольших reviewed-наборах результаты были выше, но к ним я отношусь осторожно: такие наборы полезны как sanity-check, но не заменяют большую независимую проверку.
В итоге получился ожидаемый, но важный вывод: маленькие тесты помогают убедиться, что система не разваливается, а корпусная оценка быстро показывает, где начинается реальный мир.
Система не стала волшебной кнопкой «проверьте всю библиографию без ошибок».
И это нормально.
Сканированные PDF все еще сильно зависят от качества OCR. Нестандартные списки литературы могут ломать разбиение на записи. Смешанные стили оформления усложняют парсинг. DOI и URL иногда повреждаются переносами, пробелами или OCR-шумом. Внешние сервисы имеют ограничения, иногда не отвечают, а иногда возвращают похожие, но неправильные кандидаты.
Отдельная сложность — автокоррекция.
Очень хочется, чтобы система не только находила ошибку, но и сразу предлагала исправленную запись. Но здесь легко навредить. Нельзя просто взять первую найденную карточку и заменить ей исходную ссылку. Можно сделать запись более красивой по форме, но фактически привязать ее к другой публикации.
Поэтому сейчас я рассматриваю автокоррекцию не как автоматическую замену, а как подсказку для человека: вот найденные канонические данные, вот поля, которые расходятся, вот что стоит проверить вручную.
В начале работы мне казалось, что human-in-the-loop — это скорее запасной вариант. Если алгоритм не уверен, тогда пусть человек посмотрит.
После диплома я стала воспринимать это не как запасной вариант, а как нормальную архитектурную идею.
В такой задаче система не должна изображать всезнающего судью. Ее задача — помогать автору, редактору, рецензенту или научному руководителю быстрее понять, где проблема.
Хороший результат — это не только «нашли фейковую ссылку». Хороший результат — это когда система экономит время: показывает подозрительные записи, объясняет причины, отделяет ошибки оформления от проблем подлинности и не объявляет источник несуществующим только потому, что один внешний сервис не ответил.
Поэтому статус unknown я теперь не считаю провалом. Иногда это самый честный ответ, который может дать система.
После защиты проект не хочется бросать. Наоборот, теперь стало понятнее, что именно нужно улучшать.
В первую очередь я бы хотела расширять ручную разметку, лучше тестировать русскоязычные источники и ГОСТ, аккуратнее работать с OCR, улучшать сопоставление кандидатов из внешних каталогов и развивать автокоррекцию так, чтобы она помогала, а не создавала новые ошибки.
Еще хочется доработать интерфейс под реальный сценарий проверки: чтобы пользователь мог быстро пройтись по подозрительным записям, увидеть причины, принять или отклонить предложенную правку и выгрузить итоговый отчет.
Сейчас я все меньше думаю об этом как о дипломном проекте и все больше — как о прикладном инструменте, который действительно может быть полезен при работе с научными текстами.
Когда я выбирала тему про проверку списка литературы, она казалась довольно аккуратной и даже немного скучной. Источники, DOI, библиография, оформление — звучит как техническая задача на периферии научной работы.
В итоге внутри оказались PDF-парсинг, OCR, NLP, поиск, сопоставление сущностей, внешние API, машинное обучение, объяснимость решений и постоянный инженерный вопрос: где можно автоматизировать, а где лучше честно остановиться и показать результат человеку.
Я защитила диплом, получила 5, услышала хорошие отзывы и могла бы поставить точку.
Но точка как-то не ставится.
Система уже не просто идея для ВКР. Это рабочий прототип, который умеет находить библиографию, разбирать записи, проверять источники, классифицировать риски и объяснять, почему конкретная ссылка выглядит надежной или сомнительной.
Она все еще ошибается. Ей нужны доработки. Она не закрывает всю боль [6] научной библиографии.
Но, кажется, она уже делает главное: помогает не верить ссылке только потому, что она выглядит убедительно.
Автор: varvaratikh
Источник [7]
Сайт-источник BrainTools: https://www.braintools.ru
Путь до страницы источника: https://www.braintools.ru/article/32649
URLs in this post:
[1] я уже писала : https://habr.com/ru/articles/1018664/
[2] ошибка: http://www.braintools.ru/article/4192
[3] научный: http://www.braintools.ru/article/7634
[4] Логика: http://www.braintools.ru/article/7640
[5] обучения: http://www.braintools.ru/article/5125
[6] боль: http://www.braintools.ru/article/9901
[7] Источник: https://habr.com/ru/articles/1055620/?utm_campaign=1055620&utm_source=habrahabr&utm_medium=rss
Нажмите здесь для печати.