我的数据集看起来像这样
[”, ‘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’, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”, ”]
这只是一个样本,但我会有很多更多的字符串。我该如何对它们进行聚类,使得每个聚类都有一些模式?
回答:
我提出的想法源自文本处理、自然语言处理和信息检索,并且在处理像基因信息这样的字符/信息序列时被广泛使用。因为你需要保留序列,我们可以使用n-gram的概念。我在下面的例子中使用了二元组,尽管你可以推广到更高阶的n-gram。N-gram有助于保留数据中的顺序模式。别担心——我们经常从其他科学领域借用想法——即使是编辑距离和动态规划最初也不是计算机科学的概念。
解决这个问题有许多可能的方法——每一种都是独特的,没有一种是正确的——至少没有足够的研究证明哪一种是正确的。这是我的看法。
所以目标是根据你的数据字符串创建一个类似词袋的向量——这些向量可以很容易地输入到任何机器学习工具或库中进行聚类。步骤的简要总结如下:
- 收集二元组(以及一元组等)
- 创建一个字典来获取词袋(附带代码)
- 创建从字符串获取向量的功能
让我们开始吧
import numpyfrom sklearn.cluster import KMeansdef getStringBigrams(string): if len(string) <= 0: return [] if len(string) == 1: return string[0] # 处理只有一个字符的字符串 = 提取一元组 return [string[i]+string[i+1] for i in range(len(string)-1)]def getDataBigrams(strings): return [getStringBigrams(x) for x in strings]
所以这里这些函数会将给定的字符串转换为一组两个字符(如果只有一个字符则提取单个字符)。你可以修改它们来捕获三元组甚至是所有可能的一元、二元和三元组。请随意实验。
现在如何将字符串转换为向量?我们将定义一个函数,该函数将字符串转换为向量,并考虑特定n-gram出现的次数。这被称为词袋。这里,这些是屏幕袋。以下两个函数可以帮助你实现这一点:
def generateDictionary(data): ''' 此函数识别数据中的唯一n-gram。 ''' 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): ''' 将单个文档以二元组格式转换为向量 ''' vect = [0]*len(dictionary) # 初始化向量为零 for gram in bigramData: vect[dictionary[gram]]+=1 return numpy.asarray(vect) # 转换为numpy向量
好了!我们完成了。现在将你的数据向量输入到你选择的任何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] # 仅为实验目的进行清理nGramData = getDataBigrams(strings)dictionary = generateDictionary(nGramData)data = [doc2Bow(nGramData[i], dictionary) for i in range(len(nGramData))]K = 10km = KMeans(init='k-means++', n_clusters=K, n_init=10)km.fit(data)
然后我最终可以使用KMeans类的km.labels_属性查看我的聚类是什么样的。
这里是你的聚类。查看控制台(底部)窗口 – 有十个聚类。
现在你可以修改我在代码中编写的特征生成,并查看你的修改效果如何。与其只提取二元组,不如提取所有可能的一元、二元和三元组,并使用它们来创建词袋。这将有显著的不同。你还可以使用字符串的长度作为一个特征。你还可以尝试其他算法,包括层次聚类。请务必在修改后将更新的结果发送给我。
享受吧!