Deep Learning
Keras
Data Types
Neural Networks
Machine Learning

Deep Learning model with Different data types in Keras

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

Keras can handle different kinds of inputs in the same model, but you usually do not solve that by forcing every feature into one raw array. The practical approach is to build a multi-input model where each branch uses the right dtype and preprocessing steps before the features are combined.

Why Different Data Types Need Different Treatment

Numerical columns, integer categories, text tokens, and images do not mean the same thing to a neural network. A Dense layer can consume floating-point tensors directly, but strings and categories must be encoded first, and images usually need convolutional layers or at least normalization.

That is why the Keras Functional API is a much better fit than the Sequential API for mixed-input problems. It lets you create a separate input path for each data type and join them later.

Example: Numeric and Categorical Inputs Together

Here is a small model that mixes floating-point features with a string category.

python
1import tensorflow as tf
2
3age_input = tf.keras.Input(shape=(1,), dtype=tf.float32, name="age")
4income_input = tf.keras.Input(shape=(1,), dtype=tf.float32, name="income")
5city_input = tf.keras.Input(shape=(1,), dtype=tf.string, name="city")
6
7numeric_features = tf.keras.layers.Concatenate()([age_input, income_input])
8numeric_branch = tf.keras.layers.Dense(8, activation="relu")(numeric_features)
9
10city_lookup = tf.keras.layers.StringLookup(output_mode="one_hot")
11city_lookup.adapt(tf.constant(["Toronto", "Montreal", "Toronto", "Ottawa"]))
12city_branch = city_lookup(city_input)
13
14combined = tf.keras.layers.Concatenate()([numeric_branch, city_branch])
15hidden = tf.keras.layers.Dense(16, activation="relu")(combined)
16output = tf.keras.layers.Dense(1, activation="sigmoid")(hidden)
17
18model = tf.keras.Model(
19    inputs=[age_input, income_input, city_input],
20    outputs=output
21)
22
23model.compile(optimizer="adam", loss="binary_crossentropy", metrics=["accuracy"])
24
25features = {
26    "age": tf.constant([[25.0], [42.0], [31.0]], dtype=tf.float32),
27    "income": tf.constant([[50000.0], [90000.0], [62000.0]], dtype=tf.float32),
28    "city": tf.constant([["Toronto"], ["Montreal"], ["Ottawa"]], dtype=tf.string),
29}
30labels = tf.constant([[0.0], [1.0], [0.0]], dtype=tf.float32)
31
32model.fit(features, labels, epochs=3, verbose=0)

The important part is that each input keeps a dtype that matches its meaning until preprocessing converts it into a numeric representation the network can learn from.

Example: Adding an Image Branch

If one of the inputs is an image, give it its own branch.

python
1import tensorflow as tf
2
3image_input = tf.keras.Input(shape=(32, 32, 3), dtype=tf.float32, name="image")
4meta_input = tf.keras.Input(shape=(4,), dtype=tf.float32, name="metadata")
5
6image_branch = tf.keras.layers.Rescaling(1.0 / 255)(image_input)
7image_branch = tf.keras.layers.Conv2D(16, 3, activation="relu")(image_branch)
8image_branch = tf.keras.layers.MaxPooling2D()(image_branch)
9image_branch = tf.keras.layers.Flatten()(image_branch)
10
11meta_branch = tf.keras.layers.Dense(8, activation="relu")(meta_input)
12
13combined = tf.keras.layers.Concatenate()([image_branch, meta_branch])
14output = tf.keras.layers.Dense(3, activation="softmax")(combined)
15
16model = tf.keras.Model(inputs=[image_input, meta_input], outputs=output)

This pattern is common in recommendation, fraud detection, medical imaging, and tabular-plus-image systems.

Dtype Versus Modality

It helps to separate two ideas:

  • dtype means the tensor storage type, such as float32, int32, or string
  • modality means the kind of data, such as image, text, category, or continuous numeric feature

Different modalities often imply different model branches, while dtypes mostly affect how preprocessing layers interpret the values.

Preprocessing Layers Matter

Modern Keras makes mixed data much easier because preprocessing layers can live directly in the model graph. Some common examples are:

  • 'Normalization for continuous numeric features'
  • 'StringLookup for string categories'
  • 'IntegerLookup for integer categories'
  • 'TextVectorization for text'
  • 'Rescaling for images'

Keeping preprocessing near the model reduces training-serving skew because the same transformations can run both during training and inference.

Why One Big Dense Input Is Usually Wrong

Beginners often try to force everything into one 2D numeric matrix before modeling. That can work for small classical machine-learning pipelines, but it throws away structure. Images stop looking like images, categorical strings lose their vocabulary handling, and text becomes awkward unless you manually encode everything beforehand.

Keras is most expressive when you preserve input meaning for as long as possible.

Common Pitfalls

The first pitfall is feeding a string or categorical tensor directly into a Dense layer. Dense layers expect numeric tensors, so you must encode strings and categories first.

Another pitfall is forgetting to call adapt() on lookup or normalization layers. Without adaptation, those layers do not know the vocabulary or scaling statistics they need.

A third pitfall is letting pandas object columns leak into the model pipeline without explicit conversion. Object dtype is a warning sign that your preprocessing needs cleanup.

Finally, keep output shapes consistent. When you feed a dictionary of inputs into model.fit, the keys and tensor shapes must match the named Input layers exactly.

Summary

  • Mixed data types in Keras are best handled with the Functional API and separate input branches
  • Each input should keep the right dtype until preprocessing converts it to learnable numeric features
  • Use preprocessing layers such as StringLookup, Normalization, and Rescaling
  • Combine branches only after each data type has been encoded appropriately
  • Avoid flattening every feature into one raw matrix unless you are intentionally simplifying the problem

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design