我有一些数据,我想用k均值进行聚类。
其中一个特点是一天中的时间。
问题是,23小时被认为远离'0‘小时。
如何映射数据,以便边界是循环的?
发布于 2015-11-19 02:21:26
将小时转换为两个变量是最符合逻辑的方法,这些变量在接收器中来回摆动。想象一下24小时钟的时针结束时的位置。x位置随y位置来回摆动。对于24小时的时钟,您可以通过x=sin(2pi*hour/24),y=cos(2pi*hour/24)来完成这一任务.
你需要这两个变量,否则就失去了经过时间的适当运动。这是由于sin或cos的导数在时间上的变化,当(x,y)位置在单位圆周时平稳地变化。
在欧氏空间中,这种方法对于聚类和保持午夜后15分钟到午夜前5分钟之间的距离非常有效。所有的模块建议都没有做到这一点,它们所完成的循环表示非常笨拙。
最后,考虑是否值得添加第三个特性来跟踪线性时间,从第一个记录开始,或者Unix时间戳或类似的东西开始,可以用小时(或分钟或秒)来构造线性时间。然后,这三个特征为时间的循环和线性发展提供了代理,例如,你可以提取循环现象,比如人们运动中的睡眠周期,以及人口和时间的线性增长。
希望这能有所帮助!
如果完成的话,
# Enable inline plotting
%matplotlib inline
#Import everything I need...
import numpy as np
import matplotlib as mp
import matplotlib.pyplot as plt
import pandas as pd
# Grab some random times from here: https://www.random.org/clock-times/
# put them into a csv.
from pandas import DataFrame, read_csv
df = read_csv('/Users/angus/Machine_Learning/ipython_notebooks/times.csv',delimiter=':')
df['hourfloat']=df.hour+df.minute/60.0
df['x']=np.sin(2.*np.pi*df.hourfloat/24.)
df['y']=np.cos(2.*np.pi*df.hourfloat/24.)
df
def kmeansshow(k,X):
from sklearn import cluster
from matplotlib import pyplot
import numpy as np
kmeans = cluster.KMeans(n_clusters=k)
kmeans.fit(X)
labels = kmeans.labels_
centroids = kmeans.cluster_centers_
#print centroids
for i in range(k):
# select only data observations with cluster label == i
ds = X[np.where(labels==i)]
# plot the data observations
pyplot.plot(ds[:,0],ds[:,1],'o')
# plot the centroids
lines = pyplot.plot(centroids[i,0],centroids[i,1],'kx')
# make the centroid x's bigger
pyplot.setp(lines,ms=15.0)
pyplot.setp(lines,mew=2.0)
pyplot.show()
return centroids现在让我们尝试一下:
kmeansshow(6,df[['x', 'y']].values)
你几乎看不到午夜后的一些时间包含在午夜前的绿色星系团中。现在,让我们减少集群的数量,并显示午夜前后可以在单个集群中更详细地连接:
kmeansshow(3,df[['x', 'y']].values)
查看蓝色集群如何包含午夜前后在同一集群中聚集在一起的时间.
QED!
发布于 2015-11-18 12:14:08
K-均值是为最小二乘设计的.它仅适用于欧氏距离的变式(=平方偏差之和)。
假设你有两个小时0和23。
如果它们被分配到同一个集群,k-均值将计算平均值。
这两个数值的平均值为11.5。不是23.5。
滥用k-意味着循环“距离”可能不再收敛,并将返回无意义的结果。
但是,有更多的情况下,集群中心的概念是不可行的循环数据。例如,假设每一小时都有一个活动,中心是什么?算术平均值为12,但如果将循环空间考虑在内,在循环空间中,每小时都是一个同样好的选择。因此,循环空间中的“中心”概念是脆弱的。
您可以尝试使用适当的相似性度量,例如PAM或DBSCAN。
正如其他答案所指出的,您可以通过sin/cos( time /24*2pi)将时间投影到单位圆。通过计算质心的角度,你可以把它映射回一个时间点。但是,一旦您需要额外的属性,就很难对数据进行有意义的规范化(以组合属性),并且您可以得到未定义的时间(例如,如果集群中有两个点,一个是6点,一个是18点)。我没有讨论这个问题,因为我想指出,修改距离函数对于k-方法来说不是一个好主意。
发布于 2015-11-11 15:06:18
模运算一般情况下你会做end - start mod 24
julia> mod(-23,24)
1我似乎还记得一些编程语言以不同的方式对待负数的模式,所以首先检查一下您的实现。
https://datascience.stackexchange.com/questions/8799
复制相似问题