Мой Maxent Classifier отлично работает с алгоритмом gis, но не работает с алгоритмом iis. Он не выдает никаких ошибок, просто некоторые предупреждения

Я пытаюсь внедрить классификатор Maxent, но столкнулся с проблемой при использовании алгоритма iis. Следующий код отлично работает для алгоритма gis.

import nltk
from nltk.classify import MaxentClassifier, accuracy
from featx import split_label_feats, label_feats_from_corpus
from nltk.corpus import movie_reviews
from nltk.classify import megam
from openpyxl import load_workbook
from featx import bag_of_non_words  
from nltk.tokenize import word_tokenize
movie_reviews.categories()
lfeats = label_feats_from_corpus(movie_reviews)

lfeats.keys()
train_feats, test_feats = split_label_feats(lfeats)
me_classifier = nltk.MaxentClassifier.train(train_feats, algorithm='iis', trace=0, max_iter=3)
print accuracy(me_classifier, test_feats)

Я работаю на машине WIN32, и приведенный выше код взят из книги NLTK Джейкоба Перкинса. Выброшенное им предупреждение

C:\Python27\lib\site-packages\nltk\classify\maxent.py:1308: RuntimeWarning: invalid value encountered in multiply
  sum1 = numpy.sum(exp_nf_delta * A, axis=0)
C:\Python27\lib\site-packages\nltk\classify\maxent.py:1309: RuntimeWarning: invalid value encountered in multiply
  sum2 = numpy.sum(nf_exp_nf_delta * A, axis=0)
C:\Python27\lib\site-packages\nltk\classify\maxent.py:1315: RuntimeWarning: invalid value encountered in divide
  deltas -= (ffreq_empirical - sum1) / -sum2

И тут комп зависает. Так что приходится останавливать выполнение.

.


person Abhishek Sharma    schedule 02.12.2014    source источник
comment
откуда featx?   -  person alvas    schedule 02.12.2014
comment
Он содержит 3 функции, а именно split_label_feats (для разделения меток на обучающие и тестовые функции), label_feats_from_corpus (для разделения экземпляров на метки pos и neg) и bag_of_non_words (для удаления незначащих слов). Я не думаю, что ошибка связана с featx, иначе мой код не работал бы для алгоритма gis. Он работает с алгоритмом gis, но не с алгоритмом iis.   -  person Abhishek Sharma    schedule 02.12.2014
comment
дополнил свой ответ =)   -  person alvas    schedule 03.12.2014


Ответы (1)


Во-первых, то, как вы импортируете несортированные библиотеки, слишком запутанно. Также есть много неиспользованного импорта. После некоторого поиска в Google, давайте сократим импорт и придерживаемся этого:

from collections import defaultdict

import nltk
from nltk.classify import MaxentClassifier, accuracy
from nltk.corpus import movie_reviews

Затем я обнаружил, что featx — это пример модуля, который Джейкоб Перкинс использовал для своей книги, это лучший источник (https://github.com/sophist114/Python/blob/master/EmotionAnalysis.py). Итак, давайте вот документированная версия с некоторыми пояснениями того, что делают функции:

def bag_of_words(words):
    """
    Change a document into a BOW feature vector represented by a dict object.
    """
    return dict([(word, True) for word in words])


def label_feats_from_corpus(corp, feature_detector=bag_of_words):
    """
    Change the corpus into a feature matrix. Sometimes the proceess is 
    known as vectorization. The default is the use BOW features.
    """
    label_feats = defaultdict(list)
    for label in corp.categories():
        for fileid in corp.fileids(categories=[label]):
            feats = feature_detector(corp.words(fileids=[fileid]))
            label_feats[label].append(feats)
    return label_feats


def split_label_feats(lfeats, split=0.75):
    """
    Splits corpus into train and test portion.
    This module is used after using `label_feats_from_corpus`.
    """
    train_feats = []
    test_feats = []
    for label, feats in lfeats.iteritems():
        cutoff = int(len(feats) * split)
        train_feats.extend([(feat, label) for feat in feats[:cutoff]])
        test_feats.extend([(feat, label) for feat in feats[cutoff:]])
    return train_feats, test_feats

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

# Extract features from corpus and for each document label it with the appropriate labels. 
label_feats = label_feats_from_corpus(movie_reviews)

посмотрим, что мы получим после вызова label_feats_from_corpus:

for label in label_feats:
    for document in label_feats[label]: 
        print label, document
        break
    break

[вне]:

neg {u'all': True, u'concept': True, u'skip': True, u'go': True, u'seemed': True, u'suits': True, u'presents': True, u'to': True, u'sitting': True, u'very': True, u'horror': True, u'continues': True, u'every': True, u'exact': True, u'cool': True, u'entire': True, u'did': True, u'dig': True, u'flick': True, u'neighborhood': True, u'crow': True, u'street': True, u'video': True, u'further': True, u'even': True, u'what': True, u'hide': True, u'giving': True, u'new': True, u'ever': True, u'here': True, u'understanding': True, u'entertain': True, u'studio': True, u'others': True, u'kudos': True, u'weird': True, u'makes': True, u'explained': True, u'rarely': True, u'plot': True, u'fed': True, u'disappearances': True, u'from': True, u'would': True, u'&': True, u'two': True, u'music': True, u'films': True, u'themselves': True, u'until': True, u'more': True, u'teen': True, u'clue': True, u'stick': True, u'given': True, u'me': True, u'this': True, u'package': True, u'movies': True, u'making': True, u'my': True, u'give': True, u'fuck': True, u'want': True, u'sense': True, u'!': True, u'holds': True, u'write': True, u'how': True, u'hot': True, u'stir': True, u'okay': True, u'beauty': True, u'mess': True, u'overall': True, u'after': True, u'coming': True, u'such': True, u'guys': True, u'types': True, u'a': True, u'downshifts': True, u'chasing': True, u'redundant': True, u'so': True, u'enter': True, u'playing': True, u'executed': True, u'over': True, u'insight': True, u'years': True, u'still': True, u'its': True, u'before': True, u'thrilling': True, u'somewhere': True, u',': True, u'actually': True, u'meantime': True, u'production': True, u'main': True, u'might': True, u'then': True, u'good': True, u'break': True, u'they': True, u'half': True, u'not': True, u'now': True, u'always': True, u'didn': True, u'arrow': True, u'mean': True, u'bentley': True, u'generation': True, u'idea': True, u'engaging': True, u'happen': True, u'out': True, u"'": True, u'since': True, u'7': True, u'got': True, u'highway': True, u'shows': True, u'blair': True, u'turning': True, u'little': True, u'completely': True, u'shelves': True, u'starts': True, u'terribly': True, u'american': True, u'jumbled': True, u'chopped': True, u'one': True, u'fantasy': True, u'visions': True, u'guess': True, u'"': True, u'2': True, u'too': True, u'wrapped': True, u'final': True, u'slasher': True, u'that': True, u'explanation': True, u'took': True, u'part': True, u'attempt': True, u'10': True, u'kind': True, u'scenes': True, u'feeling': True, u'and': True, u'mind': True, u'sad': True, u'have': True, u'need': True, u'seem': True, u'apparently': True, u'-': True, u'also': True, u'which': True, u'sure': True, u'normal': True, u'who': True, u'most': True, u'don': True, u'drive': True, u'ways': True, u'entertaining': True, u'review': True, u'came': True, u'ending': True, u'find': True, u'touches': True, u'craziness': True, u'(': True, u'should': True, u'only': True, u'going': True, u'pretty': True, u'joblo': True, u'folks': True, u'8': True, u'do': True, u'his': True, u'get': True, u'watch': True, u'feels': True, u'despite': True, u'him': True, u'bad': True, u'where': True, u'lazy': True, u'see': True, u'decided': True, u'are': True, u'sorta': True, u'movie': True, u'nightmare': True, u'3': True, u'unravel': True, u'melissa': True, u'correctly': True, u'flicks': True, u'we': True, u'packaged': True, u'nightmares': True, u'genre': True, u'20': True, u'memento': True, u'both': True, u'accident': True, u's': True, u'witch': True, u'point': True, u'character': True, u'whatever': True, u'tons': True, u'simply': True, u'church': True, u'throughout': True, u'decent': True, u'been': True, u'.': True, u'secret': True, u'life': True, u'kids': True, u'personally': True, u'look': True, u'these': True, u'plain': True, u'harder': True, u'apparitions': True, u'while': True, u'neat': True, u've': True, u'is': True, u'it': True, u'couples': True, u'someone': True, u'in': True, u'chase': True, u'different': True, u')': True, u'things': True, u'make': True, u'same': True, u'member': True, u'strange': True, u'9': True, u'party': True, u'applaud': True, u'drink': True, u'director': True, u'running': True, u'characters': True, u'off': True, u'i': True, u'salvation': True, u'well': True, u'obviously': True, u'edge': True, u'echoes': True, u'the': True, u'away': True, u'just': True, u'generally': True, u'elm': True, u'excites': True, u'seems': True, u'snag': True, u'wes': True, u'4': True, u'has': True, u'big': True, u'showing': True, u'five': True, u'know': True, u'world': True, u'bit': True, u'password': True, u'dreams': True, u'like': True, u'lost': True, u'audience': True, u't': True, u'looooot': True, u'because': True, u'deal': True, u'people': True, u'back': True, u'dead': True, u'unraveling': True, u'critique': True, u'confusing': True, u'for': True, u'bottom': True, u'/': True, u'does': True, u'assuming': True, u'?': True, u'be': True, u'although': True, u'by': True, u'on': True, u'about': True, u'oh': True, u'of': True, u'runtime': True, u'or': True, u'own': True, u'strangeness': True, u'into': True, u'down': True, u'your': True, u'her': True, u'there': True, u'start': True, u'way': True, u'biggest': True, u':': True, u'head': True, u'offering': True, u'but': True, u'taken': True, u'line': True, u'trying': True, u'with': True, u'he': True, u'up': True, u'us': True, u'problem': True, u'minutes': True, u'figured': True, u'doesn': True, u'an': True, u'as': True, u'girlfriend': True, u'mold': True, u'sagemiller': True, u'film': True, u'again': True, u'no': True, u'when': True, u'actors': True, u'you': True, u'really': True, u'dies': True, u'problems': True, u'ago': True}

Итак, мы получаем документ с меткой neg и для каждого слова в нашем документе мы видим, что ВСЕ слова истинны. На данный момент каждый документ содержит только ту функцию (то есть слово), которая у него есть.

Давайте двигаться дальше:

# Let's split the data up into train and test.
train_feats, test_feats = split_label_feats(label_feat) 

Теперь мы видим, что split_label_feats изменяет структуру значения ключа таким образом, что каждая итерация train_feats дает нам документ с кортежем (функции, метка)

for features, label in train_documents:
    label, features
    break

print len(train_documents)
print len(test_documents)
# Get the number of documents in movie_review corpus
num_docs_in_corpus = len(list(chain(*[movie_reviews.fileids(categories=[cat]) for cat in movie_reviews.categories()])))
print len(train_documents) + len(test_documents) == num_docs_in_corpus

[вне]:

1500
500
True

Таким образом, похоже, что ошибка может быть вызвана только вашими последними двумя строками кода, когда вы запускаете строку:

# To train the tagger.
me_classifier = nltk.MaxentClassifier.train(train_documents, algorithm='iis', trace=0, max_iter=3)

Вы получаете эти предупреждения, но обратите внимание, что код все еще строит модель !!!! Таким образом, это просто предупреждения из-за потери значимости, см. Что такое переполнение в C?

Создание классификатора занимает некоторое время, но не бойтесь, просто дождитесь его завершения и не ctr + c завершайте процесс python. Если вы завершите процесс, вы увидите следующее:

Training stopped: keyboard interrupt

Итак, давайте разберемся, почему возникает предупреждение, дано 4 предупреждения:

/usr/local/lib/python2.7/dist-packages/nltk/classify/maxent.py:1306: RuntimeWarning: overflow encountered in power
  exp_nf_delta = 2 ** nf_delta
/usr/local/lib/python2.7/dist-packages/nltk/classify/maxent.py:1308: RuntimeWarning: invalid value encountered in multiply
  sum1 = numpy.sum(exp_nf_delta * A, axis=0)
/usr/local/lib/python2.7/dist-packages/nltk/classify/maxent.py:1309: RuntimeWarning: invalid value encountered in multiply
  sum2 = numpy.sum(nf_exp_nf_delta * A, axis=0)
/usr/local/lib/python2.7/dist-packages/nltk/classify/maxent.py:1315: RuntimeWarning: invalid value encountered in divide
  deltas -= (ffreq_empirical - sum1) / -sum2

Все они указывают на одну и ту же функцию, используемую для расчета дельты в максимальной реализации NLTk, т.е. ="nofollow noreferrer">https://github.com/nltk/nltk/blob/develop/nltk/classify/maxent.py#L1208 . И вы обнаружите, что этот расчет дельты специфичен для алгоритма IIS (улучшенное итеративное масштабирование).

На этом этапе вам нужно узнать о машинном обучении и обучении с учителем, https://en.wikipedia.org/wiki/Supervised_learning

Чтобы ответить на ваш вопрос, потепление — это просто указание на то, что дельту трудно рассчитать в какой-то момент, но все же разумно иметь дело, возможно, из-за некоторых сверхмалых значений при расчете дельты. Алгоритм работает. Это не зависание, это тренировка.

Чтобы оценить изящную реализацию MaxEnt в NLTK, я предлагаю вам пройти этот курс https://www.youtube.com/playlist?list=PL6397E4B26D00A269 или более подробный курс по машинному обучению на странице https://www.coursera.org/course/ml

Обучение классификатора требует времени и вычислительной мощности, и после достаточно долгого ожидания вы должны увидеть, что он работает:

print accuracy(me_classifier, test_feats)

[вне]:

0.5

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

Кстати, не забудьте замариновать свой классификатор, чтобы вам не пришлось переучивать его в следующий раз, см. Сохранить наивный байесовский обученный классификатор в NLTK и -results-obtained">Выбор обученного классификатора дает результаты, отличные от результатов, полученных непосредственно из нового, но идентично обученного классификатора

Вот полный код:

from itertools import chain
from collections import defaultdict

import nltk
from nltk.classify import MaxentClassifier, accuracy
from nltk.corpus import movie_reviews

def bag_of_words(words):
    """
    Change a document into a BOW feature vector represented by a dict object.
    """
    return dict([(word, True) for word in words])


def label_feats_from_corpus(corp, feature_detector=bag_of_words):
    """
    Change the corpus into a feature matrix. Sometimes the proceess is 
    known as vectorization. The default is the use BOW features.
    """
    label_feats = defaultdict(list)
    for label in corp.categories():
        for fileid in corp.fileids(categories=[label]):
            feats = feature_detector(corp.words(fileids=[fileid]))
            label_feats[label].append(feats)
    return label_feats


def split_label_feats(lfeats, split=0.75):
    """
    Splits corpus into train and test portion.
    This module is used after using `label_feats_from_corpus`.
    """
    train_feats = []
    test_feats = []
    for label, feats in lfeats.iteritems():
        cutoff = int(len(feats) * split)
        train_feats.extend([(feat, label) for feat in feats[:cutoff]])
        test_feats.extend([(feat, label) for feat in feats[cutoff:]])
    return train_feats, test_feats


# Extract features from corpus and for each document label it with the appropriate labels. 
label_feats = label_feats_from_corpus(movie_reviews)
'''
for label in label_feats:
    for document in label_feats[label]: 
        print label, document
        break
    break
'''

# Let's split the data up into train and test.
train_documents, test_documents = split_label_feats(label_feats) 
'''
# Now we see that the `split_label_feats` change the key value structure such that each iteration of train_feats gives us a document with a tuple of the (features, label)
for features, label in train_documents:
    print label, features
    break

print len(train_documents)
print len(test_documents)
# Get the number of documents in movie_review corpus
num_docs_in_corpus = len(list(chain(*[movie_reviews.fileids(categories=[cat]) for cat in movie_reviews.categories()])))
print len(train_documents) + len(test_documents) == num_docs_in_corpus
'''

# To train the tagger.
me_classifier = nltk.MaxentClassifier.train(train_documents, algorithm='iis', trace=0, max_iter=3)
print accuracy(me_classifier, test_feats)
person alvas    schedule 02.12.2014
comment
Можно ли как-нибудь использовать мегаалгоритм на машине WIN32? Я слышал, что это быстрее, чем алгоритм iis. - person Abhishek Sharma; 03.12.2014
comment
это тоже лучше, у меня нет с собой Windows-машины. так что это сложно проверить, но это не должно быть слишком сложно, просто нужно загрузить бинарный файл мегама и связать его с NLTK. - person alvas; 03.12.2014