【问题标题】:How to normalize a histogram in MATLAB?如何在 MATLAB 中对直方图进行归一化?
【发布时间】:2011-07-16 07:04:21
【问题描述】:

如何对一个直方图进行归一化,使得概率密度函数下的面积等于1?

【问题讨论】:

    标签: matlab histogram normalization


    【解决方案1】:

    我对此的回答与您对earlier question 的回答相同。对于概率密度函数,the integral over the entire space is 1。除以总和将不会为您提供正确的密度。要获得正确的密度,您必须除以面积。为了说明我的观点,请尝试以下示例。

    [f, x] = hist(randn(10000, 1), 50); % Create histogram from a normal distribution.
    g = 1 / sqrt(2 * pi) * exp(-0.5 * x .^ 2); % pdf of the normal distribution
    
    % METHOD 1: DIVIDE BY SUM
    figure(1)
    bar(x, f / sum(f)); hold on
    plot(x, g, 'r'); hold off
    
    % METHOD 2: DIVIDE BY AREA
    figure(2)
    bar(x, f / trapz(x, f)); hold on
    plot(x, g, 'r'); hold off
    

    您可以自己查看哪种方法与正确答案一致(红色曲线)。

    另一种对直方图进行归一化的方法(比方法 2 更直接)是除以 sum(f * dx),它表示概率密度函数的积分,即

    % METHOD 3: DIVIDE BY AREA USING sum()
    figure(3)
    dx = diff(x(1:2))
    bar(x, f / sum(f * dx)); hold on
    plot(x, g, 'r'); hold off
    

    【讨论】:

    • “除以面积图”的总和不等于 1。我看到至少 10 个大于 0.3 的条形图点。 0.3*10 = 3.0 将 f 除以样本数不是更简单的解决方案吗?在这种情况下,10000。
    • @Rich 条形比 1 细,所以你的计算是错误的。考虑从 (-2,0) 到 (0, 0.4) 到 (2, 0) 的曲线下的三角形来估计面积。这个三角形的面积为 0.5*4*0.4 = 0.8
    • 要使总和等于 1,您需要将新的 bin 总和乘以 bin 的宽度
    • @abcd:但是这篇文章说,我们可以除以总和进行归一化:itl.nist.gov/div898/handbook/eda/section3/histogra.htm
    • 如何使用 histcounts 而不是 hist?
    【解决方案2】:

    自 2014b 以来,Matlab 在 histogram 函数中嵌入了这些规范化例程(请参阅help file,了解此函数提供的 6 个例程)。这是一个使用 PDF 归一化 的示例(所有 bin 的总和为 1)。

    data = 2*randn(5000,1) + 5;             % generate normal random (m=5, std=2)
    h = histogram(data,'Normalization','pdf')   % PDF normalization
    

    对应的PDF是

    Nbins = h.NumBins;
    edges = h.BinEdges; 
    x = zeros(1,Nbins);
    for counter=1:Nbins
        midPointShift = abs(edges(counter)-edges(counter+1))/2;
        x(counter) = edges(counter)+midPointShift;
    end
    
    mu = mean(data);
    sigma = std(data);
    
    f = exp(-(x-mu).^2./(2*sigma^2))./(sigma*sqrt(2*pi));
    

    两者加起来

    hold on;
    plot(x,f,'LineWidth',1.5)
    

    这很可能是由于实际问题的成功和接受的答案!


    编辑 - histhistc 现在是 not recommended,应该使用 histogram。请注意,使用此新功能创建垃圾箱的 6 种方法都不会产生垃圾箱 histhistc 产生。有一个 Matlab 脚本可以更新以前的代码以适应 histogram 的调用方式(bin 边缘而不是 bin 中心 - link)。通过这样做,可以比较@abcd(trapzsum)和Matlab(pdf)的pdf 归一化方法

    3pdf 归一化方法给出几乎相同的结果(在eps 的范围内)

    测试:

    A = randn(10000,1);
    centers = -6:0.5:6;
    d = diff(centers)/2;
    edges = [centers(1)-d(1), centers(1:end-1)+d, centers(end)+d(end)];
    edges(2:end) = edges(2:end)+eps(edges(2:end));
    
    figure;
    subplot(2,2,1);
    hist(A,centers);
    title('HIST not normalized');
    
    subplot(2,2,2);
    h = histogram(A,edges);
    title('HISTOGRAM not normalized');
    
    subplot(2,2,3)
    [counts, centers] = hist(A,centers); %get the count with hist
    bar(centers,counts/trapz(centers,counts))
    title('HIST with PDF normalization');
    
    
    subplot(2,2,4)
    h = histogram(A,edges,'Normalization','pdf')
    title('HISTOGRAM with PDF normalization');
    
    dx = diff(centers(1:2))
    normalization_difference_trapz = abs(counts/trapz(centers,counts) - h.Values);
    normalization_difference_sum = abs(counts/sum(counts*dx) - h.Values);
    
    max(normalization_difference_trapz)
    max(normalization_difference_sum)
    

    新的 PDF 规范化与之前的最大差异为 5.5511e-17。

    【讨论】:

    • PDF 下的区域在您的直方图中不是一个,这在概率论中是不可能的。请参阅答案 stackoverflow.com/a/38813376/54964,其中进行了一些更正。要匹配pdf 下的区域一,您应该将规范化设置为probability,而不是pdf
    【解决方案3】:

    hist 不仅可以绘制直方图,还可以返回每个 bin 中元素的计数,因此您可以获得该计数,通过将每个 bin 除以总数并使用bar 绘制结果来对其进行归一化。示例:

    Y = rand(10,1);
    C = hist(Y);
    C = C ./ sum(C);
    bar(C)
    

    或者如果您想要单线:

    bar(hist(Y) ./ sum(hist(Y)))
    

    文档:

    编辑:此解决方案回答了问题如何使所有 bin 的总和等于 1。仅当您的 bin 大小相对于数据的方差较小时,此近似值才有效。这里使用的和对应于一个简单的求积公式,更复杂的可以使用如 R 提出的trapz。 M.

    【讨论】:

      【解决方案4】:
      [f,x]=hist(data)
      

      每个条形的面积是高度*宽度。由于 MATLAB 会为条形选择等距点,所以宽度为:

      delta_x = x(2) - x(1)
      

      现在,如果我们将所有单独的条形图相加,总面积将为

      A=sum(f)*delta_x
      

      所以正确缩放的图是通过

      bar(x, f/sum(f)/(x(2)-x(1)))
      

      【讨论】:

        【解决方案5】:

        abcd 的 PDF 的面积不是一个,这是不可能的,就像许多 cmets 指出的那样。 这里的许多答案都做了假设

        1. 假设连续边之间的距离恒定。
        2. pdf 下的概率应为 1。在 histogram() 和 hist() 中,标准化应作为 Normalizationprobability,而不是 Normalizationpdf

        图。 1 hist() 方法的输出,图 2 histogram() 方法的输出

        两种方法的最大振幅不同,这表明 hist() 的方法存在一些错误,因为 histogram() 的方法使用标准归一化。 我认为 hist() 方法的错误在于部分归一化为pdf,而不是完全为probability

        带有 hist() 的代码 [已弃用]

        一些说明

        1. 第一次检查:sum(f)/N 如果手动设置了Nbins,则给出1
        2. pdf需要图表g中bin的宽度(dx

        代码

        %http://stackoverflow.com/a/5321546/54964
        N=10000;
        Nbins=50;
        [f,x]=hist(randn(N,1),Nbins); % create histogram from ND
        
        %METHOD 4: Count Densities, not Sums!
        figure(3)
        dx=diff(x(1:2)); % width of bin
        g=1/sqrt(2*pi)*exp(-0.5*x.^2) .* dx; % pdf of ND with dx
        % 1.0000
        bar(x, f/sum(f));hold on
        plot(x,g,'r');hold off
        

        输出如图1。

        带有 histogram() 的代码

        一些说明

        1. 第一次检查:a) sum(f)1,如果 Nbins 使用 histogram() 的归一化作为概率进行调整,b) 如果 Nbins 是手动设置而没有归一化,sum(f)/N 是 1。
        2. pdf需要图表g中bin的宽度(dx

        代码

        %%METHOD 5: with histogram()
        % http://stackoverflow.com/a/38809232/54964
        N=10000;
        
        figure(4);
        h = histogram(randn(N,1), 'Normalization', 'probability') % hist() deprecated!
        Nbins=h.NumBins;
        edges=h.BinEdges; 
        x=zeros(1,Nbins);
        f=h.Values;
        for counter=1:Nbins
            midPointShift=abs(edges(counter)-edges(counter+1))/2; % same constant for all
            x(counter)=edges(counter)+midPointShift;
        end
        dx=diff(x(1:2)); % constast for all
        g=1/sqrt(2*pi)*exp(-0.5*x.^2) .* dx; % pdf of ND
        % Use if Nbins manually set
        %new_area=sum(f)/N % diff of consecutive edges constant
        % Use if histogarm() Normalization probability
        new_area=sum(f)
        % 1.0000
        % No bar() needed here with histogram() Normalization probability
        hold on;
        plot(x,g,'r');hold off
        

        图 2 中的输出并满足预期输出:区域 1.0000。

        Matlab:2016a
        系统:Linux Ubuntu 16.04 64 位
        Linux 内核 4.6

        【讨论】:

        • 我很困惑,为什么MATLAB documentation 说使用pdf 而不是probability 使条形区域总和为一?当您使用 sum(h.values) 时,您不只是对 bin 高度而不是 bin 区域求和吗?
        • 我和 OP 有同样的问题,让我感到困惑的是,您所说的与 MATLAB 文档完全相反。请检查mathworks.com/help/matlab/ref/… 它明确表示使用pdf 使条形区域总和为1,而不是probability。此外,您正在使用sum(f) 其中f=h.Values 显示该区域是一个。 h.Values 对应于 bin 高度,因此根据 probability 归一化的定义,其总和为 1,但与条形区域不同。
        • "Code with histogram()":如果将 randn(N,1) 乘以某个常数,红线将不再匹配数据。
        • 我正在使用@marsei 答案。当我的直方图不是“非常”正常时,我正在使用拟合样条到 h.Value。
        • 对于非正态:[curve, goodness, output] = fit(x(:),h.Values(:),'smoothingspline','SmoothingParam',0.9999999); lPlot = plot(x(:),curve(x));.正常情况下,只需查看@marsei 的答案。
        【解决方案6】:

        对于某些分布,Cauchy 我认为,我发现 trapz 会高估该区域,因此 pdf 会根据您选择的 bin 数量而变化。在这种情况下我会这样做

        [N,h]=hist(q_f./theta,30000); % there Is a large range but most of the bins will be empty
        plot(h,N/(sum(N)*mean(diff(h))),'+r')
        

        【讨论】:

        • 嗨! mean(diff(h)) 的数量是否应该是 bin 的宽度?
        【解决方案7】:

        Histogram Adjustments in MATLAB (broken original link, archive.org link) 有一个很好的三部分指南, 第一部分是直方图拉伸。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-06-08
          • 1970-01-01
          • 2018-03-27
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多