import numpy as np # linear algebra import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv) from pprint import pprint import tensorflow as tf BATCH_SIZE = 5 # Define the data data = { 'StringFeature': ['apple', 'banana', 'cherry', 'orange', 'mango'], 'target': [0, 1, 2, 3, 0], } # Create the DataFrame train_df = pd.DataFrame(data) train_target_df = train_df.pop('target') train_target_df = pd.get_dummies(train_target_df, columns=['target']) train_target_df = {key: value.to_numpy()[:,tf.newaxis] for key, value in train_target_df.items()} train_ds = tf.data.Dataset.from_tensor_slices((dict(train_df), train_target_df)).batch(BATCH_SIZE) def get_category_encoding_layer(name, dataset): # Create a layer that turns strings into integer indices. index = tf.keras.layers.StringLookup() # Prepare a `tf.data.Dataset` that only yields the feature. feature_ds = dataset.map(lambda x, y: x[name]) # Learn the set of possible values and assign them a fixed integer index. index.adapt(feature_ds) # Encode the integer indices. encoder = tf.keras.layers.CategoryEncoding(num_tokens=index.vocabulary_size(), output_mode='one_hot') # Apply multi-hot encoding to the indices. The lambda function captures the # layer, so you can use them, or include them in the Keras Functional model later. return lambda feature: encoder(index(feature)) ##### train_all_inputs = {} train_preprocessed_features = [] ##### Categorical features str. categorical_col = tf.keras.Input(shape=(1,), name='StringFeature', dtype='string') encoding_layer = get_category_encoding_layer(name='StringFeature', dataset=train_ds) encoded_categorical_col = encoding_layer(categorical_col) train_all_inputs['StringFeature'] = categorical_col train_preprocessed_features.append(encoded_categorical_col) #### train_all_features = tf.keras.layers.concatenate(train_preprocessed_features) #### output = tf.keras.layers.Dense(4)(train_all_features) model = tf.keras.Model(train_all_inputs, output) model.compile(optimizer='adam', loss=tf.keras.losses.SparseCategoricalCrossentropy(), metrics=['accuracy']) #model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy']) tf.keras.utils.plot_model(model, show_shapes=True, show_layer_names=True, rankdir="LR") history = model.fit(train_ds, epochs=2)#, validation_data=(validation_features, validation_target))
Hi @Bruno, while creating labels I can see you are creating a dictionary structure it is recommended to use array format. with that change I have executed the code in colab I did not face any error. Thank You.
Side note: one of the loss I used was “sparse*”, which was not the one to use here, I know use 'categorical_crossentropy'. But that was not the main issue there.
The main issue was indeed the target size/dimensions. I had missed the point where I should have used an array (thanks again on that count, I lost some many hours on this one…). As I wanted the one_hot on the target (hopefully that is not a mistake), I had to change the dimension of the target so I used np.reshape. The full code below (still not familiar enough with gist).
I had to add a dimension, I believe it is due to the one_hot output_mode but not sure yet (probably won’t check if I don’t run into the problem again)
Bruno
import numpy as np # linear algebra import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv) from pprint import pprint import tensorflow as tf BATCH_SIZE = 5 # Define the data data = { 'StringFeature': ['apple', 'banana', 'cherry', 'orange', 'mango'], 'target': [0, 1, 2, 3, 0], } # Create the DataFrame train_df = pd.DataFrame(data) train_target_df = train_df.pop('target') train_target_numpy = pd.get_dummies(train_target_df, columns=['target']).to_numpy() #Solution here arr = train_target_numpy.reshape(5, 1, 4) #Solution and here #train_target_df = {key: value.to_numpy()[:,tf.newaxis] for key, value in train_target_df.items()} train_ds = tf.data.Dataset.from_tensor_slices((dict(train_df), arr)).batch(BATCH_SIZE) def get_category_encoding_layer(name, dataset): # Create a layer that turns strings into integer indices. index = tf.keras.layers.StringLookup() # Prepare a `tf.data.Dataset` that only yields the feature. feature_ds = dataset.map(lambda x, y: x[name]) # Learn the set of possible values and assign them a fixed integer index. index.adapt(feature_ds) # Encode the integer indices. encoder = tf.keras.layers.CategoryEncoding(num_tokens=index.vocabulary_size(), output_mode='one_hot') # Apply multi-hot encoding to the indices. The lambda function captures the # layer, so you can use them, or include them in the Keras Functional model later. return lambda feature: encoder(index(feature)) ##### train_all_inputs = {} train_preprocessed_features = [] ##### Categorical features str. categorical_col = tf.keras.Input(shape=(1,), name='StringFeature', dtype='string') encoding_layer = get_category_encoding_layer(name='StringFeature', dataset=train_ds) encoded_categorical_col = encoding_layer(categorical_col) train_all_inputs['StringFeature'] = categorical_col train_preprocessed_features.append(encoded_categorical_col) #### train_all_features = tf.keras.layers.concatenate(train_preprocessed_features) #### output = tf.keras.layers.Dense(4)(train_all_features) model = tf.keras.Model(train_all_inputs, output) #model.compile(optimizer='adam', loss=tf.keras.losses.CategoricalCrossentropy(), metrics=['accuracy']) model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy']) tf.keras.utils.plot_model(model, show_shapes=True, show_layer_names=True, rankdir="LR") history = model.fit(train_ds, epochs=2)#, validation_data=(validation_features, validation_target))