Усовершенствование алгоритма обнаружения признаков

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

•          Не считая слова, записанные заглавными и строчными буквами, совершенно различными, признать наличие большого количества «кричащих» слов признаком.

•          Использовать помимо отдельных слов еще и словосочетания.

•          Собирать дополнительную метаинформацию, например, о том, кто отправил письмо или в какую категорию была помещена запись блога, и помечать, что это именно метаданные.

•          Сохранять URL и числа неизменными.

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

Класс classifier может принять в качестве getfeatures любую функцию и применять ее к предъявляемым образцам. Он ожидает лишь, что функция вернет список или словарь выделенных из образца признаков. В силу общности природы классификатора вы можете написать функцию, которая работает с более сложными типами, чем строки. Например, для классификации записей в блоге можно придумать функцию,

которая принимает всю запись целиком, а не только извлеченный из нее текст, и вставляет аннотации о том, откуда взялось каждое слово. Можно также выбирать пары слов из тела текста и отдельные слова из темы. По всей видимости, разбивать на части поле creator бессмысленно, так как сообщения от некоего «Джона Смита» ничего не скажут о сообщениях какого-нибудь другого «Джона».

Добавьте в файл feedfilter.py следующую функцию выделения признаков. Обратите внимание, что она ожидает на входе всю полученную из канала запись, а не просто строку:

def entryfeatures(entry):

splitter=re.compile(‘\\W*’) f={}

#       Извлечь и аннотировать слова из заголовка titlewords=[s.lower( ) for s in splitter.split(entry[‘title’]) if len(s)>2 and len(s)<20]

for w in titlewords: f[‘Title:’+w]=1

#       Извлечь слова из резюме

summarywords=[s.lower( ) for s in splitter.split(entry[‘summary’]) if len(s)>2 and len(s)<20]

#       Подсчитать количество слов, написанных заглавными буквами uc=0

for i in range(len(summarywords)): w=summarywords[i] f[w]=1

if w.isupper( ): uc+=1

# Выделить в качестве признаков пары слов из резюме if i<len(summarywords)-1: twowords=’ ‘.join(summarywords[i:i+1]) f[twowords]=1

#       Оставить информацию об авторе без изменения f[‘Publisher:’+entry[‘publisher’]]=1

#       UPPERCASE – специальный признак, описывающий степень "крикливости" if float(uc)/len(summarywords)>0.3: f[‘UPPERCASE’]=1

return f

Эта функция извлекает слова из заголовка и резюме так же, как написанная ранее функция getwords. Все слова из заголовка она рассматривает как отдельные признаки. Слова из резюме тоже помещаются в список слов, но дополнительно признаками считаются пары соседних слов. Информация об авторе трактуется как неделимый признак. Напоследок функция подсчитывает количество слов, написанных заглавными буквами. Если их доля больше 30% от общего числа слов, то функция добавляет в список специальный признак UPPERCASE. В отличие

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

Если вы хотите применить новую версию совместно с функцией filterfeed, то последнюю придется изменить, так чтобы она передавала записи непосредственно классификатору, а не функции fulltext. Достаточно внести следующие модификации в конце ее кода:

#  Напечатать наилучшую гипотезу о текущей категории print ‘Гипотеза: ‘+str(classifier.classify(entry))

#  Попросить пользователя ввести правильную категорию и обучиться

#  на его ответе

cl=raw_input(‘Enter category: ‘) classifier.train(entry,cl)

Теперь можно инициализировать классификатор, так чтобы для выделения признаков он пользовался функцией entryfeatures:

>>> reload(feedfilter)

<module ‘feedfilter’ from ‘feedfilter.py’>

>>> cl=docclass.fisherclassifier(feedfilter.entryfeatures)

>>> cl.setdb(‘python_feed.db’) # Только если используется версия для СУБД

>>> feedfilter.read(‘python_search.xml’,cl)

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

Вы можете следить за любыми ответами на эту запись через RSS 2.0 ленту. Вы можете оставить ответ, или trackback с вашего собственного сайта.

Оставьте отзыв

XHTML: Вы можете использовать следующие теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

 
Rambler's Top100