import numpy as np
import tensorflow as tf
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Dense, Dropout, BatchNormalization, Concatenate
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.callbacks import EarlyStopping
# Simulated data shapes
num_queries = 3
input_dim = 100
num_docs = 500
# Input for each query
inputs = [Input(shape=(input_dim,), name=f'query_{i}') for i in range(num_queries)]
# Shared dense layers for each query
shared_dense = Dense(64, activation='relu')
shared_bn = BatchNormalization()
shared_dropout = Dropout(0.3)
processed_queries = []
for inp in inputs:
x = shared_dense(inp)
x = shared_bn(x)
x = shared_dropout(x)
processed_queries.append(x)
# Combine processed queries
combined = Concatenate()(processed_queries)
# Final layers
x = Dense(64, activation='relu')(combined)
x = Dropout(0.3)(x)
output = Dense(num_docs, activation='softmax')(x)
model = Model(inputs=inputs, outputs=output)
model.compile(optimizer=Adam(learning_rate=0.0005), loss='categorical_crossentropy', metrics=['accuracy'])
# Dummy data for demonstration
X_train = [np.random.rand(1000, input_dim) for _ in range(num_queries)]
y_train = tf.keras.utils.to_categorical(np.random.randint(0, num_docs, 1000), num_classes=num_docs)
X_val = [np.random.rand(200, input_dim) for _ in range(num_queries)]
y_val = tf.keras.utils.to_categorical(np.random.randint(0, num_docs, 200), num_classes=num_docs)
# Early stopping callback
early_stop = EarlyStopping(monitor='val_loss', patience=5, restore_best_weights=True)
history = model.fit(
X_train, y_train,
epochs=50,
batch_size=32,
validation_data=(X_val, y_val),
callbacks=[early_stop]
)
# After training, evaluate
train_loss, train_acc = model.evaluate(X_train, y_train, verbose=0)
val_loss, val_acc = model.evaluate(X_val, y_val, verbose=0)
print(f'Training accuracy: {train_acc*100:.2f}%')
print(f'Validation accuracy: {val_acc*100:.2f}%')