Skip to content

๐Ÿ“‹ BusinessRulesLayer

๐Ÿ“‹ BusinessRulesLayer

๐ŸŸก Intermediate โœ… Stable ๐Ÿ”ฅ Popular

๐ŸŽฏ Overview

The BusinessRulesLayer applies configurable business rules to neural network outputs, enabling the combination of learned patterns with explicit domain knowledge. This layer is particularly useful for anomaly detection and data validation where business rules can provide additional constraints.

This layer supports both numerical and categorical features with various comparison operators, making it flexible for different types of business rule validation.

๐Ÿ” How It Works

The BusinessRulesLayer processes data through configurable business rules:

  1. Rule Definition: Defines business rules for numerical or categorical features
  2. Rule Evaluation: Evaluates each rule against the input data
  3. Anomaly Detection: Identifies data that violates business rules
  4. Weight Learning: Optionally learns weights for soft rule enforcement
  5. Output Generation: Produces anomaly detection results
graph TD
    A[Input Features] --> B[Rule Evaluation]
    B --> C[Numerical Rules]
    B --> D[Categorical Rules]

    C --> E[Comparison Operators: >, <]
    D --> F[Set Operators: ==, in, !=, not in]

    E --> G[Rule Violations]
    F --> G
    G --> H[Anomaly Detection]
    H --> I[Business Anomaly Output]

    J[Learnable Weights] --> G

    style A fill:#e6f3ff,stroke:#4a86e8
    style I fill:#e8f5e9,stroke:#66bb6a
    style B fill:#fff9e6,stroke:#ffb74d
    style C fill:#f3e5f5,stroke:#9c27b0
    style D fill:#f3e5f5,stroke:#9c27b0
    style G fill:#e1f5fe,stroke:#03a9f4

๐Ÿ’ก Why Use This Layer?

Challenge Traditional Approach BusinessRulesLayer's Solution
Domain Knowledge Separate rule validation ๐ŸŽฏ Integrated business rules in neural networks
Anomaly Detection Statistical methods only โšก Rule-based anomaly detection
Data Validation Manual validation ๐Ÿง  Automatic validation with business rules
Interpretability Black box models ๐Ÿ”— Interpretable rule-based validation

๐Ÿ“Š Use Cases

  • Anomaly Detection: Detecting data that violates business rules
  • Data Validation: Validating data against business constraints
  • Domain Knowledge: Incorporating domain expertise into models
  • Quality Control: Ensuring data quality with business rules
  • Compliance: Enforcing business compliance rules

๐Ÿš€ Quick Start

Basic Usage

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import keras
from kerasfactory.layers import BusinessRulesLayer

# Create sample input data
batch_size, input_dim = 32, 1
x = keras.random.normal((batch_size, input_dim)) * 50  # Values around 0-50

# Apply business rules for numerical data
rules_layer = BusinessRulesLayer(
    rules=[(">", 0), ("<", 100)],  # Values must be between 0 and 100
    feature_type="numerical"
)
output = rules_layer(x)

print(f"Input shape: {x.shape}")           # (32, 1)
print(f"Output keys: {output.keys()}")     # ['business_anomaly']
print(f"Anomaly shape: {output['business_anomaly'].shape}")  # (32, 1)

Categorical Rules

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import keras
from kerasfactory.layers import BusinessRulesLayer

# Create sample categorical data
categorical_data = keras.ops.convert_to_tensor([
    ["red"], ["green"], ["blue"], ["yellow"]
])

# Apply business rules for categorical data
categorical_rules = BusinessRulesLayer(
    rules=[("in", ["red", "green", "blue"])],  # Only allow red, green, blue
    feature_type="categorical"
)
output = categorical_rules(categorical_data)

print(f"Anomaly detection: {output['business_anomaly']}")
# Output: [[False], [False], [False], [True]]  # yellow is anomalous

In a Sequential Model

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import keras
from kerasfactory.layers import BusinessRulesLayer

model = keras.Sequential([
    keras.layers.Dense(32, activation='relu'),
    keras.layers.Dense(16, activation='relu'),
    keras.layers.Dense(1, activation='sigmoid'),
    BusinessRulesLayer(
        rules=[(">", 0), ("<", 1)],  # Ensure output is between 0 and 1
        feature_type="numerical"
    )
])

model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

In a Functional Model

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import keras
from kerasfactory.layers import BusinessRulesLayer

# Define inputs
inputs = keras.Input(shape=(20,))  # 20 features

# Process features
x = keras.layers.Dense(32, activation='relu')(inputs)
x = keras.layers.Dense(16, activation='relu')(x)
x = keras.layers.Dense(1, activation='sigmoid')(x)

# Apply business rules
rules_output = BusinessRulesLayer(
    rules=[(">", 0), ("<", 1)],
    feature_type="numerical"
)(x)

# Combine with original output
combined = keras.layers.Concatenate()([x, rules_output['business_anomaly']])
final_output = keras.layers.Dense(1, activation='sigmoid')(combined)

model = keras.Model(inputs, final_output)

Advanced Configuration

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# Advanced configuration with trainable weights
def create_business_rules_model():
    inputs = keras.Input(shape=(25,))

    # Process features
    x = keras.layers.Dense(64, activation='relu')(inputs)
    x = keras.layers.Dense(32, activation='relu')(x)
    x = keras.layers.Dense(16, activation='relu')(x)

    # Apply business rules with trainable weights
    rules_output = BusinessRulesLayer(
        rules=[(">", 0), ("<", 100), ("!=", 50)],  # Multiple rules
        feature_type="numerical",
        trainable_weights=True,  # Learn rule weights
        weight_initializer="ones"
    )(x)

    # Combine with anomaly information
    anomaly_info = rules_output['business_anomaly']
    combined = keras.layers.Concatenate()([x, anomaly_info])

    # Final processing
    x = keras.layers.Dense(8, activation='relu')(combined)
    x = keras.layers.Dropout(0.2)(x)

    # Multi-task output
    classification = keras.layers.Dense(3, activation='softmax', name='classification')(x)
    regression = keras.layers.Dense(1, name='regression')(x)
    anomaly = keras.layers.Dense(1, activation='sigmoid', name='anomaly')(x)

    return keras.Model(inputs, [classification, regression, anomaly])

model = create_business_rules_model()
model.compile(
    optimizer='adam',
    loss={'classification': 'categorical_crossentropy', 'regression': 'mse', 'anomaly': 'binary_crossentropy'},
    loss_weights={'classification': 1.0, 'regression': 0.5, 'anomaly': 0.3}
)

๐Ÿ“– API Reference

kerasfactory.layers.BusinessRulesLayer

This module implements a BusinessRulesLayer that allows applying configurable business rules to neural network outputs. This enables combining learned patterns with explicit domain knowledge.

Classes

BusinessRulesLayer
1
2
3
4
5
6
7
8
9
BusinessRulesLayer(
    rules: list[Rule],
    feature_type: str,
    trainable_weights: bool = True,
    weight_initializer: str
    | initializers.Initializer = "ones",
    name: str | None = None,
    **kwargs: Any
)

Evaluates business-defined rules for anomaly detection.

This layer applies user-defined business rules to detect anomalies. Rules can be defined for both numerical and categorical features.

For numerical features
  • Comparison operators: '>' and '<'
  • Example: [(">", 0), ("<", 100)] for range validation
For categorical features
  • Set operators: '==', 'in', '!=', 'not in'
  • Example: [("in", ["red", "green", "blue"])] for valid categories

Attributes:

Name Type Description
rules

List of rule tuples (operator, value).

feature_type

Type of feature ('numerical' or 'categorical').

Example
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Numerical rules
layer = BusinessRulesLayer(rules=[(">", 0), ("<", 100)], feature_type="numerical")
outputs = layer(tf.constant([[50.0], [-10.0]]))
print(outputs['business_anomaly'])  # [[False], [True]]

# Categorical rules
layer = BusinessRulesLayer(
    rules=[("in", ["red", "green"])],
    feature_type="categorical"
)
outputs = layer(tf.constant([["red"], ["blue"]]))
print(outputs['business_anomaly'])  # [[False], [True]]

Initializes the layer.

Parameters:

Name Type Description Default
rules list[Rule]

List of rule tuples (operator, value).

required
feature_type str

Type of feature ('numerical' or 'categorical').

required
trainable_weights bool

Whether to use trainable weights for soft rule enforcement. Default is True.

True
weight_initializer str | Initializer

Initializer for rule weights. Default is 'ones'.

'ones'
name str | None

Optional name for the layer.

None
**kwargs Any

Additional layer arguments.

{}

Raises:

Type Description
ValueError

If feature_type is invalid or rules have invalid operators.

Source code in kerasfactory/layers/BusinessRulesLayer.py
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
def __init__(
    self,
    rules: list[Rule],
    feature_type: str,
    trainable_weights: bool = True,
    weight_initializer: str | initializers.Initializer = "ones",
    name: str | None = None,
    **kwargs: Any,
) -> None:
    """Initializes the layer.

    Args:
        rules: List of rule tuples (operator, value).
        feature_type: Type of feature ('numerical' or 'categorical').
        trainable_weights: Whether to use trainable weights for soft rule enforcement.
            Default is True.
        weight_initializer: Initializer for rule weights. Default is 'ones'.
        name: Optional name for the layer.
        **kwargs: Additional layer arguments.

    Raises:
        ValueError: If feature_type is invalid or rules have invalid operators.
    """
    # Set attributes before calling parent's __init__
    self._rules = rules
    self._feature_type = feature_type
    self._weights_trainable = trainable_weights
    self._weight_initializer = initializers.get(weight_initializer)

    # Validate feature type
    if feature_type not in ["numerical", "categorical"]:
        raise ValueError(
            f"Invalid feature_type: {feature_type}. "
            "Must be 'numerical' or 'categorical'",
        )

    super().__init__(name=name, **kwargs)

    # Set public attributes
    self.rules = self._rules
    self.feature_type = self._feature_type
    self.weights_trainable = self._weights_trainable
    self.weight_initializer = self._weight_initializer
Functions
compute_output_shape
1
2
3
compute_output_shape(
    input_shape: tuple[int | None, int]
) -> dict[str, tuple[int | None, int]]

Compute the output shape of the layer.

Parameters:

Name Type Description Default
input_shape tuple[int | None, int]

Input shape tuple.

required

Returns:

Type Description
dict[str, tuple[int | None, int]]

Dictionary mapping output names to their shapes.

Source code in kerasfactory/layers/BusinessRulesLayer.py
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
def compute_output_shape(
    self,
    input_shape: tuple[int | None, int],
) -> dict[str, tuple[int | None, int]]:
    """Compute the output shape of the layer.

    Args:
        input_shape: Input shape tuple.

    Returns:
        Dictionary mapping output names to their shapes.
    """
    batch_size = input_shape[0]
    return {
        "business_score": (batch_size, 1),
        "business_proba": (batch_size, 1),
        "business_anomaly": (batch_size, 1),
        "business_reason": (batch_size, 1),
        "business_value": input_shape,
    }

๐Ÿ”ง Parameters Deep Dive

rules (list)

  • Purpose: List of business rules to apply
  • Format: List of tuples (operator, value)
  • Examples: [(">", 0), ("<", 100)] for numerical, [("in", ["red", "green"])] for categorical
  • Impact: Defines the business constraints to enforce
  • Recommendation: Define rules based on domain knowledge

feature_type (str)

  • Purpose: Type of feature being validated
  • Options: "numerical" or "categorical"
  • Impact: Determines which operators are available
  • Recommendation: Use "numerical" for continuous data, "categorical" for discrete data

trainable_weights (bool)

  • Purpose: Whether to use trainable weights for soft rule enforcement
  • Default: True
  • Impact: Allows learning optimal rule weights
  • Recommendation: Use True for most applications

weight_initializer (str or initializer)

  • Purpose: Initializer for rule weights
  • Default: "ones"
  • Impact: Affects initial rule importance
  • Recommendation: Use "ones" for equal initial importance

๐Ÿ“ˆ Performance Characteristics

  • Speed: โšกโšกโšกโšก Very fast - simple rule evaluation
  • Memory: ๐Ÿ’พ Low memory usage - minimal additional parameters
  • Accuracy: ๐ŸŽฏ๐ŸŽฏ๐ŸŽฏ๐ŸŽฏ Excellent for rule-based validation
  • Best For: Data validation and anomaly detection with business rules

๐ŸŽจ Examples

Example 1: Financial Data Validation

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import keras
import numpy as np
from kerasfactory.layers import BusinessRulesLayer

# Create financial data validation model
def create_financial_validation_model():
    inputs = keras.Input(shape=(10,))  # 10 financial features

    # Process financial features
    x = keras.layers.Dense(32, activation='relu')(inputs)
    x = keras.layers.Dense(16, activation='relu')(x)
    x = keras.layers.Dense(1, activation='sigmoid')(x)

    # Apply financial business rules
    rules_output = BusinessRulesLayer(
        rules=[(">", 0), ("<", 1)],  # Probability must be between 0 and 1
        feature_type="numerical",
        trainable_weights=True
    )(x)

    # Combine with anomaly information
    anomaly_info = rules_output['business_anomaly']
    combined = keras.layers.Concatenate()([x, anomaly_info])

    # Final output
    outputs = keras.layers.Dense(1, activation='sigmoid')(combined)

    return keras.Model(inputs, outputs)

model = create_financial_validation_model()
model.compile(optimizer='adam', loss='binary_crossentropy')

# Test with sample data
sample_data = keras.random.normal((100, 10))
predictions = model(sample_data)
print(f"Financial validation predictions shape: {predictions.shape}")

Example 2: Categorical Data Validation

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# Create categorical data validation model
def create_categorical_validation_model():
    inputs = keras.Input(shape=(5,))  # 5 categorical features

    # Process categorical features
    x = keras.layers.Dense(32, activation='relu')(inputs)
    x = keras.layers.Dense(16, activation='relu')(x)
    x = keras.layers.Dense(1, activation='sigmoid')(x)

    # Apply categorical business rules
    rules_output = BusinessRulesLayer(
        rules=[(">", 0), ("<", 1)],  # Probability must be between 0 and 1
        feature_type="numerical",
        trainable_weights=True
    )(x)

    # Combine with anomaly information
    anomaly_info = rules_output['business_anomaly']
    combined = keras.layers.Concatenate()([x, anomaly_info])

    # Final output
    outputs = keras.layers.Dense(1, activation='sigmoid')(combined)

    return keras.Model(inputs, outputs)

model = create_categorical_validation_model()
model.compile(optimizer='adam', loss='binary_crossentropy')

Example 3: Rule Analysis

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# Analyze rule violations
def analyze_rule_violations():
    # Create model with business rules
    inputs = keras.Input(shape=(15,))
    x = keras.layers.Dense(32, activation='relu')(inputs)
    x = keras.layers.Dense(16, activation='relu')(x)
    x = keras.layers.Dense(1, activation='sigmoid')(x)

    rules_output = BusinessRulesLayer(
        rules=[(">", 0), ("<", 1)],
        feature_type="numerical"
    )(x)

    model = keras.Model(inputs, [x, rules_output['business_anomaly']])

    # Test with different input patterns
    test_inputs = [
        keras.random.normal((10, 15)),  # Random data
        keras.random.normal((10, 15)) * 2,  # Scaled data
        keras.random.normal((10, 15)) + 1,  # Shifted data
    ]

    print("Rule Violation Analysis:")
    print("=" * 40)

    for i, test_input in enumerate(test_inputs):
        prediction, anomaly = model(test_input)
        print(f"Test {i+1}: Anomaly rate = {keras.ops.mean(anomaly):.4f}")

    return model

# Analyze rule violations
# model = analyze_rule_violations()

๐Ÿ’ก Tips & Best Practices

  • Rule Definition: Define rules based on domain knowledge
  • Feature Types: Use appropriate feature types (numerical vs categorical)
  • Trainable Weights: Use trainable weights for soft rule enforcement
  • Rule Complexity: Start with simple rules, add complexity as needed
  • Validation: Test rules on known good and bad data
  • Integration: Combine with other layers for comprehensive validation

โš ๏ธ Common Pitfalls

  • Feature Types: Must match the actual data type
  • Rule Operators: Use correct operators for each feature type
  • Rule Values: Ensure rule values are appropriate for the data
  • Memory Usage: Rules are evaluated for each sample
  • Gradient Flow: Rules may not be differentiable

๐Ÿ“š Further Reading