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))