C.W.K.
Stream
Lesson 03 of 06 · published

Functional API — DAGs and Skip Connections

~14 min · functional, skip-connection, resnet, multi-io

Level 0Level 0
0 XP0/78 lessons0/17 achievements
0/100 XP to next level100 XP to go0% complete

Where production models live

The Functional API treats layer calls as function calls operating on symbolic tensors. You start with keras.Input(...), pipe tensors through layers, and pass the resulting tensors to keras.Model(inputs, outputs). This supports any directed acyclic graph (DAG) — branches, skip connections, multi-input, multi-output.

Almost every model in keras.applications (ResNet, EfficientNet, MobileNet) uses the Functional API. Reading those implementations is good practice — they're the canonical examples.

The two patterns you'll use most: residual blocks (add skip connection back into the main path) and multi-input models (image branch + metadata branch, concatenated before the classifier).

Code

Residual block — Functional 스타일·python
import keras
from keras import layers

inputs = keras.Input(shape=(32, 32, 3))

# First conv block
x = layers.Conv2D(32, 3, activation='relu', padding='same')(inputs)
x = layers.Conv2D(32, 3, activation='relu', padding='same')(x)
block1_out = layers.MaxPooling2D(2)(x)         # (16, 16, 32)

# Second block with skip connection
x = layers.Conv2D(64, 3, activation='relu', padding='same')(block1_out)
x = layers.Conv2D(64, 3, activation='relu', padding='same')(x)
shortcut = layers.Conv2D(64, 1, padding='same')(block1_out)  # 1x1 conv to match channels
block2_out = layers.add([x, shortcut])         # residual connection

x = layers.GlobalAveragePooling2D()(block2_out)
outputs = layers.Dense(10, activation='softmax')(x)

model = keras.Model(inputs, outputs, name="mini_resnet")
print(f"Parameters: {model.count_params():,}")
Multi-input + multi-output·python
import keras
from keras import layers

image_input = keras.Input(shape=(224, 224, 3), name="image")
meta_input  = keras.Input(shape=(16,), name="metadata")

x = layers.Conv2D(32, 3, activation='relu')(image_input)
x = layers.GlobalAveragePooling2D()(x)
x = layers.Dense(64, activation='relu')(x)

m = layers.Dense(32, activation='relu')(meta_input)
combined = layers.concatenate([x, m])

class_out = layers.Dense(10, activation='softmax', name="class_output")(combined)
conf_out  = layers.Dense(1, activation='sigmoid', name="confidence_output")(combined)

model = keras.Model(
    inputs=[image_input, meta_input],
    outputs=[class_out, conf_out],
    name="multi_modal"
)

model.compile(
    optimizer='adam',
    loss={'class_output': 'sparse_categorical_crossentropy',
          'confidence_output': 'binary_crossentropy'},
    metrics={'class_output': ['accuracy'],
             'confidence_output': ['accuracy']},
)

External links

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.