import copy import numpy as np import sklearn import torch from torch import nn from torch.utils.data import DataLoader, TensorDataset from sklearn.model_selection import GroupShuffleSplit from sklearn.preprocessing import StandardScaler
# 24 synthetic people; each contributes 3 records with 6 features. groups = np.repeat(np.arange(24), 3) y = (groups % 2).astype(np.int64) X = rng.normal(size=(len(groups), 6)).astype(np.float32) X[:, 0] += y * 0.8# An artificial signal, not a biological relationship.
splits = {"train": train, "valid": valid, "test": test} group_sets = {name: set(groups[index]) for name, index in splits.items()} assertnot (group_sets["train"] & group_sets["valid"]) assertnot (group_sets["train"] & group_sets["test"]) assertnot (group_sets["valid"] & group_sets["test"]) for name, index in splits.items(): labels = np.bincount(y[index], minlength=2).tolist() print(name, "groups=", len(group_sets[name]), "rows=", len(index), "labels=", labels) ifmin(labels) == 0: raise ValueError("A split has only one class; revise the evaluation design.") print("PASS: no person occurs in more than one split")
# Only training records estimate the scaler's parameters. scaler = StandardScaler().fit(X[train]) scaled = {name: scaler.transform(X[index]).astype(np.float32) for name, index in splits.items()} assert np.allclose(scaled["train"].mean(axis=0), 0, atol=1e-5)