StanfordCoreNLP является золотым стандартом в обработке языков и достаточной причиной для всех, кто серьезно занимается обработкой естественного языка, вычислительной лингвистикой или анализом текста, рассмотреть язык JVM. В этом руководстве рассказывается, как настроить и запустить минимальную функцию синтаксического анализа StanfordCoreNLP с помощью Clojure, функционального Lisp для JVM.

Настраивать

Поскольку StanfordCoreNLP — это не один .jar файл, а целый их набор, я рекомендую использовать для этого проекта lein-resource-expand. Это позволяет вам указать каталог, в котором расположены все файлы StanfordCoreNLP .jar, и использовать нотацию glob (например: mypath/CoreNLP/*.jar), чтобы выбрать их все. В противном случае первым шагом будет добавление файлов StanfordCoreNLP в путь к ресурсам.

В Лейненгене это выглядит примерно так:

(comment with resource expand!) :resource paths ["mypath/myjars/stanford-corenlp-full-2018"]

Первые шаги

После того, как вы настроили проект и .jars на своем пути к ресурсам, пришло время запустить CoreNLP.

Подход CoreNLP заключается в настройке конвейеров анализа, а затем применении этих конвейеров к аннотациям. Итак, наша задача — перенести эти классы Java в Clojure.

Для этого нам просто нужно инициировать класс StanfordCoreNLP с некоторыми свойствами, указывающими, какие аннотации применять.

(def myProps (java.util.Properties.)) (. myProps setProperty "annotators" "tokenize, ssplit, pos") (def nlPipe (edu.stanford.nlp.pipeline.StanfordCoreNLP. myProps))

Здесь мы создали свойства myProps, настроили их для обработки токенизации, разделения предложений и тегов частей речи — здесь доступен полный список аннотаторов — и использовали их для запуска nlPipe, нашего конвейера НЛП.

Затем для анализа текста мы просто создаем объект аннотации и аннотируем его с помощью нашего конвейера nlPipe.

(def sentences (edu.stanford.nlp.pipeline.Annotation. "I'll meet you by the Sample Gates. Do you know where that is?")) (.annotate nlPipe sentences) (.jsonPrint nlPipe sentences *out*)

Если вы зашли так далеко, вы должны увидеть кучу JSON, напечатанных в вашем терминале. Мы сказали конвейеру аннотировать наш объект аннотации и распечатать результаты в JSON. Если вы не хотите, чтобы ваши данные были в формате JSON, вы можете ознакомиться с документацией о том, как вернуть эти данные различными способами.

Становимся более функциональными

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

(defn pipe2JSON [pipeline t] (let [txt (.process pipeline t)] (let [buffer (java.io.StringWriter.)] (.jsonPrint pipeline txt buffer) (json/parse-string (.toString buffer)))))

А затем давайте продемонстрируем это, распечатав теги части речи для первого предложения:

(let [a (pipe2JSON nlpipe "I'll meet you by the Sample Gates. Do you know where that is?") ] (println (map (fn [x] (get x "pos")) (get (get (get a "sentences") 0)"tokens"))))

Здесь наша функция pipe2JSON берет конвейер и применяет его к строке, JSON-печатает эту строку в объект, который мы затем превращаем в знакомый Clojure PersistentArrayMap.

Более…

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

Код этого руководства доступен на моем GitHub

Первоначально опубликовано на www.jtwolohan.com.