【问题标题】:Implementing proximity matrix for clustering实现聚类的邻近矩阵
【发布时间】:2011-10-22 16:05:26
【问题描述】:

请我对这个领域有点陌生,如果这个问题听起来微不足道或基本,请原谅我。

我有一组数据集(具体来说是词袋),我需要通过使用它们彼此之间的编辑距离来查找和生成邻近矩阵来生成邻近矩阵。

然而,我很困惑如何在矩阵中跟踪我的数据/字符串。我需要邻近矩阵来进行聚类。

或者您通常如何处理该领域的此类问题。我正在使用 perl 和 R 来实现这一点。

这是我编写的一个典型的 perl 代码,它从包含我的词袋的文本文件中读取

use strict ;
   use warnings ; 
   use Text::Levenshtein qw(distance) ;
   main(@ARGV);
   sub main
   {    
    my @TokenDistances ;
    my $Tokenfile  = 'TokenDistinct.txt';
    my @Token ;
    my $AppendingCount  = 0 ; 
    my @Tokencompare ;  
    my %Levcount  = ();
    open (FH ,"< $Tokenfile" ) or die ("Error opening file . $!");
     while(<FH>)
     {
        chomp $_;
        $_ =~ s/^(\s+)$//g;
        push (@Token , $_ ); 
     }
    close(FH); 
     @Tokencompare = @Token ; 


     foreach my $tokenWord(@Tokencompare)
     { 
        my $lengthoffile =  scalar @Tokencompare;
        my $i = 0 ;
        chomp $tokenWord ;

        #@TokenDistances = levDistance($tokenWord , \@Tokencompare );
        for($i = 0 ; $i < $lengthoffile ;$i++)
        {
            if(scalar @TokenDistances ==  scalar @Tokencompare)
            {
                print "Yipeeeeeeeeeeeeeeeeeeeee\n";
            }
            chomp $tokenWord   ;
            chomp $Tokencompare[$i];
            #print   $tokenWord. "   {$Tokencompare[$i]}  " . "      $TokenDistances[$i] " . "\n";
            #$Levcount{$tokenWord}{$Tokencompare[$i]} = $TokenDistances[$i];
            $Levcount{$tokenWord}{$Tokencompare[$i]} = levDistance($tokenWord , $Tokencompare[$i] );

        }

        StoreSortedValues ( \%Levcount ,\$tokenWord , \$AppendingCount);
        $AppendingCount++;
        %Levcount = () ;

     } 
    # %Levcount  = (); 
}

sub levDistance
{
    my $string1 = shift ;
    #my @StringList = @{(shift)};
    my $string2 =  shift ;
    return distance($string1 , $string2);
}


sub StoreSortedValues {


    my $Levcount  = shift;
    my $tokenWordTopMost = ${(shift)} ; 
    my $j = ${(shift)};
    my @ListToken;
    my $Tokenfile = 'LevResult.txt';

    if($j == 0 )
    {
        open (FH ,"> $Tokenfile" ) or die ("Error opening file . $!");
    }
    else
    {
        open (FH ,">> $Tokenfile" ) or die ("Error opening file . $!");
    }

                print $tokenWordTopMost; 
                my %tokenWordMaster = %{$Levcount->{$tokenWordTopMost}};
                @ListToken = sort { $tokenWordMaster{$a} cmp $tokenWordMaster{$b} }   keys %tokenWordMaster;
            #@ListToken = keys %tokenWordMaster;

        print FH "-------------------------- " . $tokenWordTopMost . "-------------------------------------\n";
        #print FH  map {"$_  \t=>  $tokenWordMaster{$_} \n "}   @ListToken;
        foreach my $tokey (@ListToken)
        {
            print FH  "$tokey=>\t" . $tokenWordMaster{$tokey} . "\n" 

        }

        close(FH) or  die ("Error Closing File.  $!");

}

问题是我怎样才能从中表示邻近矩阵,并且仍然能够跟踪哪个比较代表我的矩阵中的哪个比较。

【问题讨论】:

  • 我很高兴我放弃了学习 Perl 而发现了 R!

标签: r machine-learning cluster-analysis data-mining


【解决方案1】:

接近度或相似度(或相异度)矩阵只是一个表格,用于存储对象对的相似度得分。所以,如果你有N个对象,那么R代码可以是simMat &lt;- matrix(nrow = N, ncol = N),那么simMat的每一个条目,(i,j),表示item i和item j的相似度。

在 R 中,您可以使用多个包(包括 vwr)来计算 Levenshtein 编辑距离。

您可能还会对这本 Wikibook 感兴趣:http://en.wikibooks.org/wiki/R_Programming/Text_Processing

【讨论】:

  • 谢谢。我了解邻近矩阵是什么我只是对生成矩阵有点困惑。如果我有一个文本 [apple ,banana , mango] 用于词袋并且我希望能够使用每个作品之间的编辑距离生成矩阵,即 [Apple,Apple] , [Apple, Banana] , [Apple, Mango ],[Mango, Banana] .... 我的主要问题是我如何记住哪个与哪个进行比较。我想我对实现细节感到困惑。如果答案似乎很明显,我很抱歉,但我才刚刚开始。
  • 如果项目在列表中,您可以简单地循环遍历(i in 1:(N-1)),(j in (i+1):N)
【解决方案2】:

RecordLinkage 包中有levenshteinDist 函数,这是一种计算字符串之间编辑距离的方法。

install.packages("RecordLinkage")
library(RecordLinkage)

设置一些数据:

fruit <- c("Apple", "Apricot", "Avocado", "Banana", "Bilberry", "Blackberry", 
    "Blackcurrant", "Blueberry", "Currant", "Cherry")

现在创建一个由零组成的矩阵,为距离表保留内存。然后使用嵌套的for 循环来计算各个距离。我们以一个矩阵结束,每个水果都有一行和一列。因此我们可以将列和行重命名为与原始向量相同。

fdist <- matrix(rep(0, length(fruit)^2), ncol=length(fruit))
for(i in seq_along(fruit)){
  for(j in seq_along(fruit)){
    fdist[i, j] <- levenshteinDist(fruit[i], fruit[j])
  }
}
rownames(fdist) <- colnames(fdist) <- fruit

结果:

fdist

             Apple Apricot Avocado Banana Bilberry Blackberry Blackcurrant
Apple            0       5       6      6        7          9           12
Apricot          5       0       6      7        8         10           10
Avocado          6       6       0      6        8          9           10
Banana           6       7       6      0        7          8            8
Bilberry         7       8       8      7        0          4            9
Blackberry       9      10       9      8        4          0            5
Blackcurrant    12      10      10      8        9          5            0
Blueberry        8       9       9      8        3          3            8
Currant          7       5       6      5        8         10            6
Cherry           6       7       7      6        4          6           10

【讨论】:

  • 这正是我遇到的问题,我从来不知道 R 可以以这种方式处理字符串。我想我会找到一种将我的 perl 代码与 R 链接的方法。
  • 只需在 R 中完成所有操作。继续,你知道你想这样做!要将文件读入 R,请使用 read.table 或其快捷方式 read.csv
  • @Andrie 是正确的:您可以在 R 中完成所有这些工作,而且您可能会从中找到更多乐趣,因为您可以直接与数据进行交互。
  • @Andrie:你可以写成:fdist &lt;- outer(fruit,fruit,levenshteinDist),而不是双 for 循环
  • @Tommy 很好。是的当然。我对mapply 的文档进行了短暂的调侃,认为这不是这样做的方法,然后继续前进! outer 非常适合。
猜你喜欢
  • 2014-05-04
  • 2017-07-24
  • 2013-09-13
  • 1970-01-01
  • 2017-12-18
  • 2019-01-03
  • 2017-10-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多