聚类算法初探

Posted Pentacrest智联万物

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了聚类算法初探相关的知识,希望对你有一定的参考价值。

聚类是一种机器学习技术,涉及对数据点进行分组。给定一组数据点,我们可以使用聚类算法将每个数据点分类到特定的组中。理论上,同一组中的数据点应该具有相似的属性和/或特征,而不同组中的数据点应该具有高度不同的属性和/或特征。聚类是一种无监督学习的方法,是用于许多领域的统计数据分析的常用技术。

你可以使用许多不同的方法来执行聚类,事实上,有很多种聚类算法。每一类都有其独特的优势和劣势。这意味着某些聚类算法将根据输入数据产生更自然的聚类分配。为数据集选择合适的聚类算法通常很困难,因为可用的选择太多了。影响这个决策的一些重要因素包括集群的特性、数据集的特性、异常值的数量和数据对象的数量。

三类流行的聚类算法包括:Partitional clustering, Hierarchical clustering, Density-basedclustering。

以下介绍各类方法的优缺点

1.Partitional clustering

Partitional clustering将数据对象划分为不重叠的组。换句话说,没有对象可以是多个集群的成员,每个集群必须至少有一个对象。这些技术要求用户指定由变量k表示的聚类数目。许多Partitional clustering算法通过迭代过程将数据点子集分配到k个聚类中。Partitional clustering算法的两个例子是k-means和k-medoids。这些算法都是不确定性的,这意味着即使运行基于相同的输入,它们也可以从两个不同的运行中产生不同的结果。

Partitional clustering法有几个优点:当每一类分布呈球形时,它们工作得很好。它们在算法复杂度方面是scalable的。

它们也有几个缺点:它们不太适合形状复杂、大小不一的簇。当与不同密度的集群一起使用时,它们会失效。

此类方法中最著名的当属Kmeans clustering方法,下边有详细描述。

2.Hierarchical clustering

Hierarchical clustering通过构建层次结构来确定聚类分配。这可以通过自下而上或自上而下的方法来实现:Hierarchical聚类是自下而上的方法,它将合并最相似的两个点,直到所有点都合并到某一个簇中;Partitional clustering是自顶向下的方法,它从所有点作为一个簇开始,在每一步中分割最不相似的簇,直到只剩下一个数据点。这些方法生成一个基于树的点层次结构,称为树状图。与Partitional clustering类似,在Hierarchical clustering中,cluster的数目(K)通常由用户预先确定。通过在指定的深度切割树状图来分配聚类,从而产生K组较小的树状图。与许多Partitional clustering技术不同,Hierarchical clustering是一个确定的过程,这意味着在相同的输入数据上运行两次算法时,集群分配不会改变。

Hierarchical clustering法的优点包括:它们常常揭示数据对象之间关系的更精细的细节。它们提供了一个可解释的树状图。

Hierarchical clustering方法的缺点包括:就算法复杂度而言,它们的计算成本很高。它们对data noise和outliers很敏感。

3.Density-based clustering

Density-based clustering根据区域中数据点的密度来确定聚类分配。在由低密度区域分隔的高密度数据点处分配簇。与其他聚类方法不同,这种方法不需要用户指定集群的数量。相反,有一个基于距离的参数充当可调阈值。此阈值决定了必须将多近的点视为群集成员。Density-based clustering算法的示例包括基于密度的应用程序(DBSCAN)的空间聚类(DBSCAN)和用于识别聚类结构的排序点(OPTICS)。

Density-based 方法的优势包括:它们擅长于识别非球形形状的簇。它们对异常值有抵抗力。

Density-based 方法的缺点包括:它们不太适合在高维空间中进行聚类。它们很难识别不同密度的cluster。



下文详细介绍两种常见的聚类算法:

K-means clustering

K-Means 可能是最著名的partitional聚类算法。它在许多介绍性的数据科学和机器学习课程中都有教授。在代码中很容易理解和实现!下面给出了算法细节。

    Given data set {x_i}, i=1,..N in D-dimensional Euclidean space partition into K clusters (which is given) Indicator variable rnk ∈ {0,1} where k =1,..,K – Describes which of K clusters data point x_n is assigned to. Objective function is the sum of squares of distances of each data point to its assigned vector µ_k. To minimize the distance of each data point‘s distance to the centroids, just follow the algorithm below:


下面是Kmeans使用c++编写的一个分类实例:

#include <ctime>#include <fstream>#include <iostream>#include <sstream>#include <vector>
using namespace std;
// Create point struction in 1Dstruct Point { double x; // 坐标 int cluster; // no default cluster double minDist; Point() : x(0.0), cluster(-1), minDist(__DBL_MAX__) {} Point(double x) : x(x), cluster(-1), minDist(__DBL_MAX__) {}
/** * 计算欧式距离 */ double distance(Point p) { return (p.x - x) * (p.x - x); }};
/** * 建立0-100的随机整数数列; */vector<Point> createPoints(int pnumber) { vector<Point> points; for (int i=1;i<=pnumber;i++){ points.push_back(Point( rand()%100 )); } return points;}
/** * Perform k-means clustering * @param points - pointer to vector of points * @param epochs - kmeans 循环次数 * @param k - 群组个数 */void kMeans(vector<Point>* points, int epochs, int k) { int n = points->size();
    // 随机选定群组中心 // 群组的index就是群组label vector<Point> centroids; srand(time(0)); for (int i = 0; i < k; ++i) { centroids.push_back(points->at(rand() % n)); }    //进入循环:对分组进行epochs次的重新分组 for (int i = 0; i < epochs; ++i) { // For each centroid, compute distance from centroid to each point // and update point's cluster if necessary for (vector<Point>::iterator c = begin(centroids); c != end(centroids); ++c) { int clusterId = c - begin(centroids);
for (vector<Point>::iterator it = points->begin(); it != points->end(); ++it) { Point p = *it; double dist = c->distance(p); if (dist < p.minDist) { p.minDist = dist; p.cluster = clusterId; } *it = p; } }
vector<int> nPoints; vector<double> sumX; for (int j = 0; j < k; ++j) { nPoints.push_back(0); sumX.push_back(0.0); }
for (vector<Point>::iterator it = points->begin(); it != points->end(); ++it) { int clusterId = it->cluster; nPoints[clusterId] += 1; sumX[clusterId] += it->x;
it->minDist = __DBL_MAX__; // reset distance } for (vector<Point>::iterator c = begin(centroids); c != end(centroids); ++c) { int clusterId = c - begin(centroids); c->x = sumX[clusterId] / nPoints[clusterId]; } }
for(int j = 0;j<k; j++){ cout<<"Cluster "<<j<<" members"<<endl; for (vector<Point>::iterator it = points->begin(); it != points->end(); ++it) { if (it->cluster==j) cout << it->x << endl; } }}
int main() {    vector<Point> points =createPoints(30);    // 将待分类数组分入3类目标群组,运行200次循环  kMeans(&points, 200, 3);}


K-Means 有几个缺点。首先,你必须选择有多少组/群。这可能是至关重要的,理想情况下,我们希望使用聚类算法为我们解决这些问题,因为它的重点是从数据中获得一些深入了解,但是预设分类组数首先假定我们对数据有一定了解,实时不总是这样。 另外K-means 从随机选择聚类中心开始,因此它可能会在算法的不同运行中产生不同的聚类结果。因此,结果可能不可重复且缺乏一致性。其他聚类方法分类结果更加一致。

K-Medians 是另一种与 K-Means 相关的聚类算法,除了我们使用组的中值向量而不是使用均值重新计算组中心点。这种方法对异常值不太敏感(因为使用中值),但对于较大的数据集要慢得多,因为在计算中值向量时每次迭代都需要排序。



以上是关于聚类算法初探的主要内容,如果未能解决你的问题,请参考以下文章

谱聚类初探

K-Means聚类算法原理

K-Means聚类算法原理

K-Means聚类算法原理

4.K-MEANS聚类算法

数术|产品聚类方法初探(基于Google Analytics中的数据)