Работа с текстовыми данными в scikit-learn (перевод документации) — часть 2

    Данная статья представляет собой перевод главы, обучающей работе с текстовыми данными, из официальной документации scikit-learn. Начало статьи вы можете прочесть в части 1.

    Обучение классификатора


    Теперь, когда мы выделили признаки, можно обучать классификатор предсказывать категорию текста. Давайте начнем с Наивного Байесовского классификатора, который станет прекрасной отправной точкой для нашей задачи. scikit-learn включает в себя несколько вариантов этого классификатора. Самый подходящий для подсчета слов — это его поли номинальный вариант:

    >>> from sklearn.naive_bayes import MultinomialNB
    >>> clf = MultinomialNB().fit(X_train_tfidf, twenty_train.target)


    Чтобы мы могли попытаться предсказать результаты на новом документе, нужно извлечь фичи (характерные признаки), используя почти такую же последовательность как и ранее. Разница состоит в том, используется метод transform вместо fit_transform из transformers, так как они уже были применены к нашей обучающей выборке:

    >>> docs_new = ['God is love', 'OpenGL on the GPU is fast']
    >>> X_new_counts = count_vect.transform(docs_new)
    >>> X_new_tfidf = tfidf_transformer.transform(X_new_counts)
    
    >>> predicted = clf.predict(X_new_tfidf)
    
    >>> for doc, category in zip(docs_new, predicted):
    ...     print('%r => %s' % (doc, twenty_train.target_names[category]))
    ...
    'God is love' => soc.religion.christian
    'OpenGL on the GPU is fast' => comp.graphics


    Создание конвейерной обработки


    Чтобы с цепочкой vectorizer => transformer => classifier было проще работать, в scikit-learn есть класс Pipeline, который функционирует как составной (конвейерный) классификатор:

    >>> from sklearn.pipeline import Pipeline
    >>> text_clf = Pipeline([('vect', CountVectorizer()),
    ...                      ('tfidf', TfidfTransformer()),
    ...                      ('clf', MultinomialNB()),
    ... ])

    Название vect, tfidf and clf (классификатор) выбраны нами произвольно. Мы рассмотрим их использование ниже, в главе grid search. Теперь обучим модель с помощью всего 1 команды:

    >>> text_clf = text_clf.fit(twenty_train.data, twenty_train.target)


    Оценка производительности при работе на тестовой выборке


    Оценка точности прогноза модели достаточно проста:

    >>> import numpy as np
    >>> twenty_test = fetch_20newsgroups(subset='test',
    ...     categories=categories, shuffle=True, random_state=42)
    >>> docs_test = twenty_test.data
    >>> predicted = text_clf.predict(docs_test)
    >>> np.mean(predicted == twenty_test.target)            
    0.834...

    Например, мы получили 83% точности. Давайте посмотрим, можем ли мы улучшить этот результат с помощью линейного метода опорных векторов (support vector machine (SVM)). Этот метод обычно считается лучшим из алгоритмов классификации текста (хотя, он немного медленнее чем наивный Байес). Мы можем сменить обучающуюся модель просто подсоединив другой объект классификации в наш конвейер:

    >>> from sklearn.linear_model import SGDClassifier
    >>> text_clf = Pipeline([('vect', CountVectorizer()),
    ...                      ('tfidf', TfidfTransformer()),
    ...                      ('clf', SGDClassifier(loss='hinge', penalty='l2',
    ...                                            alpha=1e-3, n_iter=5, random_state=42)),
    ... ])
    >>> _ = text_clf.fit(twenty_train.data, twenty_train.target)
    >>> predicted = text_clf.predict(docs_test)
    >>> np.mean(predicted == twenty_test.target)            
    0.912...

    scikit-learn также предоставляет утилиты для более детального анализа результатов:

    >>> from sklearn import metrics
    >>> print(metrics.classification_report(twenty_test.target, predicted,
    ...     target_names=twenty_test.target_names))
    ...                                         
                            precision    recall  f1-score   support
    
               alt.atheism       0.95      0.81      0.87       319
             comp.graphics       0.88      0.97      0.92       389
                   sci.med       0.94      0.90      0.92       396
    soc.religion.christian       0.90      0.95      0.93       398
    
               avg / total       0.92      0.91      0.91      1502
    
    
    >>> metrics.confusion_matrix(twenty_test.target, predicted)
    array([[258,  11,  15,  35],
           [  4, 379,   3,   3],
           [  5,  33, 355,   3],
           [  5,  10,   4, 379]])

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

    Настройка параметров для использования grid search


    Некоторые параметры мы уже посчитали, такие как use_idf в функции TfidfTransformer. Классификаторы, как правило, также имеют много параметров, например, MultinomialNB включает в себя коэффициент сглаживания alpha, а SGDClassifier имеет штрафной параметр alpha (метод штрафных функций), настраиваемую потерю и штрафные члены в целевой функции (см. раздел документации или используйте функцию подсказки Python, чтобы получить дополнительную информацию).
    Вместо поиска параметров различных компонентов в цепи, можно запустить поиск (методом полного перебора ) лучших параметров в сетке возможных значений. Мы опробовали все классификаторы на словах или биграммах, с или без idf, с штрафными параметрами 0,01 и 0,001 для SVM (метода опорных векторов):

    >>> from sklearn.grid_search import GridSearchCV
    >>> parameters = {'vect__ngram_range': [(1, 1), (1, 2)],
    ...               'tfidf__use_idf': (True, False),
    ...               'clf__alpha': (1e-2, 1e-3),
    ... }

    Очевидно, подобный поиск методом полного перебора может быть ресурсозатратным. Если в нашем распоряжении есть множество ядер процессора, мы можем запустить grid search, чтобы попробовать все комбинации параметров параллельно с параметром n_jobs. Если мы зададим этому параметру значение -1, grid search определит, как много ядер установлено, и задействует их все:

    >>> gs_clf = GridSearchCV(text_clf, parameters, n_jobs=-1)

    Экземпляр grid search ведет себя как обычная модель scikit-learn. Давайте запустим поиск на малой части обучающей выборки, чтобы увеличить скорость обработки:

    >>> gs_clf = gs_clf.fit(twenty_train.data[:400], twenty_train.target[:400])

    В результате применения метода fit на объекте GridSearchCV мы получим классификатор, который можно использовать для выполнения функции predict:

    >>> twenty_train.target_names[gs_clf.predict(['God is love'])]
    'soc.religion.christian'

    но с другой стороны, это очень большой и громоздкий объект. Мы можем все таки получить оптимальные параметры, изучая атрибут объекта grid_scores_, который является списком пар параметры\мера. Чтобы получить атрибуты мер, мы можем:

    >>> best_parameters, score, _ = max(gs_clf.grid_scores_, key=lambda x: x[1])
    >>> for param_name in sorted(parameters.keys()):
    ...     print("%s: %r" % (param_name, best_parameters[param_name]))
    ...
    clf__alpha: 0.001
    tfidf__use_idf: True
    vect__ngram_range: (1, 1)
    
    >>> score                                              
    0.900...

    Упражнения


    Чтобы выполнить упражнения, скопируйте содержание папки ‘skeletons’ в новую папку с названием ‘workspace’:

    % cp -r skeletons workspace

    ВЫ можете редактировать содержимое папки workspace, не боясь потерять исходные инструкции для упражнений.
    Затем откройте оболочку ipython и запустите незавершенный скрипт для упражнения:

    [1] %run workspace/exercise_XX_script.py arg1 arg2 arg3

    Если было вызвано исключение, используйте %debug, чтобы запустить аварийную ipdb сессию.
    Очистите реализацию и повторяйте, пока не решите задачу.
    В каждом упражнении файлы skeleton содержат все необходимые инструкции импорта, шаблоны кода для загрузки данных и примеры для кода для оценки точности предсказывания модели.

    Упражнения 1: Определение языка


    • Напишите конвейер — текстовый классификатор, используя специальную предобработку и CharNGramAnalyzer. В качестве обучающей выборки используйте статьи из Wikipedia.
    • Оцените производительность на любой тестовой выборке, не совпадающей с обучающей.

    ipython командная строка:
    %run workspace/exercise_01_language_train_model.py data/languages/paragraphs/


    Упражнение 2: Анализ предпочтений на основе отзывов фильмов


    • Напишите конвейер — текстовый классификатор для классификации отзывов о фильмах на положительные и отрицательные.
    • Подберите подходящий набор параметров, используя grid search.
    • Оцените производительность на тестовой выборке.

    ipython командная строка:
    %run workspace/exercise_02_sentiment.py data/movie_reviews/txt_sentoken/


    Упражнения 3: Утилита — текстовый классификатор в командной строке (консольное приложение)


    Используя результаты предыдущих упражнений и модуль cPickle стандартной библиотеки, напишите утилиту командной строки, которая определяет язык текста в stdin (ввод с клавиатуры) и определяет полярность (положительный или отрицательный), если текст написан на английском.

    Что дальше?


    В этой секции приведены некоторые советы, чтобы помочь вам глубже познакомиться с scikit-learn после прохождения упражнений:
    • +4
    • 23,9k
    • 3
    Поделиться публикацией

    Комментарии 3

      0
      Спасибо. Хорошая работа.

      Сейчас занимаюсь изучением классификации коротких текстов. Подскажите на каком свете сейчас обстоит работа с русскими текстами у данного решения(да и вообще языками отличными от en)? Буду благодарен, если броситесь ссылками.

        0
        В scikit-learn нет тренировочных выборок на русском, методы лемматизации и стемминга не работают, токенизация проходит. Для этих целей можно использовать АОТ или SnowballStemmer. Последний не всегда хорошо справляется.
          0
          Кстати, если будете пробовать на русских текстах, то при загрузке обучающей \ тестовой выборки нужно это указать. Например, если вы создаете выборку типа 20 newsgroups:
          train_data = load_files(".../path/container_folder", encoding = "cp1251")

        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

        Самое читаемое