You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Keras中实现节点连接任意的前馈神经网络?

Handling Non-Fully Connected Layers and Skip Connections in Keras

Hey Oscar, great question! You’re absolutely right that the Sequential API (and the older Graph class, which is now deprecated) defaults to full connectivity between consecutive layers. But don’t worry—Keras has a far more flexible tool for building custom network topologies: the Functional API. It’s designed exactly for cases like yours where you need non-standard connections, partial layer links, or skip connections.

Let’s break down how to tackle both your use cases:

1. Building Non-Fully Connected Feedforward Layers

If you want to exclude specific connections between neurons (e.g., the first node of layer 2 doesn’t connect to the second node of layer 3), you have two straightforward approaches:

Option 1: Use a Custom Weight Constraint

You can define a constraint that masks out specific weight values, ensuring they stay at 0 and aren’t updated during training. Here’s how:

from keras.layers import Input, Dense
from keras.models import Model
from keras.constraints import Constraint
import tensorflow as tf

# Define a custom constraint to mask specific connections
class ConnectionMask(Constraint):
    def __init__(self, mask_matrix):
        self.mask = mask_matrix
    
    def __call__(self, weights):
        # Multiply weights by the mask to zero out unwanted connections
        return weights * self.mask

# Step 1: Define input layer
input_layer = Input(shape=(10,))

# Step 2: First hidden layer (fully connected)
hidden_layer_1 = Dense(3, activation='relu')(input_layer)

# Step 3: Create a mask for the second hidden layer
# Mask shape: (num_neurons_in_prev_layer, num_neurons_in_current_layer)
# We'll zero out the connection from hidden_layer_1's 1st neuron to hidden_layer_2's 2nd neuron
connection_mask = tf.constant([
    [1.0, 0.0],  # Allow connection to 1st neuron, block to 2nd
    [1.0, 1.0],  # Allow both connections
    [1.0, 1.0]   # Allow both connections
], dtype=tf.float32)

# Step 4: Second hidden layer with the custom mask constraint
hidden_layer_2 = Dense(
    2,
    activation='relu',
    kernel_constraint=ConnectionMask(connection_mask)
)(hidden_layer_1)

# Step 5: Output layer
output_layer = Dense(1, activation='sigmoid')(hidden_layer_2)

# Build and compile the model
model = Model(inputs=input_layer, outputs=output_layer)
model.compile(optimizer='adam', loss='binary_crossentropy')

Option 2: Manually Modify Layer Weights

If you prefer a more direct approach, you can initialize the layer’s weights, zero out the unwanted connections, and freeze those specific weights to prevent updates:

# After defining hidden_layer_2 (before connecting it to the input)
hidden_layer_2 = Dense(2, activation='relu')
# Get the initial kernel weights (shape: 3x2)
kernel_weights = hidden_layer_2.get_weights()[0]
# Zero out the unwanted connection
kernel_weights[0, 1] = 0.0
# Reassign the weights
hidden_layer_2.set_weights([kernel_weights, hidden_layer_2.get_weights()[1]])
# Freeze the kernel weights so the masked connection stays zero
hidden_layer_2.trainable_weights[0].assign(kernel_weights)

# Now connect the layer to hidden_layer_1
hidden_layer_2 = hidden_layer_2(hidden_layer_1)

2. Adding Skip (Jump) Connections

Skip connections (like those in ResNets) are trivial to implement with the Functional API—you just connect layers directly to non-consecutive layers, then combine their outputs (via concatenation, addition, etc.). Here are two common examples:

Example 1: Concatenated Skip Connection

Connect the input layer directly to a later hidden layer by concatenating their outputs:

from keras.layers import concatenate

# Reuse the input_layer and hidden_layer_2 from earlier
# Add a skip connection: concatenate input layer with hidden_layer_2
concat_skip = concatenate([input_layer, hidden_layer_2])
# Output layer uses the concatenated tensor
output_layer = Dense(1, activation='sigmoid')(concat_skip)

model = Model(inputs=input_layer, outputs=output_layer)

Example 2: Residual Skip Connection (Addition)

For layers with matching output shapes, you can add their outputs directly (this is the core of ResNet architectures):

from keras.layers import add

# Define a hidden layer with the same output shape as hidden_layer_1
hidden_layer_2 = Dense(3, activation='relu')(hidden_layer_1)
# Add the original hidden_layer_1 output to hidden_layer_2's output
residual_connection = add([hidden_layer_1, hidden_layer_2])
# Pass the combined output to the final layer
output_layer = Dense(1, activation='sigmoid')(residual_connection)

model = Model(inputs=input_layer, outputs=output_layer)

A quick note: The old Graph class is no longer recommended for new projects—Functional API is the standard for custom models in modern Keras (and TensorFlow Keras).

内容的提问来源于stack exchange,提问作者Oscar Gabriel Reyes Pupo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:22:49