Python中如何实现拉丁超立方抽样(LHS)的续采样新增样本
LHS续采样(保留已有样本新增采样点)实现方案
直接重跑LHS采样代码会重新划分全量样本的分层区间,既无法保留已生成的旧样本,也不能保证新旧样本合并后满足LHS的分层均匀性要求,以下是可落地的实现方案:
方案1:约束分层续采样(推荐)
核心逻辑:最终总样本量为原有20个+新增10个共30个,先将每个参数维度等分为30个互不重叠的分层区间,标记原有20个样本已经占用的分层,剩余10个未被占用的分层每个区间内随机生成1个样本点,最终合并的30个样本完全满足LHS“每个维度每个分层区间有且仅有一个样本”的核心要求,且100%保留原有20个样本。
对应实现代码:
import numpy as np from smt.sampling_methods import LHS # 保持和原有采样完全一致的参数范围 limits = np.array([[870, 1125], [1200, 9000]]) n_exist = 20 n_new = 10 n_total = n_exist + n_new # -------------------------- # 这里替换成你已经生成好的原有20个样本即可 # 示例为复现原有采样过程,如果你已经保存了Xtrain直接加载即可 sampling_old = LHS(xlimits=limits) Xtrain = sampling_old(n_exist) # -------------------------- # 1. 将原有样本归一化到[0,1]区间方便分层计算 X_norm = (Xtrain - limits[:, 0]) / (limits[:, 1] - limits[:, 0]) n_dim = X_norm.shape[1] # 2. 标记原有样本已经占用的分层区间 used_bins = np.zeros((n_dim, n_total), dtype=bool) for d in range(n_dim): bin_idx = np.floor(X_norm[:, d] * n_total).astype(int) bin_idx[bin_idx == n_total] = n_total - 1 # 处理刚好取到参数上限的边界情况,避免索引越界 used_bins[d, bin_idx] = True # 3. 为新样本分配未被占用的分层区间,随机打乱保证采样随机性 new_bin_idx = [] for d in range(n_dim): free_bins = np.where(~used_bins[d])[0] np.random.shuffle(free_bins) new_bin_idx.append(free_bins[:n_new]) new_bin_idx = np.array(new_bin_idx).T # 4. 在分配到的分层区间内随机采样,映射回原始参数范围 X_new = np.zeros((n_new, n_dim)) for i in range(n_new): for d in range(n_dim): bin_low = new_bin_idx[i, d] / n_total bin_high = (new_bin_idx[i, d] + 1) / n_total rand_val = np.random.uniform(bin_low, bin_high) X_new[i, d] = rand_val * (limits[d, 1] - limits[d, 0]) + limits[d, 0] # 合并原有样本和新样本,得到最终满足LHS要求的30个样本 Xtrain_augmented = np.vstack([Xtrain, X_new])
可选优化:如果你需要更高的样本空间均匀性,可以在步骤4采样时,每个分层区间生成10~20个候选点,选择和已有所有样本欧氏距离最大的候选点作为最终新样本,即可达到类似优化LHS(如maximin准则)的效果。
方案2:固定种子一次性生成全量样本(仅适合未开展后续实验的场景)
如果你还没有基于原有20个样本开展后续仿真/计算,可以直接固定随机种子一次性生成30个样本,保证结果可复现。注意这个方法无法保留你之前已经生成的20个样本。
代码如下:
import numpy as np from smt.sampling_methods import LHS limits = np.array([[870, 1125], [1200, 9000]]) # 传入固定的random_state即可保证每次运行生成的样本完全一致 sampling = LHS(xlimits=limits, random_state=42) train_size = 30 Xtrain = sampling(train_size)
注意:该方案仅适合实验初期可重新生成全量样本的场景,如果你已经基于原有20个样本跑完了部分实验,必须用方案1实现续采样。
采样结果校验
可以用以下代码快速校验合并后的样本是否满足LHS要求:
X_aug_norm = (Xtrain_augmented - limits[:,0]) / (limits[:,1] - limits[:,0]) for d in range(n_dim): bin_counts = np.bincount( np.floor(X_aug_norm[:, d] * n_total).astype(int), minlength=n_total ) # 如果每个分层的样本数全为1,说明符合LHS要求 print(f"维度{d}各分层样本数唯一值:", np.unique(bin_counts))
内容的提问来源于stack exchange,提问作者mikepl9
相关产品推荐
相关产品推荐

