diff --git a/DBSCAN.html b/DBSCAN.html deleted file mode 100644 index fd1acb4..0000000 --- a/DBSCAN.html +++ /dev/null @@ -1,15525 +0,0 @@ -None - - - - -DBSCAN - - - - - - - - - - - - - -
-
- -
-
-
In [ ]:
-
-
-
:dep ndarray = "0.15.6"
-
- -
-
-
- -
-
-
-
In [2]:
-
-
-
:dep linfa = { version = "0.6.1" }
-// clustering is a separate crate
-:dep linfa-clustering = { version = "0.6.1" }
-
- -
-
-
- -
-
-
-
In [4]:
-
-
-
// apt install libfontconfig-dev on Ubuntu 22.04 LTS
-:dep plotters = { version = "^0.3.4", default_features = false, features = ["evcxr", "all_series"] }
-extern crate plotters;
-// Import all the plotters prelude functions
-use plotters::prelude::*;
-
- -
-
-
- -
-
-
-
In [5]:
-
-
-
:dep rand = "0.8.5"
-
- -
-
-
- -
-
-
-
In [6]:
-
-
-
// Import the linfa prelude and KMeans algorithm
-use linfa::prelude::*;
-use linfa_clustering::Dbscan;
-// We'll build our dataset on our own using ndarray and rand
-use ndarray::prelude::*;
-// Import the plotters crate to create the scatter plot
-use plotters::prelude::*;
-
- -
-
-
- -
-
-
-
In [7]:
-
-
-
use rand::prelude::*;
-use std::f32;
-
- -
-
-
- -
-
-
-
In [8]:
-
-
-
// Creates random points contained in an approximately square area
-pub fn create_square(center_point: [f32; 2], edge_length: f32, num_points: usize) -> Array2<f32> {
-    // We
-    let mut data: Array2<f32> = Array2::zeros((num_points, 2));
-    let mut rng = rand::thread_rng();
-    for i in 0..num_points {
-        let x = rng.gen_range(-edge_length * 0.5..edge_length * 0.5); // generates a float between 0 and 1
-        let y = rng.gen_range(-edge_length * 0.5..edge_length * 0.5);
-        data[[i, 0]] = center_point[0] + x;
-        data[[i, 1]] = center_point[1] + y;
-    }
-
-    data
-}
-
- -
-
-
- -
-
-
-
In [9]:
-
-
-
// Creates a circle of random points
-pub fn create_circle(center_point: [f32; 2], radius: f32, num_points: usize) -> Array2<f32> {
-    let mut data: Array2<f32> = Array2::zeros((num_points, 2));
-    let mut rng = rand::thread_rng();
-    for i in 0..num_points {
-        let theta = rng.gen_range(0.0..2.0 * f32::consts::PI);
-        let r = rng.gen_range(0.0..radius);
-        let x = r * f32::cos(theta);
-        let y = r * f32::sin(theta);
-
-        data[[i, 0]] = center_point[0] + x;
-        data[[i, 1]] = center_point[1] + y;
-    }
-
-    data
-}
-
- -
-
-
- -
-
-
-
In [10]:
-
-
-
// Creates a line y = m*x + b with some noise
-pub fn create_line(m: f64, b: f64, num_points: usize, min_max: [f64; 2]) -> Array2<f64> {
-    let mut data: Array2<f64> = Array2::zeros((num_points, 2));
-
-    let mut rng = rand::thread_rng();
-    for i in 0..num_points {
-        let var_y = rng.gen_range(-0.5..0.5f64);
-        data[[i, 0]] = rng.gen_range(min_max[0]..min_max[1]);
-        data[[i, 1]] = (m * data[[i, 0]]) + b + var_y;
-    }
-
-    data
-}
-
- -
-
-
- -
-
-
-
In [11]:
-
-
-
// Creates a quadratic y = m*x^2 + b with some noise
-pub fn create_curve(m: f64, pow: f64, b: f64, num_points: usize, min_max: [f64; 2]) -> Array2<f64> {
-    let mut data: Array2<f64> = Array2::zeros((num_points, 2));
-
-    let mut rng = rand::thread_rng();
-    for i in 0..num_points {
-        let var_y = rng.gen_range(-0.5..0.5f64);
-        data[[i, 0]] = rng.gen_range(min_max[0]..min_max[1]);
-        data[[i, 1]] = (m * data[[i, 0]].powf(pow)) + b + var_y;
-    }
-
-    data
-}
-
- -
-
-
- -
-
-
-
In [12]:
-
-
-
// Creates a hollow circle of random points with a specified inner and outer diameter
-pub fn create_hollow_circle(
-    center_point: [f32; 2],
-    radius: [f32; 2],
-    num_points: usize,
-) -> Array2<f32> {
-    assert!(radius[0] < radius[1]);
-    let mut data: Array2<f32> = Array2::zeros((num_points, 2));
-    let mut rng = rand::thread_rng();
-    for i in 0..num_points {
-        let theta = rng.gen_range(0.0..2.0 * f32::consts::PI);
-        let r = rng.gen_range(radius[0]..radius[1]);
-        let x = r * f32::cos(theta);
-        let y = r * f32::sin(theta);
-
-        data[[i, 0]] = center_point[0] + x;
-        data[[i, 1]] = center_point[1] + y;
-    }
-
-    data
-}
-
- -
-
-
- -
-
-
-
In [13]:
-
-
-
// Check the array has the correct shape for plotting (Two-dimensional, with 2 columns)
-pub fn check_array_for_plotting(arr: &Array2<f32>) -> bool {
-    if (arr.shape().len() != 2) || (arr.shape()[1] != 2) {
-        panic!(
-            "Array shape of {:?} is incorrect for 2D plotting!",
-            arr.shape()
-        );
-        // false
-    } else {
-        true
-    }
-}
-
- -
-
-
- -
-
-
-
In [14]:
-
-
-
// The goal is to be able to find each of these as distinct, and exclude some of the noise
-let circle: Array2<f32> = create_circle([5.0, 5.0], 1.0, 100); // Cluster 0
-let donut_1: Array2<f32> = create_hollow_circle([5.0, 5.0], [2.0, 3.0], 400); // Cluster 1
-let donut_2: Array2<f32> = create_hollow_circle([5.0, 5.0], [4.5, 4.75], 1000); // Cluster 2
-let noise: Array2<f32> = create_square([5.0, 5.0], 10.0, 100); // Random noise
-
-
-let data = ndarray::concatenate(
-        Axis(0),
-        &[circle.view(), donut_1.view(), donut_2.view(), noise.view()],
-    )
-    .expect("An error occurred while stacking the dataset");
-
- -
-
-
- -
-
-
-
In [19]:
-
-
-
evcxr_figure((640, 240), |root| {
-    
-    root.fill(&WHITE).unwrap();
-
-    let x_lim = 0.0..10.0f32;
-    let y_lim = 0.0..10.0f32;
-
-    let mut ctx = ChartBuilder::on(&root)
-        .set_label_area_size(LabelAreaPosition::Left, 40) // Put in some margins
-        .set_label_area_size(LabelAreaPosition::Right, 40)
-        .set_label_area_size(LabelAreaPosition::Bottom, 40)
-        .caption("DBSCAN", ("sans-serif", 25)) // Set a caption and font
-        .build_cartesian_2d(x_lim, y_lim)
-        .expect("Couldn't build our ChartBuilder");
-    
-    let circle: Array2<f32> = create_circle([5.0, 5.0], 1.0, 100); // Cluster 0
-    let donut_1: Array2<f32> = create_hollow_circle([5.0, 5.0], [2.0, 3.0], 400); // Cluster 1
-    let donut_2: Array2<f32> = create_hollow_circle([5.0, 5.0], [4.5, 4.75], 1000); // Cluster 2
-    let noise: Array2<f32> = create_square([5.0, 5.0], 10.0, 100); // Random noise
-
-    let data = ndarray::concatenate(
-        Axis(0),
-        &[circle.view(), donut_1.view(), donut_2.view(), noise.view()],
-    )
-    .expect("An error occurred while stacking the dataset");
-
-    // Compared to linfa's KMeans algorithm, the DBSCAN implementation can operate
-    // directly on an ndarray `Array2` data structure, so there's no need to convert it
-    // into the linfa-native `Dataset` first.
-    let min_points = 20;
-    let clusters = Dbscan::params(min_points)
-        .tolerance(0.6)
-        .transform(&data)
-        .unwrap();
-    // println!("{:#?}", clusters);
-
-
-    let x_lim = 0.0..10.0f32;
-    let y_lim = 0.0..10.0f32;
-    
-
-    ctx.configure_mesh().draw().unwrap();
-    let root_area = ctx.plotting_area();
-    // ANCHOR_END: configure_chart
-
-    // ANCHOR: run_check_for_plotting;
-    // check_array_for_plotting(dataset: &Array2<f32>) -> bool {}
-    check_array_for_plotting(&circle); // Panics if that's not true
-                                       // ANCHOR_END: run_check_for_plotting
-
-    // ANCHOR: plot_points
-    for i in 0..data.shape()[0] {
-        let coordinates = data.slice(s![i, 0..2]);
-
-        let point = match clusters[i] {
-            Some(0) => Circle::new(
-                (coordinates[0], coordinates[1]),
-                3,
-                ShapeStyle::from(&RED).filled(),
-            ),
-            Some(1) => Circle::new(
-                (coordinates[0], coordinates[1]),
-                3,
-                ShapeStyle::from(&GREEN).filled(),
-            ),
-            Some(2) => Circle::new(
-                (coordinates[0], coordinates[1]),
-                3,
-                ShapeStyle::from(&BLUE).filled(),
-            ),
-            // Making sure our pattern-matching is exhaustive
-            // Note that we can define a custom color using RGB
-            _ => Circle::new(
-                (coordinates[0], coordinates[1]),
-                3,
-                ShapeStyle::from(&RGBColor(255, 255, 255)).filled(),
-            ),
-        };
-
-        root_area
-            .draw(&point)
-            .expect("An error occurred while drawing the point!");
-    }
-    
-    Ok(())
-}).style("width:90%")
-
- -
-
-
- -
-
- - -
- -
Out[19]:
- - - -
- - -DBSCAN - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -0.0 - - - -1.0 - - - -2.0 - - - -3.0 - - - -4.0 - - - -5.0 - - - -6.0 - - - -7.0 - - - -8.0 - - - -9.0 - - - -10.0 - - - - -0.0 - - - -1.0 - - - -2.0 - - - -3.0 - - - -4.0 - - - -5.0 - - - -6.0 - - - -7.0 - - - -8.0 - - - -9.0 - - - -10.0 - - - - -0.0 - - - -1.0 - - - -2.0 - - - -3.0 - - - -4.0 - - - -5.0 - - - -6.0 - - - -7.0 - - - -8.0 - - - -9.0 - - - -10.0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- -
-
- -
-
-
-
In [16]:
-
-
-
extern crate plotters;
-use plotters::prelude::*;
-evcxr_figure((640, 240), |root| {
-    // The following code will create a chart context
-    let mut chart = ChartBuilder::on(&root)
-        .caption("Hello Plotters Chart Context!", ("Arial", 20).into_font())
-        .build_cartesian_2d(0f32..1f32, 0f32..1f32)?;
-    // Then we can draw a series on it!
-    chart.draw_series((1..10).map(|x|{
-        let x = x as f32/10.0;
-        Circle::new((x,x), 5, &RED)
-    }))?;
-    Ok(())
-}).style("width:60%")
-
- -
-
-
- -
-
- - -
- -
Out[16]:
- - - -
- -Hello Plotters Chart Context! - - - - - - - - - - - -
- -
- -
-
- -
-
-
-
In [ ]:
-
-
-

-
- -
-
-
- -
-
-
- - - - - - - - - diff --git a/DBSCAN.pdf b/DBSCAN.pdf new file mode 100644 index 0000000..e52b16c Binary files /dev/null and b/DBSCAN.pdf differ