louiecerv/exploring_unsupervised_learning_ml
0
1import streamlit as st2import numpy as np3import pandas as pd4import matplotlib.pyplot as plt5from matplotlib import pyplot6import seaborn as sns7 8from sklearn.datasets import make_blobs9from sklearn.preprocessing import StandardScaler10from sklearn.cluster import KMeans, DBSCAN, AgglomerativeClustering11from sklearn.mixture import GaussianMixture12from sklearn.decomposition import PCA13from sklearn.manifold import TSNE14from sklearn.metrics import silhouette_score, adjusted_rand_score15 16 17def generate_random_points_in_square(x_min, x_max, y_min, y_max, n_clusters):18 np.random.seed(42)19 return np.random.uniform(low=[x_min, y_min], high=[x_max, y_max], size=(n_clusters, 2))20 21 22def generate_data(n_samples, cluster_std, random_state, n_clusters):23 centers = generate_random_points_in_square(-4, 4, -4, 4, n_clusters)24 X, y = make_blobs(n_samples=n_samples, n_features=2, cluster_std=cluster_std,25 centers=centers, random_state=random_state)26 return X, y27 28def visualize_clusters(model, X, y, title=''):29 labels = model.fit_predict(X)30 unique_clusters = len(set(labels)) - (1 if -1 in labels else 0)31 noise_points = list(labels).count(-1)32 33 plt.figure(figsize=(8, 6))34 35 unique_labels = np.unique(labels)36 colors = pyplot.get_cmap('viridis', len(unique_labels))37 38 plt.figure(figsize=(8, 6))39 for idx, label in enumerate(unique_labels):40 cluster_mask = labels == label41 color = 'k' if label == -1 else colors(idx) # Black for noise42 plt.scatter(X[cluster_mask, 0], X[cluster_mask, 1], c=[color], s=50, edgecolor='k', label=f'Cluster {label}' if label != -1 else 'Noise')43 44 plt.title(f"{title} | Clusters Found: {unique_clusters}")45 st.pyplot(plt)46 47 st.write(f"**Number of clusters found:** {unique_clusters}")48 if noise_points > 0:49 st.write(f"**Number of noise points:** {noise_points}")50 51 # Calculate and display scores52 if unique_clusters > 1 and -1 not in labels: # Silhouette needs at least 2 clusters and no noise53 silhouette = silhouette_score(X, labels)54 st.write(f"**Silhouette Score:** {silhouette:.4f}")55 elif unique_clusters > 1 and -1 in labels and noise_points < len(X): # Silhouette needs at least 2 clusters and not all noise56 silhouette = silhouette_score(X[labels != -1], labels[labels != -1])57 st.write(f"**Silhouette Score:** {silhouette:.4f}")58 else:59 st.write("**Silhouette Score:** Not applicable (only 1 cluster or all noise)")60 61 try:62 ari = adjusted_rand_score(y, labels) # ARI can handle noise points63 st.write(f"**Adjusted Rand Index:** {ari:.4f}")64 except ValueError:65 st.write("**Adjusted Rand Index:** Not applicable (only 1 cluster)")66 67def main():68 st.title("๐ Visualizing Unsupervised Learning Algorithms")69 70 about = """71 This interactive application allows students to explore and visualize the behavior of various unsupervised learning algorithms. Users can generate synthetic data and apply clustering and dimensionality reduction techniques to understand patterns and structures in the data.72 73 **Key Features:**74 75 * **Configurable Data Generation:** Control the number of clusters, sample size, and standard deviation.76 * **Clustering Algorithms:** Explore K-Means, Hierarchical Clustering, DBSCAN, and Gaussian Mixture Models.77 * **Dimensionality Reduction:** Apply PCA and t-SNE for visualization.78 * **Interactive Exploration:** Adjust parameters and observe the effects on clustering results.79 80 **๐ก Created by: Louie F. Cervantes, M. Eng. (Information Engineering)**81 (c) 2025 West Visayas State University82 """83 84 with st.expander("About this app"):85 st.markdown(about)86 87 with st.sidebar:88 st.header("Data Parameters")89 n_samples = st.slider("Number of Samples", 300, 1000, 500)90 cluster_std = st.slider("Cluster Standard Deviation", 0.1, 3.0, 0.5)91 random_state = st.slider("Random State", 0, 100, 42)92 n_clusters = st.slider("Number of Clusters", 2, 6, 3)93 94 with st.spinner("Generating data and training models..."):95 X, y = generate_data(n_samples, cluster_std, random_state, n_clusters)96 scaler = StandardScaler()97 X_scaled = scaler.fit_transform(X)98 99 models = {100 "K-Means": KMeans(n_clusters=n_clusters, random_state=random_state),101 "Hierarchical Clustering": AgglomerativeClustering(n_clusters=n_clusters),102 "DBSCAN": DBSCAN(eps=0.3, min_samples=4),103 "Gaussian Mixture": GaussianMixture(n_components=n_clusters, random_state=random_state),104 "PCA": PCA(n_components=2),105 "t-SNE": TSNE(n_components=2, random_state=random_state)106 }107 108 st.write("Click on the tabs below to view the results of each model:")109 tabs = st.tabs(models.keys())110 111 for tab, (name, model) in zip(tabs, models.items()):112 with tab:113 st.subheader(name)114 if name in ["PCA", "t-SNE"]:115 reduced_data = model.fit_transform(X_scaled)116 plt.figure(figsize=(8, 6))117 plt.scatter(reduced_data[:, 0], reduced_data[:, 1], c="blue", s=50, edgecolor='k') # Corrected: Use reduced_data for both axes118 119 plt.title(f"{name} Visualization")120 st.pyplot(plt)121 else:122 visualize_clusters(model, X_scaled, y, title=f"{name} Clustering")123 124 st.write("ยฉ 2025 West Visayas State University")125 126 127if __name__ == "__main__":128 main()