import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
plt.style.use('ggplot')
plt.rcParams['figure.figsize'] = (12,5)
# Для кириллицы на графиках
font = {'family': 'Verdana',
'weight': 'normal'}
plt.rc('font', **font)
try:
from ipywidgets import interact, IntSlider, fixed, FloatSlider
except ImportError:
print u'Так надо'
Загрузите файл food.txt
. В нем содержится информация о пищевой ценности разных продуктов
Почему перед применением кластеризации признки необходимо нормализовать?
from scipy.cluster.hierarchy import dendrogram, fcluster, linkage
df = pd.read_csv('food.txt', sep=' ')
df.head()
Name | Energy | Protein | Fat | Calcium | Iron | |
---|---|---|---|---|---|---|
0 | Braised beef | 340 | 20 | 28 | 9 | 2.6 |
1 | Hamburger | 245 | 21 | 17 | 9 | 2.7 |
2 | Roast beef | 420 | 15 | 39 | 7 | 2.0 |
3 | Beefsteak | 375 | 19 | 32 | 9 | 2.6 |
4 | Canned beef | 180 | 22 | 10 | 17 | 3.7 |
from sklearn.datasets import load_iris
from sklearn.metrics import adjusted_rand_score, silhouette_samples, silhouette_score
from sklearn.cluster import KMeans
Загрузите данные в которых содержится описание интересов профилей учеников старшей школы США.
df_sns = pd.read_csv('snsdata.csv', sep=',')
df_sns.head()
Данные устроены так:
from sklearn.cluster import KMeans
from sklearn.feature_extraction.text import TfidfTransformer
## Your Code Here
Загрузите геоданные из geo_data.txt
(uid, timestamp, lat, lon, location_id).
Будем пытаться кластеризовать данные с помощью DBSCAN и меры haversine
import mpl_toolkits.basemap as bm
from sklearn.cluster import DBSCAN
from sklearn.neighbors import NearestNeighbors
df_geo = pd.read_csv('geo_data.txt', sep='\t', header=None,
names=['lat', 'lon'])/10000
df_geo.head()
def plot_geo(lat, lon, labels=None):
try:
lllat, lllon = lat.min()-1, lon.max()+1
urlat, urlon = lat.max()+1, lon.min()-1
plt.figure(figsize=(10, 10))
m = bm.Basemap(
llcrnrlon=lllon,
llcrnrlat=lllat,
urcrnrlon=urlon,
urcrnrlat=urlat,
projection='merc',
resolution='h'
)
m.drawcoastlines(linewidth=0.5)
m.drawmapboundary(fill_color='#47A4C9', zorder=1)
m.fillcontinents(color='#EBC4D8',lake_color='#47A4C9', zorder=2)
parallels = np.linspace(lllat, urlat, 10)
m.drawparallels(parallels,labels=[1,0,0,0],fontsize=10)
# draw meridians
meridians = np.linspace(urlon, lllon, 10)
m.drawmeridians(meridians,labels=[0,0,0,1],fontsize=10)
m.scatter(lon, lat, latlon=True, cmap=plt.cm.jet,
zorder=3, lw=0, c=labels)
except:
print 'что-то пошло не так'
plt.scatter(x=lon, y=lat, c=labels, cmap=plt.cm.jet)
plt.axis('equal')
Для начала нарисуем все точки на карте
plot_geo(df_geo.lat.values, df_geo.lon.values)
Мы будем использовать расстояние haversine - на входе требуются координаты в радианах. Выход тоже будет в радианах. Чтобы перейти от градусов в радианты мы можем вспомнить тригонометрию, а можем воспользоваться функцией np.radians
.
Для кого, чтобы не терять связь с реальностью, будем иметь ввиду, что расстояние в 1 радиан на земном шаре равно примерно 6371.0088 километрам.
Создайте матрицу X с координатами в радианах
km_in_radian = 6371.0088
X = ...
Как же определить, какие параметры для DBSCAN выставлять? Наибольшую проблемы представляет параметр eps.
Будем считать, что MinPts нам дан свыше (например MinPts = 20). Воспользуемся эвристикой, схожей с методом локтя для оценки eps:
NearestNeighbors
и метод kneighbors
)nn = NearestNeighbors(n_neighbors=20, algorithm='ball_tree', metric='haversine')
nn.fit(X)
## Your Code Here
Определим eps мы можем начать кластеризацию
dbscan = DBSCAN(...)
## Your Code Here