from IPython.core.display import HTML
HTML("""
<style>
div.cell { /* Tunes the space between cells */
margin-top:1em;
margin-bottom:1em;
}
div.text_cell_render h1 { /* Main titles bigger, centered */
font-size: 2.2em;
line-height:1.4em;
text-align:center;
}
div.text_cell_render h2 { /* Parts names nearer from text */
margin-bottom: -0.4em;
}
div.text_cell_render { /* Customize text cells */
font-family: 'Times New Roman';
font-size:1.5em;
line-height:1.4em;
padding-left:3em;
padding-right:3em;
}
</style>
""")
http://mlbootcamp.ru/round/6/sandbox/
Дано 30 бинарных признаков и 3 целевых класса. В качестве критерия качества решения задачи будет приниматься точность классификации, т.е. доля правильно классифицированных объектов.
%matplotlib inline
import pandas as pd
import numpy as np
from scipy import stats
from matplotlib import pyplot as plt
from matplotlib import cm # импортируем цветовые схемы, чтобы рисовать графики.
plt.rcParams['figure.figsize'] = 12, 8 # увеличиваем размер картинок
import seaborn as sns
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import StratifiedKFold, GridSearchCV, cross_val_score
from sklearn.manifold import TSNE
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.linear_model import SGDClassifier, LogisticRegression, RidgeClassifier
from sklearn.dummy import DummyClassifier
from xgboost import XGBClassifier
from sklearn.ensemble import VotingClassifier
from sklearn.feature_extraction.text import CountVectorizer
import statsmodels.api as sm
def read_train():
X_train = pd.read_csv('data_public/x_train.csv', header=None)
Y_train = pd.read_csv('data_public/y_train.csv', header=None, names=['target'])
data = pd.concat([X_train, Y_train], axis=1)
return data, X_train, Y_train.target
data, X_train, Y_train = read_train()
print(data.shape)
data.head()
# проверим пропуски и то как распределены значения признаков
data.describe()
def examine(clf, X, y):
cv = StratifiedKFold(n_splits=5)
scores = cross_val_score(clf, X, y, cv=3, scoring='accuracy')
print("{}. Score: {} (+/- {})".format(clf.__class__.__name__,scores.mean(), scores.std() * 2))
clf = LogisticRegression()
examine(clf, X_train, Y_train)
clf = DummyClassifier()
examine(clf, X_train, Y_train)
clf = XGBClassifier()
examine(clf, X_train, Y_train)
Для начала посмотрим на соотношение классов. И судя по графикам, всё весьма хорошо - можно сказать, что классы сбалансированы.
sns.countplot(data=data, x='target')
Логично посмотреть на форму распределения признаков по каждому классу.
Строим для каждого элемента выборки график по его бинарным признакам. Разделим по цветам 3 разных класса. Чем чаще линия проходит через одни и те же точки, тем на графике она более толстая. По оси ординат откладывается среднее значение для данного класса принимать определенное значение признака.
Из графика видно, что в целом есть некоторые отличия в средних значениях, но в целом основная масса находится в середине. Отсюда можно сделать предположение, что признаки хорошо выровнены.
points = [[],[],[]]
for j in range(3):
for row in data[data['target'] == j].drop(['target'], axis=1).iterrows():
points[j].append(row[1])
colors = ['red', 'blue', 'green']
for j in range(3):
sns.tsplot(points[j], err_style="boot_traces", n_boot=800, color=colors[j])
colors = ['red', 'blue', 'green']
for j in range(3):
sns.tsplot(points[j], n_boot=200, color=colors[j])
points = [[],[],[]]
for j in range(3):
for row in data[data['target'] == j].drop(['target'], axis=1).T.iterrows():
points[j].append(row[1])
colors = ['red', 'blue', 'green']
for j in range(3):
sns.tsplot(points[j], n_boot=800, color=colors[j])
for j in range(3):
x = data[data['target'] == j].drop(['target'], axis=1)
plt.plot(x.mean(axis=1).sort_values().reset_index()[0], color=colors[j])
Такое ощущение, что синий график как будто немного тяжелее, чем зеленый и красный вместе. Это наверное как-то отражает внутреннюю структуру данных.
Cтандартный метод оценки степени корреляции двух последовательностей. Она часто используется для поиска в длинной последовательности более короткой заранее известной. Значительная корреляция между двумя случайными величинами всегда является свидетельством существования некоторой статистической связи в данной выборке, но эта связь не обязательно должна наблюдаться для другой выборки и иметь причинно-следственный характер.
Судя по графику признаки вообще почти не коррелируют друг с другом и с целевой переменной. Это очень странно.
corr = data.corr()
mask = np.zeros_like(corr)
mask[np.triu_indices_from(mask)] = True
with sns.axes_style("white"):
sns.heatmap(corr, square=True, mask=mask)
Если мы не знаем ничего про данные, то логично посмотреть на статистику по этим данным.
Это мера остроты пика распределения случайной величины. Коэффициент эксцесса равен 0 для нормального распределения.
$$\gamma_2 = \frac{\mu_4}{\sigma^4}-3$$def prepare_statistics(X_train, Y_train):
d = pd.DataFrame(index=X_train.index)
d['target'] = Y_train
d['kurtosis'] = X_train.kurtosis(axis=1)
d['entropy'] = X_train.apply(lambda row: stats.entropy(row), axis=1)
d['std'] = X_train.std(axis=1)
d['skew'] = X_train.skew(axis=1)
d['normal_stat'] = X_train.apply(lambda row: stats.normaltest(row)[0], axis=1)
d['mean'] = X_train.mean(axis=1)
return d
d = prepare_statistics(X_train, Y_train)
d.head()
sns.pairplot(d, hue='target')
X = d.drop(['target', 'std', 'normal_stat', 'mean', 'skew'], axis=1)
Y = d['target']
X.head(2)
sns.lmplot(x='kurtosis', y='entropy', col='target', hue='target', data=d, y_jitter=.04)