AiSajjad / app.py
ReySajju742's picture
Rename main.py to app.py
e7eb368 verified
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()