ファイルのエントロピーを計算する方法は? (または単にバイトの塊を言ってみましょう)
アイデアはありますが、数学的に正しいかどうかはわかりません。
私のアイデアは次のとおりです。
さて、今私は立ち往生しています。すべての結果が0.0と1.0の間にあるような方法でカウンター結果を「投影」する方法は?しかし、とにかくアイデアは一貫していないと思います...
誰かがより良い、よりシンプルなソリューションを持っていることを望みますか?
注:ファイルの内容を推測するには、すべてが必要です。
(プレーンテキスト、マークアップ、圧縮またはバイナリ、...)
- 最後に:配列の「平均」値を計算します。
- カウンタをゼロで初期化し、配列の各エントリに対して:エントリの差を「平均」にカウンタに追加します。
someを変更すると、シャノンのエントロピーを取得できます。
「平均」の名前を「エントロピー」に変更
(float) entropy = 0
for i in the array[256]:Counts do
(float)p = Counts[i] / filesize
if (p > 0) entropy = entropy - p*lg(p) // lgN is the logarithm with base 2
編集: Wesleyが述べたように、エントロピーを8で除算して範囲を調整する必要があります。。1(または、対数の基数256を使用できます) 。
より簡単なソリューション:ファイルをgzipします。ファイルサイズの比率を使用します:(gzipのサイズ)/(オリジナルのサイズ)ランダム性(つまりエントロピー)の尺度として。
この方法では、エントロピーの正確な絶対値は得られません(gzipは「理想的な」コンプレッサーではないため)が、異なるソースのエントロピーを比較する必要がある場合には十分です。
バイトのコレクションの情報エントロピーを計算するには、tydokの答えに似た何かをする必要があります。 (tydokの答えはビットのコレクションで機能します。)
次の変数はすでに存在すると想定されています。
byte_counts
は、ファイル内の各値を持つバイト数の256要素のリストです。たとえば、byte_counts[2]
は、2
という値を持つバイト数です。
total
は、ファイルの合計バイト数です。
Pythonで次のコードを記述しますが、何が起こっているかは明らかです。
import math
entropy = 0
for count in byte_counts:
# If no bytes of this value were seen in the value, it doesn't affect
# the entropy of the file.
if count == 0:
continue
# p is the probability of seeing this byte in the file, as a floating-
# point number
p = 1.0 * count / total
entropy -= p * math.log(p, 256)
注意すべき重要な点がいくつかあります。
count == 0
のチェックは、単なる最適化ではありません。 count == 0
の場合、p == 0
、およびlog(p)は未定義(「負の無限大」)になり、エラーが発生します。 。
256
の呼び出しのmath.log
は、可能な離散値の数を表します。 8ビットで構成されるバイトには、256の可能な値があります。
結果の値は、0(ファイル内のすべての単一バイトが同じ)から1(バイトは、バイトのすべての可能な値に均等に分割されます)の間です。
対数ベース256の使用に関する説明
通常、このアルゴリズムは対数2を使用して適用されます。これにより、結果がビット単位で返されます。このような場合、任意のファイルに対して最大8ビットのエントロピーがあります。自分で試してください:byte_counts
をすべての1
または2
または100
のリストにすることにより、入力のエントロピーを最大化します。ファイルのバイトが均等に分散されると、8ビットのエントロピーがあることがわかります。
他の対数ベースを使用することもできます。 b= 2を使用すると、各ビットが2つの値を持つことができるため、ビット単位の結果が許可されます。 b= 10を使用すると、結果はditsまたは10進ビットになります。各ditには10の可能な値があるためです。 b= 256を使用すると、各バイトが256個の離散値のいずれかを持つことができるため、結果がバイト単位で得られます。
興味深いことに、ログIDを使用して、結果のエントロピーをユニット間で変換する方法を見つけることができます。ビット単位で得られた結果は、8で除算することでバイト単位に変換できます。興味深い、意図的な副作用として、これはエントロピーを0〜1の値として与えます。
要約すれば:
それが価値があるものについては、C#で表された伝統的な(エントロピーのビット)計算があります
/// <summary>
/// returns bits of entropy represented in a given string, per
/// http://en.wikipedia.org/wiki/Entropy_(information_theory)
/// </summary>
public static double ShannonEntropy(string s)
{
var map = new Dictionary<char, int>();
foreach (char c in s)
{
if (!map.ContainsKey(c))
map.Add(c, 1);
else
map[c] += 1;
}
double result = 0.0;
int len = s.Length;
foreach (var item in map)
{
var frequency = (double)item.Value / len;
result -= frequency * (Math.Log(frequency) / Math.Log(2));
}
return result;
}
これはent
が処理できるものですか? (または、おそらくあなたのプラットフォームでは利用できません。)
$ dd if=/dev/urandom of=file bs=1024 count=10
$ ent file
Entropy = 7.983185 bits per byte.
...
反例として、ここにエントロピーのないファイルがあります。
$ dd if=/dev/zero of=file bs=1024 count=10
$ ent file
Entropy = 0.000000 bits per byte.
...
私は回答に2年遅れているので、少数の賛成票にもかかわらず、これを考慮してください。
簡単な答え:ファイルの「エントロピー」をビット単位で言うとき、ほとんどの人が考えていることを得るために、以下の1番目と3番目の太字の方程式を使用してください。シャノンのHエントロピーが必要な場合は、最初の方程式を使用します。これは、ほとんどの人が気付いていない論文で13回述べているように、実際にはエントロピー/シンボルです。一部のオンラインエントロピー計算機はこれを使用しますが、シャノンのHは「特定のエントロピー」であり、「総エントロピー」であり、非常に混乱しています。正規化されたエントロピー/シンボルである0と1の間の答えが必要な場合は、1番目と2番目の方程式を使用します(ビット/シンボルではなく、データに独自の対数ベースを選択させることによるデータの「エントロピー性」の真の統計的尺度2、e、または10)を任意に割り当てる代わりに。
4種類のエントロピー N個のシンボルのファイル(データ)で、n個のユニークなタイプのシンボルがあります。ただし、ファイルの内容を知ることで、ファイルの状態がわかるため、S = 0になることに注意してください。正確には、アクセスできる大量のデータを生成するソースがある場合、そのソースの予想される将来のエントロピー/特性を計算できます。ファイルで次を使用する場合、そのソースからの他のファイルの予想されるエントロピーを推定していると言う方が正確です。
最後のものは真の「エントロピー」ですが、最初のもの(シャノンエントロピーH)は、すべての本が(必要なIMHO)資格なしで「エントロピー」と呼ぶものです。ほとんどは、それがビット/シンボルまたはシンボルごとのエントロピーであることを明らかにしません(シャノンがしたように)。 Hを「エントロピー」と呼ぶのはあまりにも緩やかです。
各シンボルの周波数が等しいファイルの場合:S = N * H =N。これは、ほとんどの大きなビットのファイルの場合です。エントロピーはデータの圧縮を行わないため、パターンを完全に無視します。したがって、000000111111は010111101000と同じHとSを持ちます(両方のケースで6 1と6 0)。
他の人が言ったように、gzipのような標準の圧縮ルーチンを使用して前後に分割すると、ファイル内の既存の「順序」の量をより正確に測定できますが、圧縮スキームに適したデータに偏っています。絶対的な「順序」を定義するために使用できる、完全に最適化された汎用コンプレッサーはありません。
考慮すべきもう1つの点は、データの表現方法を変更するとHが変化することです。ビットの異なるグループ(ビット、ニブル、バイト、または16進数)を選択すると、Hは異なります。したがって、log(n)で除算します。ここで、nはデータ内の一意のシンボルの数(バイナリの場合は2、バイトの場合は256)であり、Hは0から1の範囲です(これは正規化された集中シャノンエントロピーです)シンボルごとのエントロピーの単位で)。しかし、技術的には、256種類のバイトのうち100種類しか発生しない場合、256ではなくn = 100です。
Hは「集中的な」エントロピーです。つまり、物理学ではkgごとまたはモルごとのエントロピーである比エントロピーに類似したシンボルごとのエントロピーです。物理学のSに類似したファイルの通常の「広範な」エントロピーはS = N * Hです。ここで[〜#〜] n [〜#〜]はファイル内のシンボルの数です。 Hは、理想的なガス量の一部に正確に類似しています。情報エントロピーは、物理的なエントロピーにより「秩序化」および無秩序な配置が可能になるため、単に深い意味で物理的なエントロピーと正確に等しくすることはできません。物理的なエントロピーは、完全にランダムなエントロピー(圧縮ファイルなど)よりも多くなります。異なる側面の1つの側面理想的なガスの場合、これを説明する追加の5/2係数があります。S= k * N *(H + 5/2)ここで、H =分子あたりの可能な量子状態=(xp)^ 3/hbar * 2 * sigma ^ 2ここで、x =ボックスの幅、p =システム内の全方向性運動量の合計(運動エネルギーと分子あたりの質量から計算)、およびsigma = 0.341 1 std dev内の可能な状態。
少し計算すると、ファイルの正規化された拡張エントロピーの短い形式が得られます。
S = N * H/log(n)= sum(count_i * log(N/count_i))/ log(n)
この単位は「エントロピー」です(実際には単位ではありません)。これは、N * Hの「エントロピー」単位よりも優れた普遍的な尺度になるように正規化されます。しかし、通常の歴史的慣習では、Hシャノンのテキストで行われた説明)。
ファイルのエントロピーなどはありません。情報理論では、エントロピーはランダム変数の関数であり、固定データセットの関数ではありません(技術的には、固定データセットにはエントロピーがありますが、そのエントロピーは0になります)確率1)の可能な結果を1つだけ持つランダム分布としてのデータ。
エントロピーを計算するには、ファイルをモデル化するランダム変数が必要です。エントロピーは、そのランダム変数の分布のエントロピーになります。このエントロピーは、そのランダム変数に含まれる情報のビット数に等しくなります。
情報理論のエントロピーを使用する場合、バイトでは使用しない方が理にかなっているかもしれないことに注意してください。データがフロートで構成されている場合、代わりにそれらのフロートに確率分布を当てはめ、その分布のエントロピーを計算する必要があります。
または、ファイルの内容がユニコード文字である場合、それらを使用する必要があります。
Re:ファイルの内容を推測するためにすべてが必要です:(プレーンテキスト、マークアップ、圧縮またはバイナリ、...)
他の人が指摘しているように(または混乱/混乱している)、あなたは実際にメトリックエントロピー(メッセージの長さで割ったエントロピー)について話していると思います。 エントロピー(情報理論)-ウィキペディア で詳細を参照してください。
エントロピー異常のスキャンデータ にリンクするジッターのコメントは、根本的な目標に非常に関連しています。最終的に libdisorder(バイトエントロピーを測定するためのCライブラリ) にリンクします。このアプローチは、ファイルのさまざまな部分でメトリックエントロピーがどのように変化するかを示すため、より多くの情報を扱うように思えます。例参照4 MBのjpg画像(y軸)からの256連続バイトのブロックのエントロピーが、異なるオフセット(x軸)に対してどのように変化するかのこのグラフ。エントロピーは最初と最後で途中まで低下しますが、ほとんどのファイルで約7ビット/バイトです。
ソース: https://github.com/cyphunk/entropy_examples 。 [このグラフや他のグラフは、小説 http://nonwhiteheterosexualmalelicense.org license ....)から入手できます。
より興味深いのは、分析と同様のグラフです FAT形式のディスクのバイトエントロピーの分析| GL.IB.LY
ファイル全体および/またはファイルの最初と最後のブロックのメトリックエントロピーの最大、最小、モード、標準偏差などの統計は、署名として非常に役立ちます。
この本も関連しているようです: 電子メールとデータセキュリティのためのファイルマスカレードの検出と認識-Springer
サイズが「長さ」の符号なし文字の文字列のエントロピーを計算します。これは基本的に http://rosettacode.org/wiki/Entropy にあるコードのリファクタリングです。これを、重複なしで平均エントロピー3.9の100000000 IVのコンテナーを作成する64ビットIVジェネレーターに使用します。 http://www.quantifiedtechnologies.com/Programming.html
#include <string>
#include <map>
#include <algorithm>
#include <cmath>
typedef unsigned char uint8;
double Calculate(uint8 * input, int length)
{
std::map<char, int> frequencies;
for (int i = 0; i < length; ++i)
frequencies[input[i]] ++;
double infocontent = 0;
for (std::pair<char, int> p : frequencies)
{
double freq = static_cast<double>(p.second) / length;
infocontent += freq * log2(freq);
}
infocontent *= -1;
return infocontent;
}