Быстрое извлечение терминологии из предложений

Я работаю в Text Mining, и моя работа сосредоточена на биомедицинских объектах (генах, белках, лекарствах и заболеваниях). Я хотел бы поделиться с вами некоторыми вопросами.

Теперь моя цель — найти биомедицинские объекты в биомедицинских текстах (из Medline) и с помощью словарей терминов я могу идентифицировать каждый найденный объект с помощью его уникального идентификатора.

Для хранения текста, словарей и результатов я использую MongoDB (база данных, отличная от SQL). Каждая аннотация разбита на предложения, и каждое предложение хранится в новой записи (со списком токенов, фрагментов и тегов частей речи). Чтобы найти сущности, я получаю все предложения и для каждого создаю регулярное выражение для каждого термина в словаре (на Python):

for term in dicitonary:
     matches = re.finditer(r'(' + term + ')', sentence)
     for m in matches:
          ini = m.start()
          end = m.end()
          result.append(ini, end, dictionary.get_identification[term])

Но это очень медленно, у меня есть несколько подмножеств из 150 000 аннотаций (> 1 000 000 предложений).

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

Я думаю, что моя проблема заключается в том, чтобы делать много регулярных выражений (у меня есть словарь с 300 000 статей) для каждого предложения, потому что мне нужно найти термины в предложении. Как решить эту проблему без алгоритма машинного обучения? А с алгоритмами ML? Теперь я могу гибко менять язык программирования, базы данных...

Спасибо большое!!!

С уважением,

Алекс.


person nathan    schedule 19.07.2012    source источник
comment
На что следует обратить внимание: для Python уже доступна некоторая обработка NL: NLTK 2.0. На PyCon/India был даже разговор о текстовые сообщения MedLine. Вы можете рассмотреть возможность использования NLTK вместо развертывания собственного решения.   -  person Vinay    schedule 19.07.2012
comment
@Vinay: проблема с NLTK в том, что он довольно медленный. (Я не против этого, на самом деле я способствовал этому, но, поскольку ОП просит оптимизации, это не первое, что приходит на ум.)   -  person Fred Foo    schedule 20.07.2012


Ответы (1)


Вместо создания одного RE для каждого term создайте один дизъюнктивный RE, который может поймать их все:

pattern = re.compile("(%s)" % "|".join(re.escape(term) for term in dictionary))

затем используйте pattern.finditer.

Что касается «как использовать машинное обучение», то это слишком широкий вопрос, ИМХО. Начните с поиска в Google «биомедицинского распознавания именованных объектов» — существует огромное количество литературы об этой проблеме и различных инструментах.

person Fred Foo    schedule 19.07.2012
comment
ОК Спасибо, сегодня буду пробовать так. Я заменяю знаки препинания пробелами в предложениях (можно 2 или 3 знака препинания вместе), тогда, если терм состоит из нескольких слов, мое регулярное выражение '('+\s*.join(term.split())+' )', тогда с вашим кодом это будет: pattern = re.compile("(%s)" % "|".join(re.escape("\s*".join(term.split())) for term in dictionary)) - person nathan; 19.07.2012
comment
@nathan: будьте осторожны с re.escape, он удаляет значение * и т. д., поэтому вы захотите применить его внутри str.join. - person Fred Foo; 19.07.2012
comment
Затем pattern = re.compile("(%s)" % "|".join(re.escape(term).replace(" ", "\s*") for term in dictionary)) - person nathan; 19.07.2012
comment
Через несколько часов напишу свой результат!!! Спасибо :D Но проблема в этом двусвязном, я не могу знать, какой термин соответствует сопоставлению с его идентификатором в моем словаре. - person nathan; 19.07.2012
comment
@nathan: finditer возвращает итератор по объектам соответствия. Позвоните .group(0) по этому поводу. - person Fred Foo; 19.07.2012
comment
Мой словарь очень большой... OverflowError: regular expression code size limit exceeded Я могу попробовать разделить словарь на несколько шаблонов. - person nathan; 20.07.2012
comment
@nathan: никогда не слышал об этом. Используйте на свой риск :) - person Fred Foo; 20.07.2012
comment
С подмножеством терминов (~500) мой предыдущий алгоритм занимает 1540 секунд, а теперь с вашим предложением 222 секунды!!! Я... УУУУУУ!!! :D Я надеюсь, что новый пакет регулярных выражений сможет улучшить его еще больше!!! Еще раз спасибо @larsmans :) - person nathan; 20.07.2012
comment
Я попробовал тот же алгоритм в JAVA, компиляция быстрее, но этап распознавания занимает более 15 часов... Да, я работаю в Python для распознавания, но мне будет удобнее, если я буду использовать JAVA (т. другой код написан на JAVA). Могу ли я изменить свой код, чтобы адаптировать его? - person nathan; 27.07.2012
comment
@nathan: ну, конечно, но я недостаточно знаком с Java, чтобы знать, как это выразить эффективно. - person Fred Foo; 27.07.2012