Как я создал комплексное приложение для анализа текста за месяц

1656607337 kak ya sozdal kompleksnoe prilozhenie dlya analiza teksta za mesyacz

Джеффри Флинт

1*aIewSM1E9TbQvqxIvLy9jQ

Как это начиналось

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

Почему разработчик программного обеспечения не упрощает это, вместо того, чтобы нам знать R или Python?

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

Я научный сотрудник Лаборатории количественной критики (QCL) в UT Austin. Главные следователи предложили мне пройти курс. Этот курс, безусловно, помог мне усовершенствовать и открыть новые навыки обработки естественного языка (НЛП).

Ненароком я отложил этот вопрос на второй план, когда сосредоточился на других наборах инструментов и проектов. Во время посещения семинара по классическим исследованиям в Бостоне я заметил, что многие выражали разочарование из-за отсутствия более простых инструментов для анализа и визуализации текста.

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

Конечно, есть такие варианты как Voyant. Но нет доступных решений, предлагающих такие функции, как выделение именуемых объектов, тегирование части речи (POS), сегментацию слов из шумного текста и анализ настроений для людей без предварительного знания программирования. В сочетании с этим и вышеперечисленным, это усилило идею развернуть более простую программу для НЛП.

С чего начать?

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

Как только капитан сказал, что портативная электроника в порядке, я вынул свой ноутбук и приступил к работе. Я уверен, что парень, сидевший у меня, вероятно, думал, что я что-то сломал, проводя все свое время в консоли.

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

1*Iy5L74n4CgKbBY2acEMLrA

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

Мой входной код обычно состоит из:

  • Регистрация / Вход
  • Уведомления
  • Визуализация (Chart.js, Bootstrap Tables, Handsontable.js)
  • Маршрутизация

Другим подходом к сокращению времени разработки, особенно когда вы работаете над проектом самостоятельно, является использование готовых шаблонов администратора для пользовательского интерфейса. В разделе шаблонов веб-сайтов администратора Themeforest есть несколько отличных элементов интерфейса, которые я использую в своих проектах. Я снизил более 50% обычного времени разработки, используя предварительно созданные активы.

Разумеется, мне пришлось хорошо знать HTML, CSS и jQuery. Но поскольку эти объекты уже были разработаны, мне оставалось беспокоиться только о размещении и интеграции данных.

Мой выбор – Meteor.js. Meteor – это фреймворк JavaScript, который находится поверх Node.js. Я использую MongoDB в качестве своей базы данных и Python для трудных задач НЛП.

Для тех из вас, кто знаком с Meteor, я решил не включать только методы и вызовы для публикаций и подписок, а использовал динамический импорт для всех библиотек сторонних разработчиков, запущенных на клиенте. Это помогло повысить производительность. Я также использовал worker для любого клиентского кода, требующего манипулирования строками. Это позволило мне уменьшить размер пакета приблизительно до 500 КБ.

Я остановился на Textalytic для названия и защитил веб-сайт.

Ты думал, что это будет просто?

Я предполагал, что все это будет достаточно просто, поскольку мой опыт работы над наборами инструментов, связанных с НЛП, в лаборатории QCL. Но всегда бывают следующие моменты.

Я хотел, чтобы пользователи могли просматривать выделенные именуемые объекты в своем корпусе. Сначала мне пришлось получить быструю библиотеку, совместимую с JavaScript, чтобы извлекать именуемые объекты.

Сначала я использовал compromise.js. В известной степени это работало достаточно хорошо, но скорость относительно большого текста была чего-то желаемого.

Затем я остановился на SpaCy, но это было на Python. Мне никогда раньше не приходилось интегрировать два разных языка, поэтому я перешел в Stack Overflow для изучения.

После того, как SpaCy работал с JavaScript, я столкнулся с двумя проблемами со SpaCy. Во-первых, SpaCy не возвращает точных подсчетов.

Пользователи имели возможность просматривать частоту существительных, прилагательных, глаголов и т.д. SpaCy вернул бы 31 экземпляр «автомобиля», но во время ручного подсчета я получил 44.

Сначала у меня был дескриптор Python, который возвращал частоту существительных:

В конце концов, я решил просто вернуть необработанный массив имен существительных, а JavaScript вернул 10 самых популярных существительных.

Это привело к точным подсчетам для существительных:

Вторая проблема была связана с названными объектами. Большинство моделей анализа текста, если не все, не получат 100% точности для указанных объектов. Чтобы дополнить SpaCy, я импортировал обширный список именуемых объектов, взятых из WikiData, в MongoDB.

Текст запускается через SpaCy, возвращающий массив найденных объектов. Затем MongoDB создает большой массив из около 150 тысяч сущностей, который вместе с текстом посылается функции, выполняющей соответствие пределам слов. Учет регулярных выражений пунктуации и границ повлечет за собой много головных болей.

Эти два массива отфильтровываются, а повторяющиеся записи удаляются, чтобы получить окончательный массив сущностей. Этот метод казался самым быстрым, он возвращал результаты через 5 секунд.

Этот метод обеспечил лучшее покрытие для более точной, чем SpaCy 85,85%.

Можно ли проще, пожалуйста?

Многие учебники по задачам НЛП призывают пользователей предварительно обработать текст перед анализом. Я хотел, чтобы у пользователей был более простой подход.

С помощью Corpus Builder пользователи могут вводить, копировать и вставлять текст или выбирать файл из компьютера или Dropbox.

Предварительная обработка

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

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

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

Трансформация текста

Когда мы проходили курс анализа текста, казалось, что мы многое трансформировали текст, прежде чем начать тестировать различные модели.

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

Во время урока анализа текста пользователи должны были загружать текстовые файлы с Google Drive или загружать готовые корпуса из NLTK. Это заняло много времени, пока все загрузили и импортировали файлы.

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

Для продвинутых пользователей я хотел, чтобы у них были параметры, а не были привязаны к конфигурации по умолчанию. Я внедрил специальные стоп-слова, специальные списки самых распространенных слов и т.д. Некоторые пользователи могут захотеть искать частоту слов, заканчивающихся на «-ing», поэтому я также добавил это.

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

Не блокируйте петлю!

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

Сейчас я тестирую более сложные случаи, такие как висячие модификаторы, прямые объекты и параллельные структуры.

Производительность

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

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

Наконец-то я нашел Napa.js от Microsoft. Это было очень просто интегрировать, и мне не пришлось менять ни одну из своих функций.

Теперь приложение работало бесперебойно с большими корпусами, проанализированными несколькими пользователями. Однако всегда есть свое «но»!

При поиске с помощью корпусов, которые состояли из очень большого тела из ~500 тыс. слов, Python выдавал ValueError. SpaCy имеет установленное ограничение в 1 000 000 символов в одной строке, которое можно изменить. Конечно, я разбил корпус на части.

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

POS тегирование

Я знал, что я знал, что должен иметь в приложении часть меток речи, которая была визуализирована значимым образом. SpaCy без проблем вернул POS-теги для каждого слова в большом массиве объектов, но это было не полезно пользователю. Мне пришлось превратить этот массив в визуально приятный для пользователя формат.

Compromise.js имеет хороший формат для этого, из которого я черпал вдохновение.

Я поместил этот массив в цикл, который добавил цветные тэги на основе POS и превратил новый массив в строку и обновил страницу в следующее:

1*guZQY6nRijbY2OROxI2RPQ

Вывод

В течение месяца программа была в хорошем состоянии для выпуска. С тех пор я внес разные изменения для оптимизации и других настроек. Я стараюсь держаться подальше от сложения модулей npm, если мне этого не нужно. Все было написано на ванильном JavaScript, за исключением библиотек визуализации и уведомлений о тосте. Делая это, кодовая база становится компактнее, и мне не нужно беспокоиться о том, когда сопроводитель этого проекта собирается сделать x.

Ближе к концу этого проекта я стал думать:
«Кто воспользуется этим?»
«Действительно ли это приложение достаточно хорошее?»
«Я где-то напутался, и это будет навсегда запятнано?»

Я подавил эти мысли и подумал, что если это не удастся, я научился очень многому, чему, наверное, не научился бы, занимаясь чем-нибудь другим.

Вы можете потратить много времени, пытаясь оптимизировать каждую функцию. Я быстро научился отказываться от попытки писать функции в последнем синтаксисе ES. Однако я сосредоточился на выполнении разных функций, особенно на опыте пользователя.

Одной из лучших стратегий экономии времени было использование конвейера CI/CD Gitlab – и это бесплатно!

Вместо того чтобы вручную создавать пакет, останавливать службу, загружать и т.д., я просто сделал одну фиксацию в GitKraken. GitLab обрабатывает все остальное на сервере.

Существовала кривая обучения с настройкой NGINX с несколькими экземплярами, балансировкой нагрузки и фиксированными сессиями. Но существует так много ресурсов, которые помогут вам на этом пути, таких как freeCodeCamp, Stack Overflow и раздел блога Digital Ocean.

Я постоянно думаю о новых функциях, которые могут быть полезны пользователям. Подведение итогов документов, пользовательские модели машинного обучения и определение аргументов/позиции — это несколько функций, которые я планирую добавить в течение лета. Если вас интересует функция НЛП, которая может быть полезна, сообщите мне в разделе комментариев. Спасибо, что прочли!

Добавить комментарий

Ваш адрес email не будет опубликован.