1+ """
2+ Recreation of the simple perceptron algorithm maintaining the exact application of Rosenblatt.
3+ Rosenblatt, F. (1958). The perceptron: A probabilistic model for information storage and organization in the brain. Psychological Review, 65(6), 386–408.
4+ """
5+
6+ class SimplePerceptron :
7+ def __init__ (self , seed : float = 42.0 ) -> None :
8+ self .weights : list [float ] = []
9+ self .bias : float = 0.0
10+ self .seed = seed
11+
12+ def train (self , labeled_data : dict [tuple [float | int , ...], int ], epochs : int = 30 , learning_rate : float = 0.001 ) -> None :
13+ input_dim = len (list (labeled_data .keys ())[0 ])
14+ self .weights = [self ._lcg () for _ in range (input_dim )]
15+ self .bias = self ._lcg ()
16+
17+ for e in range (epochs ):
18+ error_count : int = 0
19+
20+ for inputs , target in labeled_data .items ():
21+ model_pred : float = self ._net_input (inputs )
22+
23+ if target != self ._binary_step (model_pred ):
24+ error_count += 1
25+ update = learning_rate * (target - self ._binary_step (model_pred )) # Product of learning rate and the difference betwen target and model prediction.
26+
27+ # Update the model bias and weights using the rosenblatt learning rule.
28+ for i in range (len (self .weights )): self .weights [i ] += update * inputs [i ]
29+ self .bias += update
30+
31+ if error_count == 0 : # Simple early stopping mechanism to use less resources.
32+ print (f"The model stopped converging at epoch { e } ." )
33+ return
34+
35+ print (f"For epoch { e } , the accuracy for actual model is { (len (labeled_data ) - error_count ) / len (labeled_data ) * 100 } percent." )
36+
37+ def inference (self , values : tuple [float | int , ...]) -> int :
38+ return self ._binary_step (self ._net_input (values ))
39+
40+ def _net_input (self , values : tuple [float ]) -> float :
41+ return sum (w_i * x_i for w_i , x_i in zip (self .weights , values )) + self .bias # The dot product of the vector of weights and values plus the bias term.
42+
43+ def _binary_step (self , pred : float ) -> int :
44+ return 1 if pred >= 0.0 else 0
45+
46+ def _lcg (self ) -> float : # Congruential linear generator.
47+ self .seed = (self .seed * 16807 ) % 2147483647
48+ return (self .seed / 2147483647 ) - 0.5 # Normalized between -0.5 and 0.5 to avoid data scaling problems.
49+
50+ or_gate : dict [tuple [int , int ], int ] = {
51+ (0 , 0 ): 0 ,
52+ (0 , 1 ): 1 ,
53+ (1 , 0 ): 1 ,
54+ (1 , 1 ): 1
55+ }
56+
57+ model = SimplePerceptron ()
58+ model .train (or_gate )
59+ pred : int = model .inference ((0 , 0 ))
60+ print (f"Prediction for (0,0): { pred } " )
0 commit comments