如何对一组字符串进行聚类?

时间:2015-06-08 08:24:08

标签: machine-learning cluster-analysis k-means hierarchical-clustering

我的数据集看起来像这样

  

['','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','','','','','我','','','','','','','',''' ,'','','','','','','','','','','AAAAA','AFGFE','FGFEEFGFEFGFEFGJJGFEACHJ','','',' ','','','','','','','','','','','','','',''','','', “ ','JFEFFFFFFF','','AAIIJFFGEFGCABAGG','','','','','','','','','','F','JFJFJFJ','' ,'','','','','','','','','','','','','','','','','',' ','','','F','','','','','','','','','F','','','',' ','','','','','','','','','','','','','',''','','', '','','','','','','','','','','','','','',''','',''' ,'','','','','','','','','','','','','','','','','',' ','','','','','','','','','','','','','',''','','', '','','','','','','','','','','','','','',''','',''' ,'','','','','','','','','F','FGFEFGFE','','','','','',''' ,'','','','','','','','','','','','','','','','','',' ','','','','','','','','','','','','','',''','','', '','','','','','','','','','','','','','',''','',''' ,'','','','','','','','','','','','','','','','','',' ','','','','','','','','','','','','','',''','','', '','','','','','','','', '','','','','','']

这只是一个示例,但我会有更多的字符串。我如何对它们进行聚类,使每个聚类都有一些模式

1 个答案:

答案 0 :(得分:2)

我建议的想法源于文本处理,NLP和信息检索,并且在您拥有遗传信息等字符/信息序列的情况下非常广泛使用。因为你必须保留序列,我们可以使用n-gram的概念。我在下面的例子中使用了bi-gram,尽管你可以推广更高阶的克数。 N-gram有助于保留数据中的顺序模式。别担心 - 我们不断借鉴其他科学领域的想法 - 即使编辑距离和动态编程也不是计算机科学概念。

有许多可能的方法可以解决这个问题 - 每一个都是独一无二的,而且没有正确的方法 - 至少没有足够的研究来证明哪一个是正确的。这是我的看法。

因此,我们的目标是从数据字符串中创建一个像矢量一样的词袋 - 这些矢量可以很容易地输入到任何机器学习工具或库中进行聚类。步骤的快速摘要: -

  1. 收集双字母(和unigrams等)
  2. 创建字典以获取Bag Of Words(附加代码)
  3. 创建从字符串中获取向量的功能
  4. 让我们开始吧

    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克甚至完整的所有可能的单,双和三克。随意尝试。

    现在如何将字符串转换为向量?我们将定义一个函数,它将字符串转换为向量,负责处理特定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_属性看到了我的簇的样子。

    这是你的集群。查看控制台(底部)窗口 - 有十个集群。 enter image description here

    现在,您可以修改我在代码中编写的功能生成,并查看修改的执行情况。而不仅仅是bigrams,提取所有可能的unigrams,bigrams和trigrams并使用它们来创建BOW。会有显着差异。您还可以使用字符串的长度作为功能。您还可以尝试其他算法,包括层次聚类。修改后请务必向我发送最新结果。

    享受!