| 
 | 1 | +"""  | 
 | 2 | +https://en.wikipedia.org/wiki/Self-organizing_map  | 
 | 3 | +"""  | 
 | 4 | +import math  | 
 | 5 | + | 
 | 6 | + | 
 | 7 | +class SelfOrganizingMap:  | 
 | 8 | +    def get_winner(self, weights: list[list[float]], sample: list[int]) -> int:  | 
 | 9 | +        """  | 
 | 10 | +        Compute the winning vector by Euclidean distance  | 
 | 11 | +
  | 
 | 12 | +        >>> SelfOrganizingMap().get_winner([[1, 2, 3], [4, 5, 6]], [1, 2, 3])  | 
 | 13 | +        1  | 
 | 14 | +        """  | 
 | 15 | +        d0 = 0.0  | 
 | 16 | +        d1 = 0.0  | 
 | 17 | +        for i in range(len(sample)):  | 
 | 18 | +            d0 += math.pow((sample[i] - weights[0][i]), 2)  | 
 | 19 | +            d1 += math.pow((sample[i] - weights[1][i]), 2)  | 
 | 20 | +            return 0 if d0 > d1 else 1  | 
 | 21 | +        return 0  | 
 | 22 | + | 
 | 23 | +    def update(  | 
 | 24 | +        self, weights: list[list[int | float]], sample: list[int], j: int, alpha: float  | 
 | 25 | +    ) -> list[list[int | float]]:  | 
 | 26 | +        """  | 
 | 27 | +        Update the winning vector.  | 
 | 28 | +
  | 
 | 29 | +        >>> SelfOrganizingMap().update([[1, 2, 3], [4, 5, 6]], [1, 2, 3], 1, 0.1)  | 
 | 30 | +        [[1, 2, 3], [3.7, 4.7, 6]]  | 
 | 31 | +        """  | 
 | 32 | +        for i in range(len(weights)):  | 
 | 33 | +            weights[j][i] += alpha * (sample[i] - weights[j][i])  | 
 | 34 | +        return weights  | 
 | 35 | + | 
 | 36 | + | 
 | 37 | +# Driver code  | 
 | 38 | +def main() -> None:  | 
 | 39 | +    # Training Examples ( m, n )  | 
 | 40 | +    training_samples = [[1, 1, 0, 0], [0, 0, 0, 1], [1, 0, 0, 0], [0, 0, 1, 1]]  | 
 | 41 | + | 
 | 42 | +    # weight initialization ( n, C )  | 
 | 43 | +    weights = [[0.2, 0.6, 0.5, 0.9], [0.8, 0.4, 0.7, 0.3]]  | 
 | 44 | + | 
 | 45 | +    # training  | 
 | 46 | +    self_organizing_map = SelfOrganizingMap()  | 
 | 47 | +    epochs = 3  | 
 | 48 | +    alpha = 0.5  | 
 | 49 | + | 
 | 50 | +    for i in range(epochs):  | 
 | 51 | +        for j in range(len(training_samples)):  | 
 | 52 | + | 
 | 53 | +            # training sample  | 
 | 54 | +            sample = training_samples[j]  | 
 | 55 | + | 
 | 56 | +            # Compute the winning vector  | 
 | 57 | +            winner = self_organizing_map.get_winner(weights, sample)  | 
 | 58 | + | 
 | 59 | +            # Update the winning vector  | 
 | 60 | +            weights = self_organizing_map.update(weights, sample, winner, alpha)  | 
 | 61 | + | 
 | 62 | +    # classify test sample  | 
 | 63 | +    sample = [0, 0, 0, 1]  | 
 | 64 | +    winner = self_organizing_map.get_winner(weights, sample)  | 
 | 65 | + | 
 | 66 | +    # results  | 
 | 67 | +    print(f"Clusters that the test sample belongs to : {winner}")  | 
 | 68 | +    print(f"Weights that have been trained : {weights}")  | 
 | 69 | + | 
 | 70 | + | 
 | 71 | +# running the main() function  | 
 | 72 | +if __name__ == "__main__":  | 
 | 73 | +    main()  | 
0 commit comments