forust 0.2.1__tar.gz → 0.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of forust might be problematic. Click here for more details.
- {forust-0.2.1 → forust-0.2.2}/Cargo.toml +2 -2
- {forust-0.2.1 → forust-0.2.2}/PKG-INFO +2 -2
- {forust-0.2.1 → forust-0.2.2}/README.md +1 -1
- {forust-0.2.1 → forust-0.2.2}/local_dependencies/forust-ml/Cargo.toml +1 -1
- {forust-0.2.1 → forust-0.2.2}/local_dependencies/forust-ml/README.md +1 -1
- forust-0.2.2/local_dependencies/forust-ml/dist/forust-0.2.2-cp311-cp311-macosx_10_7_x86_64.whl +0 -0
- forust-0.2.2/local_dependencies/forust-ml/dist/forust-0.2.2.tar.gz +0 -0
- {forust-0.2.1 → forust-0.2.2}/local_dependencies/forust-ml/rs-example.md +1 -1
- {forust-0.2.1 → forust-0.2.2}/local_dependencies/forust-ml/src/data.rs +27 -1
- {forust-0.2.1 → forust-0.2.2}/local_dependencies/forust-ml/src/gradientbooster.rs +59 -3
- {forust-0.2.1 → forust-0.2.2}/local_dependencies/forust-ml/src/tree.rs +18 -11
- {forust-0.2.1 → forust-0.2.2}/tests/test_booster.py +2 -2
- forust-0.2.1/local_dependencies/forust-ml/dist/forust-0.2.1-cp311-cp311-macosx_10_7_x86_64.whl +0 -0
- forust-0.2.1/local_dependencies/forust-ml/dist/forust-0.2.1.tar.gz +0 -0
- {forust-0.2.1 → forust-0.2.2}/.gitignore +0 -0
- {forust-0.2.1 → forust-0.2.2}/LICENSE +0 -0
- {forust-0.2.1 → forust-0.2.2}/forust/__init__.py +0 -0
- {forust-0.2.1 → forust-0.2.2}/local_dependencies/forust-ml/.github/workflows/CI.yml +0 -0
- {forust-0.2.1 → forust-0.2.2}/local_dependencies/forust-ml/.gitignore +0 -0
- {forust-0.2.1 → forust-0.2.2}/local_dependencies/forust-ml/.pre-commit-config.yaml +0 -0
- {forust-0.2.1 → forust-0.2.2}/local_dependencies/forust-ml/LICENSE +0 -0
- {forust-0.2.1 → forust-0.2.2}/local_dependencies/forust-ml/benches/forust_benchmarks.rs +0 -0
- {forust-0.2.1 → forust-0.2.2}/local_dependencies/forust-ml/resources/pdp_plot_age.png +0 -0
- {forust-0.2.1 → forust-0.2.2}/local_dependencies/forust-ml/resources/pdp_plot_age_mono.png +0 -0
- {forust-0.2.1 → forust-0.2.2}/local_dependencies/forust-ml/resources/titanic.csv +0 -0
- {forust-0.2.1 → forust-0.2.2}/local_dependencies/forust-ml/resources/tree-image-crop.png +0 -0
- {forust-0.2.1 → forust-0.2.2}/local_dependencies/forust-ml/scripts/make_resources.py +0 -0
- {forust-0.2.1 → forust-0.2.2}/local_dependencies/forust-ml/scripts/run-python-tests.ps1 +0 -0
- {forust-0.2.1 → forust-0.2.2}/local_dependencies/forust-ml/scripts/run-python-tests.sh +0 -0
- {forust-0.2.1 → forust-0.2.2}/local_dependencies/forust-ml/src/binning.rs +0 -0
- {forust-0.2.1 → forust-0.2.2}/local_dependencies/forust-ml/src/constraints.rs +0 -0
- {forust-0.2.1 → forust-0.2.2}/local_dependencies/forust-ml/src/errors.rs +0 -0
- {forust-0.2.1 → forust-0.2.2}/local_dependencies/forust-ml/src/histogram.rs +0 -0
- {forust-0.2.1 → forust-0.2.2}/local_dependencies/forust-ml/src/lib.rs +0 -0
- {forust-0.2.1 → forust-0.2.2}/local_dependencies/forust-ml/src/node.rs +0 -0
- {forust-0.2.1 → forust-0.2.2}/local_dependencies/forust-ml/src/objective.rs +0 -0
- {forust-0.2.1 → forust-0.2.2}/local_dependencies/forust-ml/src/partial_dependence.rs +0 -0
- {forust-0.2.1 → forust-0.2.2}/local_dependencies/forust-ml/src/splitter.rs +0 -0
- {forust-0.2.1 → forust-0.2.2}/local_dependencies/forust-ml/src/utils.rs +0 -0
- {forust-0.2.1 → forust-0.2.2}/pyproject.toml +0 -0
- {forust-0.2.1 → forust-0.2.2}/scratch.py +0 -0
- {forust-0.2.1 → forust-0.2.2}/src/lib.rs +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "py-forust"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.2"
|
|
4
4
|
edition = "2021"
|
|
5
5
|
|
|
6
6
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
@@ -10,6 +10,6 @@ crate-type = ["cdylib"]
|
|
|
10
10
|
|
|
11
11
|
[dependencies]
|
|
12
12
|
pyo3 = { version = "0.17", features = ["extension-module"] }
|
|
13
|
-
forust-ml = { version="0.2.
|
|
13
|
+
forust-ml = { version="0.2.2", path= "local_dependencies/forust-ml" }
|
|
14
14
|
numpy = "0.17.2"
|
|
15
15
|
ndarray = "0.15.1"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: forust
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Classifier: Programming Language :: Rust
|
|
5
5
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
6
6
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
@@ -47,7 +47,7 @@ pip install forust
|
|
|
47
47
|
|
|
48
48
|
To use in a rust project add the following to your Cargo.toml file.
|
|
49
49
|
```toml
|
|
50
|
-
forust-ml = "0.2.
|
|
50
|
+
forust-ml = "0.2.2"
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
## Usage
|
forust-0.2.2/local_dependencies/forust-ml/dist/forust-0.2.2-cp311-cp311-macosx_10_7_x86_64.whl
ADDED
|
Binary file
|
|
Binary file
|
|
@@ -119,6 +119,14 @@ impl<'a, T> Matrix<'a, T> {
|
|
|
119
119
|
idx
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
+
/// Get access to a row of the data, as an iterator.
|
|
123
|
+
pub fn get_row_iter(
|
|
124
|
+
&self,
|
|
125
|
+
row: usize,
|
|
126
|
+
) -> std::iter::StepBy<std::iter::Skip<std::slice::Iter<T>>> {
|
|
127
|
+
self.data.iter().skip(row).step_by(self.rows)
|
|
128
|
+
}
|
|
129
|
+
|
|
122
130
|
/// Get a slice of a column in the matrix.
|
|
123
131
|
///
|
|
124
132
|
/// * `col` - The index of the column to select.
|
|
@@ -138,6 +146,16 @@ impl<'a, T> Matrix<'a, T> {
|
|
|
138
146
|
}
|
|
139
147
|
}
|
|
140
148
|
|
|
149
|
+
impl<'a, T> Matrix<'a, T>
|
|
150
|
+
where
|
|
151
|
+
T: Copy,
|
|
152
|
+
{
|
|
153
|
+
/// Get a row of the data as a vector.
|
|
154
|
+
pub fn get_row(&self, row: usize) -> Vec<T> {
|
|
155
|
+
self.get_row_iter(row).copied().collect()
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
141
159
|
/// A lightweight row major matrix, this is primarily
|
|
142
160
|
/// for returning data to the user, it is especially
|
|
143
161
|
/// suited for appending rows to, such as when building
|
|
@@ -227,7 +245,6 @@ impl<T> JaggedMatrix<T> {
|
|
|
227
245
|
n_records: 0,
|
|
228
246
|
}
|
|
229
247
|
}
|
|
230
|
-
|
|
231
248
|
/// Get the column of a jagged array.
|
|
232
249
|
pub fn get_col(&self, col: usize) -> &[T] {
|
|
233
250
|
assert!(col < self.ends.len());
|
|
@@ -285,6 +302,15 @@ mod tests {
|
|
|
285
302
|
assert_eq!(m.get_col(1), &vec![5, 6, 7]);
|
|
286
303
|
}
|
|
287
304
|
|
|
305
|
+
#[test]
|
|
306
|
+
fn test_matrix_row() {
|
|
307
|
+
let v = vec![1, 2, 3, 5, 6, 7];
|
|
308
|
+
let m = Matrix::new(&v, 3, 2);
|
|
309
|
+
assert_eq!(m.get_row(2), vec![3, 7]);
|
|
310
|
+
assert_eq!(m.get_row(0), vec![1, 5]);
|
|
311
|
+
assert_eq!(m.get_row(1), vec![2, 6]);
|
|
312
|
+
}
|
|
313
|
+
|
|
288
314
|
#[test]
|
|
289
315
|
fn test_jaggedmatrix_get_col() {
|
|
290
316
|
let vecs = vec![vec![0], vec![5, 4, 3, 2], vec![4, 5]];
|
|
@@ -216,6 +216,30 @@ impl GradientBooster {
|
|
|
216
216
|
init_preds
|
|
217
217
|
}
|
|
218
218
|
|
|
219
|
+
// pub fn predict(&self, data: &Matrix<f64>, parallel: bool) -> Vec<f64> {
|
|
220
|
+
// // After we disconvered it's faster materializing the row once, and then
|
|
221
|
+
// // Passing that to each tree, let's see if we can do the same with the booster
|
|
222
|
+
// // prediction...
|
|
223
|
+
// // Clean this up..
|
|
224
|
+
// let mut init_preds = vec![self.base_score; data.rows];
|
|
225
|
+
// if parallel {
|
|
226
|
+
// init_preds.par_iter_mut().enumerate().for_each(|(i, p)| {
|
|
227
|
+
// let pred_row = data.get_row(i);
|
|
228
|
+
// for t in &self.trees {
|
|
229
|
+
// *p += t.predict_row_from_row_slice(&pred_row);
|
|
230
|
+
// }
|
|
231
|
+
// });
|
|
232
|
+
// } else {
|
|
233
|
+
// init_preds.iter_mut().enumerate().for_each(|(i, p)| {
|
|
234
|
+
// let pred_row = data.get_row(i);
|
|
235
|
+
// for t in &self.trees {
|
|
236
|
+
// *p += t.predict_row_from_row_slice(&pred_row);
|
|
237
|
+
// }
|
|
238
|
+
// });
|
|
239
|
+
// }
|
|
240
|
+
// init_preds
|
|
241
|
+
// }
|
|
242
|
+
|
|
219
243
|
/// Generate predictions on data using the gradient booster.
|
|
220
244
|
///
|
|
221
245
|
/// * `data` - Either a pandas DataFrame, or a 2 dimensional numpy array.
|
|
@@ -232,9 +256,41 @@ impl GradientBooster {
|
|
|
232
256
|
.collect()
|
|
233
257
|
};
|
|
234
258
|
let mut contribs = vec![0.; (data.cols + 1) * data.rows];
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
259
|
+
|
|
260
|
+
// Add the bias term to every bias value...
|
|
261
|
+
let bias_idx = data.cols + 1;
|
|
262
|
+
contribs
|
|
263
|
+
.iter_mut()
|
|
264
|
+
.skip(bias_idx - 1)
|
|
265
|
+
.step_by(bias_idx)
|
|
266
|
+
.for_each(|v| *v += self.base_score);
|
|
267
|
+
|
|
268
|
+
// Clean this up..
|
|
269
|
+
// materializing a row, and then passing that to all of the
|
|
270
|
+
// trees seems to be the fastest approach (5X faster), we should test
|
|
271
|
+
// something like this for normal predictions.
|
|
272
|
+
if parallel {
|
|
273
|
+
data.index
|
|
274
|
+
.par_iter()
|
|
275
|
+
.zip(contribs.par_chunks_mut(data.cols + 1))
|
|
276
|
+
.for_each(|(row, c)| {
|
|
277
|
+
let r_ = data.get_row(*row);
|
|
278
|
+
self.trees.iter().zip(weights.iter()).for_each(|(t, w)| {
|
|
279
|
+
t.predict_contributions_row(&r_, c, w);
|
|
280
|
+
});
|
|
281
|
+
});
|
|
282
|
+
} else {
|
|
283
|
+
data.index
|
|
284
|
+
.iter()
|
|
285
|
+
.zip(contribs.chunks_mut(data.cols + 1))
|
|
286
|
+
.for_each(|(row, c)| {
|
|
287
|
+
let r_ = data.get_row(*row);
|
|
288
|
+
self.trees.iter().zip(weights.iter()).for_each(|(t, w)| {
|
|
289
|
+
t.predict_contributions_row(&r_, c, w);
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
|
|
238
294
|
contribs
|
|
239
295
|
}
|
|
240
296
|
|
|
@@ -118,15 +118,9 @@ impl Tree {
|
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
|
-
pub fn predict_contributions_row(
|
|
122
|
-
&self,
|
|
123
|
-
data: &Matrix<f64>,
|
|
124
|
-
row: usize,
|
|
125
|
-
contribs: &mut [f64],
|
|
126
|
-
weights: &[f64],
|
|
127
|
-
) {
|
|
121
|
+
pub fn predict_contributions_row(&self, row: &[f64], contribs: &mut [f64], weights: &[f64]) {
|
|
128
122
|
// Add the bias term first...
|
|
129
|
-
contribs[
|
|
123
|
+
contribs[contribs.len() - 1] += weights[0];
|
|
130
124
|
let mut node_idx = 0;
|
|
131
125
|
loop {
|
|
132
126
|
let node = &self.nodes[node_idx];
|
|
@@ -134,7 +128,7 @@ impl Tree {
|
|
|
134
128
|
break;
|
|
135
129
|
}
|
|
136
130
|
// Get change of weight given child's weight.
|
|
137
|
-
let child_idx = node.get_child_idx(
|
|
131
|
+
let child_idx = node.get_child_idx(&row[node.split_feature]);
|
|
138
132
|
let node_weight = weights[node_idx];
|
|
139
133
|
let child_weight = weights[child_idx];
|
|
140
134
|
let delta = child_weight - node_weight;
|
|
@@ -154,9 +148,10 @@ impl Tree {
|
|
|
154
148
|
.iter()
|
|
155
149
|
.zip(contribs.chunks_mut(data.cols + 1))
|
|
156
150
|
.for_each(|(row, contribs)| {
|
|
157
|
-
self.predict_contributions_row(data
|
|
151
|
+
self.predict_contributions_row(&data.get_row(*row), contribs, weights)
|
|
158
152
|
})
|
|
159
153
|
}
|
|
154
|
+
|
|
160
155
|
fn predict_contributions_parallel(
|
|
161
156
|
&self,
|
|
162
157
|
data: &Matrix<f64>,
|
|
@@ -168,7 +163,7 @@ impl Tree {
|
|
|
168
163
|
.par_iter()
|
|
169
164
|
.zip(contribs.par_chunks_mut(data.cols + 1))
|
|
170
165
|
.for_each(|(row, contribs)| {
|
|
171
|
-
self.predict_contributions_row(data
|
|
166
|
+
self.predict_contributions_row(&data.get_row(*row), contribs, weights)
|
|
172
167
|
})
|
|
173
168
|
}
|
|
174
169
|
|
|
@@ -198,6 +193,18 @@ impl Tree {
|
|
|
198
193
|
}
|
|
199
194
|
}
|
|
200
195
|
|
|
196
|
+
pub fn predict_row_from_row_slice(&self, row: &[f64]) -> f64 {
|
|
197
|
+
let mut node_idx = 0;
|
|
198
|
+
loop {
|
|
199
|
+
let node = &self.nodes[node_idx];
|
|
200
|
+
if node.is_leaf {
|
|
201
|
+
return node.weight_value as f64;
|
|
202
|
+
} else {
|
|
203
|
+
node_idx = node.get_child_idx(&row[node.split_feature]);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
201
208
|
fn predict_single_threaded(&self, data: &Matrix<f64>) -> Vec<f64> {
|
|
202
209
|
data.index
|
|
203
210
|
.iter()
|
|
@@ -278,7 +278,7 @@ def test_booster_to_xgboosts_with_contributions(X_y):
|
|
|
278
278
|
objective_type="LogLoss",
|
|
279
279
|
nbins=500,
|
|
280
280
|
parallel=False,
|
|
281
|
-
base_score=0.
|
|
281
|
+
base_score=0.5,
|
|
282
282
|
)
|
|
283
283
|
fmod.fit(X, y=y)
|
|
284
284
|
fmod_preds = fmod.predict(X)
|
|
@@ -299,7 +299,7 @@ def test_booster_to_xgboosts_with_contributions(X_y):
|
|
|
299
299
|
eval_metric="auc",
|
|
300
300
|
tree_method="hist",
|
|
301
301
|
max_bin=10000,
|
|
302
|
-
base_score=0.
|
|
302
|
+
base_score=0.5,
|
|
303
303
|
)
|
|
304
304
|
xmod.fit(X, y)
|
|
305
305
|
xmod_preds = xmod.predict(X, output_margin=True)
|
forust-0.2.1/local_dependencies/forust-ml/dist/forust-0.2.1-cp311-cp311-macosx_10_7_x86_64.whl
DELETED
|
Binary file
|
|
Binary file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|