如何聚类一组字符串?
Posted
技术标签:
【中文标题】如何聚类一组字符串?【英文标题】:How to cluster a set of strings? 【发布时间】:2015-08-22 15:12:43 【问题描述】:我的数据集看起来像这样
['', 'ABCDH', '', '', 'H', 'HHIH', '', '', '', '', '', '', '', '', ' ','','','FECABDAI','','','','','','','','','','','','','' ,'','','','','FABHJJFFFFEEFGEE','FFFF','','','','','','','','','','FF ','F','FF','F','F','FFFFFFIFF','','FFFFFFF','F','','','F','','',' ','','','','','F','','','ABB','','','','','','','',' ', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ,'','FF','','','','','','','','','','','','','','', '','F','FFEIE','FF','ABABCDIIJCCFG','','FABACFFF','FEGGIHJCABAGGFEFGGFEECA','','FF','FFGEFGGFFG','F','FFF',' ', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '一世' , '', '', 'ABIIII', '', '', '', '', 'I', '', '', '', '', '', '', '', '' , '', '', '', '', '', '', '', '', '', '', 'AAAAA', 'AFGFE', 'FGFEEFGFEFGFEFGJJGFEACHJ', '', '', ' ', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ' ','JFEFFFFFFF','','AAIIJFFGEFGCABAGG','','','','','','','','','','F','JFJFJFJ','' ,'','','','','','','','','','','','','','','','',' ','','','F','','','','','','','','','F','','','',' ', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ,'','','','','','','','','','','','','','','','',' ', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ,'','','','','','','','','F','FGFEFGFE','','','','','','' ,'','','','','','','','','','','','','','','','',' ', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ,'','','','','','','','','','','','','','','','',' ', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '']
这只是一个示例,但我会有更多的字符串。我如何对它们进行聚类,使每个聚类都有一些模式
【问题讨论】:
顺便说一句:存储/传递所有这些空值真的是强制性的吗? 不,现在可以忽略空字符串。 生物信息学像数据吗? 字符有限制吗?会只选择 7-8 个字符还是可以选择 26 个英文字符或更大的词汇量? 暂时只有A-J,以后可能会增加一些 【参考方案1】:我建议的想法起源于文本处理、NLP 和信息检索,并且非常广泛地用于您拥有诸如遗传信息之类的字符/信息序列的情况。因为您必须保留序列,所以我们可以使用 n-gram 的概念。我在以下示例中使用了二元语法,尽管您可以概括为更高阶的克数。 N-gram 有助于保留数据中的顺序模式。别担心 - 我们一直在借鉴其他科学领域的想法 - 甚至编辑距离和动态编程最初都不是计算机科学概念。
有许多可能的方法来解决这个问题 - 每一种都是独一无二的,而且没有正确的方法 - 至少没有足够的研究证明哪一种方法是正确的。这是我的看法。
因此,我们的目标是从您的数据字符串中创建一个类似词袋的向量 - 这些向量可以轻松地馈送到任何机器学习工具或库中进行聚类。步骤的快速总结:-
-
收集二元组(和一元组等)
创建字典以获取词袋(附代码)
创建从字符串中获取向量的功能
让我们开始吧
import numpy
from sklearn.cluster import KMeans
def getStringBigrams(string):
if len(string) <= 0: return []
if len(string) == 1: return string[0] # Handle strings with only one character = extract unigram
return [string[i]+string[i+1] for i in range(len(string)-1)]
def getDataBigrams(strings):
return [getStringBigrams(x) for x in strings]
所以这里这些函数会将给定的字符串转换为一组两个字符(如果只有一个字符,则为单个字符)。您可以修改它们以捕获 3-gram 甚至所有可能的 uni-、bi- 和 tri-gram 的完整集。随意尝试。
现在如何将字符串转换为向量?我们将定义一个函数,它将字符串转换为向量,以处理特定 n-gram 出现的次数。这称为 BAG OF WORDS。在这里,这些是屏幕袋。以下两个函数可以帮助您:
def generateDictionary(data):
'''
This function identifies unique n-grams in your data.
'''
vocab = set()
for line in data:
for item in line:
vocab.add(item)
dictionary =
i=0
for item in vocab:
dictionary[item] = i
i+=1
return dictionary
def doc2Bow(bigramData, dictionary):
'''
Take single document in bigram format and return a vector
'''
vect = [0]*len(dictionary) # Initialize vector to zero
for gram in bigramData:
vect[dictionary[gram]]+=1
return numpy.asarray(vect) # Convert to numpy vector
瞧!我们完成了。现在将您的数据向量提供给您选择的任何 K-Means 实现。我用过SKLearn。
strings = ['', 'ABCDH', '', '', 'H', 'HHIH', '', '', '', '', '', '', '', '', '', '', '', 'FECABDAI', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'FABHJJFFFFEEFGEE', 'FFFF', '', '', '', '', '', '', '', '', '', 'FF', 'F', 'FF', 'F', 'F', 'FFFFFFIFF', '', 'FFFFFFF', 'F', '', '', 'F', '', '', '', '', '', '', '', 'F', '', '', 'ABB', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'FF', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'F', 'FFEIE', 'FF', 'ABABCDIIJCCFG', '', 'FABACFFF', 'FEGGIHJCABAGGFEFGGFEECA', '', 'FF', 'FFGEFGGFFG', 'F', 'FFF', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'I', '', '', 'ABIIII', '', '', '', '', 'I', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'AAAAA', 'AFGFE', 'FGFEEFGFEFGFEFGJJGFEACHJ', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'JFEFFFFFFF', '', 'AAIIJFFGEFGCABAGG', '', '', '', '', '', '', '', '', '', 'F', 'JFJFJFJ', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'F', '', '', '', '', '', '', '', '', 'F', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'F', 'FGFEFGFE', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '']
你应该选择从文件中读取字符串
strings = [x for x in strings if len(x) > 0] # Just cleanup for experiment purpose
nGramData = getDataBigrams(strings)
dictionary = generateDictionary(nGramData)
data = [doc2Bow(nGramData[i], dictionary) for i in range(len(nGramData))]
K = 10
km = KMeans(init='k-means++', n_clusters=K, n_init=10)
km.fit(data)
然后我终于看到使用 KMeans 类的 km.labels_ 属性的集群是什么样子了。
这是您的集群。查看控制台(底部)窗口 - 有十个集群。
现在您可以修改我在代码中编写的特征生成,看看您的修改效果如何。不仅仅是二元组,提取所有可能的一元组、二元组和三元组,并使用它们来创建 BOW。会有显着差异。您还可以使用字符串的长度作为特征。您还可以尝试其他算法,包括层次聚类。请务必在修改后将更新的结果发送给我。
享受吧!
【讨论】:
以上是关于如何聚类一组字符串?的主要内容,如果未能解决你的问题,请参考以下文章
根据2个(理想情况下推广到n个)任意分组规则对字母字符串列表进行聚类?