Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import numpy as np | |
| import matplotlib.pyplot as plt | |
| from sklearn.datasets import make_moons, make_circles, make_blobs | |
| import torch | |
| import torch.nn as nn | |
| import torch.optim as optim | |
| st.set_page_config(page_title="NN Playground", layout="wide") | |
| st.title("🧠 Neural Network Playground (Hugging Face Style)") | |
| # --- Sidebar: Dataset & Hyperparameters --- | |
| st.sidebar.header("Data & Features") | |
| dataset_choice = st.sidebar.selectbox("Dataset", ["Blobs", "Moons", "Circles", "Spiral"]) | |
| train_ratio = st.sidebar.slider("Training data ratio", 0.1, 0.9, 0.5) | |
| noise = st.sidebar.slider("Noise", 0.0, 1.0, 0.1) | |
| batch_size = st.sidebar.slider("Batch size", 1, 50, 10) | |
| learning_rate = st.sidebar.slider("Learning rate", 0.001, 0.1, 0.03) | |
| activation_choice = st.sidebar.selectbox("Activation", ["Tanh", "ReLU", "Sigmoid"]) | |
| regularization = st.sidebar.selectbox("Regularization", ["None", "L2"]) | |
| reg_rate = st.sidebar.slider("Regularization rate", 0.0, 0.1, 0.0) | |
| # --- Generate dataset --- | |
| if dataset_choice == "Blobs": | |
| X, y = make_blobs(n_samples=200, centers=2, cluster_std=noise) | |
| elif dataset_choice == "Moons": | |
| X, y = make_moons(n_samples=200, noise=noise) | |
| elif dataset_choice == "Circles": | |
| X, y = make_circles(n_samples=200, noise=noise, factor=0.5) | |
| else: # Spiral (custom) | |
| n_points = 100 | |
| theta = np.sqrt(np.random.rand(n_points)) * 4 * np.pi | |
| r_a = 2*theta + np.pi | |
| data_a = np.array([np.cos(theta)*theta, np.sin(theta)*theta]).T | |
| data_b = np.array([np.cos(theta + np.pi)*theta, np.sin(theta + np.pi)*theta]).T | |
| X = np.vstack([data_a, data_b]) | |
| y = np.array([0]*n_points + [1]*n_points) | |
| X += noise * np.random.randn(*X.shape) | |
| # Convert to torch tensors | |
| X = torch.tensor(X, dtype=torch.float32) | |
| y = torch.tensor(y, dtype=torch.long) | |
| # --- Sidebar: Network configuration --- | |
| st.sidebar.header("Network") | |
| n_layers = st.sidebar.slider("Hidden Layers", 1, 4, 2) | |
| neurons = [] | |
| for i in range(n_layers): | |
| neurons.append(st.sidebar.slider(f"Neurons in layer {i+1}", 1, 10, 4)) | |
| # --- Build model dynamically --- | |
| layers = [] | |
| input_dim = X.shape[1] | |
| for n in neurons: | |
| layers.append(nn.Linear(input_dim, n)) | |
| if activation_choice == "Tanh": | |
| layers.append(nn.Tanh()) | |
| elif activation_choice == "ReLU": | |
| layers.append(nn.ReLU()) | |
| else: | |
| layers.append(nn.Sigmoid()) | |
| input_dim = n | |
| layers.append(nn.Linear(input_dim, 2)) # output layer | |
| model = nn.Sequential(*layers) | |
| # --- Optimizer & Loss --- | |
| if regularization == "L2": | |
| optimizer = optim.SGD(model.parameters(), lr=learning_rate, weight_decay=reg_rate) | |
| else: | |
| optimizer = optim.SGD(model.parameters(), lr=learning_rate) | |
| criterion = nn.CrossEntropyLoss() | |
| # --- Train the model --- | |
| epochs = 200 | |
| for epoch in range(epochs): | |
| optimizer.zero_grad() | |
| outputs = model(X) | |
| loss = criterion(outputs, y) | |
| loss.backward() | |
| optimizer.step() | |
| # --- Decision boundary --- | |
| xx, yy = np.meshgrid(np.linspace(X[:,0].min()-1, X[:,0].max()+1, 200), | |
| np.linspace(X[:,1].min()-1, X[:,1].max()+1, 200)) | |
| grid = torch.tensor(np.c_[xx.ravel(), yy.ravel()], dtype=torch.float32) | |
| with torch.no_grad(): | |
| preds = model(grid).argmax(dim=1).numpy().reshape(xx.shape) | |
| # --- Plot --- | |
| plt.figure(figsize=(8,6)) | |
| plt.contourf(xx, yy, preds, alpha=0.3, cmap="bwr") | |
| plt.scatter(X[:,0], X[:,1], c=y, edgecolor='k', cmap="bwr") | |
| plt.title("Neural Network Decision Boundary") | |
| st.pyplot(plt) | |