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

от автора

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

Цель этой главы — это исследование некоторых из самых важных инструментов в scikit-learn на одной частной задаче: анализ коллекции текстовых документов (новостные статьи) на 20 различных тематик.
В этой главе мы рассмотрим как:

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

Инструкция по установке

Чтобы начать практическое занятие, описанное в данной главе, у вас должен быть установлен scikit-learn и все компоненты, от которых он зависит (numpy, Scipy).
Чтобы получить инструкцию по установке и рекомендации для разных ОС перейдите на эту страницу.
Локальную копию данного занятия вы можете найти в своей папке:
scikit-learn/doc/tutorial/text_analytics/
Теперь scikit-learn не устанавливается с папкой doc/ и прочим содержимым. Вы можете ее скачать с github.
Папка с обучающими примерами должна содержать следующие файлы и папки:

  • *.rst files — источник учебных документов, обработанных с помощью sphinx
  • data — папка для хранения наборов данных в процессе обучения
  • skeletons — образцы неполных скриптов для упражнений
  • solutions — решения упражнений

Также вы можете скопировать skeletons в новую папку в любое место на вашем жестком диске, названную sklearn_tut_workspace, где вы будете редактировать ваши собственные файлы для упражнений. Так изначальные skeletons останутся неизменными:

% cp -r skeletons work_directory/sklearn_tut_workspace

Алгоритмы машинного обучения нуждаются в данных. Зайдите в каждую подпапку $TUTORIAL_HOME/data и запустите оттуда скрипт fetch_data.py (для начала прочтите их).
Например:

% cd $TUTORIAL_HOME/data/languages % less fetch_data.py % python fetch_data.py

Загрузка 20 новостных наборов данных

Набор данных называется “Twenty Newsgroups”. Вот его официальное описание, взятое с сайта:

Данные «The 20 Newsgroups» — это коллекция примерно из 20000 новостных документов, разделенная (приблизительно) равномерно между 20 различными категориями. Насколько нам известно, изначально она собиралась Кеном Ленгом (Ken Lang), возможно, для его работы «Newsweeder: Learning to filter netnews» («Новостной обозреватель: учимся фильтровать новости из сети»), хотя он явно не заявлял об этом. Коллекция «The 20 newsgroups» стала популярным набором данных для экспериментов с техниками машинного обучения для текстовых приложений, таких как классификация текста или его кластеризация.

Далее мы будем использовать встроенный загрузчик наборов данных для выборки «The 20 newsgroups» из scikit-learn. Иначе, выборку можно загрузить вручную с вэб сайта, использовать функцию sklearn.datasets.load_files и указав папку «20news-bydate-train» для сохранения распакованного архива.
Чтобы первый пример быстрее исполнялся, мы будем работать только с частью нашего набора данных, разбитой на 4 категории из 20 возможных:

>>> categories = ['alt.atheism', 'soc.religion.christian', ...               'comp.graphics', 'sci.med']

Мы можем загрузить список файлов, совпадающих с нужными категориями, как показано ниже:

>>> from sklearn.datasets import fetch_20newsgroups >>> twenty_train = fetch_20newsgroups(subset='train', ...     categories=categories, shuffle=True, random_state=42)

Возвращаемый набор данных — это scikit-learn совокупность: одномерный контейнер с полями, которые могут интерпретироваться как ключи в словаре python (dict keys), проще говоря — как признаки объекта (object attributes). Например, target_names содержит список названий запрошенных категорий:

>>> twenty_train.target_names ['alt.atheism', 'comp.graphics', 'sci.med', 'soc.religion.christian']

Сами файлы загружаются в память как атрибут data. Вы также можете ссылаться на названия файлов:

>>> len(twenty_train.data) 2257 >>> len(twenty_train.filenames) 2257

Давайте выведем на печать первые строки из первого загруженного файла:

>>> print("\n".join(twenty_train.data[0].split("\n")[:3])) From: sd345@city.ac.uk (Michael Collier) Subject: Converting images to HP LaserJet III? Nntp-Posting-Host: hampton  >>> print(twenty_train.target_names[twenty_train.target[0]]) comp.graphics

Алгоритмы для обучения с учителем (контролируемого обучения) требуют, чтобы у каждого документа в обучающей выборке была помета определенной категории. В нашем случае, категория — это название новостной выборки, которая «случайно» оказывается названием папки, содержащей характерные документы.
Для увеличения скорости и эффективного использования памяти, scikit-learn загружает целевой атрибут как массив целых чисел, который соответствует индексу названия категории из списка target_names. Индекс категории каждой выборки хранится в атрибуте target:

>>> twenty_train.target[:10] array([1, 1, 3, 3, 3, 3, 3, 2, 2, 2])

Можно получить название категории:

>>> for t in twenty_train.target[:10]: ...     print(twenty_train.target_names[t]) ... comp.graphics comp.graphics soc.religion.christian soc.religion.christian soc.religion.christian soc.religion.christian soc.religion.christian sci.med sci.med sci.med

Вы можетет заметить, что выборки были рандомно перетасованы (с помощью рандомного сгенирированного числа — fixed RNG seed). Такой метод подойдет, если вы хотите использовать только первые выборки для быстрого обучения модели и если вы хотите получить общее представление о результатах перед последующим переобучением на полном наборе данных.

Извлечение характерных признаков из текстовых файлов

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

«Мешок слов» (набор слов)

Наиболее интуитивно понятный способ сделать описанное выше преобразование — это представить текст в виде набора слов:

  1. приписать уникальный целочисленный индекс каждому слову, появляющемуся в документах в обучающей выборке (например, построив словарь из слов с целочисленными индексами).
  2. для каждого документа #i посчитать количество употреблений каждого слова w и сохранить его (количество) в X[i, j]. Это будет значение признака #j, где j — это индекс слова w в словаре.

Представление «мешок слов» подразумевает, что n_features — это некоторое количество уникальных слов в корпусе. Обычно, это количество превышает 100000.
Если n_samples == 10000, то Х, сохраненный как массив numpy типа float32, потребовал бы 10000 x 100000 x 4 bytes = 4GB оперативной памяти (RAM), что едва осуществимо в современным компьютерах.
К счастью, большинство значений в X являются нулями, поскольку в одном документе используется менее чем пара сотен уникальных слов. Поэтому «мешок слов» чаще всего является высоко размерным разреженным набором данных. Мы можем сэкономить много свободной оперативки, храня в памяти только лишь ненулевые части векторов признаков.
Матрицы scipy.sparse — это структуры данных, которые именно это и делают — структурируют данные. В scikit-learn есть встроенная поддержка этих структур.

Токенизация текста с scikit-learn

Предобработка текста, токенизация и отфильтровывание стоп-слов включены в состав высоко уровневого компонента, который позволяет создать словарь характерных признаков и перевести документы в векторы признаков:

>>> from sklearn.feature_extraction.text import CountVectorizer >>> count_vect = CountVectorizer() >>> X_train_counts = count_vect.fit_transform(twenty_train.data) >>> X_train_counts.shape (2257, 35788)

CountVectorizer поддерживает подсчет N-грам слов или последовательностей символов. Векторизатор строит словарь индексов признаков:

>>> count_vect.vocabulary_.get(u'algorithm') 4690

Значение индекса слова в словаре связано с его частотой употребления во всем обучающем корпусе.

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

Подсчет словоупотреблений — это хорошее начало, но есть проблема: в длинных документах среднее количество словоупотреблений будет выше, чем в коротких, даже если они посвящены одной теме.
Чтобы избежать этих потенциальных несоответствий, достаточно разделить количество употреблений каждого слова в документе на общее количество слов в документе. Этот новый признак называется tf — Частота термина.
Следующее уточнение меры tf — это снижение веса слова, которое появляется во многих документах в корпусе, и отсюда является менее информативным, чем те, которые используются только в небольшой части корпуса. Примером низко ифнормативных слов могут служить служебные слова, артикли, предлоги, союзы и т.п.
Это снижение называется tf–idf, что значит “Term Frequency times Inverse Document Frequency” (обратная частота термина).
Обе меры tf и tf–idf могут быть вычислены следующим образом:

>>> from sklearn.feature_extraction.text import TfidfTransformer >>> tf_transformer = TfidfTransformer(use_idf=False).fit(X_train_counts) >>> X_train_tf = tf_transformer.transform(X_train_counts) >>> X_train_tf.shape (2257, 35788)

В примере кода, представленного выше, мы сначала используем метод fit(..), чтобы прогнать наш алгоритм оценки на данных, а потом — метод transform(..), чтобы преобразовать нашу числовую матрицу к представлению tf-idf. Эти два шага могут быть объединены и дадут тот же результат на выходе, но быстрее, что можно сделать с помощью пропуска излишней обработки. Для этого нужно использовать метод fit_transform(..), как показано ниже:

>>> tfidf_transformer = TfidfTransformer() >>> X_train_tfidf = tfidf_transformer.fit_transform(X_train_counts) >>> X_train_tfidf.shape (2257, 35788)


Продолжение будет в части 2.

ссылка на оригинал статьи http://habrahabr.ru/post/264339/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *