from sklearn.datasets import load_digits
digits = load_digits()
plt.imshow(digits.images[0], interpolation='nearest');
plt.grid(False)

digits.images[0]

from sklearn.datasets import fetch_20newsgroups
news = fetch_20newsgroups()
print(news.data[0])

from sklearn.feature_extraction.text import TfidfVectorizer
vec = TfidfVectorizer(stop_words="english").fit(news.data[:100])
data = vec.transform(news.data[:100])
data

plt.imshow(data.toarray()[:,:200], interpolation='nearest');

"""
Explanation: 데이터 분석의 소개
데이터 분석이란 용어는 상당히 광범위한 용어이므로 여기에서는 통계적 분석과 머신 러닝이라는 두가지 세부 영역에 국한하여 데이터 분석을 설명하도록 한다.
데이터 분석이란
데이터 분석이란 어떤 데이터가 주어졌을 때 

데이터 간의 관계를 파악하거나
파악된 관계를 사용하여 원하는 데이터를 만들어 내는 과정

으로 볼 수 있다.
데이터 분석의 유형

예측(Prediction)
클러스터링(Clustering)
모사(Approximation)

데이터 분석의 유형은 다양하다. 그 중 널리 사용되는 전형적인 방법으로는 예측(prediction), 클러스터링(clustering), 모사(approximation) 등이 있다.
예측은 어떤 특정한 유형의 입력 데이터가 주어지면 데이터 분석의 결과로 다른 유형의 데이터가 출력될 수 있는 경우이다. 예를 들어 다음과 같은 작업은 예측이라고 할 수 있다.

부동산의 위치, 주거환경, 건축연도 등이 주어지면 해당 부동산의 가치를 추정한다.
꽃잎의 길이와 너비 등 식물의 외형적 특징이 주어지면 해당하는 식물의 종을 알아낸다.
얼굴 사진이 주어지면 해당하는 사람의 이름을 출력한다.
현재 바둑돌의 위치들이 주어지면 다음 바둑돌의 위치를 지정한다.

데이터 분석에서 말하는 예측이라는 용어는 시간상으로 미래의 의미는 포함하지 않는다. 시계열 분석에서는 시간상으로 미래의 데이터를 예측하는 경우가 있는데 이 경우에는 forecasting 이라는 용어를 사용한다.
클러스터링은 동일한 유형의 데이터가 주어졌을 때 유사한 데이터끼리 몇개의 집합으로 묶는 작업을 말한다. 예를 들어 다음과 같은 작업은 클러스터링이다.

지리적으로 근처에 있는 지점들을 찾아낸다.
유사한 단어를 포함하고 있는 문서의 집합을 만든다.
유사한 상품을 구해한 고객 리스트를 생성한다.

모사는 대량의 데이터를 대표하는 소량의 데이터를 생성하는 작업이다. 

이미지나 음악 데이터를 압축한다.
주식 시장의 움직임을 대표하는 지수 정보를 생성한다.

입력 데이터와 출력 데이터
만약 예측을 하고자 한다면 데이터의 유형을 입력 데이터와 출력 데이터라는 두 가지 유형의 데이터로 분류할 수 있어야 한다.

입력 $X$
분석의 기반이 되는 데이터
독립변수 independent variable

feature, covariates, regressor, explanatory, attributes, stimulus


출력 $Y$

추정하거나 예측하고자 하는 데이터 
종속변수 dependent variable
target, response, regressand, label, tag

예측 작업에서 생성하고자 하는 데이터 유형을 출력 데이터라고 하고 이 출력 데이터를 생성하기 위해 사용되는 기반 데이터를 입력 데이터라고 한다. 회귀 분석에서는 독립 변수와 종속 변수라는 용어를 사용하며 머신 러닝에서는 일반적으로 feature와 target이라는 용어를 사용한다.
입력 데이터와 출력 데이터의 개념을 사용하여 예측 작업을 다시 설명하면 다음과 같다.

$X$와 $Y$의 관계 $f$를 파악 한다. 

$$Y = f(X)$$

현실적으로는 정확한 $f$를 구할 수 없으므로 $f$와 가장 유사한, 재현 가능한 $\hat{f}$을 구한다.

$$Y \approx \hat{f}(X)$$


$\hat{f}$를 가지고 있다면 $X$가 주어졌을 때 $Y$의 예측(추정) $\hat{Y} = \hat{f}(X)$를 구할 수 있다.


확률론적으로 $\hat{f}$는


$$ \hat{f}(X) = \arg\max_{Y} P(Y | X) $$
예측은 입력 데이터와 출력 데이터 사이의 관계를 분석하고 분석한 관계를 이용하여 출력 데이터가 아직 없거나 혹은 가지고 있는 출력 여러가지 이유로 부정확하다고 생각될 경우 보다 합리적인 출력값을 추정하는 것이다. 따라서 입력 데이터와 출력 데이터의 관계에 대한 분석이 완료된 이후에는 출력 데이터가 필요 없어도 일단 관계를 분석하기 위해서는 입력 데이터와 출력 데이터가 모두 존재해야 한다. 
데이터의 유형
예측 작업에서 생성하고자 하는 데이터 유형을 출력 데이터라고 하고 이 출력 데이터를 생성하기 위해 사용되는 기반 데이터를 입력 데이터라고 한다.
예측은 입력 데이터와 출력 데이터 사이의 관계를 분석하고 분석한 관계를 이용하여 출력 데이터가 아직 없거나 혹은 가지고 있는 출력 여러가지 이유로 부정확하다고 생각될 경우 보다 합리적인 출력값을 추정하는 것이다. 따라서 입력 데이터와 출력 데이터의 관계에 대한 분석이 완료된 이후에는 출력 데이터가 필요 없어도 일단 관계를 분석하기 위해서는 입력 데이터와 출력 데이터가 모두 존재해야 한다. 
입력 데이터와 출력 데이터의 개념을 사용하여 예측 작업을 다시 설명하면 다음과 같다.
통계적 분석이나 머신 러닝 등의 데이터 분석에 사용되는 데이터의 유형은 다음 숫자 혹은 카테고리 값 중 하나이어야 한다. 

숫자 (number)
크기/순서 비교 가능

무한 집합


카테고리값 (category)

크기/순서 비교 불가
유한 집합
Class
Binary Class
Multi Class



숫자와 카테고리 값의 차이점은 두 개의 데이터가 있을 때 이들의 크기나 혹은 순서를 비교할 수 있는가 없는가의 차이이다. 예를 들어 10kg과 23kg이라는 두 개의 무게는 23이 "크다"라고 크기를 비교하는 것이 가능하다. 그러나 "홍길동"과 "이순신"이라는 두 개의 카테고리 값은 크기를 비교할 수 없다. 
일반적으로 카테고리 값은 가질 수 있는 경우의 수가 제한되어 있다. 이러한 경우의 수를 클래스(class)라고 부르는데 동전을 던진 결과와 같이 "앞면(head)" 혹은 "뒷면(tail)"처럼 두 가지 경우만 가능하면 이진 클래스(binary class)라고 한다. 주사위를 던져서 나온 숫자와 같이 세 개 이상의 경우가 가능하면 다중 클래스(multi class)라고 한다.
카테고리값처럼 비 연속적이지만 숫자처럼 비교 가능한 경우도 있을 수 있다. 예를 들어 학점이 "A", "B", "C", "D"와 같이 표시되는 경우는 비 연속적이고 기호로 표시되지만 크기 혹은 순서를 비교할 수 있다. 이러한 경우는 서수형(ordinal) 자료라고 하며 분석의 목표에 따라 숫자로 표기하기도 하고 일반적인 카테고리값으로 표기하기도 한다.
데이터의 변환 및 전처리
숫자가 아닌 이미지나 텍스트 정보는 분석에 목표에 따라 숫자나 카테고리 값으로 변환해야 한다. 이 때 해당하는 원본 정보를 손실 없이 그대로 숫자나 카테고리 값으로 바꿀 수도 있지만 대부분의 경우에는 분석에 필요한 핵심적인 정보만을 뽑아낸다. 이러한 과정은 데이터의 전처리(preprocessing)에 해당한다.
End of explanation
"""


from sklearn.datasets import load_boston
boston = load_boston()
print(boston.DESCR)

df = pd.DataFrame(boston.data, columns=boston.feature_names)
df["MEDV"] = boston.target
df.tail()

sns.pairplot(df[["MEDV", "RM", "AGE", "DIS"]]);

from sklearn.linear_model import LinearRegression
predicted = LinearRegression().fit(boston.data, boston.target).predict(boston.data)
plt.scatter(boston.target, predicted, c='r', s=20);
plt.xlabel("Target");
plt.ylabel("Predicted");

"""
Explanation: 예측도 출력 데이터가 숫자인가 카테고리 값인가에 따라 회귀 분석(regression analysis)과 분류(classification)로 구분된다.

회귀분석(regression)
얻고자 하는 답 $Y$가 숫자
분류 (classification)
얻고자 하는 답 $Y$가 카테고리 값

|               |   X=Real        |  X=Category     |
| ------------- | --------------- | --------------- |
|Y=Real     | Regression      | ANOVA           |
|Y=Category | Classification  | Classification  |
회귀 분석
End of explanation
"""


from sklearn.datasets import load_iris
iris = load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
sy = pd.Series(iris.target, dtype="category")
sy = sy.cat.rename_categories(iris.target_names)
df['species'] = sy
df.tail()

sns.pairplot(df, hue="species");

from sklearn.cross_validation import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC

X = iris.data[:, [2,3]]
y = iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)
sc = StandardScaler()
sc.fit(X_train)
X_train_std = sc.transform(X_train)
X_test_std = sc.transform(X_test)
model = SVC(kernel="linear", C=1.0, random_state=0)
model.fit(X_train_std, y_train)

XX_min = X_train_std[:, 0].min() - 1; XX_max = X_train_std[:, 0].max() + 1;
YY_min = X_train_std[:, 1].min() - 1; YY_max = X_train_std[:, 1].max() + 1;
XX, YY = np.meshgrid(np.linspace(XX_min, XX_max, 1000), np.linspace(YY_min, YY_max, 1000))
ZZ = model.predict(np.c_[XX.ravel(), YY.ravel()]).reshape(XX.shape)
cmap = mpl.colors.ListedColormap(sns.color_palette("Set2"))
plt.contourf(XX, YY, ZZ, cmap=cmap)
plt.scatter(X_train_std[y_train == 0, 0], X_train_std[y_train == 0, 1], c=cmap.colors[0], s=100)
plt.scatter(X_train_std[y_train == 1, 0], X_train_std[y_train == 1, 1], c=cmap.colors[2], s=100)
plt.scatter(X_train_std[y_train == 2, 0], X_train_std[y_train == 2, 1], c=cmap.colors[1], s=100)
plt.xlim(XX_min, XX_max);
plt.ylim(YY_min, YY_max);

"""
Explanation: 분류

Iris 

| setosa  |  versicolor  |  virginica |
|---|---|---|
|<img src="https://upload.wikimedia.org/wikipedia/commons/5/56/Kosaciec_szczecinkowaty_Iris_setosa.jpg" style="width: 10em; height: 10em" />|<img src="https://upload.wikimedia.org/wikipedia/commons/4/41/Iris_versicolor_3.jpg" style="width: 10em; height: 10em"  />|<img src="https://upload.wikimedia.org/wikipedia/commons/9/9f/Iris_virginica.jpg" style="width: 10em; height: 10em"  />|
End of explanation
"""


from sklearn.cluster import DBSCAN
from sklearn.datasets.samples_generator import make_blobs
from sklearn.preprocessing import StandardScaler

X, labels_true = make_blobs(n_samples=750, centers=[[1, 1], [-1, -1], [1, -1]], cluster_std=0.4, random_state=0)
X = StandardScaler().fit_transform(X)
db = DBSCAN(eps=0.3, min_samples=10).fit(X)
n_clusters_ = len(set(db.labels_)) - (1 if -1 in db.labels_ else 0)
unique_labels = set(db.labels_)

f = plt.figure()
f.add_subplot(1,2,1)
plt.plot(X[:, 0], X[:, 1], 'o', markerfacecolor='k', markeredgecolor='k', markersize=10)
plt.title('Raw Data')
f.add_subplot(1,2,2)
colors = plt.cm.Spectral(np.linspace(0, 1, len(unique_labels)))
for k, col in zip(unique_labels, colors):
    if k == -1: col = 'k'
    class_member_mask = (db.labels_ == k)
    xy = X[class_member_mask]
    plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=col, markeredgecolor='k', markersize=10);
plt.title('Estimated number of clusters: %d' % n_clusters_);

"""
Explanation: 클러스터링(Clustering)
End of explanation
"""


from sklearn.cluster import KMeans
from sklearn.metrics import pairwise_distances_argmin
from sklearn.datasets import load_sample_image
from sklearn.utils import shuffle

n_colors = 64
china = load_sample_image("china.jpg")
china = np.array(china, dtype=np.float64) / 255
w, h, d = original_shape = tuple(china.shape)
assert d == 3
image_array = np.reshape(china, (w * h, d))
image_array_sample = shuffle(image_array, random_state=0)[:1000]
kmeans = KMeans(n_clusters=n_colors, random_state=0).fit(image_array_sample)
labels = kmeans.predict(image_array)

def recreate_image(codebook, labels, w, h):
    d = codebook.shape[1]
    image = np.zeros((w, h, d))
    label_idx = 0
    for i in range(w):
        for j in range(h):
            image[i][j] = codebook[labels[label_idx]]
            label_idx += 1
    return image

print("{0:,} bytes -> {1:,} bytes : {2:5.2f}%".format(image_array.nbytes, labels.nbytes, float(labels.nbytes) / image_array.nbytes * 100.0))

f = plt.figure()
ax1 = f.add_subplot(1,2,1)
plt.axis('off')
plt.title('Original image (96,615 colors)')
ax1.imshow(china);
ax2 = f.add_subplot(1,2,2)
plt.axis('off')
plt.title('Quantized image (64 colors, K-Means)')
ax2.imshow(recreate_image(kmeans.cluster_centers_, labels, w, h));

"""
Explanation: 모사(Approximation)
End of explanation
"""


