1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/wizardforcel-sklearn-cb

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
4.md 81 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 06.03.2025 03:36 55c0d1d

Глава 4 Классификация данных с помощью scikit-learn

Автор: Trent Hauck

Переводчик: Wizardforcel

Лицензия: CC BY-NC-SA 4.0

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

4.1 Реализация базовой классификации с использованием решающих деревьев

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

Подготовка

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

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

from sklearn import datasets X, y = datasets.make_classification(n_samples=1000, n_features=3, n_redundant=0)


### Шаги операции

Обработка решающего дерева довольно проста. Сначала нам нужно импортировать объект, а затем обучить модель:

```py
>>> from sklearn.tree import DecisionTreeClassifier 
>>> dt = DecisionTreeClassifier() 
>>> dt.fit(X, y) DecisionTreeClassifier(compute_importances=None, criterion='gini',
                        max_depth=None, max_features=None,
                        max_leaf_nodes=None, min_density=None,
                        min_samples_leaf=1, min_samples_split=2,
                        random_state=None, splitter='best')
>>> preds = dt.predict(X) 
>>> (y == preds).mean() 
1.0

Как видно, наши прогнозы оказались правильными. Конечно, это просто демонстрационный пример. Теперь давайте рассмотрим несколько вариантов.Если вы внимательно посмотрите на объект dt, он имеет множество ключевых параметров, определяющих его поведение. Выбор этих параметров крайне важен, поэтому стоит подробнее изучить влияние каждого из них. Первым параметром, который мы должны заметить, является max_depth. Это важный параметр, который определяет количество допустимых ветвлений. Это очень важно, так как деревья решений требуют значительного времени для генерации внешних по отношению к выборке данных; они содержат некоторую форму регуляризации. Затем мы рассмотрим, как использовать несколько неглубоких деревьев решений для создания лучшей модели. Давайте создадим более сложный набор данных и посмотрим, что происходит при различных значениях max_depth. Мы будем использовать этот набор данных для остальных рецептов.```py>>> n_features=200

X, y = datasets.make_classification(750, n_features, n_informative=5) import numpy as np training = np.random.choice([True, False], p=[0.75, 0.25], size=len(y))

accuracies = []

for x in np.arange(1, n_features+1): dt = DecisionTreeClassifier(max_depth=x)
dt.fit(X[training], y[training])
preds = dt.predict(X[~training])
accuracies.append((preds == y[~training]).mean())

import matplotlib.pyplot as plt

f, ax = plt.subplots(figsize=(7, 5))

ax.plot(range(1, n_features+1), accuracies, color='k')

ax.set_title("Точность деревьев решений") ax.set_ylabel("% Верно") ax.set_xlabel("Максимальная глубина")


Результат вывода:

![](img/4-1-1.jpg)

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

```py
>>> N = 15 
>>> import matplotlib.pyplot as plt 
>>> f, ax = plt.subplots(figsize=(7, 5))
>>> ax.plot(range(1, n_features+1)[:N], accuracies[:N], color='k')
>>> ax.set_title("Точность деревьев решений") 
>>> ax.set_ylabel("% Верно") 
>>> ax.set_xlabel("Максимальная глубина")

Результат вывода:

Это пиковая точность, которую мы видели ранее. Удивительно то, как быстро она начинает снижаться. Максимальная глубина от 1 до 3 может быть практически одинаковой. Деревья решений очень хорошо справляются с разделением данных, но важно контролировать эту глубину.Давайте рассмотрим параметр compute_importances. Для случайного леса этот параметр имеет более широкое значение. Но нам стоит лучше понять его использование. Также следует отметить, что если вы используете версию 0.16 или более раннюю, вы можете использовать следующий код:```py

dt_ci = DecisionTreeClassifier(compute_importances=True) dt.fit(X, y) #plot the importances ne0 = dt.feature_importances_ != 0

y_comp = dt.feature_importances_[ne0] x_comp = np.arange(len(dt.feature_importances_))[ne0]

import matplotlib.pyplot as plt

f, ax = plt.subplots(figsize=(7, 5)) ax.bar(x_comp, y_comp)


Результат вывода:

![](img/4-1-3.jpg)

> Обратите внимание, что вы можете получить сообщение об ошибке, которое указывает вам, что явное установление параметра `compute_importances` больше не требуется.

Можно заметить, что среди этих характеристик есть одна, которая является наиболее важной, а затем следуют несколько других значимых характеристик.
```### Принцип работы

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

Теперь давайте поговорим о различиях между энтропией и коэффициентом Джини.

Энтропия не просто представляет собой значение энтропии для данного переменного; если мы знаем значения элементов, она показывает изменения в энтропии. Это называется информационным выигрышем (ИВ), который математически записывается следующим образом:

IV(Данные, Знаменитые Характеристики) = H(Данные) - H(Данные | Знаменитые Характеристики)


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

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

## 4.2 Настройка модели дерева решений

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

### Подготовка

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

Мы будем обучать базовую модель и фактически наблюдать за её внешним видом. Затем мы будем переоценивать каждый шаг решения и указывать, как различные модификации влияют на структуру.

Если вы планируете следовать этому рецепту, вам потребуется установить `pydot`.

### Шаги выполнения

По сравнению с другими алгоритмами, деревья решений имеют множество "ручек", поэтому легко заметить, что происходит при их повороте.```py
>>> from sklearn import datasets 
>>> X, y = datasets.make_classification(1000, 20, n_informative=3)
>>> from sklearn.tree import DecisionTreeClassifier 
>>> dt = DecisionTreeClassifier() 
>>> dt.fit(X, y) 

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

>>> from StringIO import StringIO
>>> from sklearn import tree 
>>> import pydot
>>> str_buffer = StringIO() 
>>> tree.export_graphviz(dt, out_file=str_buffer) 
>>> graph = pydot.graph_from_dot_data(str_buffer.getvalue()) 
>>> graph.write("myfile.jpg")

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

>>> dt = DecisionTreeClassifier(max_depth=5) 
>>> dt.fit(X, y); 

Кстати, если вы хотите знать, почему видите точки с запятой, обычно это repr, которое фактически представляет модель дерева решений. Например, функция fit возвращает объект дерева решений, который позволяет использовать цепочку вызовов:

>>> dt = DecisionTreeClassifier(max_depth=5).fit(X, y) 

Теперь вернемся к обычному процессу.

Так как мы будем часто строить его графически, создадим функцию.

>>> def plot_dt(model, filename):
...     str_buffer = StringIO()
... >>> tree.export_graphviz(model, out_file=str_buffer)    
... >>> graph = pydot.graph_from_dot_data(str_buffer.getvalue())
... >>> graph.write_jpg(filename)
... >>> plot_dt(dt, "myfile.png")
...
```Это сгенерирует следующий график:

![](img/4-2-2.jpg)

Это дерево немного проще. Давайте посмотрим, что произойдет, если использовать энтропию в качестве критерия разделения:

```py
>>> dt = DecisionTreeClassifier(criterion='entropy', 
                                 max_depth=5).fit(X, y) 
>>> plot_dt(dt, "entropy.png") 

Это сгенерирует следующий график:

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

Аналогично обратите внимание, что энтропия первого разделения составляет 0.999, но при использовании коэффициента Джини она равна 0.5. Нам следует понять различия между двумя мерами разделения деревьев решений. Подробнее см. ниже в разделе "Как это работает". Но если нам требуется использовать энтропию для создания дерева решений, то следует использовать следующую команду:

>>> dt = DecisionTreeClassifier(min_samples_leaf=10, 
                                criterion='entropy', 
                                max_depth=5).fit(X, y)

Как это работает

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

Мы скоро увидим эту идею на практике. Случайные леса будут основаны на этой концепции простых моделей.## 4.3 Использование множества деревьев решений — случайных лесов

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

Подготовка

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

Шаги выполнения

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

  1. Создание примерной выборки данных для тренировки
  2. Обучение базового объекта случайного леса
  3. Изучение некоторых свойств обученного объекта

В следующем рецепте мы рассмотрим, как настроить случайный лес классификатора, начнем с импорта набора данных:

>>> from sklearn import datasets

Затем создаем выборку данных из OnClickListener 1000 образцов:

>>> X, y = datasets.make_classification(1000)
```Имея данные, можно создать объект классификатора и обучить его:

```py
>>> from sklearn.ensemble import RandomForestClassifier
>>> rf = RandomForestClassifier()
>>> rf.fit(X, y)

Первым делом нам стоит проверить качество обучения на тренировочных данных. Для этого используем метод predict:

>>> print("Accuracy:\t", (y == rf.predict(X)).mean())
Accuracy:	0.993
>>> print("Total Correct:\t", (y == rf.predict(X)).sum())
Total Correct:	993

Теперь давайте посмотрим на некоторые свойства и методы.

Сначала обратим внимание на несколько полезных свойств. Здесь они являются значениями по умолчанию, поскольку мы сохранили все параметры по умолчанию:

  • rf.criterion: Это критерий, который используется для разделения. По умолчанию это "gini".

  • rf.bootstrap: Логическое значение, указывающее, используют ли мы бутстрэп при обучении случайного леса.

  • rf.n_jobs: Количество задач, которые будут использоваться для обучения и прогнозирования. Установите -1, если вы хотите использовать все доступные процессоры. Однако помните, что использование слишком большого числа задач может привести к потере производительности, если ваш набор данных не является большим.

  • rf.max_features: Это количество признаков, которое будет учитываться при поиске оптимального разделения. Очень удобно при настройке модели.

  • rf.compute_importances: Это помогает нам решить, следует ли считать важность признаков. Дополнительная информация о том, как использовать этот параметр, находится в разделе «Более подробно».+ rf.max_depth: Это глубина дерева. Существует множество атрибутов, требующих внимания; более подробную информацию можно найти в официальной документации.

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

>>> probs = rf.predict_proba(X)
>>> import pandas as pd
>>> probs_df = pd.DataFrame(probs, columns=['0', '1'])
>>> probs_df['was_correct'] = rf.predict(X) == y
>>> import matplotlib.pyplot as plt
>>> f, ax = plt.subplots(figsize=(7, 5))
>>> probs_df.groupby('0').was_correct.mean().plot(kind='bar', ax=ax)
>>> ax.set_title("Accuracy at 0 class probability")
>>> ax.set_ylabel("% Correct")
>>> ax.set_xlabel("% деревьев для 0")

Как это работает

Случайный лес использует заранее определённое количество слабых решающих деревьев и обучает каждое дерево на основе случайно выбранных данных. Это крайне важно для предотвращения переобучения. Также это объясняет значение параметра bootstrap. Каждое из наших деревьев имеет следующие характеристики:

  • Класс с наибольшим количеством голосов

  • Выход, если используется регрессионное дерево

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

Важность признаков — это замечательный побочный продукт случайного леса. Обычно это помогает ответить на вопрос: среди 10 признаков, какой из них наиболее важен для определения истинного класса точки данных? В реальных приложениях это легко проверить. Например, если транзакция недействительна, мы можем захотеть узнать, есть ли специфический сигнал, который бы позволил быстрее определить класс транзакции.

Если мы хотим использовать максимальную важность признаков, мы должны указать это при создании объекта. Если вы используете scikit-learn 0.15, вы можете получить предупреждение, что это больше не обязательно. В версии 0.16 предупреждение будет удалено.

>>> rf = RandomForestClassifier(compute_importances=True)
>>> rf.fit(X, y)
>>> f, ax = plt.subplots(figsize=(7, 5))
>>> ax.bar(range(len(rf.feature_importances_)), rf.feature_importances_)
>>> ax.set_title("Feature Importances")

Вот как будет выглядеть вывод:

Мы видим, что определённые признаки важнее других при определении принадлежности к классу 0 или 1.

4.4 Настройка модели случайного леса

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

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

>>> from sklearn import datasets 
>>> X, y = datasets.make_classification(n_samples=10000,
                                        n_features=20,
                                        n_informative=15,
                                        flip_y=0.5, weights=[0.2, 0.8])

Операция

В этом рецепте мы выполним следующие действия:

  1. Создание тренировочного и тестового набора данных. В отличие от предыдущего рецепта, если не сравнивать с тренировочным набором, то настройка модели будет бесполезной.

  2. Обучение базовой модели случайного леса для оценки качества исходного алгоритма.

  3. Изменение некоторых параметров систематическим образом и наблюдение за тем, как это влияет на обучение.

Хорошо, запустим интерпретатор и импортируем NumPy:

>>> import numpy as np 
>>> training = np.random.choice([True, False], p=[0.8, 0.2],
                                size=y.shape)
>>> from sklearn.ensemble import RandomForestClassifier
>>> rf = RandomForestClassifier()
>>> rf.fit(X[training], y[training])
>>> preds = rf.predict(X[~training])
>>> print("Accuracy:\t", (preds == y[~training]).mean())
Accuracy:    0.652239557121

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

Давайте пройдёмся по рекомендованным значениям параметра max_features и посмотрим, как они влияют на обучение. Мы также будем проходить по некоторым дробным значениям, представляющим долю используемых признаков. Используйте следующую команду:```py

from sklearn.metrics import confusion_matrix max_feature_params = ['auto', 'sqrt', 'log2', .01, .5, .99] confusion_matrixes = {} for max_feature in max_feature_params: rf = RandomForestClassifier(max_features=max_feature) rf.fit(X[training], y[training]) confusion_matrixes[max_feature] = confusion_matrix( y[~training], rf.predict(X[~training])).ravel()

Используя метод `ravel`, наш двумерный массив теперь превратился в одномерный.

Теперь импортируем Pandas и посмотрим на созданную нами матрицу путаницы:

```py
>>> import pandas as pd

>>> confusion_df = pd.DataFrame(confusion_matrixes)

>>> import itertools 
>>> from matplotlib import pyplot as plt 
>>> f, ax = plt.subplots(figsize=(7, 5))

>>> confusion_df.plot(kind='bar', ax=ax)

>>> ax.legend(loc='best')

>>> ax.set_title("Предсказано против правильного (i, j), где i — это предсказание, а j — фактическое значение.")

>>> ax.grid()

>>> ax.set_xticklabels([str((i, j)) for i, j in list(itertools.product(range(2), range(2)))]); 
>>> ax.set_xlabel("Предсказано против правильного"); 
>>> ax.set_ylabel("Правильное")

image

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

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

>>> n_estimator_params = range(1, 20)
>>> confusion_matrixes = {}
>>> for n_estimator in n_estimator_params:
        rf = RandomForestClassifier(n_estimators=n_estimator)
        rf.fit(X[training], y[training])
        confusion_matrixes[n_estimator] = confusion_matrix(y[~training],
                                          rf.predict(X[~training]))
        # Здесь мы будем обновлять матрицу путаницы с помощью операции, которую мы обсуждали ранее
>>> accuracy = lambda x: np.trace(x) / np.sum(x, dtype=float) 
>>> confusion_matrixes[n_estimator] = accuracy(confusion_matrixes[n_estimator])
>>> accuracy_series = pd.Series(confusion_matrixes) 
>>> import itertools 
>>> from matplotlib import pyplot as plt
>>> f, ax = plt.subplots(figsize=(7, 5))
>>> accuracy_series.plot(kind='bar', ax=ax, color='k', alpha=.75) 
>>> ax.grid()
>>> ax.set_title("Accuracy by Number of Estimators") 
>>> ax.set_ylim(0, 1) # We need the full scale
>>> ax.set_ylabel("Accuracy") 
>>> ax.set_xlabel("Number of Estimators")
```График:

![](img/4-4-2.jpg)

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

### Принцип работы

Использование бутстрэпа  это отличный трюк для расширения других частей модели. Обычно этот подход демонстрируется с примерами, где стандартная ошибка складывается со средним значением. Здесь мы оцениваем результаты и объединяем эти оценки в вероятность.

Таким образом, увеличивая количество оценщиков, мы увеличиваем число подвыборок, что приводит к более быстрой конвергенции в целом.

### Дополнительно

Мы можем захотеть ускорить процесс обучения. Я уже упоминал этот процесс ранее, но также можно установить значение `n_jobs`, равное количеству деревьев, которое вы хотите обучить. Это должно быть приблизительно равно колич数字应该被翻译成数字形式

根据规则将文本中的中文描述翻译为俄文并将数字文字转换为数字

График:

![](img/4-4-2.jpg)

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

### Принцип работы

Использование бутстрэпа  это отличный трюк для расширения других частей модели. Обычно этот подход демонстрируется с примерами, где стандартная ошибка складывается со средним значением. Здесь мы оцениваем результаты и объединяем эти оценки в вероятность.

Таким образом, увеличивая количество оценщиков, мы увеличиваем число подвыборок, что приводит к более быстрой конвергенции в целом.

### Дополнительно

Мы можем захотеть ускорить процесс обучения. Я уже упоминал этот процесс ранее, но также можно установить значение `n_jobs`, равное количеству деревьев, которое вы хотите обучить. Это должно быть приблизительно равно количеству ядер вашего компьютера.

```py
>>> rf = RandomForestClassifier(n_jobs=4, verbose=True)
>>> rf.fit(X, y)
[Parallel(n_jobs=4)]: Done   1 out of   4 | elapsed:    0.3s remaining:   0.9s
[Parallel(n_jobs=4)]: Done   4 out of   4 | elapsed:    0.3s finished
```

Это также позволяет выполнять параллельное прогнозирование:

```py
>>> rf.predict(X)
[Parallel(n_jobs=4)]: Done   1 out of   4 | elapsed:    0.0s remaining:     0.0s
[Parallel(n_jobs=4)]: Done   4 out of   4 | elapsed:    0.0s finished
```array([1, 1, 0, ..., 1, 1, 1])
```

## 4.5 Классификация данных с помощью метода опорных векторов

Метод опорных векторов (SVM) является одним из наших любимых алгоритмов машинного обучения, который сложно объяснить через вероятностные рамки. Основной идеей SVM является поиск плоскости, которая делит набор данных на группы таким образом, чтобы обеспечить максимальное расстояние между самыми ближайшими точками. Эти точки называются опорными векторами.

### Подготовка

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

```py
>>> from sklearn import datasets
>>> X, y = datasets.make_classification()
```

### Шаги выполнения

Процесс создания объекта SVM для классификации очень прост. Есть множество доступных параметров. Вот что мы делаем:

1. Создаём объект SVC и обучаем его на синтетических данных.
2. Обучаем объект SVC на реальных данных.
3. Обсуждаем несколько параметров SVC.

Импортируем SVC из модуля SVM:

```py
>>> from sklearn.svm import SVC
>>> base_svm = SVC()
>>> base_svm.fit(X, y)
```

Давайте рассмотрим некоторые атрибуты:+ `C`: если наши данные не разделены правильно, то параметр `C` увеличивает штраф за ошибки. Чем больше значение `C`, тем больше штраф за ошибки, и SVM будет стремиться найти более узкий интервал, даже если это приведёт к большему количеству ошибочно классифицированных точек.

+ `class_weight`: этот параметр указывает, какой вес должен быть присвоен каждому классу в задаче. Он предоставляется в виде словаря, где ключами являются классы, а значениями  веса, связанные с этими классами.+   `gamma`: это параметр Гамма для ядра, который поддерживается типами ядер `rbf`, `sigmoid` и `poly`.

+   `kernel`: это используемое ядро. В данном примере используется ядро `linear`, хотя более популярным является ядро `rbf`, которое также является значением по умолчанию.

### Принцип работы

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

Сначала обучим модель на наборе данных, а затем отобразим её.

```py
>>> X, y = datasets.make_blobs(n_features=2, centers=2) 
>>> from sklearn.svm import LinearSVC 
>>> svm = LinearSVC() 
>>> svm.fit(X, y) 
```

Так как мы уже обучили нашу модель поддержки векторов, теперь мы можем отобразить результат каждой точки на графике. Это покажет нам приближённую границу решений.

```py
>>> from itertools import product 
>>> from collections import namedtuple

>>> Point = namedtuple('Point', ['x', 'y', 'outcome']) 
>>> decision_boundary = [] 
>>> xmin, xmax = np.percentile(X[:, 0], [0, 100]) 
>>> ymin, ymax = np.percentile(X[:, 1], [0, 100])

>>> for xpt, ypt in product(np.linspace(xmin-2.5, xmax+2.5, 20),
                            np.linspace(ymin-2.5, ymax+2.5, 20)):
        p = Point(xpt, ypt, svm.predict([xpt, ypt]))
        decision_boundary.append(p)

>>> import matplotlib.pyplot as plt 
>>> f, ax = plt.subplots(figsize=(7, 5)) 
>>> import numpy as np 
>>> colors = np.array(['r', 'b']) 
>>> for xpt, ypt, pt in decision_boundary:
        ax.scatter(xpt, ypt, color=colors[pt[0]], alpha=.15)
        ax.scatter(X[:, 0], X[:, 1], color=colors[y], s=30)
        ax.set_ylim(ymin, ymax)
        ax.set_xlim(xmin, xmax)
        ax.set_title("Датасет с хорошим разделением")
```Результат будет следующим:

![](img/4-5-1.jpg)

Теперь давайте рассмотрим другой пример, но на этот раз граница решения не так очевидна:

```py
>>> X, y = datasets.make_classification(n_features=2,
                                        n_classes=2,            
                                        n_informative=2,        
                                        n_redundant=0)
```

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

```py

>>> svm.fit(X, y) 
>>> xmin, xmax = np.percentile(X[:, 0], [0, 100]) 
>>> ymin, ymax = np.percentile(X[:, 1], [0, 100]) 
>>> test_points = np.array([[xx, yy] for xx, yy in
                            product(np.linspace(xmin, xmax),
                                    np.linspace(ymin, ymax))]) 
>>> test_preds = svm.predict(test_points)
>>> import matplotlib.pyplot as plt 
>>> f, ax = plt.subplots(figsize=(7, 5)) 
>>> import numpy as np 
>>> colors = np.array(['r', 'b']) 
>>> ax.scatter(test_points[:, 0], test_points[:, 1],
               color=colors[test_preds], alpha=.25) 
>>> ax.scatter(X[:, 0], X[:, 1], color=colors[y]) 
>>> ax.set_title("Отделённый набор данных")

```

Выход будет следующим:

![](img/4-5-2.jpg)

Можно заметить, что граница решений не идеальна, но в конечном итоге это лучший линейный SVM, который мы можем получить.

### Дополнительно

Даже если мы не можем достичь лучших линейных SVM, классификатор SVC в Scikit использует радиальную базисную функцию. Мы уже видели эту функцию, но давайте рассмотрим, как она вычисляет границу решений для нашего последнего набора данных.```py

>>> radial_svm = SVC(kernel='rbf')
>>> radial_svm.fit(X, y)
>>> xmin, xmax = np.percentile(X[:, 0], [0, 100])
>>> ymin, ymax = np.percentile(X[:, 1], [0, 100])
>>> test_points = np.array([[xx, yy] for xx, yy in
                             product(np.linspace(xmin, xmax),
                                     np.linspace(ymin, ymax))])
>>> test_preds = radial_svm.predict(test_points)
>>> import matplotlib.pyplot as plt
>>> f, ax = plt.subplots(figsize=(7, 5))
>>> import numpy as np
>>> colors = np.array(['r', 'b'])
>>> ax.scatter(test_points[:, 0], test_points[:, 1],
               color=colors[test_preds], alpha=.25)
>>> ax.scatter(X[:, 0], X[:, 1], color=colors[y])
>>> ax.set_title("SVM с радиальной базисной функцией")

```

Выход будет следующим:

![](img/4-5-3.jpg)

Можно заметить, что граница решений изменилась. Мы даже можем передать свою собственную радиальную базисную функцию, если потребуется.```py
>>> def test_kernel(X, y):
        """Тестовое ядро, которое возвращает экспоненту от скалярного произведения матриц X и y."""
        return np.exp(np.dot(X, y.T))
>>> test_svc = SVC(kernel=test_kernel)
>>> test_svc.fit(X, y)
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0, degree=3,
    gamma=0.0, kernel=<function test_kernel at 0x121fdfb90>, max_iter=-1,
    probability=False, random_state=None, shrinking=True, tol=0.001,
    verbose=False)
```## 4.6 Использование многоклассовой классификации для обобщения

В этом рецепте мы рассмотрим многоклассовую классификацию. В зависимости от выбранного алгоритма вы можете легко реализовать многоклассовую классификацию или определить модели для сравнения.

### Подготовка

При работе с линейными моделями, такими как логистическая регрессия, нам следует использовать `OneVsRestClassifier`. Эта модель создает классификатор для каждого класса.### Операция

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

Затем мы фактически включаем `OneVsRestClassifier` в нашу модель:

```py
>>> from sklearn import datasets 
>>> X, y = datasets.make_classification(n_samples=10000, n_classes=3,
                                        n_informative=3)
>>> from sklearn.tree import DecisionTreeClassifier 
>>> dt = DecisionTreeClassifier() 
>>> dt.fit(X, y) 
>>> dt.predict(X) 
array([1, 1, 0, ..., 2, 1, 1])
```

Вы видите, что мы можем обучить классификатор минимальными усилиями.

Теперь давайте перейдем к случаю с многоклассовым классификатором. Для этого нам потребуется импортировать `OneVsRestClassifier`. Также нам понадобится `LogisticRegression`.

```py
>>> from sklearn.multiclass import OneVsRestClassifier 
>>> from sklearn.linear_model import LogisticRegression
```

Теперь мы заменим `LogisticRegression` классификатором, при этом заметив, что можем сделать это параллельно. Если мы хотим узнать, как работает `OneVsRestClassifier`, то он просто тренирует отдельные модели и сравнивает их. Поэтому мы можем одновременно обучать каждую модель отдельно.

```py
>>> mlr = OneVsRestClassifier(LogisticRegression(), n_jobs=2) 
>>> mlr.fit(X, y) 
>>> mlr.predict(X) 
array([1, 1, 0, ..., 2, 1, 1])
```

### Принцип работы

Как быстрее создать свой собственный `OneVsRestClassifier`?Сначала нам нужно организовать способ итерации через каждый класс, обучая классификатор для каждого класса. Затем мы должны предсказывать каждый класс:

```py
>>> import numpy as np 
>>> def train_one_vs_rest(y, class_label):
        y_train = (y == class_label).astype(int)
        return y_train
>>> classifiers = [] 
>>> for class_i in sorted(np.unique(y)):
        l = LogisticRegression()
        y_train = train_one_vs_rest(y, class_i)
        l.fit(X, y_train)
        classifiers.append(l)
```
Хорошо, теперь что мы настроили режим OneVsRest, нам нужно сделать всего лишь одно  вычислить вероятность каждого наблюдения относительно каждого классификатора. После этого мы присваиваем каждому наблюдению классификатор с наибольшей вероятностью.

Например, давайте предсказываем `X[0]`:

```py
for classifier in classifiers:
    >>> print(classifier.predict_proba(X[0]))

[[0.90443776 0.09556224]]
[[0.03701073 0.96298927]]
[[0.98492829 0.01507171]]
```

Вы можете видеть, что второй классификатор (индекс 1) имеет максимальную вероятность для положительной категории, поэтому мы присваиваем этому объекту метку 1.

## 4.7 Использование LDA для классификации

Линейный дискриминантный анализ (LDA) пытается найти линейные комбинации признаков для прогнозирования целевой переменной. LDA обычно используется как предварительная обработка, и в этой статье мы рассмотрим оба метода.

## Подготовка

В этом руководстве мы будем выполнять следующие действия:1. Получение данных акций с сайта Yahoo
2. Упорядочивание данных в удобном для анализа формате
3. Создание объекта LDA для обучения и прогнозирования классовых меток
4. Пример использования LDA для снижения размерности данных## Шаги выполнения

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

T1 = текущие активы / общая стоимость активов. Измеряет текущие активы относительно размера компании.

T2 = накопленная прибыль / общая стоимость активов. Измеряет доходность, которая отражает возраст и прибыльность компании.

T3 = чистый доход до процентов и налогов / общая стоимость активов. Измеряет эффективность операционной деятельности вне зависимости от налоговой нагрузки и уровня заемного капитала. Это очень важно для долгосрочной жизнеспособности компании.

T4 = рыночная стоимость акционерного капитала / балансовая стоимость обязательств. Добавление рыночной составляющей позволяет использовать колебания цен на акции как сигнал опасности.

T5 = оборот / общая стоимость активов. Общая мера оборачиваемости активов (значительно различается между отраслями).

Это цитата из Википедии:

[1] Altman, Эдвард И. (Сентябрь 1968). "Финансовые коэффициенты, дискриминантный анализ и прогнозирование корпоративного банкротства". Журнал Финансов: 189209.В этом анализе мы используем Pandas для получения некоторых финансовых данных с сайта Yahoo. Мы попробуем предсказать, будет ли цена акции расти в течение следующих шести месяцев, основываясь на текущих характеристиках акций. Очевидно, нет ничего лучше Z-оценки Altman. Давайте возьмём некоторые автомобильные акции:```py
>>> тикеры = ["F", "TM", "GM", "TSLA"]
>>> from pandas.io import data as внешние_данные
>>> панель_данных = внешние_данные.DataReader(тикеры, "yahoo")
```
Эта структура данных является `panel`, аналогичной OLAP кубу или трёхмерному `DataFrame`. Давайте взглянем на эти данные, чтобы познакомиться с закрытой ценой, так как мы будем сравнивать её.

```py
>>> stock_df = панель_данных.Close.dropna()
>>> stock_df.plot(figsize=(7, 5))
```

Ниже представлен вывод:

![](img/4-7-1.jpg)

Хорошо, теперь нам нужно сравнить цену каждой акции со значением за последние шесть месяцев. Если цена выше, то значение будет равно OnClickListener 1, в противном случае  0.

Для этого нам нужно просто переместить данные на 180 дней вперёд и выполнить сравнение:

```py
# Этот DataFrame указывает, была ли цена акции выше через 180 дней
>>> classes = (stock_df.shift(-180) > stock_df).astype(int)
```

Следующее, что нам нужно сделать, это развернуть набор данных:

```py
>>> X = панель_данных.to_frame()
>>> classes = classes.unstack()
>>> classes = classes.swaplevel().sort_index()
>>> classes = classes.to_frame()
>>> classes.index.names = ['Дата', 'подчинённая']
>>> данные = X.join(classes).dropna()
>>> данные.rename(columns={0: 'является_выше'}, inplace=True)
>>> данные.head()
```

Вывод следующий:

![](img/4-7-2.jpg)

Отлично, теперь нам нужно создать матрицу для SciPy. Для этого мы используем библиотеку `patsy`. Это очень мощная библиотека, которая позволяет создавать матрицы принятия решений, аналогично R.```py
>>> import patsy
>>> X = patsy.dmatrix("Open + High + Low + Close + Volume + is_higher - 1", data.reset_index(), return_type='dataframe')
>>> X.head()
```

Вывод следующий:

![](img/4-7-3.jpg)

Библиотека `patsy` действительно мощная. Например, если бы мы хотели использовать некоторые методы предварительной обработки из первой главы, в `patsy` можно было бы модифицировать формулу, как в R, чтобы изменять матрицу принятия решений. В данном примере мы этого не делаем, но если бы мы хотели масштабировать данные до среднего значения 0 и стандартного отклонения 1, функция выглядела бы так: `scale(Open) + scale(High)`.

Отлично. Теперь у нас есть набор данных. Давайте обучим объект LDA.

```py
>>> import pandas as pd
>>> from sklearn.lda import LDA
>>> lda = LDA()
>>> lda.fit(X.iloc[:, :-1], X.iloc[:, -1])
```

Можно заметить, что прогнозируемый набор данных не слишком плох. На самом деле, мы планируем улучшить модель, используя другие параметры и выполняя тестирование модели.```py
>>> from sklearn.metrics import classification_report
>>> print(classification_report(X.ix[:, -1].values,
                                 lda.predict(X.ix[:, :-1])))
             точность     полнота    f1-мера      поддержка  
0               0,63        0,59       0,61            1895
1               0,60        0,64       0,62            1833
среднее/общее   0,61        0,61       0,61            3728 
```Эти метрики описывают различные аспекты того, как модель соответствует данным.

+ Для **точности** (precision) предположим, что модель прогнозирует положительные значения. Какова доля случаев, когда эти прогнозы верны? (`TP / (TP + FP)`)
```+ Для **полноты** (recall) предположим, что состояние некоторого класса является правильным. Какую долю таких состояний мы выбираем? Поскольку полнота часто используется в задачах поиска, я использую термин "выбор". Например, если есть потенциальные веб-страницы, связанные с определённым поисковым запросом, то это будет доля выбранных страниц. (`TP / (TP + FN)`)

+ **F1-мера** пытается объединить эти два показателя. (`2 * p * r / (p + r)`)

## Как это работает

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

LDA является упрощённой версией QDA, которая будет рассмотрена в следующем разделе. Здесь мы предполагаем, что ковариация всех классов одинакова, тогда как в QDA этот допущение не строгое. Можно сравнить их соотношение с отношением между KNN и GMM.

# 4.8 Использование QDA — Нелинейная LDA

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

## ПодготовкаМы будем расширять предыдущий рецепт и использовать объект QDA для выполнения квадратичного дискриминантного анализа (QDA).

Мы говорили, что будем делать предположения относительно ковариационной матрицы модели. В данном случае мы ослабляем это предположение.

## Шаги операции

QDA является частью модуля `sklearn.qda`. Вы можете использовать его следующим образом:

```py
>>> from sklearn.qda import QDA 
>>> qda = QDA()

>>> qda.fit(X.iloc[:, :-1], X.iloc[:, -1]) 
>>> predictions = qda.predict(X.iloc[:, :-1]) 
>>> predictions.sum() 
2812.0

>>> from sklearn.metrics import classification_report 
>>> print(classification_report(X.iloc[:, -1].values, predictions))

              precision     recall     f1-score     support 
0.0                0.75       0.36        0.49         1895 
1.0                0.57       0.88        0.69         1833 
avg / total        0.66       0.62        0.59         3728
```

Как видите, в целом результаты примерно такие же. Если вы обратитесь к рецепту LDA, вы заметите, что для класса 0 изменения значительны, а для класса 1 они минимальны.

## Принцип работы

Как мы уже говорили в предыдущей хакерской технике, здесь мы сопоставляем вероятности. Как это происходит? Давайте попробуем использовать цены для сравнения `is_higher` категории.

Мы предполагаем, что закрытые цены следуют логнормальному распределению. Для вычисления вероятностей каждой категории нам потребуется создать подмножество закрытых цен для каждого класса, а также тренировочные и тестовые наборы данных. В качестве подготовки к следующей главе мы будем использовать встроенные методы кросс-валидации:```py
>>> from sklearn import cross_validation as cv
>>> import scipy.stats as sp
>>> for test, train in cv.ShuffleSplit(len(X.Close), n_iter=1):
        train_set = X.iloc[train]
        train_close = train_set.Close
        
        train_0 = train_close[~train_set.is_higher.astype(bool)]
        train_1 = train_close[train_set.is_higher.astype(bool)]

        test_set = X.iloc[test]
        test_close = test_set.Close.values

        ll_0 = sp.norm.pdf(test_close, train_0.mean())
        ll_1 = sp.norm.pdf(test_close, train_1.mean())
```

У нас есть две вероятности классов, которые можно сравнивать и назначать классы:

```py
>>> (ll_0 > ll_1).mean()
0.15588673621460505
```

## 4.9 Использование стохастического градиентного спуска для классификации

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

### Подготовка

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

### Операция

Сначала давайте создадим некоторые базовые данные:

```py
>>> from sklearn import datasets
>>> X, y = datasets.make_classification()
```

Затем создадим экземпляр `SGDClassifier`:

```py
>>> from sklearn import linear_model
>>> sgd_clf = linear_model.SGDClassifier()
```

Как обычно, обучим модель:
``````py
>>> sgd_clf.fit(X, y)
SGDClassifier(alpha=0.0001, class_weight=None, epsilon=0.1, eta0=0.0,
               fit_intercept=True, l1_ratio=0.15,
               learning_rate='optimal', loss='hinge', max_iter=1000,
               n_jobs=None, penalty='l2', power_t=0.5,
               random_state=None, shuffle=True, tol=None,
               validation_fraction=0.1, verbose=0, warm_start=False)
```Можно установить параметр `class_weight`, чтобы учитывать изменения в общем количестве неравновесия в наборе данных. Функция потери Hinge определяется следующим образом:

```
max(0, 1 - t * y)
```

Здесь `t`  это истинная метка классификации, которая может принимать значения +1 или -1 в зависимости от ситуации. Вектор коэффициентов обозначается как `y`, так как он вычисляется моделью. `x`  это интересующее нас значение.

Это также хорошая мера. Можно представить её в другом виде:

```
t  {-1, 1}
y = βx + b
```

## 4.10 Классификация данных с помощью нивелированного Байеса

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

### Подготовка

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

Основная идея состоит в том, чтобы использовать частоту слов из тестового набора данных с метками для обучения классификации документов. После этого можно применять этот метод к тренировочному набору данных для попытки прогнозирования меток.Мы используем набор данных `newsgroups` из библиотеки Scikit-learn для работы с моделью нивелированного Байеса. Это ценная коллекция данных, поэтому мы используем её вместо загрузки. Мы ограничиваем классификацию только двумя категориями: `rec.autos` и `rec.motorcycles`.

```py
>>> from sklearn.datasets import fetch_20newsgroups

>>> categories = ["rec.autos", "rec.motorcycles"]
>>> newgroups = fetch_20newsgroups(categories=categories)

# Посмотрим
>>> print("\n".join(newgroups.data[:1]))
From: gregl@zimmer.CSUFresno.EDU (Greg Lewis)
Subject: Re: WARNING.....(please read)...
Keywords: BRICK, TRUCK, DANGER
Nntp-Posting-Host: zimmer.csufresno.edu
Organization: CSU Fresno
Lines: 33

[...]

>>> newgroups.target_names[newgroups.target[:1]]
'rec.autos'
```

Теперь что у нас есть `newgroups`, нам нужно представить каждый документ в виде вектора частот слов. Это представление и даёт название модели «нивелированный Байес». Модель считается «нивелированной», потому что она не учитывает никакую ковариацию между словами в разных документах при классификации. Это можно рассматривать как недостаток, но нивелированный Байес уже давно показал свою надёжность.

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

```py
>>> from sklearn.feature_extraction.text import CountVectorizer

>>> count_vec = CountVectorizer()
>>> bow = count_vec.fit_transform(newgroups.data)
```Этот матричный объект представляет собой разряженную матрицу, её размерность составляет количество документов, умноженное на количество уникальных слов. Её значения представляют частоту каждого слова в каждом документе.


```py
>>> bow <1192x19177 sparse matrix of type '<class 'scipy.sparse.csr.csr_matrix'>'
    with 164296 stored elements in Compressed Sparse Row format>
```

Действительно, нам потребуется представить эту матрицу как плотный массив для использования в объектах Naive Bayes Classifier. Поэтому давайте преобразуем её.

```py
>>> bow = np.array(bow.todense())
```

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

```py
>>> words = np.array(count_vec.get_feature_names())
>>> words[bow[0] > 0][:5]
array(['10pm', '1qh336innfl5', '33', '93740',
       '________________________________________________________________________'],
      dtype=object)
```

Теперь эти слова являются примерами слов первого документа? Давайте используем следующие команды:

```py
>>> '10pm' in новогруппы.данные[0].lower()
True
>>> '1qh336innfl5' in новогруппы.данные[0].lower()
True
```

### Операция

Хорошо, так что нам требуется больше времени для подготовки данных, поскольку мы работаем с текстовыми данными, а не с обычной матрицей.

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

```py
>>> from sklearn import naive_bayes
>>> clf = naive_bayes.MultinomialNB()
```

Перед тем как обучить модель, разобьём набор данных на тренировочный и тестовый наборы.```py
>>> маска = np.random.choice([True, False], len(bow))
>>> clf.fit(bow[маска], новогруппы.tarгет[маска])
>>> прогнозы = clf.predict(bow[~маска])
```

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

```py
>>> np.mean(прогнозы == новогруппы.tarгет[~маска])
0.92446043165467628
```

### Принцип работы

Основной принцип Naive Bayes Classifier заключается в том, что мы можем оценить вероятность принадлежности данных к определенному классу на основе признаковых векторов (`P(Ci|X)`).

Это можно преобразовать с помощью теоремы Байеса в условную вероятность признаковых векторов (`P(X|Ci)`). Если признаковый вектор имеет наибольшую вероятность, то классификация будет выбирать этот класс.

### Дополнительно

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

```py
>>> from sklearn.datasets import fetch_20newsgroups 
>>> mn_categories = ["rec.autos", "rec.motorcycles",
                     "talk.politics.guns"]
>>> mn_newgroups = fetch_ Yöntemler = fetch_20newsgroups(categories=mn_categories)
```

Нам потребуется векторизовать эти данные.

```py
>>> mn_bow = count_vec.fit_transform(mn_newgroups.data) 
>>> mn_bow = np.array(mn_bow.todense())
```

Давайте создадим маску для разделения данных на обучающую и тестовую выборки.
``````py
>>> mn_mask = np.random.choice([True, False], len(mn_newgroups.data))
>>> multinom = naive_bayes.MultinomialNB()
>>> multinom.fit(mn_bow[mn_mask], mn_newgroups.target[mn_mask])
>>> mn_predict = multinom.predict(mn_bow[~mn_mask])
>>> np.mean(mn_predict == mn_newgroups.target[~mn_mask]) # 0.96594778660612934
```

Мы справились хорошо, что совсем не удивительно. Мы показали хорошие результаты при работе с двумя категориями, а поскольку категория `talk.politics.guns` почти ортогональна остальным, мы также должны были показать хорошие результаты.

## 4.11 Передача меток, полунадзорное обучение

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

### ПодготовкаЕще одна область применения — это отсутствие данных. Вы можете представить ситуацию, когда временные рамки влияют на вашу способность собирать данные. Например, вы проводите эксперимент с лекарствами на пациентах и измеряете их реакцию. Иногда вы можете измерить эффект лекарства. Если вам повезет достаточно быстро, то вы сможете планировать прогнозирование эффекта лекарства, которое действует медленнее. Эти лекарства могут оказывать смертельное воздействие на некоторых пациентов, требуя экстренной помощи.### Операция

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

```py
>>> from sklearn import datasets 
>>> d = datasets.load_ious()
```

Поскольку мы будем манипулировать данными, сделаем резервную копию и добавим элемент `unlabeled` к массиву названий меток. Это поможет легко идентифицировать данные. Теперь используйте `-1` для обновления `y`, это будет маркером незначимых данных. Именно поэтому мы добавили `unlabeled` в конец.

```py
>>> y[np.random.choice([True, False], len(y))] = -1 
```

Наши данные теперь содержат ряд отрицательных значений (`-1`), случайно распределённых среди реальных данных:

```py
>>> y[:10]
array([-1, -1, -1, -1,  0,  0, -1, -1,  0, -1])
```

```py
>>> names[y[:10]]
array(['unlabeled', 'unlabeled', 'unlabeled', 'unlabeled', 'setosa',
       'setosa', 'unlabeled', 'unlabeled', 'setosa', 'unlabeled'],
       dtype='|S10')
```

Мы явно имеем дело с большим количеством незначимых данных, и наша цель  использовать `LabelPropagation` для прогнозирования меток:

```py
>>> from sklearn import semi_supervised
>>> lp = semi_supervised.LabelPropagation()

>>> lp.fit(X, y)

LabelPropagation(alpha=1, gamma=20, kernel='rbf', max_iter=30,
                  n_neighbors=7, tol=0.001)

>>> preds = lp.predict(X)
>>> (preds == d.target).mean()
0.98666666666666669
```

Не так уж плохо. Мы использовали все данные, что является некоторым мошенничеством. Также, набор данных `iris` хорошо разделён.Хотя мы закончили, давайте взглянем на `LabelSpreading`, который является родственным классом `LabelPropagation`. В разделе "Как это работает" мы рассмотрим технические различия между `LabelSpreading` и `LabelPropagation`, но легко заметить их схожесть.

```py
>>> ls = semi_supervised.LabelSpreading()
```

Проследив за его работой, можно сказать, что `LabelSpreading` более надёжен и шумоустойчив.

```py
>>> ls.fit(X, y)
LabelSpreading(alpha=0.2, gamma=20, kernel='rbf', max_iter=30,
                n_neighbors=7, tol=0.001)

>>> (ls.predict(X) == d.target).mean()
0.96666666666666667
```

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

### Как это работает

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

```
wij(θ) = dij / θ^2
```

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

---

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

```
wij(θ) = dij / θ^2
```

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

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/wizardforcel-sklearn-cb.git
git@api.gitlife.ru:oschina-mirror/wizardforcel-sklearn-cb.git
oschina-mirror
wizardforcel-sklearn-cb
wizardforcel-sklearn-cb
master