地址的亲和传播聚类

我有一份许多人的地址列表(每人1到8个地址),我想确定每个人拥有的唯一地址数量。

这里是一个人的地址数据样本

#df[df['ID'] =='12345'][['address','zip]].valuesaddresses = [['PULMONARY MED ASSOC MED GROUP INC 1485 RIVER PARK DR STE 200',        '95815'],       ['1485 RIVER PARK DRIVE SUITE 200', '95815'],       ['1485 RIVER PARK DR SUITE 200', '95815'],       ['3637 MISSION AVE SUITE 7', '95608']]

我有一个地址解析器,可以将地址的不同部分分开,如“attn”、门牌号、街道名称、邮政信箱等,以便我可以单独比较它们(代码见这里

从上面的数据可以看出,地址1-3可能是相同的,而地址4是不同的。

我编写了以下相似度计算方法——权重没有特别的魔力,只是基于我的直觉认为哪些是最重要的

def calcDistance(a1, a2,z1,z2, parser):    z1 = str(z1)    z2 = str(z2)    add1 = parser.parse(a1)    add2 = parser.parse(a2)    zip_dist = 0 if z1 == z2 else distance.levenshtein(z1,z2)    zip_weight = .4    attn_dist = distance.levenshtein(add1['attn'],add2['attn']) if add1['attn'] and add2['attn'] else 0    attn_weight = .1 if add1['attn'] and add2['attn'] else 0    suite_dist = distance.levenshtein(add1['suite_num'],add2['suite_num']) if add1['suite_num'] and add2['suite_num'] else 0    suite_weight = .1 if add1['suite_num'] and add2['suite_num'] else 0    street_dist = distance.levenshtein(add1['street_name'],add2['street_name']) if add1['street_name'] and add2['street_name'] else 0    street_weight = .3 if add1['street_name'] and add2['street_name'] else 0    house_dist = distance.levenshtein(add1['house'],add2['house']) if add1['house'] and add2['house'] else 0    house_weight = .1 if add1['house'] and add2['house'] else 0    weight = (zip_dist * zip_weight + attn_dist * attn_weight + suite_dist * suite_weight + street_dist * street_weight            + house_dist * house_weight ) / (zip_weight +attn_weight + suite_weight + street_weight + house_weight )    return weight

将此函数应用于我的每个地址,你可以看到地址1-3完全相似是正确的,而地址4略有不同。

similarity = -1*np.array([[calcDistance(a1[0],a2[0],a1[1],a2[1],addr_parser) for a1 in addresses] for a2 in addresses])print similarity array([[-0.        , -0.        , -0.        , -5.11111111],       [-0.        , -0.        , -0.        , -5.11111111],       [-0.        , -0.        , -0.        , -5.11111111],       [-5.11111111, -5.11111111, -5.11111111, -0.        ]])

为了对这些地址进行聚类,我认为亲和聚类可能是最好的方法——聚类数量是可变的,它可以处理距离,并且可以识别出典型的例子,我可以使用“最佳”地址来代表聚类。然而,我得到了一些奇怪的结果——亲和聚类器对这些数据产生了3个聚类,而不是2个。

affprop = sklearn.cluster.AffinityPropagation(affinity="precomputed", damping=.5)affprop.fit(similarity)print affprop.labels_array([0, 0, 1, 2], dtype=int64)

相反,DBSCAN正确地聚类成了两个

dbscan = sklearn.cluster.DBSCAN(min_samples=1)dbscan.fit(similarity)print dbscan.labels_array([0, 0, 0, 1], dtype=int64)

查看这个问题,看起来问题是聚类器添加了小的随机起始点,并将完全相似的记录视为退化情况。

有没有办法解决这个问题,或者我应该放弃亲和聚类而坚持使用DBSCAN?


回答:

虽然我认为随着不同组的样本增多(见下面的例子),这个问题会消失,但在你的情况下,看起来你需要增加damping因子来获得所需的结果。从0.95开始,你可以得到正确的分组:

>>> affprop = sklearn.cluster.AffinityPropagation(affinity="precomputed", damping=.95)>>> affprop.fit(similarity)AffinityPropagation(affinity='precomputed', convergence_iter=15, copy=True,          damping=0.95, max_iter=200, preference=None, verbose=False)>>> print affprop.labels_[0 0 0 1]

正如我最初提到的,随着你向数据集中添加更多不同的数据,这个问题似乎会消失。查看你引用的问题中的例子,我们看到他们最初也有同样的问题:

>>> c = [[0], [0], [0], [0], [0], [0], [0], [0]]>>> af = sklearn.cluster.AffinityPropagation (affinity = 'euclidean').fit (c)>>> print (af.labels_)[0 1 0 1 2 1 1 0]

这在增加阻尼后消失了:

>>> c = [[0], [0], [0], [0], [0], [0], [0], [0]]>>> af = sklearn.cluster.AffinityPropagation (affinity = 'euclidean', damping=.99).fit (c)>>> print (af.labels_)[0 0 0 0 0 0 0 0]

或者当我们引入更多组时:

>>> c = [[0], [0], [0], [1], [2], [1], [2], [1]]>>> af = sklearn.cluster.AffinityPropagation (affinity = 'euclidean', damping=.5).fit (c)>>> print (af.labels_)[0 0 0 2 1 2 1 2]

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注