| 233 | let (a, b) = ols_line(x, y); |
| 234 | let effect = x.iter().zip(y.iter()).map(|(vx, vy)| (a + b * *vx - *vy).abs()).sum::<f64>() |
| 235 | / x.len() as f64; |
| 236 | store.insert(j, effect); |
| 237 | } |
| 238 | store |
| 239 | } |
| 240 | |
| 241 | fn get_pairwise_effect<F>( |
| 242 | pairs: &[(usize, usize)], |
| 243 | predictor: &F, |
| 244 | x: &[Vec<f64>], |
| 245 | num_values: usize, |
| 246 | feature_values: &[Vec<f64>], |
| 247 | partial_dep: &[Vec<f64>], |
| 248 | ) -> BTreeMap<String, f64> |
| 249 | where |
| 250 | F: Fn(&[Vec<f64>]) -> Vec<f64>, |
| 251 | { |
| 252 | let mut store = BTreeMap::new(); |
| 253 | for &(k, l) in pairs { |
| 254 | let yk_centered = center(&partial_dep[k]); |
| 255 | let yl_centered = center(&partial_dep[l]); |
| 256 | let mut vals = Vec::with_capacity(num_values * num_values); |
| 257 | |
| 258 | for (ik, &xk) in feature_values[k].iter().enumerate() { |
| 259 | for (il, &xl) in feature_values[l].iter().enumerate() { |
| 260 | let mut x_mod = x.to_vec(); |
| 261 | for row in &mut x_mod { |
| 262 | row[k] = xk; |
| 263 | row[l] = xl; |
| 264 | } |
| 265 | let ykl = predictor(&x_mod).iter().sum::<f64>() / x.len() as f64; |
| 266 | vals.push((ykl, yk_centered[ik], yl_centered[il])); |
| 267 | } |
| 268 | } |
| 269 | |
| 270 | let mean_ykl = vals.iter().map(|(v, _, _)| *v).sum::<f64>() / vals.len() as f64; |
| 271 | let mut acc = 0.0; |
| 272 | for (ykl, yk, yl) in vals { |
| 273 | acc += (ykl - mean_ykl - yk - yl).abs(); |
| 274 | } |
| 275 | store.insert(format!("({k}, {l})"), acc / (num_values * num_values) as f64); |