title: Error using class_weights parameter with Keras in Multi-Class Classification problem
body: <p>This problem has been asked in other forums and I have tried their variations with no avail: <a href="https://stackoverflow.com/questions/49806437/class-weight-for-imbalanced-data-keras">class_weight for imbalanced data - Keras</a></p>
  <p><a href="https://datascience.stackexchange.com/questions/13490/how-to-set-class-weights-for-imbalanced-classes-in-keras">how to set class-weights for imbalanced classes in keras</a></p>
  <p>However it seems stale as no one has answered the question. Does anyone know how to implement the <code>class_weight</code> parameter in Keras when using <code>categorical_crossentropy</code>?
  I have been trying to use the <code>class_weight</code> parameter in Keras but keep getting this error:</p>
  <blockquote>
  <p>ValueError: Expected <code>class_weight</code> to be a dict with keys from 0 to one less than the number of classes, found {'prediction': {0: 1.217169570760731, 1: 5.323420074349443, 2: 0.5023680056130504}</p>
  </blockquote>
  <p>Each sample will be classified either 0, 1, or 2 (softmax). The bias in this dataset is significant. My model using the Keras functional API.</p>
  <p>The class_weights were calculated using Sklearn:</p>
  <pre><code>class_weights = class_weight.compute_class_weight('balanced', np.unique(np.array(y_trn_labels_HB_2_pd['labels'])), y_trn_labels_HB_2_pd['labels'])
  class_weight_dict = dict(enumerate(class_weights))
  class_weight_dict
  </code></pre>
  <p>Here is my last layer:</p>
  <pre><code>prediction = Dense(3, activation=&quot;softmax&quot;, name = 'prediction')(x)
  </code></pre>
  <p>Here is my model:</p>
  <pre><code>tf.__version__ = 2.3.0
  
  model = Model(inputs = [sequence_input_head, sequence_input_body, semantic_feat,
               wordOL_feat, avg_subj_feat], outputs = [prediction])
  model.compile(loss = 'categorical_crossentropy',
               optimizer='adam',
               metrics = ['accuracy'])
  model.summary()
  </code></pre>
  <p>Here is my class_weight parameter:</p>
  <pre><code>class_weight= {'prediction': {0:1.217169570760731, 1:5.323420074349443, 2:0.5023680056130504} })
  </code></pre>
  <p>Here is the full error:</p>
  <pre><code>---------------------------------------------------------------------------
  ValueError                                Traceback (most recent call last)
  &lt;ipython-input-271-e3bb78b84171&gt; in &lt;module&gt;()
       26                                        y_val_2_cat),
       27                     callbacks = [es],
  ---&gt; 28                     class_weight= {'prediction': class_weights})
       29 
       30 modeled = model.save(os.path.join(save_path, path_model))
  
  3 frames
  /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py in _method_wrapper(self, *args, **kwargs)
      106   def _method_wrapper(self, *args, **kwargs):
      107     if not self._in_multi_worker_mode():  # pylint: disable=protected-access
  --&gt; 108       return method(self, *args, **kwargs)
      109 
      110     # Running inside `run_distribute_coordinator` already.
  
  /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py in fit(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, validation_batch_size, validation_freq, max_queue_size, workers, use_multiprocessing)
     1061           use_multiprocessing=use_multiprocessing,
     1062           model=self,
  -&gt; 1063           steps_per_execution=self._steps_per_execution)
     1064 
     1065       # Container that configures and calls `tf.keras.Callback`s.
  
  /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/data_adapter.py in __init__(self, x, y, sample_weight, batch_size, steps_per_epoch, initial_epoch, epochs, shuffle, class_weight, max_queue_size, workers, use_multiprocessing, model, steps_per_execution)
     1120     dataset = self._adapter.get_dataset()
     1121     if class_weight:
  -&gt; 1122       dataset = dataset.map(_make_class_weight_map_fn(class_weight))
     1123     self._inferred_steps = self._infer_steps(steps_per_epoch, dataset)
     1124 
  
  /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/data_adapter.py in _make_class_weight_map_fn(class_weight)
     1299         &quot;Expected `class_weight` to be a dict with keys from 0 to one less &quot;
     1300         &quot;than the number of classes, found {}&quot;).format(class_weight)
  -&gt; 1301     raise ValueError(error_msg)
     1302 
     1303   class_weight_tensor = ops.convert_to_tensor_v2(
  
  ValueError: Expected `class_weight` to be a dict with keys from 0 to one less than the number of classes, found {'prediction': {0: 1.217169570760731, 1: 5.323420074349443}}
  </code></pre>
  <p>EDIT1:</p>
  <p>I tried your suggestion @Prateek Bhatt</p>
  <pre><code>history = model.fit({'headline': hl_pd_tr, 'articleBody':bd_pd_train, 'semantic': semantic_sim_180_train_x, 'wordOverlap': wrd_OvLp_train_x, 'avg_subjectivity': avg_subj_hb_train_x}, #@param [&quot;model.fit({'headline': hl_pd_tr, 'articleBody':bd_pd_train},&quot;, &quot;model.fit({'headline': hl_pd_tr, 'articleBody':bd_pd_train, 'semantic': semantic_x_tr},&quot;, &quot;model.fit({'headline': hl_pd_tr, 'articleBody':bd_pd_train, 'semantic': semantic_x_tr, 'wordOverlap': wrd_OvLp_x_tr},&quot;, &quot;model.fit({'headline': hl_pd_tr, 'articleBody':bd_pd_train, 'semantic': semantic_x_tr, 'wordOverlap': wrd_OvLp_x_tr, 'avgsubj': avg_subj_x_tr},&quot;] {type:&quot;raw&quot;, allow-input: true}
                      {'prediction':y_train_2_cat},
                      epochs=100,
                      batch_size= BATCH__SIZE,
                      shuffle= True,
                      validation_data = ([hl_pd_val, bd_pd_val, semantic_sim_180_val_x, wrd_OvLp_val_x, avg_subj_hb_val_x], y_val_2_cat),
                      callbacks = [es],
                      class_weight= {0:1.217169570760731, 1:5.323420074349443, 2:0.5023680056130504})
  </code></pre>
  <p>However, I get this error:</p>
  <pre><code>ValueError: `class_weight` is only supported for Models with a single output.
  </code></pre>
  <p>Full error:</p>
  <pre><code>ValueError                                Traceback (most recent call last)
  &lt;ipython-input-272-bfbab936a723&gt; in &lt;module&gt;()
       26                                        y_val_2_cat),
       27                     callbacks = [es],
  ---&gt; 28                     class_weight= {0:1.217169570760731, 1:5.323420074349443, 2:0.5023680056130504})
       29 
       30 modeled = model.save(os.path.join(save_path, path_model))
  
  16 frames
  /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py in _method_wrapper(self, *args, **kwargs)
      106   def _method_wrapper(self, *args, **kwargs):
      107     if not self._in_multi_worker_mode():  # pylint: disable=protected-access
  --&gt; 108       return method(self, *args, **kwargs)
      109 
      110     # Running inside `run_distribute_coordinator` already.
  
  /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py in fit(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, validation_batch_size, validation_freq, max_queue_size, workers, use_multiprocessing)
     1061           use_multiprocessing=use_multiprocessing,
     1062           model=self,
  -&gt; 1063           steps_per_execution=self._steps_per_execution)
     1064 
     1065       # Container that configures and calls `tf.keras.Callback`s.
  
  /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/data_adapter.py in __init__(self, x, y, sample_weight, batch_size, steps_per_epoch, initial_epoch, epochs, shuffle, class_weight, max_queue_size, workers, use_multiprocessing, model, steps_per_execution)
     1120     dataset = self._adapter.get_dataset()
     1121     if class_weight:
  -&gt; 1122       dataset = dataset.map(_make_class_weight_map_fn(class_weight))
     1123     self._inferred_steps = self._infer_steps(steps_per_epoch, dataset)
     1124 
  
  /usr/local/lib/python3.6/dist-packages/tensorflow/python/data/ops/dataset_ops.py in map(self, map_func, num_parallel_calls, deterministic)
     1693     &quot;&quot;&quot;
     1694     if num_parallel_calls is None:
  -&gt; 1695       return MapDataset(self, map_func, preserve_cardinality=True)
     1696     else:
     1697       return ParallelMapDataset(
  
  /usr/local/lib/python3.6/dist-packages/tensorflow/python/data/ops/dataset_ops.py in __init__(self, input_dataset, map_func, use_inter_op_parallelism, preserve_cardinality, use_legacy_function)
     4043         self._transformation_name(),
     4044         dataset=input_dataset,
  -&gt; 4045         use_legacy_function=use_legacy_function)
     4046     variant_tensor = gen_dataset_ops.map_dataset(
     4047         input_dataset._variant_tensor,  # pylint: disable=protected-access
  
  /usr/local/lib/python3.6/dist-packages/tensorflow/python/data/ops/dataset_ops.py in __init__(self, func, transformation_name, dataset, input_classes, input_shapes, input_types, input_structure, add_to_graph, use_legacy_function, defun_kwargs)
     3369       with tracking.resource_tracker_scope(resource_tracker):
     3370         # TODO(b/141462134): Switch to using garbage collection.
  -&gt; 3371         self._function = wrapper_fn.get_concrete_function()
     3372         if add_to_graph:
     3373           self._function.add_to_graph(ops.get_default_graph())
  
  /usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/function.py in get_concrete_function(self, *args, **kwargs)
     2937     &quot;&quot;&quot;
     2938     graph_function = self._get_concrete_function_garbage_collected(
  -&gt; 2939         *args, **kwargs)
     2940     graph_function._garbage_collector.release()  # pylint: disable=protected-access
     2941     return graph_function
  
  /usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/function.py in _get_concrete_function_garbage_collected(self, *args, **kwargs)
     2904       args, kwargs = None, None
     2905     with self._lock:
  -&gt; 2906       graph_function, args, kwargs = self._maybe_define_function(args, kwargs)
     2907       seen_names = set()
     2908       captured = object_identity.ObjectIdentitySet(
  
  /usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/function.py in _maybe_define_function(self, args, kwargs)
     3211 
     3212       self._function_cache.missed.add(call_context_key)
  -&gt; 3213       graph_function = self._create_graph_function(args, kwargs)
     3214       self._function_cache.primary[cache_key] = graph_function
     3215       return graph_function, args, kwargs
  
  /usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/function.py in _create_graph_function(self, args, kwargs, override_flat_arg_shapes)
     3073             arg_names=arg_names,
     3074             override_flat_arg_shapes=override_flat_arg_shapes,
  -&gt; 3075             capture_by_value=self._capture_by_value),
     3076         self._function_attributes,
     3077         function_spec=self.function_spec,
  
  /usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/func_graph.py in func_graph_from_py_func(name, python_func, args, kwargs, signature, func_graph, autograph, autograph_options, add_control_dependencies, arg_names, op_return_value, collections, capture_by_value, override_flat_arg_shapes)
      984         _, original_func = tf_decorator.unwrap(python_func)
      985 
  --&gt; 986       func_outputs = python_func(*func_args, **func_kwargs)
      987 
      988       # invariant: `func_outputs` contains only Tensors, CompositeTensors,
  
  /usr/local/lib/python3.6/dist-packages/tensorflow/python/data/ops/dataset_ops.py in wrapper_fn(*args)
     3362           attributes=defun_kwargs)
     3363       def wrapper_fn(*args):  # pylint: disable=missing-docstring
  -&gt; 3364         ret = _wrapper_helper(*args)
     3365         ret = structure.to_tensor_list(self._output_structure, ret)
     3366         return [ops.convert_to_tensor(t) for t in ret]
  
  /usr/local/lib/python3.6/dist-packages/tensorflow/python/data/ops/dataset_ops.py in _wrapper_helper(*args)
     3297         nested_args = (nested_args,)
     3298 
  -&gt; 3299       ret = autograph.tf_convert(func, ag_ctx)(*nested_args)
     3300       # If `func` returns a list of tensors, `nest.flatten()` and
     3301       # `ops.convert_to_tensor()` would conspire to attempt to stack
  
  /usr/local/lib/python3.6/dist-packages/tensorflow/python/autograph/impl/api.py in wrapper(*args, **kwargs)
      253       try:
      254         with conversion_ctx:
  --&gt; 255           return converted_call(f, args, kwargs, options=options)
      256       except Exception as e:  # pylint:disable=broad-except
      257         if hasattr(e, 'ag_error_metadata'):
  
  /usr/local/lib/python3.6/dist-packages/tensorflow/python/autograph/impl/api.py in converted_call(f, args, kwargs, caller_fn_scope, options)
      530 
      531   if not options.user_requested and conversion.is_whitelisted(f):
  --&gt; 532     return _call_unconverted(f, args, kwargs, options)
      533 
      534   # internal_convert_user_code is for example turned off when issuing a dynamic
  
  /usr/local/lib/python3.6/dist-packages/tensorflow/python/autograph/impl/api.py in _call_unconverted(f, args, kwargs, options, update_cache)
      337 
      338   if kwargs is not None:
  --&gt; 339     return f(*args, **kwargs)
      340   return f(*args)
      341 
  
  /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/data_adapter.py in _class_weights_map_fn(*data)
     1310     if nest.is_sequence(y):
     1311       raise ValueError(
  -&gt; 1312           &quot;`class_weight` is only supported for Models with a single output.&quot;)
     1313 
     1314     if y.shape.rank &gt; 2:
  
  ValueError: `class_weight` is only supported for Models with a single output.
  </code></pre>