Spaces:
Runtime error
Runtime error
import numpy as np | |
class DynamicalSOM: | |
def __init__(self, input_dim, map_dim): | |
self.input_dim = input_dim | |
self.map_dim = map_dim | |
self.weights = np.random.rand(map_dim[0], map_dim[1], input_dim) | |
self.cluster_labels = np.zeros(map_dim) | |
self.cluster_centers = np.zeros((0, input_dim)) | |
self.num_clusters = 0 | |
def find_best_matching_unit(self, input_vector): | |
distances = np.linalg.norm(self.weights - input_vector, axis=-1) | |
bmu_index = np.unravel_index(np.argmin(distances), distances.shape) | |
return bmu_index | |
def update_weights(self, input_vector, bmu_index, learning_rate): | |
for i in range(self.map_dim[0]): | |
for j in range(self.map_dim[1]): | |
distance_to_bmu = np.linalg.norm(np.array([i, j]) - np.array(bmu_index)) | |
neighborhood_function = np.exp(-(distance_to_bmu**2) / (2 * learning_rate**2)) | |
self.weights[i, j] += neighborhood_function * learning_rate * (input_vector - self.weights[i, j]) | |
def train(self, input_data, num_epochs, initial_learning_rate): | |
for epoch in range(num_epochs): | |
learning_rate = initial_learning_rate * np.exp(-epoch / num_epochs) | |
np.random.shuffle(input_data) | |
for input_vector in input_data: | |
bmu_index = self.find_best_matching_unit(input_vector) | |
self.update_weights(input_vector, bmu_index, learning_rate) | |
def cluster_neurons(self): | |
# Initialize cluster centers with the first neuron's weight vector | |
self.cluster_centers = np.expand_dims(self.weights[0, 0], axis=0) | |
# Assign all neurons to the first cluster | |
self.cluster_labels[:] = 0 | |
for i in range(self.map_dim[0]): | |
for j in range(self.map_dim[1]): | |
# Calculate the distance between the current neuron and each cluster center | |
distances_to_clusters = np.linalg.norm(self.weights[i, j] - self.cluster_centers, axis=-1) | |
# Find the closest cluster center | |
closest_cluster_index = np.argmin(distances_to_clusters) | |
# Assign the neuron to the closest cluster | |
self.cluster_labels[i, j] = closest_cluster_index | |
# Update cluster centers based on the mean of neurons in each cluster | |
for cluster_index in range(self.num_clusters): | |
cluster_neurons_indices = np.where(self.cluster_labels == cluster_index) | |
cluster_neurons = self.weights[cluster_neurons_indices] | |
cluster_center = np.mean(cluster_neurons, axis=0) | |
self.cluster_centers[cluster_index] = cluster_center | |
def introduce_fox_neuron(self): | |
if self.num_clusters > 1: | |
# Calculate distances between cluster centers | |
distances = np.linalg.norm(self.cluster_centers[:, np.newaxis, :] - self.cluster_centers, axis=-1) | |
# Find the indices of the two closest clusters | |
closest_clusters_indices = np.unravel_index(np.argpartition(distances, 1, axis=None)[:2], distances.shape) | |
# Average the two cluster centers to get the fox neuron | |
fox_neuron = np.mean(self.cluster_centers[closest_clusters_indices], axis=0) | |
# Add the fox neuron to the map | |
self.weights = np.append(self.weights, np.expand_dims(fox_neuron, axis=(0, 1)), axis=0) | |
self.num_clusters += 1 | |
# Update cluster labels with the new neuron | |
self.cluster_labels = np.append(self.cluster_labels, np.full((1, self.map_dim[1]), self.num_clusters - 1), axis=0) | |
def summary(self): | |
print("Dynamical Self-Organizing Map Summary:") | |
print("Input Dimension:", self.input_dim) | |
print("Map Dimension:", self.map_dim) | |
print("Number of Neurons:", self.map_dim[0] * self.map_dim[1]) | |
print("Number of Clusters:", self.num_clusters) | |
# Example usage: | |
input_data = np.random.rand(1000, 100) | |
map_dimensions = (10, 10) | |
som = DynamicalSOM(input_dim=100, map_dim=map_dimensions) | |
num_epochs = 100 | |
initial_learning_rate = 0.1 | |
som.train(input_data, num_epochs, initial_learning_rate) | |
som.cluster_neurons() | |
som.introduce_fox_neuron() | |
som.summary() | |