Data visualization with TSNE
Overview
Teaching: 20 min
Exercises: 0 minQuestions
How to apply TSNE for data visualization?
Objectives
Apply TSNE from scikit-learn package
13. TSNE for Visualization
- t-SNE (t-distributed Stochastic Neighbor Embedding) is a machine learning algorithm that visualizes high-dimensional data in two or three dimensions.
- It was developed by Laurens van der Maaten and Geoffrey Hinton in 2008
- The algorithm is non-linear. Its goal is to take a set of points in a high-dimensional space and find a faithful representation of those points in a lower-dimensional space in 2D or 3D plane
- TSNE has tunable parameters “perplexity,” which says (loosely) how to balance attention between local and global aspects the data.
- “perplexity” can be considered to be number of nearest neighbors (the higher the number, the better fit the data) when considered for each data point when constructing the probability distribution of similarities in high-dimensional space.
- According to authors, “The performance of SNE is fairly robust to changes in the perplexity, and typical values are between 5 and 50”
- This chapter discusses some aspect of TSNE and its perplexity with different kind of input data. The code will be given as well.
-
What is good perplexity?
+ typical range 5-50: small data (5-30), large data (30-50) + 1-5: disconnected structure and poorly representation + > 50: overlapping structure and loss detail
Load scikit-learn library and create some sample data
- The data is taken from datasets, used in Unsupervised Learning chapter that I introduced earlier in Chapter 9
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
from sklearn.manifold import TSNE
from sklearn import cluster, datasets, mixture
# ============
# Generate datasets. We choose the size big enough to see the scalability
# of the algorithms, but not too big to avoid too long running times
# ============
n_samples = 500
seed = 30
Noisy Circle data
- Let’s create noisy circle data in 2D plane that have X variables containing the coordinate of the points and y variable which contains the labels of predefinded group:
noisy_circles = datasets.make_circles(
n_samples=n_samples, factor=0.5, noise=0.05, random_state=seed
)
X,y = noisy_circles
- Let’s plot the noisy circle raw plot:
dfX = pd.DataFrame(X,columns=["X1","X2"])
dfX["Cluster"]=y
sns.scatterplot(x="X1", y="X2",
data=dfX,
hue='Cluster', # color by cluster
legend=True).set(title="Noisy Circle Raw plot")
- Next, let’s apply TSNE to this dataset and visualize in 2D plane:
- The perplexity is not specified so it perplexity=30 by default
model_tsne = TSNE(n_components=2)
tsne_X = model_tsne.fit_transform(dfX)
df_tsne = pd.DataFrame(tsne_X,columns=['TSNE1','TSNE2'])
df_tsne['Cluster'] = y
sns.scatterplot(x="TSNE1", y="TSNE2",
data=df_tsne,
hue='Cluster', # color by cluster
legend=True).set(title="TSNE")
- We can visualize the transformation of TSNE with different variable of perplexity
- Here, we compare the raw data with perplexity range from 1 to 200:
- And here is the animation code of TSNE for noisy circle with perplexity range from 1 to 100:
import matplotlib.animation as animation
prange = range(0,100)
def animate(p):
plt.clf() # Clear the previous frame
model_tsne = TSNE(n_components=2,perplexity=p+1)
tsne_X = model_tsne.fit_transform(dfX)
df_tsne = pd.DataFrame(tsne_X,columns=['TSNE1','TSNE2'])
df_tsne['Cluster'] = y
sns.scatterplot(x="TSNE1", y="TSNE2",
data=df_tsne,
hue='Cluster', # color by cluster
legend=True).set(title="Perplexity = {}".format(p))
ani = animation.FuncAnimation(plt.gcf(), animate, frames=len(prange),interval=10)
ani.save('noisy_moon.gif', writer='pillow')
Noisy Moon
- To create noisy moon, we use the datasets make_moons:
noisy_moons = datasets.make_moons(n_samples=n_samples, noise=0.05, random_state=seed)
X,y = noisy_moons
- The sensitivity of noisy moon with different perplexity is plotted below:
- Similarly, we have the animation of TSNE with 2D for this Noisy moon:
Blobs data with 3 groups
- Next, Let’s create data with 3 separate group from make_blobs function in datasets
X, y = datasets.make_blobs(n_samples=n_samples, cluster_std=[1.0, 2.5, 0.5],random_state=123)
- We can visualize the Raw data with TSNE from different perplexity as below on 2D plane:
- And the animation of TSNE visualization with perplexity range from 1-100:
MNIST data
- Not only using the 2D plane model, we can use TSNE to visualize the multi-dimension.
- One of the example that we are using is the digital number data called MNIST
- To download the MNIST data, we can use tensorflow keras datasets:
from tensorflow.keras.datasets import mnist
(X_train,y_train),(X_test,y_test) = mnist.load_data()
- The training data contains 60000 images and the testing contains 10000 images.
- The image has resolution of 28x28 and is in gray scale with color range from 0-255
- To quickly visualize the MNIST data:
for i in range(64):
ax = plt.subplot(8, 8, i+1)
ax.axis('off')
plt.imshow(X_train[i], cmap='Greys')
- Because of its resolution 28x28 = 784, this dataset has the dimension of 784 and we can utilize TSNE to visualize the 10000 testing images in 2D or 3D scale
- First, let reshape the data:
X = X_test.reshape(10000,28*28)
y = y_test
- And apply TSNE with 2D plane and default perplexity
model_tsne = TSNE(n_components=2)
tsne_X = model_tsne.fit_transform(X)
df_tsne = pd.DataFrame(tsne_X,columns=['TSNE1','TSNE2'])
df_tsne['Cluster'] = y
- We can then visualize the MNIST dataset on 2D plane of TSNE:
tsne = sns.lmplot(x="TSNE1", y="TSNE2",
data=df_tsne,
fit_reg=False,
hue='Cluster', # color by cluster
legend=True,
scatter_kws={"s": 5}, # specify the point size
height=8)
- Animation for perplexity from 1 to 50:
- We can even visualize the 784 dimension data in 3D perspective by fitting TSNE with 3 dimensions:
model_tsne = TSNE(n_components=3)
tsne_X = model_tsne.fit_transform(X)
df_tsne = pd.DataFrame(tsne_X,columns=['TSNE1','TSNE2','TSNE3'])
df_tsne['Cluster'] = y
fig = plt.figure(figsize=(50, 30))
ax = plt.axes(projection ='3d')
# defining all 3 axis
x = df_tsne["TSNE1"]
y = df_tsne["TSNE2"]
z = df_tsne["TSNE3"]
# plotting
ax.scatter(x, y, z, c = df_tsne["Cluster"])
ax.set_title('3D line plot geeks for geeks')
plt.show()
- Additionally, we can also plot using raw images from Xtest data:
from PIL import Image
tx, ty = df_tsne['TSNE1'], df_tsne['TSNE2']
tx = (tx-np.min(tx)) / (np.max(tx) - np.min(tx))
ty = (ty-np.min(ty)) / (np.max(ty) - np.min(ty))
width = 4000
height = 3000
max_dim = 10
full_image = Image.new(mode="RGB", size=(width, height),color = (255, 255, 255))
for idx, x in enumerate(X_test):
tile = Image.fromarray(np.uint8(x * 255))
rs = max(1, tile.width / max_dim, tile.height / max_dim)
full_image.paste(tile, (int((width-max_dim) * tx[idx]),
int((height-max_dim) * ty[idx])))
full_image
full_image.save("MNIST_number.jpg")
FMNIST data
- Fashion MNIST is similar to MNIST data but using fashion image like shirt, trouser, shoes, etc
- One of the example that we are using is the digital number data called FMNIST
- To download the FMNIST data, we can use tensorflow keras datasets and we will visualize using testing data
from tensorflow.keras.datasets import fashion_mnist
(X_train,y_train),(X_test,y_test) = fashion_mnist.load_data()
X = X_test.reshape(10000,28*28)
y = y_test
- Setup the model:
model_tsne = TSNE(n_components=2,perplexity=30)
tsne_X = model_tsne.fit_transform(X)
Cluster_name = ["T-shirt/top","Trouser","Pullover","Dress","Coat",
"Sandal","Shirt","Sneaker","Bag","Ankle boot"]
df_tsne = pd.DataFrame(tsne_X,columns=['TSNE1','TSNE2'])
df_tsne['Cluster'] = y
df_tsne['Cluster_name'] = pd.Series(y).apply(lambda x:Cluster_name[x])
- Visualize with TSNE using default perplexity:
tsne1 = sns.lmplot(x="TSNE1", y="TSNE2",
data=df_tsne,
fit_reg=False,
hue='Cluster_name', # color by cluster
legend=True,
scatter_kws={"s": 5}, # specify the point size
height=8)
- We can also visulize using images and we can clearly the grouping to images by clicking on the image to zoom in :
tx, ty = df_tsne['TSNE1'], df_tsne['TSNE2']
tx = (tx-np.min(tx)) / (np.max(tx) - np.min(tx))
ty = (ty-np.min(ty)) / (np.max(ty) - np.min(ty))
from PIL import Image
width = 4000
height = 3000
max_dim = 10
full_image = Image.new(mode="RGB", size=(width, height),color = (255, 255, 255))
for idx, x in enumerate(X_test):
tile = Image.fromarray(np.uint8(x * 255))
rs = max(1, tile.width / max_dim, tile.height / max_dim)
full_image.paste(tile, (int((width-max_dim) * tx[idx]),
int((height-max_dim) * ty[idx])))
full_image.save("FMNIST.jpg")
Dashboard with Python Shiny:
Key Points
Visualization