У меня есть несколько списков строк, уже классифицированных как
<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, обнаружив две проблемы:
учебный файл для CRFClassifier должен иметь одно слово в строке, поэтому я не нашел способа классифицировать группы слов с помощью одного тега
Я не понимаю, должен ли я сделать один классификатор для каждого тега или один классификатор для всех, потому что одна строка может быть классифицирована с помощью 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 (возможно, выбрав их совершенно разными)?