基于TensorFlow Federated的联邦数据集:特征标签划分与训练测试集拆分技术问题
Hey there! Let's tackle your two federated learning dataset questions one by one, building on your existing TensorFlow Federated (TFF) setup:
1. Splitting Features and Labels (Pandas iloc-style Logic)
From your sample tensor tuple, each data point is a 12-element tuple. To replicate the DataFrame.iloc[1:-1] (features) and what I assume is DataFrame.iloc[:,-1] (labels—likely a typo in your question, since labels are usually a single column), we can use tf.data.Dataset.map() to process each sample:
def split_features_labels(sample): # Features: Grab elements from index 1 to the second-last (matches iloc[1:-1]) features = sample[1:-1] # Label: Grab the last element of the tuple (standard for single-column labels) label = sample[-1] return features, label # Apply the split to a client's dataset client_dataset = source.create_tf_dataset_for_client('client_1').map(split_features_labels) # Verify the output for feat, lbl in client_dataset.take(1): print("Features:", feat) print("Label:", lbl)
If you really intended labels to be iloc[:-1] (all elements except the last, which is unusual for labels), just replace label = sample[-1] with label = sample[:-1].
2. Splitting Each Client's Dataset into Train/Test Sets
There are two flexible ways to split client data for federated training—either dynamically per client during the training loop, or as a preprocessing step. Here's how to implement both:
Option 1: Fixed Ratio Split (e.g., 80% Train / 20% Test)
This method calculates the exact split size based on the client's dataset cardinality:
def split_client_train_test(client_dataset, train_ratio=0.8): # Shuffle the dataset first (optional but recommended to avoid order bias) client_dataset = client_dataset.shuffle(buffer_size=1000) # Get total number of samples total_samples = tf.data.experimental.cardinality(client_dataset).numpy() train_size = int(total_samples * train_ratio) # Split into train and test sets train_dataset = client_dataset.take(train_size).batch(32) test_dataset = client_dataset.skip(train_size).batch(32) return train_dataset, test_dataset # Example usage for client_1 client_data = source.create_tf_dataset_for_client('client_1').map(split_features_labels) train_ds, test_ds = split_client_train_test(client_data)
Option 2: Handle Large/Unknown-Size Datasets
If your dataset is too large to calculate cardinality quickly, use a modulo-based filter to split samples (this approximates a fixed ratio without knowing total size):
def split_client_train_test_unknown_size(client_dataset, test_every_n=5): # Shuffle and cache for efficiency client_dataset = client_dataset.shuffle(buffer_size=1000).cache() # Add index to each sample, then filter indexed_dataset = client_dataset.enumerate() # Train set: all samples except every nth one train_dataset = indexed_dataset.filter(lambda idx, x: idx % test_every_n != 0).map(lambda idx, x: x).batch(32) # Test set: every nth sample (approx 1/test_every_n ratio) test_dataset = indexed_dataset.filter(lambda idx, x: idx % test_every_n == 0).map(lambda idx, x: x).batch(32) return train_dataset, test_dataset
Integrate with Federated Training Loop
To use this in your federated workflow, just split the data when sampling clients:
import random def federated_training_loop(source, num_rounds=10): for round_num in range(num_rounds): # Sample a subset of clients sampled_clients = random.sample(source.client_ids, k=5) for client_id in sampled_clients: # Load and preprocess client data client_data = source.create_tf_dataset_for_client(client_id).map(split_features_labels) # Split into train/test train_ds, test_ds = split_client_train_test(client_data) # Run local training on train_ds, evaluate on test_ds # ... (insert your model training/evaluation logic here)
内容的提问来源于stack exchange,提问作者Eden

