Python Forum
Class function is not running at all even though it is clearly run in the code
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Class function is not running at all even though it is clearly run in the code
#1
I'm very confused as to why my code won't run properly. Below I put the last lines of the main file which just runs some functions of the class. I put print statements around the line of code that runs the function and a print statement on the first line of the function, but only the two print statements outside the function execute. I put the full code at the bottom if you want to try running it yourself. Also if you were wondering, the reason I'm not using a library like TorchPy is because I wanted to try making some Machine learning code by myself from scratch. Thanks in advance for any suggestions on why this may be happening.

The bit of code at the end of main.py:
data = DataHandler()
AI = AIClass()
for _ in range(10):
    batch = list(data.get_batch())
    for info in batch:
        print("Execute Training function")
        AI.train_neurons(info[0], info[1])
        print('Training finished')
The class:
class AIClass:
    def __init__(self):
        .
        .

    def train_neurons(self, image, number, test=False):
        print("Training")
        .
        .
Full code:
from data_handler import DataHandler
import random, numpy


def sigmoid(number):
    return 1 / (1 + numpy.exp(-number))


def get_desired_output(number):
    output = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    output[number] = 1
    return output


def position_or_negative(number):
    if number < 0:
        return -1
    elif number > 0:
        return 1
    return 0


class AIClass:
    def __init__(self):
        self.nodes = [{}, {}, {}]
        self.weight_changes = [{}, {}, {}]
        self.nodeOutput = [{}, {}]
        self.costNodes = [{}, {}]
        self.output = []
        self.decay = 1

        # self.nodes setup
        for node in range(16):
            self.nodes[0].update({node: {}})
            self.weight_changes[0].update({node: {}})
            self.costNodes[0].update({node: []})
            self.nodes[0][node].update({'bias': 0})
            for pixel in range(28*28):
                self.nodes[0][node].update({pixel: random.uniform(-1, 1)})
                self.weight_changes[0][node].update({pixel: []})
        for node in range(16):
            self.nodes[1].update({node: {}})
            self.weight_changes[1].update({node: {}})
            self.costNodes[1].update({node: []})
            self.nodes[1][node].update({'bias': 0})
            for previousNode in range(16):
                self.nodes[1][node].update({previousNode: random.uniform(-1, 1)})
                self.weight_changes[1][node].update({previousNode: []})
        for node in range(10):
            self.nodes[2].update({node: {}})
            self.weight_changes[2].update({node: {}})
            self.nodes[2][node].update({'bias': 0})
            for previousNode in range(16):
                self.nodes[2][node].update({previousNode: random.uniform(-1, 1)})
                self.weight_changes[2][node].update({previousNode: []})

        # self.nodeOutput setup
        for node in range(16):
            self.nodeOutput[0].update({node: 0})
        for node in range(16):
            self.nodeOutput[1].update({node: 0})

    def train_neurons(self, image, number, test=False):
        print("Training")
        if not test:
            self.output.append([])
        for node in range(16):
            nodesum = 0
            for pixel in range(28*28):
                nodesum += image[pixel]*self.nodes[0][node][pixel]
            if not test:
                self.nodeOutput[0][node] = sigmoid(nodesum)
        for node in range(16):
            nodesum = 0
            for previousNode in range(16):
                nodesum += self.nodeOutput[0][node] * self.nodes[1][node][previousNode]
            if not test:
                self.nodeOutput[1][node] = sigmoid(nodesum)
        for node in range(10):
            nodesum = 0
            for previousNode in range(16):
                nodesum += self.nodeOutput[1][node] * self.nodes[2][node][previousNode]
            if not test:
                self.output[len(self.output)-1].append(sigmoid(nodesum))
            else:
                yield sigmoid(nodesum)
        if not test:
            self.backprop(number, image)

    def backprop(self, number, image):
        desiredOutput = get_desired_output(number)
        for node in range(10):
            output = self.output[len(self.output) - 1][node]
            cost = (output - desiredOutput[node])**2
            direction = position_or_negative(desiredOutput[node] - output)
            for affectNode in range(16):
                value = self.nodeOutput[1][affectNode]
                # print(f"Node: {node}; Output: {output}; Desired Output: {desiredOutput[node]}\nCost: {cost}; Direction: {direction}; Value: {value}\n__________________")
                self.costNodes[1][affectNode].append(value*direction)
                self.weight_changes[2][node][affectNode].append(value * direction * cost * self.decay)
        for node in range(16):
            cost = sum(self.costNodes[1][node])/len(self.costNodes[1][node])
            self.costNodes[1][node] = []
            for affectNode in range(16):
                value = self.nodeOutput[0][affectNode]
                self.costNodes[0][affectNode].append(value * position_or_negative(cost))
                self.weight_changes[1][node][affectNode].append(value * cost * self.decay)
        for node in range(16):
            cost = sum(self.costNodes[0][node]) / len(self.costNodes[0][node])
            self.costNodes[0][node] = []
            for pixel in range(28*28):
                value = image[pixel]
                self.weight_changes[0][node][pixel].append(value * cost * self.decay)

    def update_weights_and_biases(self):
        for row in range(len(self.weight_changes)):
            for node in range(len(self.weight_changes[row])):
                for weight in range(len(self.weight_changes[row][node])):
                    weight_changes = [weight + 1 for weight in self.weight_changes[row][node][weight]]
                    self.output = []
                    self.nodes[row][node][weight] *= sum(weight_changes)/len(weight_changes)
                    self.weight_changes[row][node][weight] = []
        self.decay *= 9/10

    def test(self, data):
        batch = data.get_batch()
        for info in batch:
            results = list(self.train_neurons(info[0], info[1], True))
            print("Test Results")
            print(f"Prediction:    {results}")
            print(f"Wanted output: {get_desired_output(info[1])}")

data = DataHandler()
AI = AIClass()
for _ in range(10):
    batch = list(data.get_batch())
    for info in batch:
        print("Execute Training function")
        AI.train_neurons(info[0], info[1])
        print('Training finished')
    AI.update_weights_and_biases()

AI.test(data)
Code for data_handler.py
from mnist import MNIST


class DataHandler:
    def __init__(self):
        data = MNIST('MNIST_DATA')  # You need a folder named "MNIST_DATA" inside the same directory as main.py, and it needs to have the files train-images-idx3-ubyte and train-labels-idx1-ubyte from http://yann.lecun.com/exdb/mnist/ just download the first two files listed and unpack them with some program into this folder.
        self.images, self.labels = data.load_training()
        self.index = -1

    def get_batch(self):
        for number in range(10):
            self.index += 1
            yield self.images[self.index], number
Reply
#2
Because the method yields, it returns a generator object. The code isn't run until you get data from the generator.

Because you don't assign the return value, the generator is never accessed. Maybe change

        print("Execute Training function")
        i = AI.train_neurons(info[0], info[1])
        print(next(i))
        print('Training finished')
Reply
#3
Oh I never knew that generator objects worked that way. I defined a list, appended all the values into that list, and then simply returned it, rather than trying to simplify my code a little with a yield. Thanks for the help!
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Putting code into a function breaks its functionality, though the code is identical! PCesarano 1 110 Apr-05-2021, 05:40 PM
Last Post: deanhystad
  rtmidi problem after running the code x times philipbergwerf 1 147 Apr-04-2021, 07:07 PM
Last Post: philipbergwerf
  Running a few lines of code as soon as my timer ends nethatar 3 277 Feb-26-2021, 01:02 PM
Last Post: jefsummers
  Assistance with running a few lines of code at an EXACT time nethatar 5 356 Feb-24-2021, 10:43 PM
Last Post: nilamo
  "SyntaxError: invalid syntax" running code in Doing Math With Python b saucerdesigner 2 367 Nov-03-2020, 04:23 PM
Last Post: saucerdesigner
  Running code online aqua_ed 1 267 Oct-29-2020, 03:04 AM
Last Post: Larz60+
  PermissionError while running function Laplace12 19 1,521 Aug-05-2020, 04:05 PM
Last Post: Laplace12
  Test a class function via "unittest " Penguin827 1 475 Jul-10-2020, 08:31 AM
Last Post: Gribouillis
  Question re: running code in Editor (i.e. Atom) vs Python interpreter rok 3 602 Jun-29-2020, 09:20 PM
Last Post: bowlofred
  Modify code from running program ? samuelbachorik 2 624 Jun-26-2020, 08:17 PM
Last Post: samuelbachorik

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020