MiniSom Documentation

repository·master·Indexed 23 days ago

https://github.com/justglowing/minisom

A minimalistic, NumPy-based implementation of Self-Organizing Maps (SOM) designed for simplicity and research. MiniSom supports JIT acceleration via Numba for high-performance training on large datasets. Key features include PCA weight initialization, U-Matrix visualization, and tools for clustering, classification, and color space mapping. It provides methods for calculating quantization, topographic, and distortion errors, as well as mapping class proportions to neurons via labels_map.

Tokens
9.4K
Snippets
25
Records
39
Agent score
81%

What's inside MiniSom

  1. Export and load a trained SOM model

    master

    You can save a trained MiniSom model using Python's pickle module and load it later.

    Warning: If you use a lambda function to define the decay factor, the model will not be picklable.

    import pickle
    som = MiniSom(7, 7, 4)
    
    # ...train the som here
    
    # saving the som in the file som.p
    with open('som.p', 'wb') as outfile:
        pickle.dump(som, outfile)
    
    # loading the som
    with open('som.p', 'rb') as infile:
        som = pickle.load(infile)
  2. Train a Self-Organizing Map (SOM)

    master

    To use MiniSom, organize your data as a Numpy matrix (where each row is an observation) or a list of lists.

    Initialize the MiniSom object by specifying the map dimensions (width, height) and the input dimension. Then, call .train() with your data and the number of iterations.

    If you have installed the [fast] version (Numba), use .train_batch_offline_fast() for significant speedups on large datasets. Note that the first call will be slower due to JIT compilation.

    from minisom import MiniSom    
    som = MiniSom(6, 6, 4, sigma=0.3, learning_rate=0.5) # initialization of 6x6 SOM
    som.train(data, 100) # trains the SOM with 100 iterations
  3. Install MiniSom

    master

    You can install MiniSom using pip. To enable JIT-accelerated training via Numba, install the [fast] extra.

    Standard installation:

    pip install minisom

    JIT-accelerated installation:

    pip install minisom[fast]

    Alternatively, you can install from source:

    git clone https://github.com/JustGlowing/minisom.git
    python setup.py install
    pip install minisom
  4. Perform feature selection using Self-Organizing Maps

    master

    You can achieve feature selection by analyzing the weights of a trained MiniSom. This method helps identify important features while avoiding redundant or complementary features that provide similar information.

    Key Considerations:

    1. SOM Quality: The selection process relies on the weights of the SOM, so the map must represent the data well (e.g., low topographic error).
    2. Parameter a: The selection depends on an arbitrary parameter a. Values between 0.03 and 0.06 are generally effective.

    The algorithm works by comparing the normalized weights of the target variable against the weights of other features. It selects features that most closely follow the target's pattern (or its complement) and then masks those patterns to prevent selecting redundant features.

    import numpy as np
    from minisom import MiniSom
    
    # 1. Initialize and train SOM
    size = 15
    som = MiniSom(size, size, len(X[0]),
                  neighborhood_function='gaussian', sigma=1.5,
                  random_seed=1)
    som.pca_weights_init(X)
    som.train_random(X, 1000, verbose=True)
    
    # 2. Get weights
    W = som.get_weights()
    
    # 3. Apply feature selection (using the algorithm logic)
    # Note: The implementation of `som_feature_selection` is provided in the example notebook
    selected_features, target_name = som_feature_selection(W, feature_names, 0, 0.04)
    print(f"Target variable: {target_name}\nSelected features: {selected_features}")
  5. Initialize and train a MiniSom with hexagonal topology

    master

    To create a Self-Organizing Map (SOM) with a hexagonal grid, initialize the MiniSom class with topology='hexagonal'. This topology is often used for better spatial relationships between neurons compared to a rectangular grid.

    Common parameters for initialization include:

    • x and y: Dimensions of the map.
    • input_len: Length of the input vector.
    • sigma: Standard deviation of the Gaussian kernel.
    • learning_rate: Initial learning rate.
    • activation_distance: Distance function (e.g., 'euclidean').
    • neighborhood_function: Function used for neighborhood updates (e.g., 'gaussian').
    • random_seed: Seed for reproducibility.

    After initialization, call .train(data, num_iteration, verbose=True) to train the map on your dataset.

    from minisom import MiniSom
    
    # initialization and training of 15x15 SOM
    som = MiniSom(15, 15, data.shape[1], sigma=1.5, learning_rate=.7, activation_distance='euclidean',
                  topology='hexagonal', neighborhood_function='gaussian', random_seed=10)
    
    som.train(data, 1000, verbose=True)
  6. Cluster data using MiniSom

    master

    To perform clustering with MiniSom, you map input data points to the winning neuron (Best Matching Unit) in the Self-Organizing Map. Each neuron in the SOM grid represents a cluster.

    1. Normalize your data: SOMs are sensitive to the scale of input features. It is recommended to normalize data (e.g., using Z-score normalization) before training.
    2. Initialize and train: Create a MiniSom instance with the desired grid shape and input dimension, then use train_batch for batch training.
    3. Identify clusters: Use the winner(x) method for each data point x to find its corresponding neuron coordinates. These coordinates can be used to group data points into clusters.
    from minisom import MiniSom
    import numpy as np
    import pandas as pd
    
    # 1. Load and normalize data
    data = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/00236/seeds_dataset.txt', 
                        names=['area', 'perimeter', 'compactness', 'length_kernel', 'width_kernel',
                       'asymmetry_coefficient', 'length_kernel_groove', 'target'], usecols=[0, 5], 
                       sep='\t+', engine='python')
    data = (data - np.mean(data, axis=0)) / np.std(data, axis=0)
    data = data.values
    
    # 2. Initialize and train
    som_shape = (1, 3)
    som = MiniSom(som_shape[0], som_shape[1], data.shape[1], sigma=.5, learning_rate=.5,
                  neighborhood_function='gaussian', random_seed=10)
    som.train_batch(data, 500, verbose=True)
    
    # 3. Identify clusters
    winner_coordinates = np.array([som.winner(x) for x in data]).T
    # Convert 2D neuron coordinates to 1D cluster indices
    cluster_index = np.ravel_multi_index(winner_coordinates, som_shape)
  7. Perform Outlier Detection using MiniSom

    master

    You can detect outliers in a dataset by identifying samples with a high quantization error. The general workflow is:

    1. Train a SOM on your dataset.
    2. Compute the quantization error for each sample. This is the Euclidean distance between the original data point and its winning neuron (the quantization vector).
    3. Set a threshold for the quantization error. Samples with an error exceeding this threshold are labeled as outliers.

    In practice, the threshold can be determined using percentiles of the quantization error distribution. For example, if you expect a certain percentage of outliers, you can set the threshold at a percentile that isolates that percentage.

    Note: The threshold is typically a parameter that needs to be tuned experimentally.

  8. Perform topic extraction using MiniSom

    master

    You can use MiniSom for topic modeling by clustering document vectors (such as TF-IDF representations) using a Self-Organizing Map. The number of neurons in the SOM grid determines the number of topics extracted. After training, the 'topics' are identified by inspecting the weights of each neuron and mapping the highest-weight indices back to the original feature names (e.g., words from a TF-IDF vectorizer).

    import numpy as np
    from minisom import MiniSom
    from sklearn.feature_extraction.text import TfidfVectorizer
    
    # 1. Prepare data (e.g., TF-IDF matrix D and feature names)
    # D is a list of lists representing the document vectors
    # tfidf_feature_names is the list of words corresponding to vector indices
    
    # 2. Initialize and train SOM
    n_neurons = 2
    m_neurons = 4
    no_features = 1000
    som = MiniSom(n_neurons, m_neurons, no_features)
    som.random_weights_init(D)
    som.train(D, 5000, random_order=False, verbose=True)
    
    # 3. Extract topics
    top_keywords = 10
    weights = som.get_weights()
    
    for i in range(n_neurons):
        for j in range(m_neurons):
            # Get indices of the top weights for this neuron
            keywords_idx = np.argsort(weights[i,j,:])[-top_keywords:]
            # Map indices to feature names
            keywords = ' '.join([tfidf_feature_names[k] for k in keywords_idx])
            print(f'Topic: {keywords}')
  9. Solve a classification problem with MiniSom

    master

    To use MiniSom for classification, you can map input samples to neurons and assign labels to those neurons based on the majority class of the training samples they represent.

    1. Prepare Data: Load your dataset and scale the features (e.g., using sklearn.preprocessing.scale).
    2. Initialize MiniSom: Create a MiniSom instance specifying the grid dimensions, input dimension, and hyperparameters like sigma, learning_rate, and neighborhood_function.
    3. Initialize Weights: Use som.pca_weights_init(X_train) to initialize weights using Principal Component Analysis, which often improves convergence.
    4. Train: Use som.train_random(X_train, num_iteration) to train the map.
    5. Classify: Use som.labels_map(X_train, y_train) to create a mapping of winning neurons to their most frequent labels. For new samples, find the winning neuron using som.winner(sample) and retrieve the associated label from the map.
    from minisom import MiniSom
    import numpy as np
    import pandas as pd
    from sklearn.preprocessing import scale
    from sklearn.model_selection import train_test_split
    from sklearn.metrics import classification_report
    
    # 1. Prepare and scale data
    columns=['area', 'perimeter', 'compactness', 'length_kernel', 'width_kernel', 
            'asymmetry_coefficient', 'length_kernel_groove', 'target']
    data = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/00236/seeds_dataset.txt', 
                        names=columns, 
                        sep='\t+', engine='python')
    labels = data['target'].values
    data = scale(data.values)
    
    # 2. Split data
    X_train, X_test, y_train, y_test = train_test_split(data, labels, stratify=labels)
    
    # 3. Initialize and train MiniSom
    som = MiniSom(7, 7, data.shape[1], sigma=3, learning_rate=0.5, 
                  neighborhood_function='triangle', random_seed=10)
    som.pca_weights_init(X_train)
    som.train_random(X_train, 500, verbose=False)
    
    # 4. Classification logic using labels_map
    def classify(som, data, X_train, y_train):
        winmap = som.labels_map(X_train, y_train)
        # Determine a default class from the most common label in the winmap
        default_class = list(winmap.values())[0].most_common()[0][0] 
        result = []
        for d in data:
            win_position = som.winner(d)
            if win_position in winmap:
                result.append(winmap[win_position].most_common()[0][0])
            else:
                result.append(default_class)
        return result
    
    # 5. Evaluate
    print(classification_report(y_test, classify(som, X_test, X_train, y_train)))