N维直方图计数

时间:2011-07-29 17:11:19

标签: matlab

我目前正在尝试编写一个函数,使用直方图计数将概率分配给一组向量。这基本上是一项计算练习,但需要一些技巧才能有效地实现。我将举例说明:

假设我有一个带有X = [x1, x2....xM]行和N列的矩阵M。这里,X代表MN维向量的集合。换句话说,X的每列都是N维向量。

例如,我们可以使用以下内容为X向量和M = 10000维度生成N = 5这样的内容:

X = randint(5,10000)

这将生成一个0 x 10000和0s的矩阵,其中每列代表一个1和0的5维向量。

我想通过基本直方图计数为每个这些向量分配概率。步骤很简单:首先找到X的唯一列;第二,计算每个唯一列出现的次数。特定事件发生的概率是此列在X中的次数/ X中的总列数。

回到上面的例子,我可以使用MATLAB中的unique函数执行第一步,如下所示:

UniqueXs = unique(X','rows')' 

上面的代码将返回UniqueXs,这是一个N行的矩阵,只包含X的唯一列。请注意,转置是由于奇怪的MATLAB输入要求。

但是,我无法找到一个很好的方法来计算UniqueX中的每个列在X中的次数。所以我想知道是否有人有任何建议?

从广义上讲,我可以想到两种实现计数步骤的方法。第一种方法是使用find函数,但我认为这可能很慢,因为find是元素操作。第二种方法是递归调用unique,因为它还可以提供X中唯一列的一个的索引。这应该允许我们从结果X上的unique和重做X中删除该列并继续计数。

理想情况下,我认为unique可能已经在进行一些计数,因此最有效的方法可能是在没有内置函数的情况下工作。

1 个答案:

答案 0 :(得分:1)

这里有两个解决方案,一个假设所有值都是0或1(就像你的描述中的例子),另一个则没有。两个代码都应该非常快(更具有二进制值的代码),即使在大数据上也是如此。

1)只有零和一个

%# random vectors of 0's and 1's
x = randi([0 1], [5 10000]);    %# RANDINT is deprecated, use RANDI instead

%# convert each column to a binary string
str = num2str(x', repmat('%d',[1 size(x,1)])); %'

%# convert binary representation to decimal number
num = (str-'0') * (2.^(size(s,2)-1:-1:0))';    %'# num = bin2dec(str);

%# count frequency of how many each number occurs
count = accumarray(num+1,1);                   %# num+1 since it starts at zero

%# assign probability based on count
prob = count(num+1)./sum(count);

2)任何正整数

%# random vectors with values 0:MAX_NUM
x = randi([0 999], [5 10000]);

%# format vectors as strings (zero-filled to a constant length)
nDigits = ceil(log10( max(x(:)) ));
frmt = repmat(['%0' num2str(nDigits) 'd'], [1 size(x,1)]);
str = cellstr(num2str(x',frmt));               %'

%# find unique strings, and convert them to group indices
[G,GN] = grp2idx(str);

%# count frequency of occurrence
count = accumarray(G,1);

%# assign probability based on count
prob = count(G)./sum(count);

现在我们可以看到例如每个“唯一向量”发生了多少次:

>> table = sortrows([GN num2cell(count)])
table = 
    '000064850843749'    [1]       # original vector is: [0 64 850 843 749]
    '000130170550598'    [1]       # and so on..
    '000181606710020'    [1]
    '000220492735249'    [1]
    '000275871573376'    [1]
    '000525617682120'    [1]
    '000572482660558'    [1]
    '000601910301952'    [1]
    ...

请注意,在我的随机数据示例中,向量空间变得非常稀疏(当你增加最大可能值时),因此如果所有计数都等于1,我不会感到惊讶...