Why linfa::clustering import is not working

I am using following demo code from here :

use linfa::clustering::{generate_blobs, KMeans, KMeansHyperParams};
use ndarray::array;
use ndarray_rand::rand::SeedableRng;
use rand_isaac::Isaac64Rng;

fn main() {
    // Our random number generator, seeded for reproducibility
    let mut rng = Isaac64Rng::seed_from_u64(42);

    // For each our expected centroids, generate 1000 data points around it (a "blob")
    let expected_centroids = array![[10., 10.], [1., 12.], [20., 30.], [-20., 30.]];
    let dataset = generate_blobs(10000, &expected_centroids, &mut rng);

    // Configure our training algorithm
    let n_clusters = 4;
    let hyperparams = KMeansHyperParams::new(n_clusters)
        .max_n_iterations(200)
        .tolerance(1e-5)
        .build();

    // Infer an optimal set of centroids based on the training data distribution
    let model = KMeans::fit(hyperparams, &dataset, &mut rng);

    // Assign each point to a cluster using the set of centroids found using `fit`
    let labels = model.predict(&dataset);
}

However, I am getting following error:

$ cargo run
error[E0432]: unresolved import `linfa::clustering`
 --> src/main.rs:8:12
  |
8 | use linfa::clustering::{generate_blobs, KMeans, KMeansHyperParams};
  |            ^^^^^^^^^^ could not find `clustering` in `linfa`

For more information about this error, try `rustc --explain E0432`.

The Cargo.toml file is as follows:

$ cat Cargo.toml
[package]
name = "rnml_linfa"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
linfa = "0.6.1"
linfa-clustering = "0.6.1"
ndarray = "0.15.6"
ndarray-rand = "0.14.0"
rand_isaac = "0.3.0"

Where is the problem and how can it be solved? Thanks.

The documentation was not absolutely clear, but from looking at the source code, there is never a linfa::clustering module. You need to use linfa_clustering:: instead — it's a separate crate.

1 Like

I added: use linfa_clustering::* .
Now there are more errors:

error[E0425]: cannot find function `generate_blobs` in this scope
  --> src/main.rs:20:19
   |
20 |     let dataset = generate_blobs(10000, &expected_centroids, &mut rng);
   |                   ^^^^^^^^^^^^^^ not found in this scope

error[E0433]: failed to resolve: use of undeclared type `KMeansHyperParams`
  --> src/main.rs:24:23
   |
24 |     let hyperparams = KMeansHyperParams::new(n_clusters)
   |                       ^^^^^^^^^^^^^^^^^
   |                       |
   |                       use of undeclared type `KMeansHyperParams`
   |                       help: a struct with a similar name exists: `KMeansParams`

error[E0599]: no function or associated item named `fit` found for struct `KMeans` in the current scope
  --> src/main.rs:30:25
   |
30 |     let model = KMeans::fit(hyperparams, &dataset, &mut rng);
   |                         ^^^ function or associated item not found in `KMeans<_, _>`

Some errors have detailed explanations: E0425, E0433, E0599.
For more information about an error, try `rustc --explain E0425`.
error: could not compile `rnml_linfa` due to 3 previous errors

Those names existed in an old version of linfa-clustering, 0.4.0 but not in the current one, 0.6.1. When you have missing items or other compilation errors suggesting an API mismatch, always check if you are using example code that would apply to an older version.

You can choose to use the old version, or update the code to use whatever the new equivalents are.

I cannot run demo code in newer version of linfa_clustering also:

error[E0432]: unresolved import `linfa_datasets::generate`
 --> src/main.rs:7:5
  |
7 | use linfa_datasets::generate;
  |     ^^^^^^^^^^^^^^^^^^^^^^^^ no `generate` in the root

It's very sad.

You need to add a dependency on linfa-datasets to your Cargo.toml.

In general, any time you write somenamespace::somename, somenamespace must be either a name you defined or a dependency you added to Cargo.toml. It will never be the case that adding a single dependency like linfa adds many names to the namespace you can use from your Rust code. You will have to add a dependency on each crate that you want to use.

1 Like

Its already added in Cargo.toml:

[package]
name = "rnml_linfa"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
approx = "0.5.1"
linfa = "0.6.1"
linfa-clustering = "0.6.1"
linfa-datasets = "0.6.1"
ndarray = "0.15.6"
ndarray-rand = "0.14.0"
rand_isaac = "0.3.0"
rand_xoshiro = "0.6.0"

Also, the compiler is not complaining of absence of dependency. Following is the error if I remove linfa-datasets (using command: cargo remove linfa-datasets ):

error[E0432]: unresolved import `linfa_datasets`
 --> src/main.rs:7:5
  |
7 | use linfa_datasets::generate;
  |     ^^^^^^^^^^^^^^ use of undeclared crate or module `linfa_datasets`

You don't have the generate feature enabled.

Thanks for this important point! But how do I enable it?

Please read the relevant documentation for basic stuff like this. All of the required knowledge is in the Cargo book.

Yes, the code is working now.

So, I need to check "Feature Flags" for all dependencies and they may have to be added explicitly to the file Cargo.toml?

Yes.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.