marcoancona / DeepExplain

A unified framework of perturbation and gradient-based attribution methods for Deep Neural Networks interpretability. DeepExplain also includes support for Shapley Values sampling. (ICLR 2018)
https://arxiv.org/abs/1711.06104
MIT License
729 stars 133 forks source link

Issue with embedding layers: ValueError: None values not supported. #28

Open axsaucedo opened 5 years ago

axsaucedo commented 5 years ago

When running DeepExplain with Input layers, I don't have any problems, but I have several categorical columns that ideally would go through an Embedding column instead.

When I run the code with only Input layers I am able to get attribution values, but when I run it with Embedding columns I get the error ValueError: None values not supported. (Full stack trace below)

The dataset is the Census dataset for income classification. The following code is the one I use to build the model with Embedding columns, which errors out:

def build_model(df, X):
    input_els = []
    encoded_els = []
    dtypes = list(zip(X.dtypes.index, map(str, X.dtypes)))
    for k,dtype in dtypes:
        e = Input(shape=(1,))
        input_els.append(e)
        if dtype == "int8":
            e = Flatten()(Embedding(df[k].max()+1, 1)(e))
        encoded_els.append(e)
    encoded_els = concatenate(encoded_els)

    layer1 = Dropout(0.5)(Dense(100, activation="relu")(encoded_els))
    out = Dense(1, activation='sigmoid')(layer1)

    # train model
    model = Model(inputs=input_els, outputs=[out])
    model.compile(optimizer="adam", loss='binary_crossentropy', metrics=['accuracy'])
    return model

The following code without embedding columns doesn't error out:

def build_model_ins(df, X):
    input_els = []
    encoded_els = []
    for k in X.columns:
        input_els.append(Input(shape=(1,)))
    encoded_els = concatenate(input_els)

    layer1 = Dropout(0.5)(Dense(100, activation="relu")(encoded_els))
    out = Dense(1, activation='sigmoid')(layer1)

    # train model
    model = Model(inputs=input_els, outputs=[out])
    model.compile(optimizer="adam", loss='binary_crossentropy', metrics=['accuracy'])
    return model

The code that is used to call the DeepPredict function is:

with DeepExplain(session=K.get_session()) as de:
    model = build_model(df, X)
    model.fit(f_in(X_train), y_train, epochs=5, batch_size=512, shuffle=True, validation_data=(f_in(X_valid), y_valid), verbose=0, validation_split=0.05,)

    l_in = list(X.iloc[:100,:].values.T.reshape(13, 100, 1))

    input_tensors = model.inputs
    fModel = Model(inputs=input_tensors, outputs=model.outputs)
    target_tensor = fModel(input_tensors)
    attributions = de.explain("grad*input", target_tensor, input_tensors, l_in)
    print(attributions)

Would you know what the issue may be? Happy to provide further detail.

The full stacktrace error is the following:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-64-182fb0ef3e24> in <module>
     49     fModel = Model(inputs=input_tensors, outputs=model.outputs)
     50     target_tensor = fModel(input_tensors)
---> 51     attributions = de.explain("grad*input", target_tensor, input_tensors, l_in)
     52     print(attributions)
     53 

~/Programming/bias-eval/src/deepexplain/deepexplain/tensorflow/methods.py in explain(self, method, T, X, xs, **kwargs)
    456         _ENABLED_METHOD_CLASS = method_class
    457         method = _ENABLED_METHOD_CLASS(T, X, xs, self.session, self.keras_phase_placeholder, **kwargs)
--> 458         result = method.run()
    459         if issubclass(_ENABLED_METHOD_CLASS, GradientBasedMethod) and _GRAD_OVERRIDE_CHECKFLAG == 0:
    460             warnings.warn('DeepExplain detected you are trying to use an attribution method that requires '

~/Programming/bias-eval/src/deepexplain/deepexplain/tensorflow/methods.py in run(self)
    122 
    123     def run(self):
--> 124         attributions = self.get_symbolic_attribution()
    125         results =  self.session_run(attributions, self.xs)
    126         return results[0] if not self.has_multiple_inputs else results

~/Programming/bias-eval/src/deepexplain/deepexplain/tensorflow/methods.py in get_symbolic_attribution(self)
    190         return [g * x for g, x in zip(
    191             tf.gradients(self.T, self.X),
--> 192             self.X if self.has_multiple_inputs else [self.X])]
    193 
    194 

~/Programming/bias-eval/src/deepexplain/deepexplain/tensorflow/methods.py in <listcomp>(.0)
    188 
    189     def get_symbolic_attribution(self):
--> 190         return [g * x for g, x in zip(
    191             tf.gradients(self.T, self.X),
    192             self.X if self.has_multiple_inputs else [self.X])]

~/anaconda3/lib/python3.6/site-packages/tensorflow/python/ops/math_ops.py in r_binary_op_wrapper(y, x)
    891   def r_binary_op_wrapper(y, x):
    892     with ops.name_scope(None, op_name, [x, y]) as name:
--> 893       x = ops.convert_to_tensor(x, dtype=y.dtype.base_dtype, name="x")
    894       return func(x, y, name=name)
    895 

~/anaconda3/lib/python3.6/site-packages/tensorflow/python/framework/ops.py in convert_to_tensor(value, dtype, name, preferred_dtype)
   1048       name=name,
   1049       preferred_dtype=preferred_dtype,
-> 1050       as_ref=False)
   1051 
   1052 

~/anaconda3/lib/python3.6/site-packages/tensorflow/python/framework/ops.py in internal_convert_to_tensor(value, dtype, name, as_ref, preferred_dtype, ctx)
   1144 
   1145     if ret is None:
-> 1146       ret = conversion_func(value, dtype=dtype, name=name, as_ref=as_ref)
   1147 
   1148     if ret is NotImplemented:

~/anaconda3/lib/python3.6/site-packages/tensorflow/python/framework/constant_op.py in _constant_tensor_conversion_function(v, dtype, name, as_ref)
    227                                          as_ref=False):
    228   _ = as_ref
--> 229   return constant(v, dtype=dtype, name=name)
    230 
    231 

~/anaconda3/lib/python3.6/site-packages/tensorflow/python/framework/constant_op.py in constant(value, dtype, shape, name, verify_shape)
    206   tensor_value.tensor.CopyFrom(
    207       tensor_util.make_tensor_proto(
--> 208           value, dtype=dtype, shape=shape, verify_shape=verify_shape))
    209   dtype_value = attr_value_pb2.AttrValue(type=tensor_value.tensor.dtype)
    210   const_tensor = g.create_op(

~/anaconda3/lib/python3.6/site-packages/tensorflow/python/framework/tensor_util.py in make_tensor_proto(values, dtype, shape, verify_shape)
    428   else:
    429     if values is None:
--> 430       raise ValueError("None values not supported.")
    431     # if dtype is provided, forces numpy array to be the type
    432     # provided if possible.

ValueError: None values not supported.