含缺失值的二进制权重线性优化(最大化调整R²)求解方法
带缺失值的0-1权重列筛选优化实现方案
这个问题本质是适配前置缺失值的0-1整数特征选择问题,目标是筛选原始数据列组合,让构造出的滞后回归模型调整R²最大,完全没必要用Excel规划求解,按下面的思路实现,效率能提升几个数量级。
核心问题简化
首先先把冗余计算砍掉:
- 你的缺失值都集中在每列前若干行,不需要每次计算都全矩阵判断NaN,提前预计算每列的第一个非缺失值行号、对应非缺失值片段即可,单轮目标计算速度能提10倍以上。
- 调整R²和普通R²在这个场景下完全单调等价:回归的样本量固定为28(y从第3行开始共28个观测),自变量个数固定为3(xt当期、滞后1期、滞后2期加截距),最大化调整R²等价于最小化回归残差平方和SSE,不需要每次调用
fitlm算全套统计量,直接用矩阵左除做最小二乘即可,单轮计算速度比fitlm快几十倍。
调整R²公式验证:
$$ R^2_{adj} = 1 - \frac{(1-R^2)(n-1)}{n-p-1} $$
n=28、p=3固定时,R²越大调整R²必然越大,完全不需要额外计算调整项。
基础预计算代码
rng('default') % 复现测试数据 data = randi([-1000 1000],30,500); yt = randi([-1000 1000],30,1); miss_row = randi([1 15],1,500); miss_col_flag = rand(1,500) < .5; for i = 1:500 if miss_col_flag(i) == 1 data(1:miss_row(i),i) = nan; end end % 预计算每列有效信息 start_row = zeros(1,500); col_valid_vals = cell(1,500); for i = 1:500 first_valid = find(~isnan(data(:,i)),1,'first'); % 标记有效起始行晚于28的无效列,这些列永远进不了回归样本 if first_valid <=28 start_row(i) = first_valid; col_valid_vals{i} = data(first_valid:end,i); else start_row(i) = 31; end end y = yt(3:end);
快速目标函数
写一个输入二进制权重、输出SSE的函数,全程不用任何高级统计函数:
function sse = calc_obj(wgts, start_row, col_valid_vals, yt) xt = zeros(30,1); selected = find(wgts == 1); for i = selected sr = start_row(i); if sr > 30 continue end xt(sr:end) = xt(sr:end) + col_valid_vals{i}; end % 构造回归矩阵,带截距项 X = [xt(3:end), xt(2:end-1), xt(1:end-2), ones(28,1)]; % 最小二乘求解,比fitlm快两个数量级 coef = X\yt(3:end); res = yt(3:end) - X*coef; sse = sum(res.^2); end
求解方案选择
根据你对解的精度要求选对应方案,都比Excel求解器快得多:
- 快速求近优解(推荐,秒级出结果):用序列前向选择+局部交换优化
- 初始权重全为0,每次迭代遍历所有未选入的列,选能让SSE下降最多的列加入,直到达到你设定的选入列数约束(比如
sum(wgts)=k)或者没有列能让SSE下降为止。 - 做局部迭代优化:每次尝试将一个已选入列和一个未选入列交换,如果交换后SSE更低就保留交换,直到不存在能降低SSE的交换对为止。
这个方法在特征选择场景下的解质量非常接近全局最优,500列的规模跑一次只需要几秒。
- 求高质量近优解(分钟级):如果装了MATLAB全局优化工具箱,直接把目标函数、0-1变量边界、可选的列数等式约束传给
ga遗传算法求解器,种群规模设200,迭代80-100代即可,解的质量比序列选择更高。 - 求精确全局最优解:用定制分支定界法,针对0-1变量做剪枝——因为SSE随选入列的变化有明确的下界,每一步选入列后都可以剪掉不可能优于当前最优解的分支,你这个样本量只有28的场景,十几分钟就能跑出全局精确解,远高于Excel求解器200变量的上限。
额外优化技巧
- 可以提前预计算每一列单独生成的xt向量,计算列组合的xt时直接把对应列的xt向量相加即可,能把单轮目标计算压到微秒级。
- 如果加了选入列数约束,可以在序列选择阶段直接选到对应列数就停止,不用遍历所有列。
- 提前过滤掉和y相关性极低的列,减少决策变量规模,进一步提速。
内容的提问来源于stack exchange,提问作者Barbab
相关产品推荐
相关产品推荐

