import tensorflow as tf
import numpy as np
# import matplotlib.pyplot as plt
from prepare import load_and_preprocess_data
from tensorflow.keras import layers, Model, regularizers
class FeatureGrouping(layers.Layer):
"""特征分组层:将输入特征按类型分组"""
def __init__(self, group_config, **kwargs):
"""
group_config: 分组配置字典,例如{'group1': [0,1,2], 'group2': [3,4,5]}
"""
super(FeatureGrouping, self).__init__(**kwargs)
self.group_config = group_config
self.group_names = list(group_config.keys())
def call(self, inputs):
"""将输入特征按配置分组"""
grouped_features = {}
for group_name, indices in self.group_config.items():
grouped_features[group_name] = tf.gather(inputs, indices, axis=1)
return grouped_features
class FeatureEmbedding(layers.Layer):
"""特征嵌入层:为每个特征组创建嵌入表示"""
def __init__(self, embedding_dims, **kwargs):
"""
embedding_dims: 每个组的嵌入维度字典,例如{'group1': 16, 'group2': 32}
"""
super(FeatureEmbedding, self).__init__(**kwargs)
self.embedding_dims = embedding_dims
self.embedding_layers = {}
def build(self, input_shapes):
"""为每个特征组创建嵌入层"""
for group_name, shape in input_shapes.items():
dim = self.embedding_dims[group_name]
self.embedding_layers[group_name] = layers.Dense(
dim, activation='relu', name=f'embed_{group_name}')
super().build(input_shapes)
def call(self, inputs):
"""应用嵌入转换"""
embeddings = {}
for group_name, features in inputs.items():
embeddings[group_name] = self.embedding_layers[group_name](features)
return embeddings
class MultiHeadSelfAttention(layers.Layer):
"""多头自注意力机制"""
def __init__(self, num_heads, key_dim, **kwargs):
super(MultiHeadSelfAttention, self).__init__(**kwargs)
self.mha = layers.MultiHeadAttention(
num_heads=num_heads, key_dim=key_dim)
self.norm = layers.LayerNormalization(epsilon=1e-6)
self.add = layers.Add()
def call(self, inputs):
"""应用多头自注意力"""
attn_output = self.mha(query=inputs, value=inputs, key=inputs)
out = self.add([inputs, attn_output])
return self.norm(out)
class PhysicsConstrainedModel(Model):
"""物理约束融合模型"""
def __init__(self, group_config, embedding_dims, num_heads, key_dim, output_dim,
physics_constraint_fn, constraint_weight=0.1, **kwargs):
"""
physics_constraint_fn: 物理约束函数,接受输入和预测输出,返回约束损失
constraint_weight: 物理约束的权重系数
"""
super(PhysicsConstrainedModel, self).__init__(**kwargs)
self.grouping = FeatureGrouping(group_config)
self.embedding = FeatureEmbedding(embedding_dims)
self.attention_layers = {}
# 为每个组创建自注意力层
for group_name in group_config.keys():
self.attention_layers[group_name] = MultiHeadSelfAttention(
num_heads, key_dim)
# 融合层和输出层
self.concat = layers.Concatenate()
self.dense1 = layers.Dense(64, activation='relu')
self.dense2 = layers.Dense(32, activation='relu')
self.output_layer = layers.Dense(output_dim)
# 物理约束参数
self.physics_constraint_fn = physics_constraint_fn
self.constraint_weight = constraint_weight
def call(self, inputs):
"""前向传播"""
# 特征分组
grouped = self.grouping(inputs)
# 特征嵌入
embedded = self.embedding(grouped)
# 应用自注意力
attended = {}
for group_name, features in embedded.items():
# 添加位置编码
seq_length = tf.shape(features)[1]
positions = tf.range(start=0, limit=seq_length, delta=1)
positions = tf.cast(positions, dtype=tf.float32)
positions = tf.expand_dims(positions, axis=0) # (1, seq_length)
positions = tf.tile(positions, [tf.shape(features)[0], 1]) # (batch, seq_length)
positions = tf.expand_dims(positions, axis=-1) # (batch, seq_length, 1)
# 合并特征和位置编码
features_with_pos = tf.concat([features, positions], axis=-1)
attended[group_name] = self.attention_layers[group_name](features_with_pos)
# 池化每个组的特征
pooled = [layers.GlobalAveragePooling1D()(feat) for feat in attended.values()]
# 特征融合
fused = self.concat(pooled)
x = self.dense1(fused)
x = self.dense2(x)
return self.output_layer(x)
def train_step(self, data):
"""自定义训练步骤,包含物理约束"""
x, y = data
with tf.GradientTape() as tape:
# 前向传播
y_pred = self(x, training=True)
# 计算主损失
main_loss = self.compiled_loss(y, y_pred)
# 计算物理约束损失
physics_loss = self.physics_constraint_fn(x, y_pred)
# 总损失 = 主损失 + 约束损失
total_loss = main_loss + self.constraint_weight * physics_loss
# 计算梯度并更新权重
trainable_vars = self.trainable_variables
gradients = tape.gradient(total_loss, trainable_vars)
self.optimizer.apply_gradients(zip(gradients, trainable_vars))
# 更新指标
self.compiled_metrics.update_state(y, y_pred)
# 返回指标
return {m.name: m.result() for m in self.metrics}
# 示例物理约束函数:能量守恒约束
def energy_conservation_constraint(inputs, predictions):
"""
简单的能量守恒约束:输入的总和应等于输出的总和
在实际应用中,应根据具体物理规律设计约束
"""
input_sum = tf.reduce_sum(inputs, axis=1, keepdims=True)
output_sum = tf.reduce_sum(predictions, axis=1, keepdims=True)
return tf.reduce_mean(tf.square(input_sum - output_sum))
# 生成模拟数据
def generate_data(num_samples=1000, input_dim=10):
"""生成模拟数据"""
# 随机输入特征
X = np.random.randn(num_samples, input_dim).astype(np.float32)
# 目标输出:输入特征的线性组合加噪声
weights = np.random.randn(input_dim, 1)
y = X @ weights + 0.1 * np.random.randn(num_samples, 1)
return X, y
# 配置参数
INPUT_DIM = 10
OUTPUT_DIM = 1
NUM_SAMPLES = 10000
BATCH_SIZE = 32
EPOCHS = 50
# 特征分组配置
GROUP_CONFIG = {
'group1': [0, 1, 2, 3], # 第一组特征索引
'group2': [4, 5, 6], # 第二组特征索引
'group3': [7, 8, 9] # 第三组特征索引
}
# 嵌入维度配置
EMBEDDING_DIMS = {
'group1': 16,
'group2': 16,
'group3': 16
}
# 注意力参数
NUM_HEADS = 4
KEY_DIM = 8
# 物理约束权重
CONSTRAINT_WEIGHT = 0.1
# 生成数据
X_train, y_train = generate_data(NUM_SAMPLES, INPUT_DIM)
print(f"训练数据形状: {X_train.shape}, 目标数据形状: {y_train.shape}")
# X_train, X_test, y_train, y_test, preprocessor = load_and_preprocess_data('E:\\神经网络\\分类数据集.xlsx') # 替换为实际文件路径
# 创建模型
model = PhysicsConstrainedModel(
group_config=GROUP_CONFIG,
embedding_dims=EMBEDDING_DIMS,
num_heads=NUM_HEADS,
key_dim=KEY_DIM,
output_dim=OUTPUT_DIM,
physics_constraint_fn=energy_conservation_constraint,
constraint_weight=CONSTRAINT_WEIGHT
)
# 编译模型
model.compile(
optimizer=tf.keras.optimizers.Adam(learning_rate=0.001),
loss='mse',
metrics=['mae']
)
# 训练模型
print("开始训练物理约束模型...")
history = model.fit(
X_train, y_train,
batch_size=BATCH_SIZE,
epochs=EPOCHS,
validation_split=0.2
)
# 评估模型
test_loss, test_mae = model.evaluate(X_train[:100], y_train[:100])
print(f"\n测试损失: {test_loss:.4f}, 测试MAE: {test_mae:.4f}")
# 可视化训练过程
# plt.figure(figsize=(12, 5))
# plt.subplot(1, 2, 1)
# plt.plot(history.history['loss'], label='训练损失')
# plt.plot(history.history['val_loss'], label='验证损失')
# plt.title('模型损失')
# plt.ylabel('损失')
# plt.xlabel('Epoch')
# plt.legend()
# plt.subplot(1, 2, 2)
# plt.plot(history.history['mae'], label='训练MAE')
# plt.plot(history.history['val_mae'], label='验证MAE')
# plt.title('平均绝对误差')
# plt.ylabel('MAE')
# plt.xlabel('Epoch')
# plt.legend()
# plt.tight_layout()
# plt.show()
# 模型结构可视化
tf.keras.utils.plot_model(
model, to_file='physics_constrained_model.png',
show_shapes=True, show_layer_names=True
)
上面这段代码在运行时出现
Traceback (most recent call last):
File "e:\神经网络\multi-head-attention.py", line 226, in <module>
history = model.fit(
File "C:\Users\Administrator\.conda\envs\ens\lib\site-packages\tensorflow\python\keras\engine\training.py", line 1193, in fit
tmp_logs = self.train_function(iterator)
File "C:\Users\Administrator\.conda\envs\ens\lib\site-packages\tensorflow\python\eager\def_function.py", line 885, in __call__
result = self._call(*args, **kwds)
File "C:\Users\Administrator\.conda\envs\ens\lib\site-packages\tensorflow\python\eager\def_function.py", line 933, in _call
self._initialize(args, kwds, add_initializers_to=initializers)
File "C:\Users\Administrator\.conda\envs\ens\lib\site-packages\tensorflow\python\eager\def_function.py", line 759, in _initialize
self._stateful_fn._get_concrete_function_internal_garbage_collected( # pylint: disable=protected-access
File "C:\Users\Administrator\.conda\envs\ens\lib\site-packages\tensorflow\python\eager\function.py", line 3066, in _get_concrete_function_internal_garbage_collected
graph_function, _ = self._maybe_define_function(args, kwargs)
File "C:\Users\Administrator\.conda\envs\ens\lib\site-packages\tensorflow\python\eager\function.py", line 3463, in _maybe_define_function
graph_function = self._create_graph_function(args, kwargs)
File "C:\Users\Administrator\.conda\envs\ens\lib\site-packages\tensorflow\python\eager\function.py", line 3298, in _create_graph_function
func_graph_module.func_graph_from_py_func(
File "C:\Users\Administrator\.conda\envs\ens\lib\site-packages\tensorflow\python\framework\func_graph.py", line 1007, in func_graph_from_py_func
func_outputs = python_func(*func_args, **func_kwargs)
File "C:\Users\Administrator\.conda\envs\ens\lib\site-packages\tensorflow\python\eager\def_function.py", line 668, in wrapped_fn
out = weak_wrapped_fn().__wrapped__(*args, **kwds)
File "C:\Users\Administrator\.conda\envs\ens\lib\site-packages\tensorflow\python\framework\func_graph.py", line 994, in wrapper
raise e.ag_error_metadata.to_exception(e)
ValueError: in user code:
C:\Users\Administrator\.conda\envs\ens\lib\site-packages\tensorflow\python\keras\engine\training.py:862 train_function *
return step_function(self, iterator)
e:\神经网络\multi-head-attention.py:112 call *
features_with_pos = tf.concat([features, positions], axis=-1)
C:\Users\Administrator\.conda\envs\ens\lib\site-packages\tensorflow\python\util\dispatch.py:206 wrapper **
return target(*args, **kwargs)
C:\Users\Administrator\.conda\envs\ens\lib\site-packages\tensorflow\python\ops\array_ops.py:1769 concat
return gen_array_ops.concat_v2(values=values, axis=axis, name=name)
C:\Users\Administrator\.conda\envs\ens\lib\site-packages\tensorflow\python\ops\gen_array_ops.py:1226 concat_v2
_, _, _op, _outputs = _op_def_library._apply_op_helper(
C:\Users\Administrator\.conda\envs\ens\lib\site-packages\tensorflow\python\framework\op_def_library.py:748 _apply_op_helper
op = g._create_op_internal(op_type_name, inputs, dtypes=None,
C:\Users\Administrator\.conda\envs\ens\lib\site-packages\tensorflow\python\framework\func_graph.py:599 _create_op_internal
return super(FuncGraph, self)._create_op_internal( # pylint: disable=protected-access
C:\Users\Administrator\.conda\envs\ens\lib\site-packages\tensorflow\python\framework\ops.py:3561 _create_op_internal
ret = Operation(
C:\Users\Administrator\.conda\envs\ens\lib\site-packages\tensorflow\python\framework\ops.py:2041 __init__
self._c_op = _create_c_op(self._graph, node_def, inputs,
C:\Users\Administrator\.conda\envs\ens\lib\site-packages\tensorflow\python\framework\ops.py:1883 _create_c_op
raise ValueError(str(e))
ValueError: Shape must be rank 2 but is rank 3 for '{{node physics_constrained_model/concat}} = ConcatV2[N=2, T=DT_FLOAT, Tidx=DT_INT32](physics_constrained_model/feature_embedding/embed_group1/Relu, physics_constrained_model/ExpandDims_1, physics_constrained_model/concat/axis)' with input shapes: [32,16], [32,16,1], [].,请帮我解决代码问题
最新发布