### GPU-Accelerated PyTorch DBSCAN: Fit, Predict, and Score on CUDA Source: https://context7.com/adversarian/torch-dbscan/llms.txt This example showcases the `DBSCANTorch` class for GPU-accelerated DBSCAN using PyTorch and CUDA. It covers converting data to CUDA tensors, fitting the model on the GPU, evaluating clustering performance, and making predictions, with options to return results as NumPy arrays or PyTorch tensors. ```python import torch import numpy as np from sklearn.datasets import make_blobs # Assume DBSCANTorch is imported from torch_dbscan # from torch_dbscan import DBSCANTorch # Placeholder for the actual class definition if not imported class DBSCANTorch: def __init__(self, eps, minPts): self._eps = eps self._minPts = minPts self._centroids = None if torch.cuda.is_available(): self.device = "cuda" else: self.device = "cpu" print("CUDA not available, falling back to CPU.") def fit(self, X_torch): # Mock implementation for demonstration print(f"Fitting DBSCANTorch with eps={self._eps}, minPts={self._minPts} on {self.device}") n_samples = X_torch.shape[0] n_clusters = 5 # Mock number of clusters self._centroids = torch.rand(n_clusters, X_torch.shape[1], device=self.device) return torch.randint(0, n_clusters, (n_samples,), device=self.device) # Mock labels on GPU def predict(self, X, as_numpy=True): # Mock implementation print(f"Predicting with DBSCANTorch on {self.device}") n_samples = X.shape[0] if isinstance(X, np.ndarray) else X.shape[0] result = torch.randint(0, 5, (n_samples,), device=self.device) # Mock predictions on GPU if as_numpy: return result.cpu().numpy() else: return result def score(self, X, y): # Mock implementation print(f"Scoring with DBSCANTorch") # In a real scenario, this would call predict and compare with true labels # For this mock, we'll ensure the predictions are numpy compatible if needed predictions_np = self.predict(X, as_numpy=True) from sklearn.metrics import adjusted_mutual_info_score as AMI, adjusted_rand_score as ARI return AMI(y, predictions_np), ARI(y, predictions_np) # Check if CUDA is available before running the example if torch.cuda.is_available(): # Generate dataset X, y, _ = make_blobs(n_samples=1000, centers=5, cluster_std=0.6, return_centers=True) # Convert to PyTorch tensor and move to GPU X_torch = torch.tensor(X, dtype=torch.float32, device="cuda") # Initialize and fit on GPU clusterer = DBSCANTorch(eps=0.4, minPts=4) labels = clusterer.fit(X_torch) # Returns torch.Tensor on GPU print(f"Labels device: {labels.device}") # Evaluate clustering ami, ari = clusterer.score(X, y) print(f'AMI: {ami:.3f}, ARI: {ari:.3f}') # Predict with automatic numpy conversion predictions_np = clusterer.predict(X, as_numpy=True) print(f'NumPy predictions: {predictions_np[:5]}') # Predict keeping tensors on GPU predictions_torch = clusterer.predict(X, as_numpy=False) print(f'GPU tensor predictions: {predictions_torch[:5]}') print(f"Predictions device: {predictions_torch.device}") # Access GPU centroids if clusterer._centroids is not None: centroids_gpu = clusterer._centroids # torch.Tensor on CUDA print(f"Centroids device: {centroids_gpu.device}") centroids_cpu = centroids_gpu.cpu().numpy() # Convert to NumPy if needed print(f'CPU centroids shape: {centroids_cpu.shape}') else: print('Centroids not yet computed.') else: print("Skipping DBSCANTorch example because CUDA is not available.") ``` -------------------------------- ### DBSCAN PyTorch GPU Execution and Visualization Source: https://github.com/adversarian/torch-dbscan/blob/main/torch-dbscan.ipynb This snippet demonstrates how to instantiate and use the `DBSCANTorch` class for fitting data, predicting cluster assignments, and evaluating the results using metrics like AMI and ARI. It also visualizes the data points and the identified cluster centroids. ```python clusterer = DBSCANTorch(0.4, 2*X.shape[1]) X_torch = torch.tensor(X, device="cuda") clusterer.fit(X_torch) ami, ari = clusterer.score(X, y) print(f'AMI: {ami}, ARI: {ari}') y_pred = clusterer.predict(X) best_centroids = np.array( [centroid for centroid in clusterer._centroids.cpu().numpy()] ) plt.scatter(X[:,0], X[:,1], c=y_pred); plt.scatter(best_centroids[:,0], best_centroids[:,1], marker='+', color='red'); ``` -------------------------------- ### Python Imports for DBSCAN Source: https://github.com/adversarian/torch-dbscan/blob/main/torch-dbscan.ipynb Imports necessary libraries for data manipulation, machine learning, and visualization, including networkx for graph operations, torch for potential tensor operations, and scikit-learn for dataset generation and metrics. ```python import networkx as nx import torch from collections import deque from matplotlib import pyplot as plt from sklearn.datasets import make_blobs from sklearn.metrics import ( adjusted_mutual_info_score as AMI, adjusted_rand_score as ARI, ) ``` -------------------------------- ### DBSCAN Clustering Execution and Visualization in Python Source: https://github.com/adversarian/torch-dbscan/blob/main/torch-dbscan.ipynb This snippet demonstrates how to instantiate and use the DBSCANVectorized class. It initializes the clusterer, fits it to data X, scores the results against true labels y, and visualizes the clustered data points along with the calculated centroids. Requires `matplotlib.pyplot` and `numpy`. ```python clusterer = DBSCANVectorized(0.4, 2*X.shape[1]) clusterer.fit(X) ami, ari = clusterer.score(X, y) print(f'AMI: {ami}, ARI: {ari}') y_pred = clusterer.predict(X) best_centroids = np.array( [centroid for centroid in clusterer._centroids] ) plt.scatter(X[:,0], X[:,1], c=y_pred); plt.scatter(best_centroids[:,0], best_centroids[:,1], marker='+', color='red'); ``` -------------------------------- ### DBSCAN PyTorch GPU Performance Benchmark Source: https://github.com/adversarian/torch-dbscan/blob/main/torch-dbscan.ipynb This code snippet uses the `%timeit` magic command to measure the execution time of fitting the `DBSCANTorch` model. It provides a benchmark for the GPU-accelerated implementation, indicating the average time taken for the `fit` operation. ```python %timeit DBSCANTorch(0.4, 2*X.shape[1]).fit(X_torch) ``` -------------------------------- ### Python NumPy Seed and Dataset Creation Source: https://github.com/adversarian/torch-dbscan/blob/main/torch-dbscan.ipynb Sets a random seed for NumPy for reproducible results and generates a synthetic dataset using make_blobs. The dataset is then visualized. ```python import numpy as np np.random.seed(42) X, y, centroids_true = make_blobs( n_samples=1000, centers=5, cluster_std=0.6, return_centers=True ) plt.scatter(X[:,0], X[:,1], c=y); ``` -------------------------------- ### Python DBSCAN Graph-Based Clustering Execution and Visualization Source: https://github.com/adversarian/torch-dbscan/blob/main/torch-dbscan.ipynb Instantiates and fits the `DBSCANGraphBased` model, then evaluates its performance using AMI and ARI scores. The predicted clusters are visualized, along with the calculated centroids. ```python clusterer = DBSCANGraphBased(0.4, 2*X.shape[1]) clusterer.fit(X) ami, ari = clusterer.score(X, y) print(f'AMI: {ami}, ARI: {ari}') y_pred = clusterer.predict(X) best_centroids = np.array( [centroid for centroid in clusterer._centroids.values()] ) plt.scatter(X[:,0], X[:,1], c=y_pred); plt.scatter(best_centroids[:,0], best_centroids[:,1], marker='+', color='red'); ``` -------------------------------- ### DBSCANBase Abstract Class: Common Interface Definition Source: https://context7.com/adversarian/torch-dbscan/llms.txt This snippet defines the abstract base class `DBSCANBase` which establishes a common interface for all DBSCAN implementations. It outlines the constructor (__init__) and the core methods: fit, predict, and score, ensuring consistency across different algorithm variants. ```python from sklearn.metrics import adjusted_mutual_info_score as AMI, adjusted_rand_score as ARI from sklearn.datasets import make_blobs # Placeholder for DBSCANVectorized if not imported elsewhere # Assume DBSCANVectorized inherits from DBSCANBase and implements its methods class DBSCANVectorized: def __init__(self, eps, minPts): self._eps = eps self._minPts = minPts self._centroids = None def fit(self, X): print(f"Mock fitting DBSCANVectorized") n_samples = X.shape[0] n_clusters = 3 # Mock number of clusters self._centroids = np.random.rand(n_clusters, X.shape[1]) return np.random.randint(0, n_clusters, n_samples) # Mock labels def predict(self, X): print(f"Mock predicting with DBSCANVectorized") n_samples = X.shape[0] return np.random.randint(0, 3, n_samples) # Mock predictions def score(self, X, y): print(f"Mock scoring with DBSCANVectorized") y_pred = self.predict(X) return AMI(y, y_pred), ARI(y, y_pred) class DBSCANBase: def __init__(self, eps, minPts): self._eps = eps # Maximum distance between neighbors self._minPts = minPts # Minimum points to form dense region def fit(self, X): """Fit the clustering model to data X""" raise NotImplementedError("Subclasses must implement this method") def predict(self, X): """Predict cluster labels for new data points""" raise NotImplementedError("Subclasses must implement this method") def score(self, X, y): """Evaluate clustering using AMI and ARI metrics""" # Default implementation using predict. Subclasses might override for efficiency. y_pred = self.predict(X) try: return AMI(y, y_pred), ARI(y, y_pred) except ValueError as e: print(f"Error during scoring: {e}. Ensure y and y_pred are compatible.") # Return NaN or handle error appropriately return float('nan'), float('nan') # Usage example with any implementation X, y, _ = make_blobs(n_samples=500, centers=3, cluster_std=0.5, return_centers=True) # Works with any subclass implementation that inherits from DBSCANBase # Ensure DBSCANVectorized is defined or imported before this usage example clusterer = DBSCANVectorized(eps=0.4, minPts=4) clusterer.fit(X) # Score method automatically calls predict internally ami, ari = clusterer.score(X, y) print(f'Clustering Quality - AMI: {ami:.3f}, ARI: {ari:.3f}') ``` -------------------------------- ### Benchmarking DBSCANVectorized Fit Method in Python Source: https://github.com/adversarian/torch-dbscan/blob/main/torch-dbscan.ipynb This code uses the IPython magic command `%timeit` to measure the execution time of fitting the DBSCANVectorized model to the data X. It provides an average execution time and standard deviation over multiple runs, indicating the performance of the vectorized implementation. Requires `numpy`. ```python %timeit DBSCANVectorized(0.4, 2*X.shape[1]).fit(X) ``` -------------------------------- ### DBSCAN PyTorch GPU Implementation Source: https://github.com/adversarian/torch-dbscan/blob/main/torch-dbscan.ipynb This class implements the DBSCAN algorithm using PyTorch for GPU acceleration. It includes methods for fitting the model, predicting cluster assignments, calculating distance matrices, and expanding clusters. The implementation aims to leverage GPU parallelization for faster computation compared to CPU-based methods. ```python class DBSCANTorch(DBSCANBase): def fit(self, X): if type(X) is not torch.Tensor: self._X = torch.tensor(X, device="cuda") else: self._X = X.to("cuda") dist_matrix = self._get_distance_matrix() # initialization cluster = 1 n_objs = self._X.shape[0] labels = torch.zeros(n_objs, device="cuda") for i in range(n_objs): if not labels[i]: neighbors = self._get_nearest_neighbours(dist_matrix[i]) if ( len(neighbors) > self._minPts ): # not >= because self is included in neighbours labels[i] = cluster labels = self._expand_cluster( dist_matrix, neighbors, cluster, labels ) cluster += 1 self._centroids = self._get_centroids(labels, cluster - 1) return labels def predict(self, X, as_numpy=True): X = torch.tensor(X[None, ...], device="cuda") centroids = self._centroids[:, None, ...] all_diff = X - centroids all_dist = torch.einsum("...k, ...k -> ...", all_diff, all_diff).sqrt() preds = torch.argmin(all_dist, dim=0) if as_numpy: return preds.cpu().numpy() else: return preds def _get_distance_matrix(self): # reimplement cdist diff_mat = self._X[:, None] - self._X[None, :] return torch.einsum("...k, ...k -> ...", diff_mat, diff_mat).sqrt() def _get_centroids(self, labels, last_cluster): return torch.stack( [ self._X[torch.where(labels == i)].mean(dim=0) for i in range(1, last_cluster + 1) ] ) def _get_nearest_neighbours(self, x): return torch.where(x <= self._eps)[0] def _expand_cluster(self, X, neighbors, cluster, labels): for neighbor in neighbors: if not labels[neighbor]: # if point is unassigned neighbors_of_neighbor = self._get_nearest_neighbours(X[neighbor]) if len(neighbors_of_neighbor) >= self._minPts: # if point is core labels[neighbor] = cluster labels = self._expand_cluster( X, neighbors_of_neighbor, cluster, labels ) return labels ``` -------------------------------- ### Python Base DBSCAN Class Definition Source: https://github.com/adversarian/torch-dbscan/blob/main/torch-dbscan.ipynb Defines a base class for DBSCAN, outlining common methods like fit, score, predict, and initialization with epsilon (eps) and minimum points (minPts). It includes placeholders for abstract methods. ```python class DBSCANBase: def __init__(self, eps, minPts): self._eps = eps self._minPts = minPts def fit(self, X): pass def score(self, X, y): y_pred = self.predict(X) return (AMI(y, y_pred), ARI(y, y_pred)) def predict(self, X): pass ``` -------------------------------- ### Python DBSCAN Graph-Based Fit Performance Timing Source: https://github.com/adversarian/torch-dbscan/blob/main/torch-dbscan.ipynb Measures the execution time of the `fit` method for the `DBSCANGraphBased` class using IPython's %timeit magic command to assess performance. ```python %timeit DBSCANGraphBased(0.4, 2*X.shape[1]).fit(X) ``` -------------------------------- ### Python Naive DBSCAN Graph-Based Implementation Source: https://github.com/adversarian/torch-dbscan/blob/main/torch-dbscan.ipynb A naive implementation of DBSCAN using a graph-based approach with Breadth-First Search (BFS). It constructs a distance graph, identifies core points, assigns clusters using BFS, and handles outliers. The predict method assigns points to the nearest centroid. ```python class DBSCANGraphBased(DBSCANBase): def fit(self, X): self._construct_graph(X) self._get_clusters() self._get_centroids(X) self._cluster_outliers(X) def predict(self, X): y = [] for x in X: distances = { label: self._distance(x, centroid) for label, centroid in self._centroids.items() } y.append(min(distances, key=distances.get)) return y def _construct_graph(self, X): cardinality = len(X) graph = nx.Graph() graph.add_nodes_from( list(range(cardinality)), is_core=False, visited=False, cluster=None ) for i in range(cardinality): for j in range(i + 1, cardinality): if self._distance(X[i], X[j]) < self._eps: graph.add_edge(i, j) if graph.degree[i] >= self._minPts: graph.nodes[i]["is_core"] = True self._graph = graph def _get_clusters(self): cluster_label = 0 for node in self._graph: if not self._graph.nodes[node]["visited"] and self._graph.nodes[node][ "is_core" ]: self._graph.nodes[node]["visited"] = True self._graph.nodes[node]["cluster"] = cluster_label self._bfs_node(node, cluster_label) cluster_label += 1 self._num_clusters = cluster_label def _bfs_node(self, source, cluster_label): neighbors = self._graph.neighbors queue = deque([(source, len(self._graph), neighbors(source))]) while queue: _, depth_now, children = queue[0] try: child = next(children) if not self._graph.nodes[child]["visited"]: self._graph.nodes[child]["visited"] = True self._graph.nodes[child]["cluster"] = cluster_label if depth_now > 1: queue.append((child, depth_now - 1, neighbors(child))) except StopIteration: queue.popleft() def _get_centroids(self, X): self._centroids = {} for i in range(self._num_clusters): X_list = [] for node in self._graph: if self._graph.nodes[node]["cluster"] == i: X_list.append(X[i]) self._centroids.update({i: np.mean(X_list, axis=0)}) def _cluster_outliers(self, X): for node in self._graph: if self._graph.nodes[node]["cluster"] is None: self._graph.nodes[node]["cluster"] = self.predict(X[node]) @staticmethod def _distance(p1, p2): return np.linalg.norm(p1 - p2) ``` -------------------------------- ### Benchmark DBSCAN Implementations (Graph, NumPy, PyTorch GPU) Source: https://context7.com/adversarian/torch-dbscan/llms.txt This Python code benchmarks the performance of three different DBSCAN implementations: graph-based, vectorized NumPy, and GPU-accelerated PyTorch. It generates a dataset, times the execution of the `fit` method for each implementation, and prints the results along with speedup comparisons. The code highlights that vectorized NumPy is fastest for CPU, while GPU performance varies and becomes advantageous for larger datasets. ```python import numpy as np import torch from sklearn.datasets import make_blobs import time # Generate test dataset X, y, _ = make_blobs(n_samples=1000, centers=5, cluster_std=0.6, return_centers=True, random_state=42) # Prepare GPU data X_torch = torch.tensor(X, dtype=torch.float32, device="cuda") # Benchmark parameters eps = 0.4 minPts = 2 * X.shape[1] # 4 for 2D data # Benchmark 1: Graph-based implementation (slowest) start = time.time() clusterer_graph = DBSCANGraphBased(eps, minPts) clusterer_graph.fit(X) graph_time = time.time() - start print(f"Graph-based: {graph_time:.3f}s (~1.32s expected)") # Benchmark 2: Vectorized NumPy implementation (fastest CPU) start = time.time() clusterer_vec = DBSCANVectorized(eps, minPts) clusterer_vec.fit(X) vec_time = time.time() - start print(f"Vectorized NumPy: {vec_time:.3f}s (~0.026s expected)") print(f"Speedup vs Graph: {graph_time/vec_time:.1f}x") # Benchmark 3: GPU-accelerated PyTorch (varies by GPU) start = time.time() clusterer_torch = DBSCANTorch(eps, minPts) clusterer_torch.fit(X_torch) torch_time = time.time() - start print(f"PyTorch GPU: {torch_time:.3f}s (~0.40s expected)") # Note: GPU slower for small datasets due to transfer overhead # GPU becomes faster with datasets > 10,000 points print(f"\nFor 1000 samples, vectorized NumPy is optimal") print(f"GPU advantage starts at ~10k+ samples") ``` -------------------------------- ### Vectorized NumPy DBSCAN: Fit, Predict, and Score Source: https://context7.com/adversarian/torch-dbscan/llms.txt This snippet demonstrates the usage of the `DBSCANVectorized` class for CPU-based DBSCAN clustering. It shows how to initialize the clusterer, fit it to data, evaluate clustering quality using AMI and ARI scores, and predict cluster labels for new data points. It also accesses cluster centroids. ```python import numpy as np from sklearn.datasets import make_blobs from sklearn.metrics import adjusted_mutual_info_score as AMI, adjusted_rand_score as ARI # Assume DBSCANVectorized is imported from torch_dbscan # from torch_dbscan import DBSCANVectorized # Placeholder for the actual class definition if not imported class DBSCANVectorized: def __init__(self, eps, minPts): self._eps = eps self._minPts = minPts self._centroids = None def fit(self, X): # Mock implementation for demonstration print(f"Fitting DBSCANVectorized with eps={self._eps}, minPts={self._minPts}") # In a real scenario, this would compute cluster labels and centroids n_samples = X.shape[0] n_clusters = 5 # Mock number of clusters self._centroids = np.random.rand(n_clusters, X.shape[1]) return np.random.randint(0, n_clusters, n_samples) # Mock labels def predict(self, X): # Mock implementation print(f"Predicting with DBSCANVectorized") n_samples = X.shape[0] return np.random.randint(0, 5, n_samples) # Mock predictions def score(self, X, y): # Mock implementation print(f"Scoring with DBSCANVectorized") # In a real scenario, this would call predict and compare with true labels return 0.95, 0.95 # Mock scores # Generate sample dataset X, y, _ = make_blobs(n_samples=1000, centers=5, cluster_std=0.6, return_centers=True) # Initialize and fit clusterer clusterer = DBSCANVectorized(eps=0.4, minPts=4) labels = clusterer.fit(X) # Evaluate clustering quality ami, ari = clusterer.score(X, y) print(f'AMI: {ami:.3f}, ARI: {ari:.3f}') # Predict cluster for new points new_points = np.array([[0.5, 0.5], [10.0, 10.0]]) predictions = clusterer.predict(new_points) print(f'Predictions: {predictions}') # Access cluster centroids if clusterer._centroids is not None: print(f'Centroids shape: {clusterer._centroids.shape}') else: print('Centroids not yet computed.') ``` -------------------------------- ### Expand Cluster using Recursive DFS - NumPy Source: https://context7.com/adversarian/torch-dbscan/llms.txt Implements the core clustering logic for expanding clusters using a recursive Depth-First Search (DFS) approach. This function traverses neighbors of core points to assign cluster labels. It takes the distance matrix, current neighbors to process, the cluster label, and the labels array as input, modifying the labels array in-place. ```python import numpy as np class DBSCANVectorized: def _expand_cluster(self, X, neighbors, cluster, labels): """Recursively expand cluster by visiting neighbors Args: X: Distance matrix (n_samples, n_samples) neighbors: Array of neighbor indices to process cluster: Current cluster label to assign labels: Array of cluster assignments (modified in-place) Returns: Updated labels array """ for neighbor in neighbors: if not labels[neighbor]: # If point is unassigned neighbors_of_neighbor = self._get_nearest_neighbours(X[neighbor]) if len(neighbors_of_neighbor) >= self._minPts: # If point is core labels[neighbor] = cluster labels = self._expand_cluster( X, neighbors_of_neighbor, cluster, labels ) return labels def _get_nearest_neighbours(self, x): """Find all points within epsilon distance""" return np.where(x <= self._eps)[0] # Complete clustering example X = np.array([[0, 0], [0.3, 0.3], [0.5, 0.5], # Cluster 1 [5, 5], [5.2, 5.2], [5.4, 5.4], # Cluster 2 [20, 20]]) # Outlier clusterer = DBSCANVectorized(eps=0.6, minPts=2) labels = clusterer.fit(X) print(f"Cluster labels: {labels}") # First 3 points cluster 1, next 3 cluster 2, last is outlier # Outlier detection: points with label 0 after initial clustering outliers = np.where(labels == 0)[0] print(f"Outlier indices: {outliers}") ``` -------------------------------- ### DBSCANVectorized Class Implementation in Python Source: https://github.com/adversarian/torch-dbscan/blob/main/torch-dbscan.ipynb This Python class implements a vectorized version of the DBSCAN clustering algorithm. It calculates distances using numpy einsum for efficiency and uses implicit DFS for cluster expansion. The class requires `numpy` and inherits from `DBSCANBase` (not provided). ```python class DBSCANVectorized(DBSCANBase): def fit(self, X): dist_matrix = self._get_distance_matrix(X) # initialization cluster = 1 n_objs = X.shape[0] labels = np.zeros(n_objs) for i in range(n_objs): if not labels[i]: neighbors = self._get_nearest_neighbours(dist_matrix[i]) if ( len(neighbors) > self._minPts ): # not >= because self is included in neighbours labels[i] = cluster labels = self._expand_cluster( dist_matrix, neighbors, cluster, labels ) cluster += 1 self._centroids = self._get_centroids(X, labels, cluster - 1) return labels def predict(self, X): X = X[None, ...] centroids = self._centroids[:, None, ...] all_diff = X - centroids all_dist = np.sqrt(np.einsum("...k, ...k -> ...", all_diff, all_diff)) return np.argmin(all_dist, axis=0) @staticmethod def _get_distance_matrix(X): # reimplement cdist diff_mat = X[:, None] - X[None, :] return np.sqrt(np.einsum("...k, ...k -> ...", diff_mat, diff_mat)) def _get_centroids(self, X, labels, last_cluster): return np.array( [ np.mean(X[np.where(labels == i)], axis=0) for i in range(1, last_cluster + 1) ] ) def _get_nearest_neighbours(self, x): return np.where(x <= self._eps)[0] def _expand_cluster(self, X, neighbors, cluster, labels): for neighbor in neighbors: if not labels[neighbor]: # if point is unassigned neighbors_of_neighbor = self._get_nearest_neighbours(X[neighbor]) if len(neighbors_of_neighbor) >= self._minPts: # if point is core labels[neighbor] = cluster labels = self._expand_cluster( X, neighbors_of_neighbor, cluster, labels ) return labels ``` -------------------------------- ### Calculate Cluster Centroids and Predict New Data Points Source: https://context7.com/adversarian/torch-dbscan/llms.txt This Python code defines a `DBSCANVectorized` class that calculates cluster centroids as the mean positions of points within each cluster. It then uses these centroids to classify new data points by assigning them to the nearest centroid. Dependencies include NumPy for numerical operations and scikit-learn for data generation. ```python import numpy as np class DBSCANVectorized: def _get_centroids(self, X, labels, last_cluster): """Calculate mean position of each cluster Args: X: Original data points (n_samples, n_features) labels: Cluster assignments for each point last_cluster: Highest cluster label number Returns: Array of centroids (n_clusters, n_features) """ return np.array([ np.mean(X[np.where(labels == i)], axis=0) for i in range(1, last_cluster + 1) ]) def predict(self, X): """Assign new points to nearest cluster centroid Args: X: New data points to classify (n_samples, n_features) Returns: Cluster labels for new points """ X = X[None, ...] # Add dimension for broadcasting centroids = self._centroids[:, None, ...] all_diff = X - centroids all_dist = np.sqrt(np.einsum("...k, ...k -> ...", all_diff, all_diff)) return np.argmin(all_dist, axis=0) # Complete example with training and prediction from sklearn.datasets import make_blobs # Training data X_train, y_train, _ = make_blobs(n_samples=300, centers=3, cluster_std=0.5, random_state=42) clusterer = DBSCANVectorized(eps=0.5, minPts=5) labels_train = clusterer.fit(X_train) print(f"Found {len(clusterer._centroids)} clusters") print(f"Centroids:\n{clusterer._centroids}") # Predict on new test data X_test = np.array([[0, 0], [5, 5], [-5, -5]]) labels_test = clusterer.predict(X_test) print(f"Test predictions: {labels_test}") # Calculate distances to centroids for confidence scoring distances = np.array([ np.linalg.norm(X_test[i] - clusterer._centroids[labels_test[i]]) for i in range(len(X_test)) ]) print(f"Distances to assigned centroids: {distances}") ``` -------------------------------- ### Compute Pairwise Euclidean Distance Matrix - NumPy Source: https://context7.com/adversarian/torch-dbscan/llms.txt Calculates the pairwise Euclidean distance matrix for a given set of samples using NumPy broadcasting and Einstein summation. This method is optimized for memory and computation speed on CPU. It takes a NumPy array of shape (n_samples, n_features) as input and returns a distance matrix of shape (n_samples, n_samples). ```python import numpy as np class DBSCANVectorized: @staticmethod def _get_distance_matrix(X): """Compute pairwise Euclidean distance matrix Args: X: numpy array of shape (n_samples, n_features) Returns: Distance matrix of shape (n_samples, n_samples) """ # Broadcasting: (n, 1, d) - (1, n, d) = (n, n, d) diff_mat = X[:, None] - X[None, :] # Einstein summation for dot product along last axis return np.sqrt(np.einsum("...k, ...k -> ...", diff_mat, diff_mat)) # Example usage X = np.array([[0, 0], [1, 1], [2, 2], [10, 10]]) dist_matrix = DBSCANVectorized._get_distance_matrix(X) print("Distance matrix:") print(dist_matrix) # Output: # [[ 0. 1.414 2.828 14.142] # [ 1.414 0. 1.414 12.728] # [ 2.828 1.414 0. 11.314] # [14.142 12.728 11.314 0. ]] # Find neighbors within epsilon distance olds = 2.0 neighbors_of_point_0 = np.where(dist_matrix[0] <= eps)[0] print(f"Neighbors of point 0 within {eps}: {neighbors_of_point_0}") # [0, 1] ``` -------------------------------- ### Compute Pairwise Euclidean Distance Matrix - PyTorch GPU Source: https://context7.com/adversarian/torch-dbscan/llms.txt Calculates the pairwise Euclidean distance matrix using PyTorch with CUDA acceleration. This is suitable for large datasets requiring parallel computation on GPUs. The function assumes the input data `self._X` is already on a CUDA device and returns a distance matrix as a PyTorch tensor on the CUDA device. ```python import torch class DBSCANTorch: def _get_distance_matrix(self): """Compute pairwise Euclidean distance matrix on GPU Returns: Distance matrix as torch.Tensor on CUDA device """ # self._X is already on GPU diff_mat = self._X[:, None] - self._X[None, :] return torch.einsum("...k, ...k -> ...", diff_mat, diff_mat).sqrt() # Example usage X = torch.tensor([[0, 0], [1, 1], [2, 2], [10, 10]], dtype=torch.float32, device="cuda") clusterer = DBSCANTorch(eps=0.4, minPts=2) clusterer._X = X dist_matrix_gpu = clusterer._get_distance_matrix() print("Distance matrix on GPU:") print(dist_matrix_gpu) # tensor([[ 0.0000, 1.4142, 2.8284, 14.1421], # [ 1.4142, 0.0000, 1.4142, 12.7279], # [ 2.8284, 1.4142, 0.0000, 11.3137], # [14.1421, 12.7279, 11.3137, 0.0000]], device='cuda:0') # Transfer to CPU if needed dist_matrix_cpu = dist_matrix_gpu.cpu().numpy() ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.