1

I am trying to build a very simple multi class classification model. I am using the following code to create, compile and train the model:

model = tf.keras.Sequential([
  tf.keras.layers.Dense(171, activation='softmax')
])

model.compile(
    optimizer = 'adam',
    loss='sparse_categorical_crossentropy', 
    metrics=['accuracy']
    )

history = model.fit(loc_array, label_array, epochs=500, verbose=False)
print('finished')

I use the following code to create loc_array and label_array

loc_array = df.iloc[:, 1:2]
label_array = df.iloc[:, 3]

loc_array represents the x values and is 1 column and 1344 rows label_array is the y value and is 1 column and 1344 rows

There are 171 distinct classes in label array (as entered into Dense layer of the model), however these values take on 6 digit integer values eg the first class is 100358.

When I run the train model step I get the following error:

InvalidArgumentError                      Traceback (most recent call last)
<ipython-input-48-5fd9efae2d96> in <module>()
----> 1 history = model.fit(loc_array, label_array, epochs=500, verbose=False)
      2 print('finished')

8 frames
/usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/execute.py in quick_execute(op_name, num_outputs, inputs, attrs, ctx, name)
     58     ctx.ensure_initialized()
     59     tensors = pywrap_tfe.TFE_Py_Execute(ctx._handle, device_name, op_name,
---> 60                                         inputs, attrs, num_outputs)
     61   except core._NotOkStatusException as e:
     62     if name is not None:

InvalidArgumentError:  Received a label value of 200837 which is outside the valid range of [0, 171).  Label values: 121695 105012 126480 125374 122189 102036 110191 104270 129375 108730 105839 122189 105011 200837 128990 102128 129850 129731 105839 104020 129731 129375 122189 126603 105011 105030 126603 126603 126603 102490 126480 121695
     [[node sparse_categorical_crossentropy/SparseSoftmaxCrossEntropyWithLogits/SparseSoftmaxCrossEntropyWithLogits (defined at <ipython-input-48-5fd9efae2d96>:1) ]] [Op:__inference_train_function_1411]

Function call stack:
train_function

It appears as though I need to convert my 6 digit, 171 classes to values between 0 and 171? If I do that the code works. But is there any way to run the code without having to convert those values as this then brings the need to convert the values between 0 and 171 back to the actual values when I apply the model.

desertnaut
  • 57,590
  • 26
  • 140
  • 166
Jon
  • 55
  • 2
  • 15

1 Answers1

1

What you are modelling is a classification problem, which is why you are setting the loss parameter of model.compile() to 'sparse_categorical_entropy'. The definition of this metric shows that your data will indeed have to be in the form of classes in the range [0, 171). If you would like integer values as outputs, perhaps modelling it as a regression problem and using loss='mean_squared_error' is more appropriate.

k-venkatesan
  • 655
  • 1
  • 8
  • 15
  • Thank you very much for the response. I do need to model to be a classification problem. Essentially, I want is a probability of getting each of the 171 classes. I want the model to produce 171 probabilities. The 6 digit values are just keys referring to 171 animals. So I want to know the prob of getting each animal given the input variable. This is why I need a multiclass-classification model. If Im forced to convert the 6 digit key to a value between 0 and 171 then is there a slick an easy way to convert them back to the original 6 digit keys when applying the model (using it to predict)? – Jon Apr 29 '20 at 08:16
  • 1
    There might be a more efficient way of doing it, but using a dictionary to map the 6-digit keys to the discrete classification integers is a solid option. If you need the mapping to go both ways, there's a pretty neat implementation shown in the accepted answer to [this question](https://stackoverflow.com/questions/1456373/two-way-reverse-map). – k-venkatesan Apr 29 '20 at 10:30
  • Thank you so much, I appreciate the advice. It makes sense to me and I will try to figure out the best way based on the suggestions. – Jon Apr 29 '20 at 18:58