Виджеты в jupyter notebook - это по сути добавление к интерфейсу тетрадок. Они привносят интерактив, могут использоваться для хранения и передачи информации. С их помощью можно превратить тетрадку в нечто понятное простому пользователю и использовать как dashboard или простой аналитический инструмент.
Вот что вы увидите:
Самый простой способ работать с этой тетрадкой - использовать https://try.jupyter.org/. Это официальная возможность загрузить и запустить тетрадку.
Установка сама по себе не является сложной: это можно сделать через pip:
pip install ipywidgets
pip install widgetsnbextension
jupyter nbextension enable --py widgetsnbextension
Или через Anaconda:
conda install -c conda-forge ipywidgets
conda install -c conda-forge widgetsnbextension
Но вот нюанс: установить-то легко, а вот заставить корректно работать - сложно. Если достаточно, чтобы всё работало в локальной тетрадке, то можно просто установить самые последние версии (только проверьте, что они последние, а то в канале может быть не самая последняя версия). Если же хочется, чтобы этим можно было поделиться, например, через nbviewer, нужно ставить ipywidgets 6.0.0 и widgetsnbextension 2.0.0 - nbviewer пока не поддерживает более новые версии. С другой стороны, nbviewer всё равно не может отображать все виджеты корректно.
#Импорт библиотек
import datetime
import time
import ipywidgets as widgets
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
from ipywidgets import interact, interact_manual, interactive
%matplotlib inline
from IPython.display import display
Во-первых, можно просто отобразить виджет сам по себе.
widgets.IntSlider()
Но это просто создаёт слайдер, с которым можно поиграться, а пользы от него нет. Следующим шагом является создание переменной с виджетом
w = widgets.IntSlider(value=2)
w
И теперь мы можем получить значение виджета и использовать для чего-нибудь.
print(w.value, w.value ** 2)
Другой вариант - отображение виджета с помощью функции IPython display; это работает точно также как и сам вызов переменной.
display(w)
Вы передвигали слайдер в прошлой ячейке? Если нет - попробуйте. Можно заметить, что слайдер двигается в обеих ячейках, где была использована переменная w. Это нормальное поведение - у нас есть лишь один объект на back-end, так что получаются синхронизированные объекты на front-end.
После того как в виджете было установлено некое значение, виджет можно закрыть командой w.close()
.
Пока мы видели простые виджеты, значения которых можно было использовать в дальнейшем. Если же хочется, чтобы с выбранным значением что-то произошло сразу, стоит использовать interact
. interact
позволяет вызывать функцию, в которую передаётся значение виджета. При изменении значения виджета функция будет динамически показывать обновлённый результат.
def f(x):
return x, str(x) * 2
interact(f, x=10);
Замечу, что в interact
обязательно передавать начальное значение, поскольку это напрямую определяет тип виджета. Если передать int или float, то будет слайдер с соответствующими данными (как это показано выше).
Кроме того можно передать:
interact(f, x='Текст');
interact(f, x=['лопата', 'солнце']);
interact(f, x=True);
Кому-то может быть интересна возможность использовать interact
в качестве декоратора. В таком случае функцию можно не передавать в interact
.
@interact(x=1.0)
def g(x):
return x
Наконец, есть такая интересная штука как interactive
. По сути это является комбинацией двух предыдущих спообов: мы задаем функцию, а потом можем использовать как сами результаты, так и значения отдельных виджетов.
По умолчанию interactive
показывает только сами виджеты, но не результат функции. Чтобы увидеть результат, надо явно его отображать, используя display
.
Замечу, что можно использовать больше одной переменной и получить больше одного виджета.
def f(x, y, z):
if z == 'Сумма':
display(x + y)
return x + y
else:
display(x * y)
return x * y
w = interactive(f, x=1, y=2.5, z=['Сумма', 'Произведение'])
w
print(w.kwargs)
print(w.result)
До сих пор я показывал отдельные виджеты и простые способы их использования, но с ними можно делать много интересных вещей. Просто перечислять их довольно нудно, поэтому я буду приводить примеры и на их основе объяснять возможности.
Мы уже видели, что в interact
можно передавать функцию, результат которой будет обновляться при изменении параметров. Интереснее посмотреть это на примере построения графиков. Я хочу сделать график, который будет зависеть от задаваемого параметра, а также предложить возможность выбирать цвет графика.
Для начала нужно создать виджет для выбора цвета. Вообще говоря виджеты можно передавать в функцию как значение параметра, но это громоздко, поэтому удобнее создать виджет, а потом передавать его в виде переменной.
Виджеты имеют 2 группы свойств: общие (например, описание или начальное значение) и специфичные для типа виджета (например, границы для числовых виджетов).
Этот виджет имеет следующие параметры:
pick_color = widgets.ColorPicker(
concise=False,
description='Цвет линии:',
value='teal',
disabled=False
)
Теперь сам интерактивный виджет. Функция для построения графика будет иметь 2 параметра:
Далее использую interact
:
def h(n=3, c='orange'):
x = np.linspace(0, 5, 10)
plt.plot(x, x ** (n / (x + 1)) + x ** (x / n) / (n ** 2) + (n - x) ** 2 - x * np.log(n) + n * np.exp(x / n), color=c)
plt.show()
interact(h, n=[i for i in range(2, 6)], c=pick_color);
Виджеты позволяют делать вызов функции после определённых событий:
Кроме того можно связать виджеты - чтобы при изменении значения одного виджета изменялось значение другого виджета.
Рассмотрим пример: пользователь задаёт длины сторон прямоугольника и хочет узнать его площадь. Для начала я задаю 2 виджета с соответсвующими названиями. Для ограничения значений можно задать минимальное и максимальное значение, а также шаг, с которым будут изменяться значения.
x1 = widgets.IntSlider(min=2, max=40.0, step=2, description='Высота')
x2 = widgets.FloatSlider(min=2, max=80.0, step=0.5, description='Ширина', value=5.0)
Добавим ограничение - высота прямоугольника не может быть больше его ширины. Для этого используется observe
- при каждом изменении объекта мгновенно вызывается функция. А в функции мы будет приравнивать максимальное значение виджета x к текущему значению виджета y.
def update_x1_range(*args):
x1.max = x2.value
x2.observe(update_x1_range, 'value')
Теперь создадим кнопку, при нажатии на которую будет происходить вычисление. Для этого задаём соответствующий объект. И здесь в первый раз используется настройка внешнего вида виджетов. layout
позволяет настраивать css объектов. Большинство параметров взять из самого CSS, но есть и различия, почитать подробнее можно тут. В данном случае я просто задаю ширину кнопки.
При нажатии на кнопку будет показана площадь прямоугольника, кнопка и слайдеры станут неактивными (значение disabled
становится True
).
button1 = widgets.Button(description="Нажмите, чтобы посчитать площадь прямоугольника!", layout=widgets.Layout(width='40%'))
def on_button_clicked(b):
print('Площадь прямоугольника: {}.'.format(x1.value * x2.value))
button1.disabled = True
x1.disabled = True
x2.disabled = True
def stat(x1, x2):
print('Высота: {0}. Ширина: {1}.'.format(x1, x2))
interact(stat, x1=x1, x2=x2);
display(button1)
button1.on_click(on_button_clicked)
Для полноты картины добавлю ещё одну кнопку, которая откроет данные для ввода, чтобы можно было ещё раз посчитать площать прямоугольника.
Стоит заметить, что старые результаты по умолчанию остаются, а новые появляются на следующих строках.
button2 = widgets.Button(description="Использовать другие данные", layout=widgets.Layout(width='40%'))
def on_button_clicked2(b):
button1.disabled = False
x1.disabled = False
x2.disabled = False
display(button2)
button2.on_click(on_button_clicked2)
На основе игрушечного примера о заказе компьютера я продемонстрирую большое количество разнообразных виджетов и то, как они могут быть использованы.
Для начала мы предлагаем пользователю выбрать интересующий его товар. Этот виджет позволяет выбрать одно значение из списка.
print('Выбор товара:')
pc_type = widgets.Select(
options=['Компьютер', 'Планшет', 'Ноутбук'],
value='Компьютер',
description='Товар:'
)
pc_type
Теперь предложим указать количество товара. jslink
связывает 2 виджета, имеющих сравнимые значения (например числа), либо изменяет значения виджетов согласно заданному правилу (например, при положительных значениях получается один текст, при неотрицательных - другой).
Также здесь используется новый виджет - BoundedIntText
. Это поле для ввода integer, для которого можно задать минимальные и максимальные значения. Можно попробовать ввести значение вне заданных пределов, но после того, как будет выделено что-то другое, значение сбросится к ближайшему значению из пределов.
a = widgets.BoundedIntText(min=1, max=5)
b = widgets.IntSlider(min=1, max=5)
print('Укажите количество - введите число или выберите нужное значение')
display(a, b)
mylink = widgets.jslink((a, 'value'), (b, 'value'))
В качестве шутки предложим выбрать мощность покупаемой техники. Для этого используется виджет-слайдер для которого можно добавить ранжированный список текстовых значений.
power = widgets.SelectionSlider(
options=['калькулятор', 'хороший', 'мощный', 'deep learning', 'kaggle'],
value='хороший',
description='Мощность:',
disabled=False,
orientation='horizontal',
readout=True, layout=widgets.Layout(width='40%')
)
power
А теперь подарим клиенту бонус. Это виджет для множественного выбора с помощью клавиш Ctrl/Shift.
sel_mult = widgets.SelectMultiple(
options=['Ручка', 'Стикер', 'Скидка'],
value=['Стикер'],
#rows=10,
description='Бонусы:',
disabled=False
)
sel_mult
Заказ укомплектован, теперь пора обговорить условия доставки. Первое - как будет доставлен товар. RadioButtons
, как и Select
, даёт возможность выбора одной опции.
Заодно познакомимся с такой удобной штукой как HBo
x. Он позволяет делать более гибкую настройку отображения виджетов и их описания. Например, изменять ширину описания виджета можно его свойствами, а можно описание и виджет вложить внутрь Box
. HBox
и VBox
являются соответственно горизонтальными и вертикальными контейнерами для виджетов или их описаний.
delivery = widgets.RadioButtons(
options=['Доставка', 'Самовывоз'],
disabled=False
)
widgets.HBox([widgets.Label(value="Способ доставки:"), delivery])
Настала пора выбрать способ оплаты. ToggleButtons
выводит кнопки, одна из которых может быть нажата. Виджет позволяет настроить названия кнопок, всплывающие тултипы и даже иконки (для задания иконок используются названия иконок для Font Awesome).
Также здесь используется задание параметров виджета используя style
. Это дополнительный способ (по отношению к layout
), но это уже не css, а внутренние свойства виджетов. Есть ряд свойств, которые относятся только к определённым виджетам.
pay_method = widgets.ToggleButtons(
options=['Карта', 'Наличные'],
description='Способ оплаты:',
disabled=False,
button_style='success',
tooltips=['Карта', 'Наличные'],
icons=['credit-card', 'money']
)
pay_method.style.button_width='100px'
pay_method
Ещё есть виджет для выбора даты доставки.
date = widgets.DatePicker(
description='',
disabled=False
)
date
widgets.VBox([widgets.Label(value="Дата доставки:"), date])
Дата вполне может быть выбрана неверно. Допустим мы позволяет выбрать дату в промежутке от 2 до 7 дней от текущего. Сделаем проверку.
Для отображения результата будет использован виджет Valid
, который показывает валидность.
button3 = widgets.Button(description="Проверить дату", layout=widgets.Layout(width='40%'))
def on_button_clicked3(d):
valid = widgets.Valid(
value=False,
description='Корректная дата!',
)
valid.style.description_width='200px'
if date.value == None:
valid.description='Некорректная дата!'
display(valid)
print('Дата доставки не указана.')
elif (date.value - datetime.datetime.today().date()).days in range(2,8):
valid.value = True
display(valid)
else:
valid.description='Некорректная дата!'
display(valid)
print('Дата доставки должна быть в периоде 2-7 дней от текущей даты.')
display(button3)
button3.on_click(on_button_clicked3)
Теперь можно выбрать время дня, в которое следует осуществить доставку. IntRangeSlider
позволяет указать интервал.
period = widgets.IntRangeSlider(
value=[9, 18],
min=7,
max=22,
step=1,
description='Время:',
disabled=False,
continuous_update=False,
orientation='vertical',
readout=True,
readout_format='',
)
period
И, конечно, есть виджет для ввода текста. Для ввода короткого текста можно использовать Text, для текста побольше - Textarea.
Здесь мы видим событие on_submit при вводе текста - оно происходит после ввода текста и нажатия Enter.
text_comment = widgets.Text(
value=' ',
description='Комментарий к доставке:',
disabled=False
)
text_comment
def text_submit(t=text_comment):
print("Комментарий '{0}' зафиксирован.".format(text_comment.value.strip()))
text_comment.style.description_width='200px'
display(text_comment)
text_comment.on_submit(text_submit)
Заказ оформлен, теперь надо бы показать клиенту все, что он указывал раньше, и предложить ввести адрес доставки. Первый вариант этого - сделать вложенные VBox
и HBox
, второй вариант - использовать Accordion
и Tab
.
Предварительно я "поворачиваю" слайдер для выбора временного периода доставки в горизонтальное положение, а также создаю новый виджет для ввода адреса доставки. Textarea
позволяет задавать значение по умолчанию, а также значение, которое будет отображаться, если очистить поле.
Виджет Tab
содержит в себе Accordion
. Accordion
, в свою очередь, содержит в себе обычные виджеты, каждый из которых хранится на отдельной мини-вкладке. Это осуществляется перез параметр children
. Названия этих мини-вкладок задаются для соответствующих индексов через set_title
. Подобным образом Accordion
вкладывается в Tab
.
period.orientation='horizontal'
address = widgets.Textarea(
value='Адрес',
placeholder='Не дом и не улица',
description='Адрес:',
disabled=False
)
tab_nest = widgets.Tab()
accordion1 = widgets.Accordion(children=[pc_type, b, power, sel_mult])
accordion1.set_title(0, 'Товар:')
accordion1.set_title(1, 'Количество:')
accordion1.set_title(2, 'Мощность:')
accordion1.set_title(3, 'Бонус:')
accordion2 = widgets.Accordion(children=[widgets.HBox([widgets.Label(value="Способ доставки:"), delivery]),
pay_method,
widgets.VBox([widgets.Label(value="Дата доставки:"), date]),
period,
text_comment, address])
accordion2.set_title(0, 'Способ доставки:')
accordion2.set_title(1, 'Способ оплаты:')
accordion2.set_title(2, 'Дата доставки:')
accordion2.set_title(3, 'Время доставки:')
accordion2.set_title(4, 'Комментарий:')
accordion2.set_title(5, 'Адрес доставки:')
tab_nest.children = [accordion1, accordion2]
tab_nest.set_title(0, 'Заказ:')
tab_nest.set_title(1, 'Доставка:')
tab_nest
На завершающем этапе пользователь видит итоговую информацию о заказе.
Во-первых, используется виджет для отображения прогресса. Самый удобный способ обновлять его значение - увеличивать его value
при определенном событии.
progress = widgets.IntProgress(
value=0,
min=0,
max=10,
step=1,
description='',
bar_style='success',
orientation='horizontal'
)
Ещё один интересный виджет - Out
. Он отображает то, что передаётся в него: это может быть просто печать данных через print
, rich text, media и другие вещи.
out = widgets.Output()
out
button4 = widgets.Button(description="Проверить данные", layout=widgets.Layout(width='40%'))
def on_button_clicked4(d):
with out:
display(widgets.VBox([widgets.Label(value="Проверка информации заказе:"), progress]))
print('Информация о заказе:')
for i in range(len(accordion1.children)):
if type(accordion1.children[i].value) != tuple:
print(accordion1.get_title(i), accordion1.children[i].value)
progress.value +=1
time.sleep(0.5)
else:
print(accordion1.get_title(i), ' '.join([j for j in accordion1.children[i].value]))
progress.value +=1
time.sleep(0.5)
#print(accordion1.get_title(i)), [print(j) for j in accordion1.children[i].value]
for i, e in enumerate([delivery, pay_method, date, period, text_comment, address]):
print(accordion2.get_title(i), e.value)
progress.value +=1
time.sleep(0.5)
display(button4)
button4.on_click(on_button_clicked4)
Поскольку этот гайд о виджетах, а не об оформлении доставки, я не делаю много вещей, которые следовало бы делать: проверка на заполненность и адекватность значений, разные возможности при выборе самовывоза и доставки и т. д.
Я описал почти все возможности и способы применения ipywidgets. Есть ещё некоторые, но они являются более глубокими и будут реже использоваться, поэтому не буду заострять на этом внимание.
Поскольку наш курс посвящён машинному обучению, я решил сделать дополнительную часть, где с помощью виджетов можно поиграть с датасетом iris и попробовать разные алгоритмы машинного обучения. Это простой пример того, как виджеты могут использоваться для создания интерфейса, который может быть понятным простому пользователю.
В ячейке ниже будет импорт всех библиотек, определение функций и задание виджетов, чтобы дальше ничто не отвлекало от взаимодействия с интерфейсом. В этой ячейке содержится следующее:
Стоит заметить, что для запуска классификации используется interact_manual
, а не просто interact
. В результате появляется кнопка для запуска, и не происходит автоматический пересчёт результатов. Это довольно удобно, иначе при передвижении слайдеров модели несколько раз пересчитывались бы.
from sklearn import linear_model
from sklearn.cluster import KMeans
from sklearn.datasets import load_iris
from sklearn.decomposition import PCA
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import adjusted_rand_score
from sklearn.model_selection import cross_val_score, train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.neural_network import MLPClassifier
from sklearn.svm import SVC
from sklearn.tree import DecisionTreeClassifier
iris = load_iris()
X = iris.data
y = iris.target
data = pd.DataFrame(np.concatenate((X, y.reshape(-1, 1)), axis=1), columns=iris.feature_names + ['y'])
def pp(kind='scatter', diag_kind='hist'):
sns.pairplot(data, hue='y', kind=kind, diag_kind=diag_kind, vars=iris.feature_names);
def dp(graph_type='distr', variable=iris.feature_names[0]):
if graph_type == 'distr':
sns.distplot(data[variable]);
elif graph_type == 'box':
sns.boxplot(y=variable, orient='v', width=0.2, x="y", data=data)
else:
sns.stripplot(x="y", y=variable, data=data, jitter=True);
c = widgets.Checkbox(
value=True,
description='Stratify',
disabled=False
)
ts = widgets.FloatSlider(value=0.25, min=0.05, max=0.4, description='Test_size', step=0.05)
ts.style.handle_color = 'lightblue'
def plot_graph(clf, X_train, y_train):
x_min, x_max = X_train[:, 0].min() - .5, X_train[:, 0].max() + .5
y_min, y_max = X_train[:, 1].min() - .5, X_train[:, 1].max() + .5
xx, yy = np.meshgrid(np.arange(x_min, x_max, .02), np.arange(y_min, y_max, .02))
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.figure(1, figsize=(4, 3))
plt.pcolormesh(xx, yy, Z)
plt.scatter(X_train[:, 0], X_train[:, 1], c=y_train, edgecolor='k')
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())
plt.xlabel('Признак 1')
plt.ylabel('Признак 2')
plt.show()
def kn(n_neighbors=5, weights='uniform', test_size=ts.value, strat=c.value):
X1 = PCA(n_components=2).fit_transform(X)
if c.value == True:
X_train, X_valid, y_train, y_valid = train_test_split(X1, y, test_size=test_size, stratify=y)
else:
X_train, y_train, X_valid, y_valid = train_test_split(X1, y, test_size=test_size, stratify=None)
clf = KNeighborsClassifier(n_neighbors=n_neighbors, weights=weights)
clf.fit(X_train, y_train)
plot_graph(clf, X_train, y_train)
print('Точность на кросс-валидации: {0:.2f}%.'.format(cross_val_score(clf, X_train, y_train).mean() * 100))
print('Точность на отложенной выборке: {0:.2f}%.'.format((np.sum(y_valid == clf.predict(X_valid)) / len(y_valid)) * 100))
def lr(reg=1.0, fi=True, solver='newton-cg', multi_class='ovr', test_size=ts.value, strat=c.value):
X1 = PCA(n_components=2).fit_transform(X)
if c.value == True:
X_train, X_valid, y_train, y_valid = train_test_split(X1, y, test_size=test_size, stratify=y)
else:
X_train, y_train, X_valid, y_valid = train_test_split(X1, y, test_size=test_size, stratify=None)
clf = linear_model.LogisticRegression(C=reg, fit_intercept=fi, solver=solver, max_iter=1000, multi_class=multi_class)
clf.fit(X_train, y_train)
plot_graph(clf, X_train, y_train)
print('Точность на кросс-валидации: {0:.2f}%.'.format(cross_val_score(clf, X_train, y_train).mean() * 100))
print('Точность на отложенной выборке: {0:.2f}%.'.format((np.sum(y_valid == clf.predict(X_valid)) / len(y_valid)) * 100))
def svc(reg=1.0, kernel=True, sfs='ovr', test_size=ts.value, strat=c.value):
X1 = PCA(n_components=2).fit_transform(X)
if c.value == True:
X_train, X_valid, y_train, y_valid = train_test_split(X1, y, test_size=test_size, stratify=y)
else:
X_train, y_train, X_valid, y_valid = train_test_split(X1, y, test_size=test_size, stratify=None)
clf = SVC(C=reg, kernel=kernel, decision_function_shape=sfs)
clf.fit(X_train, y_train)
plot_graph(clf, X_train, y_train)
print('Точность на кросс-валидации: {0:.2f}%.'.format(cross_val_score(clf, X_train, y_train).mean() * 100))
print('Точность на отложенной выборке: {0:.2f}%.'.format((np.sum(y_valid == clf.predict(X_valid)) / len(y_valid)) * 100))
def dt(criterion='gini', min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, test_size=ts.value,
strat=c.value):
X1 = PCA(n_components=2).fit_transform(X)
if c.value == True:
X_train, X_valid, y_train, y_valid = train_test_split(X1, y, test_size=test_size, stratify=y)
else:
X_train, y_train, X_valid, y_valid = train_test_split(X1, y, test_size=test_size, stratify=None)
clf = DecisionTreeClassifier(criterion=criterion, max_depth=None, min_samples_split=2, min_samples_leaf=min_samples_leaf,
min_weight_fraction_leaf=min_weight_fraction_leaf, max_features=None)
clf.fit(X_train, y_train)
plot_graph(clf, X_train, y_train)
print('Точность на кросс-валидации: {0:.2f}%.'.format(cross_val_score(clf, X_train, y_train).mean() * 100))
print('Точность на отложенной выборке: {0:.2f}%.'.format((np.sum(y_valid == clf.predict(X_valid)) / len(y_valid)) * 100))
def rf(n_estimators=10, criterion='gini', min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0,
test_size=ts.value, strat=c.value):
X1 = PCA(n_components=2).fit_transform(X)
if c.value == True:
X_train, X_valid, y_train, y_valid = train_test_split(X1, y, test_size=ts.value, stratify=y)
else:
X_train, y_train, X_valid, y_valid = train_test_split(X1, y, test_size=ts.value, stratify=None)
clf = RandomForestClassifier(n_estimators=10, criterion=criterion, max_depth=None, min_samples_split=min_samples_split,
min_samples_leaf=min_samples_leaf, min_weight_fraction_leaf=min_weight_fraction_leaf,
max_features='auto')
clf.fit(X_train, y_train)
plot_graph(clf, X_train, y_train)
print('Точность на кросс-валидации: {0:.2f}%.'.format(cross_val_score(clf, X_train, y_train).mean() * 100))
print('Точность на отложенной выборке: {0:.2f}%.'.format((np.sum(y_valid == clf.predict(X_valid)) / len(y_valid)) * 100))
def mlp(hidden_layers=10, nodes=100, activation='relu', solver='adam', alpha=0.0001, test_size=ts.value, strat=c.value):
X1 = PCA(n_components=2).fit_transform(X)
if c.value == True:
X_train, X_valid, y_train, y_valid = train_test_split(X1, y, test_size=ts.value, stratify=y)
else:
X_train, y_train, X_valid, y_valid = train_test_split(X1, y, test_size=ts.value, stratify=None)
clf = MLPClassifier(hidden_layer_sizes=tuple([nodes for i in range(3)]), activation=activation, solver=solver,
alpha=alpha, max_iter=2000)
clf.fit(X_train, y_train)
plot_graph(clf, X_train, y_train)
print('Точность на кросс-валидации: {0:.2f}%.'.format(cross_val_score(clf, X_train, y_train).mean() * 100))
print('Точность на отложенной выборке: {0:.2f}%.'.format((np.sum(y_valid == clf.predict(X_valid)) / len(y_valid)) * 100))
def km(n_clusters=3):
reduced_data = PCA(n_components=2).fit_transform(X)
kmeans = KMeans(init='k-means++', n_clusters=n_clusters)
kmeans.fit(reduced_data)
x_min, x_max = reduced_data[:, 0].min() - 1, reduced_data[:, 0].max() + 1
y_min, y_max = reduced_data[:, 1].min() - 1, reduced_data[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02), np.arange(y_min, y_max, 0.02))
Z = kmeans.predict(np.c_[xx.ravel(), yy.ravel()]).reshape(xx.shape)
plt.figure(1)
plt.imshow(Z, interpolation='nearest',
extent=(xx.min(), xx.max(), yy.min(), yy.max()),
cmap=plt.cm.Paired,
aspect='auto', origin='lower')
plt.plot(reduced_data[:, 0], reduced_data[:, 1], 'k.', markersize=2)
centroids = kmeans.cluster_centers_
plt.scatter(centroids[:, 0], centroids[:, 1], marker='x', s=169, linewidths=3, color='w', zorder=10)
plt.title('K-means кластеризация')
plt.xlim(x_min, x_max)
plt.ylim(y_min, y_max)
plt.xlabel('Признак 1')
plt.ylabel('Признак 2')
plt.show()
print('Adjusted Rand Index: {0:.2f}%.'.format(adjusted_rand_score(y, kmeans.labels_) * 100))
print('Pairplot показывает взаимодействие между переменными в датасете')
interact(pp, kind=['scatter', 'reg'], diag_kind=['hist', 'kde']);
print('Распределение переменных:')
interact(dp, graph_type=['distr', 'box', 'swarm'], variable=iris.feature_names);
print('Параметры разбиения тренировочных данных:')
display(ts)
display(c)
print('Кластеризация с помощью KMeans:')
interact_manual(km, n_clusters=(2,50));
print('Классификация с помощью KNeighborsClassifier:')
interact_manual(kn, n_neighbors=(1,50), weights=['uniform', 'distance']);
print('Классификация с помощью Logistic Regression:')
interact_manual(lr, reg=np.logspace(-3, 1, 10), fi=True, solver=['newton-cg', 'sag', 'saga', 'lbfgs'],
multi_class=['ovr', 'multinomial']);
print('Классификация с помощью SVC:')
interact_manual(svc, reg=np.logspace(-3, 1, 10), kernel=['linear', 'poly', 'rbf', 'sigmoid'], sfs=['ovr', 'ovo']);
print('Классификация с помощью Decision Tree:')
interact_manual(dt, criterion=['gini', 'entropy'], min_samples_split=(2,30), min_samples_leaf=(1,30),
min_weight_fraction_leaf=(0.0, 0.5));
print('Классификация с помощью Random Forest:')
interact_manual(rf, n_estimators=(2, 100), criterion=['gini', 'entropy'], min_samples_split=(2,30), min_samples_leaf=(1,30),
min_weight_fraction_leaf=(0.0, 0.5));
print('Классификация с помощью Multi-layer Perceptron:')
interact_manual(mlp, hidden_layers=(1, 10), nodes=(3, 100), activation=['identity', 'logistic', 'tanh', 'relu'],
solver=['lbfgs', 'sgd', 'adam'], alpha=np.logspace(-3, 1, 10));