DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一种流行的聚类算法,它基于数据点的密度来形成簇。以下是一个在C#中实现DBSCAN算法的基本示例,以及一个VB.NET的示例。
using System;
using System.Collections.Generic;
using System.Linq;
public class DBSCAN
{
private readonly double eps;
private readonly int minPts;
public DBSCAN(double eps, int minPts)
{
this.eps = eps;
this.minPts = minPts;
}
public List<Cluster> Run(IEnumerable<Point> points)
{
var clusters = new List<Cluster>();
var visited = new HashSet<Point>();
foreach (var point in points)
{
if (visited.Contains(point))
continue;
visited.Add(point);
var neighbors = GetNeighbors(points, point);
if (neighbors.Count < minPts)
{
// Noise point
continue;
}
var cluster = new Cluster();
ExpandCluster(points, visited, neighbors, cluster);
clusters.Add(cluster);
}
return clusters;
}
private void ExpandCluster(IEnumerable<Point> points, HashSet<Point> visited, List<Point> neighbors, Cluster cluster)
{
foreach (var neighbor in neighbors)
{
if (!visited.Contains(neighbor))
{
visited.Add(neighbor);
var neighborNeighbors = GetNeighbors(points, neighbor);
if (neighborNeighbors.Count >= minPts)
{
neighbors.AddRange(neighborNeighbors);
}
}
if (!cluster.Points.Contains(neighbor))
{
cluster.Points.Add(neighbor);
}
}
}
private List<Point> GetNeighbors(IEnumerable<Point> points, Point point)
{
return points.Where(p => Distance(p, point) <= eps).ToList();
}
private double Distance(Point a, Point b)
{
return Math.Sqrt(Math.Pow(a.X - b.X, 2) + Math.Pow(a.Y - b.Y, 2));
}
}
public class Point
{
public double X { get; set; }
public double Y { get; set; }
}
public class Cluster
{
public List<Point> Points { get; set; } = new List<Point>();
}
Imports System
Imports System.Collections.Generic
Imports System.Linq
Public Class DBSCAN
Private eps As Double
Private minPts As Integer
Public Sub New(eps As Double, minPts As Integer)
Me.eps = eps
Me.minPts = minPts
End Sub
Public Function Run(points As IEnumerable(Of Point)) As List(Of Cluster)
Dim clusters As New List(Of Cluster)()
Dim visited As New HashSet(Of Point)()
For Each point In points
If visited.Contains(point) Then Continue For
visited.Add(point)
Dim neighbors = GetNeighbors(points, point)
If neighbors.Count < minPts Then
' Noise point
Continue For
End If
Dim cluster As New Cluster()
ExpandCluster(points, visited, neighbors, cluster)
clusters.Add(cluster)
Next
Return clusters
End Function
Private Sub ExpandCluster(points As IEnumerable(Of Point), visited As HashSet(Of Point), neighbors As List(Of Point), cluster As Cluster)
For Each neighbor In neighbors
If Not visited.Contains(neighbor) Then
visited.Add(neighbor)
Dim neighborNeighbors = GetNeighbors(points, neighbor)
If neighborNeighbors.Count >= minPts Then
neighbors.AddRange(neighborNeighbors)
End If
End If
If Not cluster.Points.Contains(neighbor) Then
cluster.Points.Add(neighbor)
End If
Next
End Sub
Private Function GetNeighbors(points As IEnumerable(Of Point), point As Point) As List(Of Point)
Return points.Where(Function(p) Distance(p, point) <= eps).ToList()
End Function
Private Function Distance(a As Point, b As Point) As Double
Return Math.Sqrt(Math.Pow(a.X - b.X, 2) + Math.Pow(a.Y - b.Y, 2))
End Function
End Class
Public Class Point
Public Property X As Double
Public Property Y As Double
End Class
Public Class Cluster
Public Property Points As New List(Of Point)()
End Class
无论是在C#还是VB.NET中,你都可以这样使用DBSCAN类:
// C# 示例
var points = new List<Point>
{
new Point { X = 1, Y = 1 },
new Point { X = 1, Y = 2 },
new Point { X = 2, Y = 1 },
new Point { X = 6, Y = 6 },
new Point { X = 6, Y = 7 },
new Point { X = 7, Y = 6 }
};
var dbscan = new DBSCAN(2, 2);
var clusters = dbscan.Run(points);
foreach (var cluster in clusters)
{
Console.WriteLine($"Cluster with {cluster.Points.Count} points:");
foreach (var point in cluster.Points)
{
Console.WriteLine($"({point.X}, {point.Y})");
}
}
' VB.NET 示例
Dim points As New List(Of Point) From {
New Point With {.X = 1, .Y = 1},
New Point With {.X = 1, .Y = 2},
New Point With {.X = 2, .Y = 1},
New Point With {.X = 6, .Y = 6},
New Point With {.X = 6, .Y = 7},
New Point With {.X = 7, .Y = 6}
}
Dim dbscan As New DBSCAN(2, 2)
Dim clusters = dbscan.Run(points)
For Each cluster In clusters
Console.WriteLine($"Cluster with {cluster.Points.Count} points:")
For Each point In cluster.Points
Console.WriteLine($"({point.X}, {point.Y})")
Next
Next
这些示例代码创建了一个简单的二维点集,并使用DBSCAN算法对其进行聚类。你可以根据需要调整eps
和minPts
参数,以及点的集合。
领取专属 10元无门槛券
手把手带您无忧上云