from __future__ import division, print_function
# отключим всякие предупреждения Anaconda
import warnings
warnings.filterwarnings('ignore')
%pylab inline
import seaborn as sns
import pandas as pd
from sklearn.preprocessing import scale
from sklearn import svm
from scipy import stats
from sklearn.decomposition import PCA
Считываем данные по моделям Playboy.
girls = pd.read_csv('data/girls.csv', header=0)
Процент "выбросов", задаваемый пользователем. Ищем 1% выбросов в данных, то есть ограничимся 6-7 «странными» девушками. (Переменные в Python, записанные в верхнем регистре, символизируют константы и обычно записываются в начале файла после подключения модулей).
OUTLIER_FRACTION = 0.01
Посмотрим общую статистику девушек.
girls.info()
Дальше узнаем про девушек побольше.
girls.describe()
Посмотрим на выбросы, которые бросаются в глаза.
girls[girls['Waist'] == 89]
Для красоты можно еще построить и гистограммы распределения параметров девушек.
Распределение охвата груди.
girls['Bust'].hist(bins=40, facecolor='blue', label="Bust")
Распределение охвата талии.
girls['Waist'].hist(bins=40, label="Waist", facecolor='red')
Распределение охвата бедер.
girls['Hips'].hist(bins=40, label="Hips", facecolor='green')
Распределение роста.
girls['Height'].hist(bins=40, label="Height", facecolor='cyan')
Распределение веса.
girls['Weight'].hist(bins=40, label="Weight", facecolor='yellow')
sns.pairplot(girls[['Bust', 'Waist', 'Hips', 'Height', 'Weight']])
Убираем признаки месяц
и год
.
girl_params = np.array(girls.values[:,2:], dtype="float64")
Шкалируем данные.
girl_params = scale(girl_params)
Выделяем в них две главные компоненты.
X = PCA(n_components=2).fit_transform(girl_params)
Для обнаружения «выбросов» в данных используем одноклассовую машину опорных векторов. Создаем SVM классификатор с гауссовым ядром.
svm_clf = svm.OneClassSVM(kernel="rbf")
"Скармливаем" ему данные.
svm_clf.fit(X)
В результате обучения алгоритма получаем вектор индикаторов, является ли объект "выбросом".
dist_to_border = svm_clf.decision_function(X).ravel()
threshold = stats.scoreatpercentile(dist_to_border,
100 * OUTLIER_FRACTION)
is_outlier = dist_to_border < threshold
Визуализация.
girls_num = girl_params.shape[0]
xx, yy = np.meshgrid(np.linspace(-7, 7, 500), np.linspace(-7, 7, 500))
n_inliers = int((1. - OUTLIER_FRACTION) * girls_num)
n_outliers = int(OUTLIER_FRACTION * girls_num)
Z = svm_clf.decision_function(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.title("Outlier detection")
plt.contourf(xx, yy, Z, levels=np.linspace(Z.min(), threshold, 7),
cmap=plt.cm.Blues_r)
a = plt.contour(xx, yy, Z, levels=[threshold],
linewidths=2, colors='red')
plt.contourf(xx, yy, Z, levels=[threshold, Z.max()],
colors='orange')
b = plt.scatter(X[is_outlier, 0], X[is_outlier, 1], c='black')
c = plt.scatter(X[is_outlier == 0, 0], X[is_outlier == 0, 1], c='white')
plt.axis('tight')
plt.legend([a.collections[0], b, c],
['learned decision function', 'outliers', 'inliers'],
prop=matplotlib.font_manager.FontProperties(size=11))
plt.xlim((-7, 7))
plt.ylim((-7, 7))
Смотрим на "выбросы" - девушек с параметрами, отличающимися от средних.
girls[is_outlier]