Шестаков А.В. Майнор по анализу данных - 26/01/2016
Начнем работу с матрицами пока безотносительно анализа данных. Как я заявил на самом первом семинаре, класс numpy.matrix достаточно глючный. В своё время мне порекомендовали использовать вместо него простые numpy.array.
Пока я буду следовать этому совету, но иногда рядом писать код, если бы что-то было проделано с numpy.matrix
Итак, обзор основных функций:
import numpy as np
import scipy as sp
# Задаём свою матрицу
A = np.array([[3, 1, 4], [1, 5, 9], [2, 6, 5]])
# A = np.mat([[3, 1, 4], [1, 5, 9], [2, 6, 5]])
print A
# Транспонируем
A.T
# A.A # Представляем numpy.matrix в виде numpy.array
# Устраняем одну размерность
A.flatten()
# A.A1
A + np.eye(A.shape[0])
A.dot(np.linalg.inv(A))
# A.I * A
np.linalg.matrix_power(A, 3)
# A**3 # A*A*A
b = np.array([1,2,3])
b
A.dot(b)
# A*b
b.dot(A)
# b.T * A
A.reshape(9,1)
# A.resize(9,1)
np.vstack((A,b))
# np.hstack((A,b))
np.hstack((A,b[:,np.newaxis]))
e, u = np.linalg.eig(A)
print A.dot(u)
print u.dot(np.diag(e))
Если мы имеет линейную систему $$ Ax = b, $$ то в общем виде $x$ можно попытаться найти так: $$x = A^{-1}b$$
print A
print b
x = np.linalg.inv(A).dot(b)
x
# Проверка:
A.dot(x) - b
В случае матриц не самого приятного вида ине лучших размеров, лучше воспользоваться другими способами, например:
np.linalg.solve(A, b)
from scipy import linalg as lin
LU = lin.lu_factor(A)
lin.lu_solve(LU, b)
Для простоты рассмотрим эту тему на простом датасете - Iris.
from sklearn import datasets
iris = datasets.load_iris()
iris.keys()
iris['feature_names']
X = iris.data.copy()
X[:5, :]
y = iris.target
print y[:5]
print np.unique(y)
Расчет расстояний (схожести) между наблюдениями призват ответить на вопрос: "насколько близки (схожи) эти наблюдения". Рассмотрим наиболее известные расстояния:
Многие из вариантов можно посмотреть здесь
from scipy.spatial import distance
import matplotlib.pyplot as plt
plt.style.use('ggplot')
plt.rcParams['figure.figsize'] = (10.0, 8.0)
%matplotlib inline
d = distance.pdist(X, metric='euclidean')
D = distance.squareform(d)
D.shape
plt.figure(figsize=(10,10))
plt.imshow(D, interpolation=None)
plt.colorbar()
# Представим, что класс растений - тоже является признаком, причем номинальным.
# Считать любые из вышеперечисленных расстояний не имеет смысла
#
# Но можно сделать так:
dummy = (y[:, None] == np.unique(y)).astype(float)
dummy[:5,:]
Представьте, что в Iris признаки 2-4 стали измеряться в метрах
X[:, 1:] = X[:, 1:]/100
X[:5, :]
d = distance.pdist(X, metric='euclidean',)
D = distance.squareform(d)
plt.figure(figsize=(10,10))
plt.imshow(D, interpolation=None)
plt.colorbar()
Из-за того, что значения в первом признаке велики по сравнению со значениями в остальных признаках, то он автоматически получает бОльший вес при расчете расстояний. Выход - нормализовать признаки так, чтобы они находились в одной физической шкале
X = (X - X.mean(axis=0))/X.std(axis=0)
print X.mean(axis=0)
print X.std(axis=0)
print X.min()
print X.max()
X = (X - X.min(axis=0))/(X.max(axis=0) - X.min(axis=0))
print X.mean(axis=0)
print X.std(axis=0)
print X.min()
print X.max()
Надо понижать размерность признакового пространства. Но как?
Метод главных компонент - метод уменьшения размерности данных. Он позволяет отобрать самые "изменчивые" переменные. Но это не просто отбор.
Метод главных компонент производит замену исходных переменных на новые, т.ч.:
1. Новые переменные равны линейной комбинацией старых переменных
2. Новые переменные не коррелируют между собой
3. Новые переменные подбираются так, чтобы максимировать собственную выборочную дисперсию
Для любой матрицы $A$ размера $n \times m$ можно найти разложение вида: $$ A = U \Sigma V^\top ,$$ где
Матрицы $U$ и $V$ ортогональны и могут быть использованы для перехода к ортогональному базису: $$ AV = U\Sigma $$
Сокращение размерности заключается в том, что вместо того, чтобы умножать $A$ на всю матрицу $V$, а лишь на первые $k<m$ её столбцов - матрицу $V'$
Квадраты сингулярных чисел в $\Sigma$ содержат долю дисперсии, которая содержится в соответствующих главных компонентах
# Вновь возьмем нажу матрицу из Iris
X = iris.data.copy()
# Стандартизируем её
X = (X - X.mean(axis=0))/X.std(axis=0)
u.shape
u,s,v = np.linalg.svd(X)
PC = X.dot(v.T)
v_expl = s*s/(s*s).sum()
# Доля дисперсии в главных компонентах
plt.bar(xrange(4), v_expl)
plt.ylabel('\% of variance')
palette = plt.cm.flag
plt.scatter(PC[:,0], PC[:, 1])
А теперь, если мы успеем, давайте посмотрим на эти данные