"""
Unsupervised learning
=====================
A category of learning algorithms is able to discover inherent groups that may exist in a set of data.

K-means algorithm
-----------------
The k-means algorithm uses the mean points in a given dataset to cluster and discover groups within the dataset.
K is the number of clusters that we want and are hoping to discover. After the k-means algorithm has generated the
groupings, we can pass it additional but unknown data for it to predict to which group it will belong.

Note that in this kind of algorithm, only the raw uncategorized data is fed to the algorithm.
It is up to the algorithm to find out if the data has inherent groups within it.

E.g. 100 data points consisting of x and y values. We will feed these values to the learning algorithm and expect that
the algorithm will cluster the data into two sets. We will color the two sets so that the clusters are visible.

Each data point in original_set will belong to a cluster after our k-means algorithm has finished its training.
The k-mean algorithm represents the two clusters it discovers as 1s and 0s. If we had asked the algorithm to cluster
the data into four, the internal representation of these clusters would have been 0, 1, 2, and 3.


The algorithm discovers two distinct clusters in our sample data.
The two mean points of the two clusters are denoted with the red star symbol.

Prediction
---------
With the two clusters that we have obtained, we can predict the group that a new set of data might belong to.

At the barest minimum, we can expect the two test datasets to belong to different clusters. Prove: right when the print
statement prints 1 and 0, thus confirming that our test data does indeed fall under two different clusters.
"""

# K-means algorithm


import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans

# Let's create a sample data of 100 records of x and y pairs
original_set = -2 * np.random.rand(100, 2)
second_set = 1 + 2 * np.random.rand(50, 2)
# The last 50 numbers in original_set will be replaced
original_set[50:100, :] = second_set
# =>  we created two subsets of data, one set has numbers in the negative while the other in the positive.
# print(original_set)
# print(second_set)

# makes the algorithm cluster all its data under only two groups.
k_mean = KMeans(n_clusters=2)
k_mean.fit(original_set)

# The clusters generated by the algorithm will revolve around a certain mean point.
# => get the points that define these two mean points:
print(k_mean.cluster_centers_)
# to print out the various clusters that each dataset belongs:
print(k_mean.labels_)

# There are 100 1s and 0s. Each shows the cluster that each data point falls under.
# To chart the points of each group and color it appropriately to show the clusters:
for i in set(k_mean.labels_):
    # select all points that correspond to the group i
    # When i=0, all points belonging to the group 0 are returned to index
    index = k_mean.labels_ == i
    # plots these data points using o as the character for drawing each point.
    plt.plot(original_set[index, 0], original_set[index, 1], 'o')

# plot the centroids or mean values around which the clusters have formed:
plt.plot(k_mean.cluster_centers_[0][0], k_mean.cluster_centers_[0][1], '*', c='r', ms=10)
plt.plot(k_mean.cluster_centers_[1][0], k_mean.cluster_centers_[1][1], '*', c='r', ms=10)


# show the whole graph with the two means illustrated by a star:
plt.show()


# Prediction
# With the two clusters that we have obtained, we can predict the group that a new set of data might belong to.
sample = np.array([[-1.4, -1.4]])
print(k_mean.predict(sample))

another_sample = np.array(([[2.5, 2.5]]))
print(k_mean.predict(another_sample))

