Классификация машинным обучением списков строк в JAVA без какого-либо окружающего их контекста

У меня есть несколько списков строк, уже классифицированных как

<string>                        <tag>    

088 9102355                     PHONE NUMBER
091 910255                      PHONE NUMBER
...
Alfred St                       STREET
German St                       STREET
...
RE98754TO                       IDENTIFIER
AUX9654TO                       IDENTIFIER
...
service open all day long       DESCRIPTION
service open from 8 to 22       DESCRIPTION
...
[email protected]            EMAIL
[email protected]      EMAIL
...
www.serviceSite.com             URL
...
Florence                        CITY
...

с большим количеством строк на тег, и мне нужно создать java-программу, которая, учитывая новый список строк (предполагаемый все тот же тег), назначает вероятность для каждого тега в список. Программа должна быть полностью независимой от языка, и все знания должны исходить из списков строк с тегами, как описано выше.

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

Я решил использовать CRF (т. е. условное случайное поле), потому что нашел аналогичный подход, используемый в инструменте интеграции данных Karma, как описано в этом Статья, параграф 3.1, где семантическими типами являются мои теги.

Для работы с программой я загрузил Stanford Named Entity Recognizer (NER) и немного поиграл с JAVA API через NERDemo.java, обнаружив две проблемы:

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

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

Это правильный подход к проблеме? Есть ли способ использовать Stanford NER или другой JAVA API с CRF или другим подходящим алгоритмом машинного обучения для этого?

Обновлять

Мне удалось обучить классификатор CRF сначала с каждым словом, классифицированным независимо с тегом, и каждой группой слов, разделенных двумя запятыми (классифицированными как без тега (0)), затем с группой слов как с одним словом с символами подчеркивания, заменяющими пробелы, но У меня очень неутешительные результаты в небольшом тесте, который я сделал. Я не совсем понимаю, какие функции я должен включить, а какие исключить из тех, что описаны в javadoc NERFeatureFactory, учитывая, что они не могут иметь ничего общего с языком.

Обновление 2

Результаты теста начинают обретать смысл, я отделил каждую строку (помечая каждый токен) от других двумя новыми строками вместо ужасных двух запятых, помеченных 0, и я использовал Стэнфордский PTBTokenizer< /em> вместо того, что я сделал. Кроме того, я настроил функции, включив функции usePrev и useNext и используя суффикс/префикс Ngrams длиной до 6 символов и другие вещи.

Учебный файл с именем training.tsv имеет следующий формат:

rt05201201010to identifier


1442955884000 identifier


rt100005154602cv identifier


Alfred street
Street street


Robert street
Street street

и это флаги в файле свойств:

# these are the features we'd like to train with
# some are discussed below, the rest can be
# understood by looking at NERFeatureFactory
useClassFeature=true
useWord=true
# word character ngrams will be included up to length 6 as prefixes
# and suffixes only 
useNGrams=true
noMidNGrams=true
maxNGramLeng=6
usePrev=true
useNext=true
useTags=false
useWordPairs=false
useDisjunctive=true
useSequences=false
usePrevSequences=true
useNextSequences=true
# the next flag can have these values: IO, IOB1, IOB2, IOE1, IOE2, SBIEO
entitySubclassification=IO
printClassifier=HighWeight
cacheNGrams=true
# the last 4 properties deal with word shape features
useTypeSeqs=true
useTypeSeqs2=true
useTypeySequences=true
wordShape=chris2useLC

Однако я обнаружил другую проблему: мне удалось обучить только 39 меток по 100 строк в каждой, хотя у меня около 150 меток с более чем 1000 строками в каждой, но даже в этом случае обучение занимает около 5 минут, и если я немного увеличу эти числа, это выдает ошибку Java Heap Out of Memory Error.

Есть ли способ увеличить эти числа с помощью одного классификатора? Не лучше ли обучить 150 (или меньше, может быть, один с двумя или тремя метками) маленьких классификаторов и потом объединить их? Нужно ли мне тренироваться с более чем 1000 строками для каждой метки или я могу остановиться на 100 (возможно, выбрав их совершенно разными)?


comment
Вы должны определить вероятность появления каждого из предоставленных тегов на основе количества наблюдаемых образцов? Это не проблема машинного обучения. Требуется ли классифицировать список строк как тег? Мне непонятно, как вы говорите, что вас не интересует тег, данный классификатором.   -  person John    schedule 17.10.2015
comment
@John, я написал это, потому что мне нужно иметь несколько вариантов для одной строки из-за перекрытия классов, например, библиотека может быть СЛУЖБОЙ или МЕСТОМ, и если я использую только один классификатор для всех тегов, это дает мне только один ответ , поэтому вместо этого я должен смотреть на вероятности.   -  person learningTask    schedule 17.10.2015
comment
@John Чтобы ответить на ваши вопросы: необходимо классифицировать список строк как тег, но окончательная классификация производится пользователем из-за этого перекрытия. Я не смотрю на вероятность возникновения, я должен смотреть на структуру помеченных укусов.   -  person learningTask    schedule 17.10.2015


Ответы (1)


Первое, о чем вы должны знать, это то, что теггеры (линейные цепочки) CRF не предназначены для этой цели. Они пришли как очень хорошее решение для прогнозирования на основе контекста, то есть когда у вас есть слова до и после именованных объектов, и вы ищете подсказки в ограниченном окне (например, 2 слова до/после текущего слова). Вот почему вам пришлось вставить двойные строки: чтобы разграничить предложения. Они также обеспечивают согласованность между тегами, связанными со словами, что действительно хорошо в вашем случае.

Теггер CRF должен работать, но с дополнительными затратами на этапе обучения, которых можно было бы избежать, используя более простые (максимальная энтропия, SVM), но все же точные методы машинного обучения. В Java для вашей задачи разве Weka не будет лучшим решением? Я бы также посчитал, что пометка BIO не имеет отношения к вашему делу.

Какое бы программное обеспечение/кодирование вы ни использовали, неудивительно, что ngram на уровне символов дает хорошие улучшения, но я считаю, что вы можете добавить специальные функции. Например, поскольку важны морфологические подсказки (наличие «@», прописных букв или цифр), вы можете использовать коды (см. ссылку [1]), которые являются очень удобным методом описания строк. Вы также, скорее всего, получите лучшие результаты, используя списки имен (лексикон), которые могут быть активированы в качестве дополнительных функций.

[1] Алгоритмы ранжирования для извлечения именованных объектов: бустинг и персептрон с голосованием (Майкл Коллинз, 2002 г.)

person eldams    schedule 18.10.2015
comment
спасибо за ответ, я понимаю, что CRF не предназначен для этого, но я выбираю этот метод, потому что моя проблема имеет аналогичную предысторию той, что описана в статье о карме, связанной с моим вопросом. Я выбираю Stanford NER, потому что мне кажется, что это самая простая и удобная библиотека с CRF, я думаю, что у Weka ее нет. Мне кажется сложным использовать список имен и быть независимым от языка (по крайней мере, для западных языков). Есть ли у вас какие-либо предложения по выбору функции, если вместо этого я выберу классификатор SVM? как выбрать веса в этом случае? - person learningTask; 20.10.2015
comment
Что касается SVM, я не уверен, что выбор функций или выбор весов имеют решающее значение: либо машинное обучение справится с этим, либо вы потратите время на точную настройку процедуры обучения (забавно, но не всегда эффективно). Пытались ли вы внедрить некоторые специальные средства обнаружения подсказок (например, как обычно записываются телефонные номера, адреса, URL-адреса, количество слов в выражении), при необходимости используя регулярное выражение или частичные лексиконы (имена, части адреса и т. д.), и предоставить их как дополнительные возможности к SVM/CRF? Разработка признаков часто требует более точного описания того, какой критерий можно использовать для различения классов. - person eldams; 23.10.2015