web-dev-qa-db-ja.com

MATLABでヒストグラムを正規化する方法は?

確率密度関数の下の面積が1になるようにヒストグラムを正規化する方法は?

44
cMinor

これに対する私の答えは、あなたの 以前の質問 に対する答えと同じです。確率密度関数の場合、 空間全体の積分は1 です。合計で除算すると、notで正しい密度が得られます。適切な密度を得るには、面積で分割する必要があります。私のポイントを説明するために、次の例を試してください。

[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

どのメソッドが正しい答えに一致するかを自分で確認できます(赤い曲線)。

enter image description here

ヒストグラムを正規化する別の方法(方法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
120
abcd

2014b以降、Matlabにはhistogram関数にこれらのネイティブに埋め込まれた正規化ルーチンがあります(この関数が提供する6つのルーチンについては ヘルプファイル を参照してください)。 PDF正規化を使用した例を次に示します(すべてのビンの合計は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)

enter image description here

実際の質問と受け入れられた回答が成功したことによる改善の可能性が非常に高い!


編集-histhistcの使用は 非推奨 となり、代わりにhistogramを使用する必要があります。この新しい関数でビンを作成する6つの方法のいずれも、ビンhistおよびhistcを生成しないことに注意してください。 histogramが呼び出される方法に合わせて以前のコードを更新するMatlabスクリプトがあります(ビンの中心ではなくビンのエッジ- link )。そうすることで、pdf正規化方法を比較 @abcd(trapzおよびsum)とMatlab(pdf)を比較できます。

つのpdf正規化方法では、ほぼ同じ結果が得られます(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)

enter image description here

新しいPDF正規化と前の正規化の最大の違いは5.5511e-17です。

23
marsei

histはヒストグラムをプロットするだけでなく、各ビンの要素数を返すため、各ビンを合計で除算し、barを使用して結果をプロットすることでカウントを取得して正規化できます。例:

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

または、ワンライナーが必要な場合:

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

ドキュメンテーション:

Edit:このソリューションは質問に答えますすべてのビンの合計を1に等しくする方法。この近似は、ビンのサイズがデータの分散に比べて小さい場合にのみ有効です。ここで使用される合計は、単純な直交公式に対応します。より複雑なものは、Rが提案するtrapzのように使用できます。 M。

11
Simon
[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
Moppi

AbcdのPDFの領域は1ではなく、多くのコメントで指摘されているように不可能です。ここで多くの回答で行われた仮定

  1. 連続するエッジ間の距離が一定であると仮定します。
  2. pdfでの確率は1である必要があります。正規化は、histogram()およびhist(で、Normalizationprobabilityとしてではなく、Normalizationpdfとして実行する必要があります。 )。

図1 hist()アプローチの出力、図2 histogram()アプローチの出力

enter image description hereenter image description here

Histogram()のアプローチは標準の正規化を使用するため、hist()のアプローチには何らかの誤りがあることを提案する2つのアプローチ間で最大振幅が異なります。ここでのhist()のアプローチの間違いは、完全にpdfとしてではなく、部分的にprobabilityとしての正規化に関するものだと思います。

Hist()を使用したコード[非推奨]

いくつかの発言

  1. 最初のチェック:sum(f)/Nは、Nbinsが手動で設定されている場合、1を返します。
  2. pdfでは、グラフのビンの幅(dx)が必要ですg

コード

%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 if Nbins if histogram() 's Normalization as potential、b)Nbinsが手動の場合sum(f)/Nは1正規化せずに設定します。
  2. pdfでは、グラフのビンの幅(dx)が必要ですg

コード

%%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

一部のディストリビューションでは、trapzが面積を過大評価することがわかったため、選択したビンの数に応じてpdfが変化します。その場合、私はします

[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')
1
user1240280

MATLABのヒストグラム調整壊れた元のリンクarchive.orgリンク )の優れた3部ガイドがあり、最初の部分はヒストグラムにありますストレッチ。

1
anna