多属性决策中的权重缩放:带范围约束的权重归一化技术问询
Got it, let's break down how to solve this problem step by step—we've got two levels to handle: attribute-level (within a feature) and feature-level, both needing to map real numbers to constrained weight ranges and normalize to a total sum of 1. Here's a practical, actionable approach:
Core Idea
For both attributes (under a single feature like Accommodation) and features themselves, we follow a 3-step workflow:
- Assign initial real values to each item.
- Map those values to their predefined weight ranges.
- Normalize the mapped weights to sum to 1, while respecting each item's range constraints.
Step 1: Assign Initial Real Values
First, pick real numbers for each attribute/feature. These can be:
- Randomly generated (e.g., from a normal distribution)
- Based on business logic (e.g., higher values for more important attributes)
- User-provided scores
Example for an Accommodation feature with 3 attributes:
- Room Type:
2.0 - Bed Count:
0.5 - Location:
-1.0
Step 2: Map Real Values to Target Weight Ranges
We need to convert the initial real numbers into values that fit each item's [low, high] weight range. Two reliable methods:
Option 1: Sigmoid Mapping (for arbitrary real numbers)
Sigmoid compresses any real number into the [0,1] interval, then we scale it to the target range:
import math def sigmoid(x): return 1 / (1 + math.exp(-x)) def map_to_range(x, low, high): normalized_x = sigmoid(x) return low + (high - low) * normalized_x
Using our example (with ranges: Room Type [0.3,0.6], Bed Count [0.2,0.4], Location [0.1,0.3]):
- Room Type:
0.3 + (0.6-0.3)*sigmoid(2.0) ≈ 0.564 - Bed Count:
0.2 + (0.4-0.2)*sigmoid(0.5) ≈ 0.324 - Location:
0.1 + (0.3-0.1)*sigmoid(-1.0) ≈ 0.154
Option 2: Min-Max Normalization (for bounded real numbers)
If your initial real values have a known min/max, use this to normalize to [0,1] first:
def min_max_norm(x, x_min, x_max): return (x - x_min) / (x_max - x_min) if x_max != x_min else 0.5 def map_to_range(x, low, high, x_min, x_max): normalized_x = min_max_norm(x, x_min, x_max) return low + (high - low) * normalized_x
Step 3: Normalize to Sum = 1 (With Range Constraints)
After mapping, the weights might not sum to 1. We need to adjust them while keeping each value within its [low, high] range.
Simple Linear Scaling (if no range breaks)
Calculate the total sum of mapped weights, then scale each weight by 1/total_sum:
mapped_weights = [0.564, 0.324, 0.154] total = sum(mapped_weights) # ~1.042 scaled_weights = [w / total for w in mapped_weights] # Result: ~[0.541, 0.311, 0.148] (sum ≈1, all within ranges)
Constrained Optimization (if scaling breaks ranges)
If linear scaling pushes a weight outside its [low, high] range, use constrained optimization to adjust weights while minimizing the difference from your mapped values. Here's how to do it with scipy:
from scipy.optimize import minimize import numpy as np # Objective: minimize the difference between adjusted and initial mapped weights def objective(w, initial_weights): return np.sum((w - initial_weights)**2) # Constraint: total sum must be 1 constraints = ({'type': 'eq', 'fun': lambda w: np.sum(w) - 1}) # Boundaries for each weight bounds = [(0.3, 0.6), (0.2, 0.4), (0.1, 0.3)] # Initial guess: our mapped weights initial_weights = np.array([0.564, 0.324, 0.154]) # Solve the optimization problem result = minimize(objective, initial_weights, args=(initial_weights,), constraints=constraints, bounds=bounds) final_weights = result.x # Sum is 1, all values stay within their ranges
Apply the Same Logic to Features
Once you've handled all attributes within each feature, repeat the exact same 3-step process for the features themselves:
- Assign real values to each feature.
- Map each value to its feature-level weight range.
- Normalize the feature weights to sum to 1, respecting their range constraints.
内容的提问来源于stack exchange,提问作者user5642824

