Search code examples
pythoninputiterationneural-networkactivation

Python Neural Networking: Run 10 iterations but I get the same output


I'm new to coding so I'm having some simple issues. When I run 10 iterations, I get the same numbers.. -0.5 for activation and 0.0 for input even though at the bottom I set the starting activation's to 1.0, 1.0 and 0.0 to each corresponding node in the nodes list.

I thought by setting initial states. They send an input to the other node: which is the sender.activation * weight of 1. I SHOULDVE gotten a new input value. Which then would be applied to my activation which I then would be able to -0.5 and get a new activation for the node.

At least that's what I TRIED to do. And somehow it's just spitting out 0.0 and -0.5.

# 
#                               Preparations 
# 

nodes=[] 
NUMNODES=3

# 
#                                   Defining Node Class
# 

class Node(object): 

    def __init__(self,name=None): 
        self.name=name 
        self.activation_threshold=1.0
        self.net_input=0.0
        self.outgoing_connections=[] 
        self.incoming_connections=[] 
        self.connections=[] 
        self.activation=None

    def addconnection(self,sender,weight=0.0):
        self.connections.append(Connection(self,sender,weight)) 

    def update_input(self): 
        self.net_input=0.0
        for conn in self.connections: 
            self.net_input += conn.weight * conn.sender.activation 
        print 'Updated Input is', self.net_input 

    def update_activation(self): 
        self.activation = self.net_input - 0.5
        print 'Updated Activation is', self.activation 

# 
#                                   Defining Connection Class
# 

class Connection(object): 
    def __init__(self, sender, reciever, weight=1.0): 
        self.weight=weight 
        self.sender=sender 
        self.reciever=reciever 
        sender.outgoing_connections.append(self) 
        reciever.incoming_connections.append(self) 
# 
#                                 Other Programs 
# 


def set_activations(act_vector): 
    """Activation vector must be same length as nodes list"""
    for i in xrange(len(act_vector)): 
        nodes[i].activation = act_vector[i] 


for i in xrange(NUMNODES): 
    nodes.append(Node()) 


for i in xrange(NUMNODES):#go thru all the nodes calling them i 
    for j in xrange(NUMNODES):#go thru all the nodes calling them j 
        if i!=j:#as long as i and j are not the same 
            nodes[i].addconnection(nodes[j])#connects the nodes together
#
#                                         Setting Activations
#
set_activations([1.0,1.0,0.0])

#
#                                        Running 10 Iterations
#

for i in xrange(10): 
    for thing in nodes: 
        thing.update_activation() 
        thing.update_input()

Solution

  • So, you coded that

    def addconnection(self,sender,weight=0.0):
        self.connections.append(Connection(self,sender,weight)) 
        print "Node", str(self), "now contains", str(self.connections[-1])
    

    and you call it with

    nodes[i].addconnection(nodes[j]) #connects the nodes together
    

    You don't specify a weight right here. So you might be thinking that you're using the default value weight = 1.0 of the Connections class, but you're not.
    If you look closely, you do specify weight = 0.0 as default parameter in defining addconnection, right? :
    def addconnection(self,sender,weight=0.0):

    And since you call the Connection class __init__ method with
    self.connections.append(Connection(self,sender,weight))
    you actually pass it a value for weight: the default 0.0 you specified in the addconnection method. So all the connections will have the default weight 0.0. This effectively locks all values for inputs at 0.0 and activations at -0.5.

    To change this, you could perhaps specify a weight at line 75 where you use the addconnection method, and/or let only addconnection have a default value for weight (and let it be 1.0) while the Connection class __init__ method should always require a weight value, with no default. This is what I did in the code below, plus some __str__ methods to check things up.

    (This is a version with a default value of 1.0 in addconnection and no default in the Connection __init__):

    [EDIT: Added a first initialization of net_input.]

    # 
    #                               Preparations 
    # 
    
    nodes=[] 
    NUMNODES=3
    
    # 
    #                                   Defining Node Class
    # 
    
    class Node(object): 
    
        def __init__(self,name=None): 
            self.name=name 
            self.activation_threshold=1.0
            self.net_input=0.0
            self.outgoing_connections=[] 
            self.incoming_connections=[] 
            self.connections=[] 
            self.activation=None
    
        def __str__(self):
            return self.name
    
        def addconnection(self,sender,weight=1.0):
            self.connections.append(Connection(self,sender,weight)) 
            print "Node", str(self), "now contains", str(self.connections[-1])
    
        def update_input(self): 
            self.net_input=0.0
            for conn in self.connections: 
                self.net_input += conn.weight * conn.sender.activation 
            print 'Updated Input for node', str(self), 'is', self.net_input 
    
        def update_activation(self): 
            self.activation = self.net_input - 0.5
            print 'Updated Activation for node', str(self), 'is', self.activation 
    
    # 
    #                                   Defining Connection Class
    # 
    
    class Connection(object): 
        def __init__(self, sender, reciever, weight): 
            self.weight=weight 
            self.sender=sender 
            self.reciever=reciever 
            sender.outgoing_connections.append(self) 
            reciever.incoming_connections.append(self) 
            print 'Created', str(self)
    
        def __str__(self):
            string = "Connection from " + str(self.sender) + " to " + str(self.reciever) + ", weight = " + str(self.weight)
            return string
    # 
    #                                 Other Programs 
    # 
    
    
    def set_activations(act_vector): 
        """Activation vector must be same length as nodes list"""
        for i in xrange(len(act_vector)): 
            nodes[i].activation = act_vector[i] 
    
    
    for i in xrange(NUMNODES): 
        nodes.append(Node(str(i)))
        print "Created node:", nodes[i]
    
    
    for i in xrange(NUMNODES):#go thru all the nodes calling them i 
        for j in xrange(NUMNODES):#go thru all the nodes calling them j 
            if i!=j:#as long as i and j are not the same 
                nodes[i].addconnection(nodes[j])#connects the nodes together
    #
    #                                         Setting Activations
    #
    set_activations([1.0,1.0,0.0])
    
    #
    #                                        Running 10 Iterations
    #
    for thing in nodes:
        thing.update_input() #initializing inputs
    
    for i in xrange(10): 
        for thing in nodes: 
            thing.update_activation() 
            thing.update_input()