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
  The function of double underscore back and front in a class function name? Pedroski55 9 562 Feb-19-2024, 03:51 PM
Last Post: deanhystad
  problem in running a code akbarza 7 546 Feb-14-2024, 02:57 PM
Last Post: snippsat
  super() and order of running method in class inheritance akbarza 7 594 Feb-04-2024, 09:35 AM
Last Post: Gribouillis
  writing and running code in vscode without saving it akbarza 1 345 Jan-11-2024, 02:59 PM
Last Post: deanhystad
  the order of running code in a decorator function akbarza 2 479 Nov-10-2023, 08:09 AM
Last Post: akbarza
  "Name is not defined" when running a class lil_e 6 3,764 Jan-12-2023, 11:57 PM
Last Post: lil_e
  Code running many times nad not just one? korenron 4 1,325 Jul-24-2022, 08:12 AM
Last Post: korenron
  Error while running code on VSC maiya 4 3,548 Jul-01-2022, 02:51 PM
Last Post: maiya
  TimeOut a function in a class ? Armandito 1 1,586 Apr-25-2022, 04:51 PM
Last Post: Gribouillis
  code running for more than an hour now, yet didn't get any result, what should I do? aiden 2 1,421 Apr-06-2022, 03:41 PM
Last Post: Gribouillis

Forum Jump:

User Panel Messages

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