tensorflow / neural-structured-learning

Training neural models with structured signals.
https://www.tensorflow.org/neural_structured_learning
Apache License 2.0
980 stars 189 forks source link

TypeError: argument of type 'Tensor' is not iterable #73

Closed WrathofBhuvan11 closed 3 years ago

WrathofBhuvan11 commented 3 years ago
#load datasets
X = np.load("indiana_XIMAGE_VECTORS_train.npy")
X_t = np.load("indiana_XIMAGE_VECTORS_test.npy")
Y = to_categorical(np.array(list(report_df_train["BINARY"])))
Y_t = to_categorical(np.array(list(report_df_test["BINARY"])))

# Compile, train, and evaluate.
##merge_img_classify.fit(X, Y, epochs=15, batch_size = 16, verbose=1)
merge_img_classify = build_img_model_classify(X)
# Wrap the model with adversarial regularization.
adv_config = nsl.configs.make_adv_reg_config(multiplier=0.2, adv_step_size=0.05)
adv_model = nsl.keras.AdversarialRegularization(merge_img_classify, adv_config=adv_config)
# Compile, train, and evaluate.
adv_model.compile(optimizer='adam',
                  loss='sparse_categorical_crossentropy',
                  metrics=['accuracy'])
adv_model.fit(x=X, y=Y, batch_size=32, epochs=10)
adv_model.evaluate(x=X_t, y=Y_t, verbose=1)

Epoch 1/10

TypeError Traceback (most recent call last) in () 8 loss='sparse_categorical_crossentropy', 9 metrics=['accuracy']) ---> 10 adv_model.fit(x=X, y=Y, batch_size=32, epochs=10) 11 adv_model.evaluate(x=X_t, y=Y_t, verbose=1)

TypeError: argument of type 'Tensor' is not iterable

DualityGap commented 3 years ago

Thank you for raising this issue, @WrathofBhuvan11 Can you make sure the 'base model' (i.e., merge_img_classify, no adv regularization) is able to run correctly w/o this error?

csferng commented 3 years ago

nsl.keras.AdversarialRegularization expects both input data and target data in one dictionary passing to the x argument:

adv_model.fit(x={'image': X, 'label': Y}, ...)
adv_model.evaluate(x={'image': X_t, 'label': Y_t}, ...)

Depending on how the base model is constructed, you may need to name the input layer using the name arg, e.g. tf.keras.Input(..., name='image'). Please see the doc for more details and examples.

aheydon-google commented 3 years ago

WrathofBhuvan11@, did the reply from csferng@ solve your problem? Thanks for any update!

WrathofBhuvan11 commented 3 years ago

I'm sorry for the late response. Yes, @csferng solution helped. But I have one more question/ scenario where the same problem arose. It is if I'm using Image data generator. and flow from directory method. Any suggestions for that?

WrathofBhuvan11 commented 3 years ago

Thank you for raising this issue, @WrathofBhuvan11 Can you make sure the 'base model' (i.e., merge_img_classify, no adv regularization) is able to run correctly w/o this error?

yes base model works

WrathofBhuvan11 commented 3 years ago

nsl.keras.AdversarialRegularization expects both input data and target data in one dictionary passing to the x argument:

adv_model.fit(x={'image': X, 'label': Y}, ...)
adv_model.evaluate(x={'image': X_t, 'label': Y_t}, ...)

Depending on how the base model is constructed, you may need to name the input layer using the name arg, e.g. tf.keras.Input(..., name='image'). Please see the doc for more details and examples.

how to address the same issue for flow from directory / flow_from_dataframe? Let me try this where you have given the solution to wrap a generator with another generator https://github.com/tensorflow/neural-structured-learning/issues/3#issuecomment-528646087

WrathofBhuvan11 commented 3 years ago

I have already split full_df into train_df and valid_df dataframes.

IMG_SIZE = (128, 128)
core_idg = ImageDataGenerator(samplewise_center=True, 
                              samplewise_std_normalization=True, 
                              horizontal_flip = True, 
                              vertical_flip = False, 
                              height_shift_range= 0.05, 
                              width_shift_range=0.1, 
                              rotation_range=5, 
                              shear_range = 0.1,
                              fill_mode = 'reflect',
                              zoom_range=0.15)
# custom flow_from_dataframe
def flow_from_dataframe(img_data_gen, in_df, path_col, y_col, **dflow_args):
    base_dir = os.path.dirname(in_df[path_col].values[0])
    print('## Ignore next message from keras, values are replaced anyways')
    df_gen = img_data_gen.flow_from_directory(base_dir, 
                                     class_mode = 'sparse',
                                    **dflow_args)
    df_gen.filenames = in_df[path_col].values
    df_gen.classes = np.stack(in_df[y_col].values)
    df_gen.samples = in_df.shape[0]
    df_gen.n = in_df.shape[0]
    df_gen._set_index_array()
    df_gen.directory = '' # since we have the full path
    print('Reinserting dataframe: {} images'.format(in_df.shape[0]))
    return df_gen
def nsl_train_generator(datagen):
    train_gen = datagen.flow_from_dataframe(dataframe=train_df,
                                         directory=None,
                                         x_col = 'newpath',
                                         y_col = 'newLabel',
                                         class_mode = 'categorical',
                                         classes = all_labels,
                                         target_size = IMG_SIZE,
                                         color_mode = 'rgb',
                                         batch_size = 64)
    for x_batch, y_batch in train_gen:
         yield {'feature': x_batch, 'label': y_batch}

def nsl_valid_generator(datagen):
    valid_gen = core_idg.flow_from_dataframe(dataframe=valid_df,
                                         directory=None,
                                         x_col = 'newpath',
                                         y_col = 'newLabel',
                                         class_mode = 'categorical',
                                         classes = all_labels,
                                         target_size = IMG_SIZE,
                                         color_mode = 'rgb',
                                         batch_size = 1024) 
    for x_batch, y_batch in valid_gen:
         yield {'feature': x_batch, 'label': y_batch}

the above functions nsl_train_generator and nsl_valid_generator, I referred https://github.com/tensorflow/neural-structured-learning/issues/3#issuecomment-528646087

train_generator = nsl_train_generator(core_idg)
valid_generator = nsl_valid_generator(core_idg)
hist = adv_model.fit_generator(train_gen, 
                              steps_per_epoch=STEP_SIZE_TRAIN,
                              validation_data = valid_gen, 
                              epochs = 1,
                              callbacks = callbacks_list)

I'm getting this error,

Found 42276 validated image filenames belonging to 13 classes.
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-38-6b51ad0b4644> in <module>()
      4                               validation_data = valid_gen,
      5                               epochs = 1,
----> 6                               callbacks = callbacks_list)
      7 

15 frames
/usr/local/lib/python3.6/dist-packages/neural_structured_learning/keras/adversarial_regularization.py in <listcomp>(.0)
    633         # Converts input dictionary to a list so it conforms with the model's
    634         # expected input.
--> 635         inputs = [inputs[name] for name in base_input_names]
    636     elif not self._base_with_labels_in_features:
    637       # Removes labels and sample weights from the input dictionary, since they

KeyError: 'input_2'