title: Unseen category in validation set gives error when using Keras
body: <p>I have data that consists of numerical and categorical variables. The categorical variables have a lot of categories so I'm using Embeddings to represent these. My model is a simple neural network.
  I know that when you define the Embedding layer you need to pass <code>input_dim=number of categories + 1</code> in order to account for unseen-in-training categories. This is what I had done.<br>
  Also, when encoding these categories to numerical values in order to input them into the neural network I have done the following:<br>
  1. Enumerate all the unique values in the <strong>training set</strong> and put them into a dictionary. Save also a variable called <code>num_values</code> which is the number of unique categories + 1.<br>
  2. For the validation set, if the value is not in the dictionary then I give it the value of <code>num_values</code>.</p>
  
  <p>This introduces a problem because when I want to evaluate the model (using <code>model.predict()</code>) I get an error like:</p>
  
  <pre class="lang-py prettyprint-override"><code>tensorflow.python.framework.errors_impl.InvalidArgumentError: indices[0,0] = 118752 is not in [0, 118752)
  </code></pre>
  
  <p>This is because I had an unseen-before category in the validation set in some variable, and it was mapped to <code>num_values</code>, but <code>num_values</code> <strong>is never assigned to any category in the training set</strong> because the dictionary building takes place on the training set. I don't how to solve this issue.</p>
  
  <p>I am using Keras 2.3.1 and Tensorflow 1.13.1</p>
  
  <p>The relevant code:</p>
  
  <pre class="lang-py prettyprint-override"><code>class EmbeddingMapping:
      """
      An instance of this class should be defined
      for each categorical variable you want to use.
      """
      def __init__(self, series: pd.Series) -&gt; None:
          # get a list of unique values
          values = series.unique().tolist()
  
          # dictionary mapping
          self.embedding_dict: Dict[str, int] = {value: int_value + 1 for int_value, value in enumerate(values)}
          self.num_values: int = len(values) + 1  # +1 for unknown categories
  
      def get_mapping(self, value: str) -&gt; int:
          # return value if it was seen in training
          if value in self.embedding_dict:
              return self.embedding_dict[value]
          # else return num_values which is the same for all
          # unseen values
          else:
              return self.num_values
  
  
  # build mappings
  res_dict_train: Dict[str, EmbeddingMapping] = {}
  res_dict_val: Dict[str, EmbeddingMapping] = {}
  for var in categorical_features:
      embd_train = EmbeddingMapping(X_train_categorical[var])
  
  
      temp_series_train = X_train_categorical[var].apply(embd_train.get_mapping)
      temp_series_val = X_val_categorical[var].apply(embd_train.get_mapping)
  
      res_dict_train[var] = temp_series_train
      res_dict_val[var] = temp_series_val
  
  X_train_categorical = X_train_categorical.assign(**res_dict_train)
  X_val_categorical = X_val_categorical.assign(**res_dict_val)
  
  # Keras
  # Categorical vars
  models_lst = []
  inputs = []
  for cat_feature in categorical_features:
      print('---------------------------------------')
      print(f'Info for categorical feature {cat_feature}')
      input_i = Input(shape=(1,), dtype='int32')
      inputs.append(input_i)
      num_categories = EmbeddingMapping(X_train_categorical[cat_feature]).num_values
      print(f"Number of categories: {num_categories}")
      embedding_size = min(np.ceil(num_categories/2), 50)     # rule of thumb
      embedding_size = int(embedding_size)
      print(f'Embedding size: {embedding_size}')
      model_i = Embedding(input_dim=num_categories, output_dim=embedding_size, input_length=1, name=f'embedding_{cat_feature}')(input_i)
      model_i2 = Reshape(target_shape=(embedding_size,))(model_i)
  
      models_lst.append(model_i2)
  
  # layer for numerical
  input_numerical = Input(shape=(len(numerical_features),), dtype='float32')
  numerical_model = Reshape(target_shape=(2,))(input_numerical)
  models_lst.append(numerical_model)
  inputs.append(input_numerical)
  
  concatenated = concatenate(models_lst, axis=-1)
  mymodel = Dense(50, activation="relu")(concatenated)
  mymodel2 = Dense(15, activation="relu")(mymodel)
  mymodel3 = Dense(1, activation='sigmoid')(mymodel2)
  
  final_model = models.Model(inputs, mymodel3)
  
  final_model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['acc', 'binary_accuracy'])
  
  final_model.fit(x=train_input_list, validation_data=(val_input_list, y_val), y=y_train, epochs=1, batch_size=128)
  </code></pre>
  
  <p>I get the error when the epoch ends and the model tries to compute validation statistics.</p>