-2

I've got a problem concerning the attributes of an object. As you see the mnist_network objects have some attributes that I have to use in some methods (attributes: train_img, train_res, test_img, test_res). When I call the function test_predict(self) I get the following error: AttributeError: 'mnist_network' object has no attribute 'test_img' . Can you explain this? I'm pretty new to OOP in Python. I use Spyder and I tried to use 'help' to find out what went wrong with the attributes but I only get 'no documentation available'. So that's not helpful...

Here's my code (it's supposed to predict handwritten digits):

# import keras and the MNIST dataset
from tensorflow.keras.datasets import mnist
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from keras.utils import np_utils

# import matplotlib to show pictures
import matplotlib.pyplot as plt

# numpy is necessary since keras uses numpy arrays
import numpy as np

class mnist_network():
    def __init__(self):
        """ load data, create and train model """
        # load data
        (X_train, y_train), (X_test, y_test) = mnist.load_data()
        # flatten 28*28 images to a 784 vector for each image
        num_pixels = X_train.shape[1] * X_train.shape[2]
        X_train = X_train.reshape((X_train.shape[0], num_pixels)).astype('float32')
        X_test = X_test.reshape((X_test.shape[0], num_pixels)).astype('float32')
        # normalize inputs from 0-255 to 0-1
        X_train = X_train / 255
        X_test = X_test / 255
        # one hot encode outputs
        y_train = np_utils.to_categorical(y_train)
        y_test = np_utils.to_categorical(y_test)
        num_classes = y_test.shape[1]


        # create model
        model = Sequential()
        model.add(Dense(num_pixels, input_dim=num_pixels, kernel_initializer='normal', activation='relu'))
        model.add(Dense(num_classes, kernel_initializer='normal', activation='softmax'))
        # Compile model
        model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

        # train the model
        model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=10, batch_size=200, verbose=2)

        self = model
        self.train_img = X_train
        self.train_res = y_train
        self.test_img = X_test
        self.test_res = y_test


    def test_all(self):
        """ evaluates the success rate using all the test data """
        scores = self.evaluate(self.test_img, self.test_res, verbose=0)
        print("Baseline Error: %.2f%%" % (100-scores[1]*100))

    def predict(self, img, show=False):
        """ img has to be a 784 vector """
        """ predicts the number in a picture (vector) """
        if show:
            # show the picture
            plt.imshow(img, cmap='Greys')
            plt.show()

        num_pixels = img.shape[1] * img.shape[2]
        # the actual number
        res_number = np.argmax(self.predict(img.reshape(-1,num_pixels)), axis = 1)


        return res_number[0]    # res_number is a list containing one element

    def test_predict(self):
        """ test a random number from the test part of the data set """
        index = random.randrange(0,10000) # there are 10000 images in the test part of the data set
        """ the actual result stored in the data set 
            It's represented as a list of 10 elements one of which being 1, the rest 0 """
        num_pixels = self.test_img.shape[1] * self.test_img.shape[2]
        correct_res = self.test_res[index].index(1)
        predicted_res = np.argmax(self.predict(self.test_img[index].reshape(-1, num_pixels)), axis = 1)

        if correct_res != predicted_res:
            print("Error in predict ! \
                  index = ", index, " predicted result = ", predicted_res, " correct result = ", correct_res)
        else:
            print("alright")



network = mnist_network()
network.test_predict()
Johanna
  • 143
  • 1
  • 10
  • Well ```self = model``` seems weird to me. I don't think, you will be able to assign a Keras Sequencial to a class. You should use something like ```self.model = model``` Check this out about self assigments in classes : https://stackoverflow.com/a/1216361/12422518 – furkanayd Dec 07 '19 at 22:23
  • why are you doing `self = model`??? Surely, that creates a whole lot of problems... – Tomerikoo Dec 07 '19 at 22:23

1 Answers1

1

Because you've assigned self (which is a reference to the current instance of that object) to model, which is an instance of Sequential, which has indeed not attribute test_img. For example if you where to do:

class mnist_network(Sequential):
    def __init__(self):
         self = "foo bar"

Then when you do instance = mnist_network(), you would essentially have a reference to a place in memory reserved for a string that says "foo bar" in your instance, NOT an instance of the class mnist_network. Generally speaking, you would NEVER do something like

self = some_stuff

anywhere. This makes no sense. I'm not super familiar with tensorflow & keras, but what I suspect you may be trying to do is more along the lines of:

class mnist_network(Sequential):
    def __init__(self):
         # do stuff....

Or perhaps what you really mean to do is:

class mnist_network:
    def __init__(self):
         # do stuff
         self.model = Sequential()

The former you would do if you were trying to use the methods, attributes of the class Sequential but wanted to expand on them - which in OOP is called inheritence. You get all the benefits from being a Sequantial object instance, but you are then free to add new methods & attributes to it inside your class mnist_network.

The later you would do if you need to have a Sequential object accessible in your class and ask him to perform operations. This is called composition.

logicOnAbstractions
  • 2,178
  • 4
  • 25
  • 37