在这里使用哪种聚类算法?

时间:2017-06-19 13:23:54

标签: algorithm machine-learning

我对机器学习算法完全陌生,希望有一些方向可以走向。

一般情景

我有两个参数LocationTime。我需要对在特定时间从特定位置上传的帖子进行分组。没有特定的预设位置或时间。随机有趣事件可以在位置平面中的任何位置随时发生。一组用户可以在特定时间在特定位置发现有趣的内容时立即开始上传。该算法需要检测当时在该位置上传的这些帖子。

接受的场景

事件发生在A(1,3)的{​​{1}}点。人们开始拍摄活动的照片并开始从A点周围上传,例如,一些示例上传位置4:00(1,2)(1.5,3))在时间(1,2.5)左右像4:004:014:10

未接受的场景

  1. 事件发生在4:22 A(1,3)点。人们开始拍摄活动的照片并开始从A点周围上传,例如,一些示例上传位置4:00(9,2)(1.5,15))在时间(21,62.5)左右像4:004:014:10
  2. 事件发生在4:22 A(1,3)点。人们开始拍摄活动的照片并开始从A点周围上传,例如,一些示例上传位置4:00(1,2)(1.5,3))在时间(1,2.5)左右像4:0014:0108:10
  3. 了解到目前为止

    据我了解,我看到如果这只是基于位置,那么可以使用K-Means聚类算法完成。但是,由于我们也有时间维度,我需要另一种在3D中聚类的算法。我认为DBSCAN可能会这样做,但我不确定,因为我的理解非常模糊。

    那么,哪种算法可以帮助我呢?如果不是直接回答,我想要一些我可以研究的方向,因为这是一个非常广阔的领域,可以通过每一个算法。

    修改

    我尝试了以下测试实现

    13:22

    输出

    from sklearn.cluster import KMeans, MeanShift, DBSCAN
    import numpy as np
    
    # Scene one, similar timestamp (turn timestamp into decimal so that the difference is not too large)
    # First three are from event 1,
    # next 2 are from event 2,
    # 3rd one is a random post.
    X = np.array([[12.975466, 77.639363, 149794.3292], [12.975273, 77.639358, 149794.3311], [12.975317, 77.639562, 149794.3314],
                  [12.973567, 77.635589, 149794.3328], [12.973525, 77.635685, 149794.3336], [12.969739, 77.620912, 149794.3349]])
    
    kmeans = KMeans(n_clusters=3, random_state=0).fit(X)
    print('K-Means cluster:', kmeans.labels_)
    
    meanshift = MeanShift().fit(X)
    print('MeanShift cluster:', meanshift.labels_)
    
    dbscan = DBSCAN(eps=1).fit(X)
    print('DBSCAN cluster:', dbscan.labels_)
    

    在这里,K-means聚类非常适合聚类正确的点。但是,如答案所述,缺点是我需要提及输入中的簇数,这是不可能的,因为实际上我不知道在我的应用程序逻辑中知道它。

    我也试过了一个MeanShift和DBSCAN,但是,因为我不知道对它们的正确输入应该是什么,这可能就是为什么我没有得到理想的结果。

    那么,如何使用其他算法在不传递输出簇数的情况下获得与K-Means聚类相同的结果?

    P.S。如果你认为这个问题需要改进/关闭,只需评论原因,我希望通过更多细节来改进它。只是不要继续投票。我永远不会知道如何改进,这完全违背了Stack Overflow的存在。

3 个答案:

答案 0 :(得分:1)

k-means算法是通用的,可以在任意数量的维度上工作。 因此,我们需要将(时间,空间)数据转换为三维空间。

假设您的数据格式为:

data = [
    location: (1, 1), time: "4:00", 
    location: (1, 2), time: "4:01", 
    ... 
]

我们需要将时间轴转换为空间轴:

def get3DCoordinate(point):
    "tau is a hyper parameter"
    return (location[0], location[1], tau * time.convertToDist())
map(get3DCoordinate, data)

这可让您将数据转换为:

data = [
    (1, 1, 960),
    (1, 2, 961),
    ... 
]

这些点可以通过k方式直接使用。

答案 1 :(得分:1)

您的问题有两个方面。

首先是如何将时间作为另一个维度。为了回答这个问题,大多数聚类算法(包括k均值)都适用于多维数据集。您可以将时间转换为数字,然后将其作为数据的第三维包含在内。在执行此操作时,您需要考虑使用哪些单位,以及时间单位与空间单位的关系。例如:如果您的位置数据单位是公里,那么应该等于什么时间?假设你到达15分钟。然后你应该缩放你的时间维度,使1单位= 15分钟。 (这可以在稍后的某些算法中处理,但你应该考虑它)。

第二个是在这种情况下使用的合适的聚类算法。虽然k-means是默认的算法,但它的缺点是需要指定簇的数量。由于数据点的数量在您的系统中逐日增长/缩小,因此考虑固定数量的集群并不直观,并且不容易弄清楚集群数量与数据数量之间的关系要点。

您可以针对此用例尝试mean shift algorithm。在这里,您不必指定群集的数量,算法会随着它的发现而发现它。但是,您需要指定"带宽"参数,它粗略地决定彼此相距一定距离的两个点是否合并到一个集群,或者保留在它们自己的集群中。您可能还需要一些迭代来确定正确的带宽,但与群集数量不同,这可能会对给定的应用程序保持稳定。

通常,您需要尝试一些群集运行并查看所获得的内容,并进一步调整参数。

答案 2 :(得分:0)

可以使用k均值对多媒体数据的时间序列进行聚类。 this paper explains how