Як обчислити ентропію файлу?


74

Як обчислити ентропію файлу? (Або скажімо просто купу байтів)
У мене є ідея, але я не впевнений, що це математично правильно.

Моя ідея полягає в наступному:

  • Створіть масив з 256 цілих чисел (усі нулі).
  • Пройдіть по файлу та для кожного з його байт
    збільште відповідну позицію в масиві.
  • В кінці: Обчисліть "середнє" значення для масиву.
  • Ініціалізуйте лічильник нулем,
    і для кожного з записів масиву:
    додайте різницю запису до "середнього" до лічильника.

Ну, тепер я застряг. Як "спроектувати" результат лічильника таким чином, щоб усі результати лежали між 0,0 і 1,0? Але я впевнений, ідея все одно суперечлива ...

Сподіваюся, хтось має кращі та простіші рішення?

Примітка: Мені потрібно все це, щоб зробити припущення щодо вмісту файлу:
(відкритий текст, розмітка, стислий або якийсь двійковий файл, ...)



1
Ви маєте на увазі метричну ентропію? ентропія, поділена на довжину повідомлення
user2622016

Ой, ця примітка, яку ви додали: Note: I need the whole thing to make assumptions on the file's contents: (plaintext, markup, compressed or some binary, ...)... Ви щойно попросили богоподібної магії, удачі в розробці доказово оптимального стиснення даних.
MickLH

Чи можете ви опублікувати, будь ласка, псевдокод остаточного результату?
Гай Калон,

Відповіді:


51
  • В кінці: Обчисліть "середнє" значення для масиву.
  • Ініціалізуйте лічильник нулем, і для кожного з записів масиву: додайте різницю запису до "середнього" до лічильника.

З деякими модифікаціями ви можете отримати ентропію Шеннона:

перейменувати "середнє" в "ентропія"

(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

Редагувати: Як згадував Веслі, ми повинні розділити ентропію на 8, щоб відрегулювати її в діапазоні 0. . 1 (або в якості альтернативи ми можемо використовувати логарифмічну основу 256).


2
Одна корекція: вам потрібно пропустити елементи з Counts [i] == 0.
Ігор Кривокон

Ви маєте рацію Кривоконе, дякую! Я бачу, що Веслі зробив це правильно, за винятком того, що він обрав "дивну" базу логарифмів.
Нік Дандулакіс,

3
Так, це точно дивно. Однак, оскільки ви використовуєте більш звичну основу журналу 2, ви отримуєте значення від 0 до 8. Можливо, ви захочете згадати це, щоб запитувач пам’ятав розділити результат на 8, щоб отримати значення від 0 до 1. (Хоча вітаю із швидкою відповіддю - мені довелося шукати ці матеріали у Вікіпедії, щоб запам'ятати їх.: P)
Уеслі

Це хороший метод, я використовував його для аналізу "ентропії" зображення, порівнюючи піксельні дані, і це дало хороші результати.
Метт Уоррен,

4
Ця оцінка ентропії передбачає, що байти є незалежними, що в цілому є помилковим. Наприклад, візьміть зображення у градаціях сірого з рівномірним горизонтальним градієнтом від білого до чорного.
leonbloy

34

Більш просте рішення: gzip файл. Використовуйте співвідношення розмірів файлів: (розмір згенованого) / (розмір оригіналу) як міра випадковості (тобто ентропія).

Цей метод не дає точного абсолютного значення ентропії (оскільки gzip не є "ідеальним" компресором), але він досить хороший, якщо вам потрібно порівняти ентропію різних джерел.


1
У мене також була така ідея (як останній варіант), але мені потрібно проаналізувати велику кількість файлів, тому сжатування ВСІХ їх не є ефективним варіантом.
ivan_ivanovich_ivanoff

3
Це залежить від того, наскільки величезними є ваші ВСІ. Я просто спробував зібрати всі файли в / usr / bin, це приблизно 1000 файлів, 200 Мб. Це зайняло близько 7 сек. Це команда, яку ви колись можете використати, щоб отримати розмір: cat * | gzip - швидко | wc -c. Це повільніше, ніж просто читання файлів за байтами, але не набагато.
Ігор Кривокон

gzip мав багато людських років програмних зусиль, що значно оптимізував. Можна також скористатися цим.
Носредна

3
Це насправді може бути кращою оцінкою ентропії, ніж оцінки прийнятої відповіді, особливо якщо файл великий.
leonbloy

2
Я згоден, що це краща оцінка ніж прийнята відповідь. Насправді існує кілька наукових робіт, які використовують цей тип наближення.
Уго Серено Феррейра

33

Щоб обчислити інформаційну ентропію набору байтів, вам потрібно буде зробити щось подібне до відповіді 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і журнал ( стор ) буде невизначеним ("негативна нескінченність"), що спричинить помилку.

  • 256У виклику math.logявляє собою число дискретних значень, які можливі. Байт, що складається з восьми бітів, матиме 256 можливих значень.

Отримане значення буде від 0 (кожен окремий байт у файлі однаковий) до 1 (байти рівномірно розподіляються між усіма можливими значеннями байта).


Пояснення щодо використання журналу 256

Це правда, що цей алгоритм зазвичай застосовується з використанням журналу бази 2. Це дає отриману відповідь у бітах. У такому випадку у вас є максимум 8 біт ентропії для будь-якого даного файлу. Спробуйте самі: максимізуйте ентропію введення, склавши byte_countsсписок усіх 1або 2або 100. Коли байти файлу розподіляються рівномірно, ви виявите, що існує ентропія у 8 бітів.

Можливе використання інших основ логарифму. Використання b = 2 дозволяє отримати результат у бітах, оскільки кожен біт може мати 2 значення. Використання B = 10 поміщає результат в дітах або десяткових розрядах, так як існує 10 можливих значень для кожного DIT. Використання b = 256 дасть результат у байтах, оскільки кожен байт може мати одне з 256 дискретних значень.

Цікаво, що, використовуючи ідентифікатори журналу, ви можете розробити спосіб перетворення отриманої ентропії між одиницями. Будь-який результат, отриманий в одиницях бітів, може бути перетворений в одиниці байтів шляхом ділення на 8. Як цікавий, навмисний побічний ефект, це дає ентропію як значення від 0 до 1.

Підсумовуючи:

  • Ви можете використовувати різні одиниці для вираження ентропії
  • Більшість людей виражають ентропію бітами ( b = 2)
    • Для колекції байтів це дає максимальну ентропію 8 біт
    • Оскільки запитувач хоче отримати результат від 0 до 1, розділіть цей результат на 8 для значущого значення
  • Алгоритм, наведений вище, обчислює ентропію в байтах ( b = 256)
    • Це еквівалентно (ентропія в бітах) / 8
    • Це вже дає значення від 0 до 1

Дякую за коментар ... о, куди це поділося? У будь-якому випадку, я згоден, що використання "частоти байтів" трохи заплутане. Цей термін було вилучено.
Уеслі

+1 зараз. Я погоджуюсь з вашими коментарями та модифікаціями, особливо важливим роз'ясненням, що цей підхід надає ентропію в байтах, тоді як звичайне значення - у бітах, хоча байти більше відповідають тому, що просив ОП. (Вибачте за видалення раніше. Я вирішив, що не хочу брати участь у цьому, і сподівався, що видалив свій коментар, перш ніж хтось його побачив.)
tom10

Це не ентропія, це передбачає, що байти не є незалежними. Дивіться мій коментар до відповіді Ніка
leonbloy

20

Для чого це варте, ось традиційне (біти ентропії) обчислення, представлене на 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;
}

Це фантастична відповідь. Щоб розширити вихідне питання, як би ви обчислили його, якби відповіді були відносними, а не абсолютними? Наприклад, припустимо, ви шукали географічну ентропію; рекламна кампанія працює на національному рівні, і ви фіксуєте географічні координати респондентів. Жодні два записи, ймовірно, не матимуть однакових координат, але якась функція ентропії все одно повинна мати змогу повідомити вам, що, ймовірно, буде кілька локалізованих гарячих точок, або що загальний національний розподіл буде більш ефективним.
Paul Smith

1
Чи не повинно бути перевірки нульових значень у map? Інакше Math.Log(frequency)може повернутися -INF.
страти

(Math.Log (частота) / Math.Log (2)) == Math.Log (частота, 2)
citykid

16

Це щось, з чим 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.
...

1
Дякую! Добре знати цей інструмент. Але мені потрібно вирішити це програмно і незалежно від платформи, звідси і моє запитання.
ivan_ivanovich_ivanoff

1
+1 Дякую за вказівник. Це існує , по крайней мере в Debian: packages.debian.org/wheezy/ent
tripleee

14

Я запізнився з відповідями на два роки, тож, будь ласка, розгляньте це, незважаючи на лише кілька голосів за.

Коротка відповідь: використовуйте моє 1-е та 3-е напівжирне рівняння нижче, щоб отримати те, про що думає більшість людей, коли вони кажуть "ентропія" файлу бітами. Використовуйте лише 1-е рівняння, якщо ви хочете ентропію H Шеннона, яка насправді є ентропією / символом, як він 13 разів зазначив у своїй роботі, чого більшість людей не знають. Деякі калькулятори ентропії в Інтернеті використовують цей, але Н Шеннона - це "специфічна ентропія", а не "повна ентропія", що викликало стільки плутанини. Використовуйте 1-е та 2-е рівняння, якщо ви хочете, щоб відповідь від 0 до 1 була нормалізованою ентропією / символом (це не біти / символ, а справжній статистичний показник "ентропійного характеру" даних, дозволяючи даним вибирати власну базу журналів замість довільного присвоєння 2, e або 10).

Існує 4 типи ентропії файлів (даних) із N символів довжиною з n унікальними типами символів. Але майте на увазі, що, знаючи вміст файлу, ви знаєте стан, в якому він перебуває, а отже S = 0. Якщо бути точним, якщо у вас є джерело, яке генерує багато даних, до яких ви маєте доступ, тоді ви можете розрахувати очікувану майбутню ентропію / характер цього джерела. Якщо ви використовуєте наступне у файлі, точніше сказати, що він оцінює очікувану ентропію інших файлів із цього джерела.

  • Ентропія Шеннона (конкретна) H = -1 * сума (count_i / N * log (count_i / N)),
    де count_i - це кількість разів, коли я зазнав символ у N.
    Одиниці виміру - це біти / символ, якщо журнал - база 2, nats / символ якщо натуральний журнал.
  • Нормалізована специфічна ентропія: H / log (n)
    Одиниці виміру є ентропією / символом. Діапазони від 0 до 1. 1 означає, що кожен символ зустрічався однаково часто, а біля 0 - всі символи, крім 1, траплялися лише один раз, а решта дуже довгого файлу була іншим символом. Журнал знаходиться в тій же основі, що і H.
  • Абсолютна ентропія S = N * H
    Одиниці - це біти, якщо log - основа 2, nats - якщо ln ()).
  • Нормалізована абсолютна ентропія S = N * H / log (n)
    Одиниця виміру "ентропія", варіюється від 0 до N. Журнал знаходиться в тій же основі, що і H.

Хоча остання є найправдивішою "ентропією", перша (ентропія Шеннона H) - це те, що всі книги називають "ентропією" без (необхідної кваліфікації IMHO). Більшість не уточнює (як це зробив Шеннон), що це біти / символ або ентропія на символ. Називання Н "ентропією" говорить занадто розкуто.

Для файлів з однаковою частотою кожного символу: S = N * H = N. Це стосується більшості великих файлів бітів. Ентропія не здійснює жодного стиснення даних і, таким чином, повністю не знає жодних шаблонів, тому 000000111111 має ті самі H і S, що і 010111101000 (6 1 і 6 0 в обох випадках).

Як сказали інші, використання стандартної процедури стиснення, як gzip та ділення до і після, дасть кращий показник кількості вже існуючого "замовлення" у файлі, але це упереджено щодо даних, які краще відповідають схемі стиснення. Не існує ідеально оптимізованого компресора загального призначення, який ми можемо використовувати для визначення абсолютного "замовлення".

Ще одне, що слід врахувати: H змінюється, якщо ви змінюєте спосіб вираження даних. H буде іншим, якщо ви виберете різні групи бітів (біти, пересічки, байти або шістнадцяткові символи). Отже, ви ділитесь на log (n), де n - кількість унікальних символів у даних (2 для двійкових, 256 для байтів), а H коливатиметься від 0 до 1 (це нормована інтенсивна ентропія Шеннона в одиницях ентропії на символ) . Але технічно, якщо з 256 типів байтів трапляється лише 100, то n = 100, а не 256.

H - це "інтенсивна" ентропія, тобто вона є символом, що є аналогом специфічної ентропії у фізиці, яка є ентропією на кг або на моль. Регулярною "великою" ентропією файлу, аналогічного фізичному S, є S = N * H, де N- кількість символів у файлі. H був би точно аналогічний частині ідеального об'єму газу. Інформаційна ентропія не може бути просто рівною фізичній ентропії в більш глибокому розумінні, оскільки фізична ентропія допускає "впорядковані", а також невпорядковані механізми: фізична ентропія виходить більше, ніж повністю випадкова ентропія (наприклад, стислий файл). Один аспект різного Для ідеального газу існує додатковий коефіцієнт 5/2, щоб врахувати це: S = k * N * (H + 5/2), де H = можливі квантові стани на молекулу = (xp) ^ 3 / hbar * 2 * сигма ^ 2 де x = ширина коробки, p = загальний неспрямований імпульс в системі (розрахований з кінетичної енергії та маси на молекулу) і сигма = 0,341 відповідно до принципу невизначеності, що дає лише кількість можливі стани в межах 1-ї розробки

Трохи математики дає коротший вигляд нормалізованої великої ентропії для файлу:

S = N * H / log (n) = сума (count_i * log (N / count_i)) / log (n)

Одиницями цього є "ентропія" (що насправді не є одиницею). Він нормований як кращий універсальний показник, ніж одиниці "ентропії" N * H. Але його також не слід називати "ентропією" без роз'яснень, оскільки звичайною історичною конвенцією є помилково називати H "ентропією" (що суперечить уточнення, зроблені в тексті Шеннона).


Я хочу підтримати вашу відповідь, але є певна неясність, яку ви повинні спершу прояснити: у рівняннях 2 та 4 і там, де ви говорите: "Отже, ви ділитесь на log (n), де n - кількість унікальних символів у даних", журнал що з n? Вхід натуральний, log2 (n)? Як правило, в математиці, без вказаної бази, log (n) означає log10 (n). Будь ласка, поясніть.
Адам Вайт

Я згадував у рівняннях 1 та 3, користувач вибирає базу. Для рівнянь 2 і 4 це має бути та сама основа (в якій був Н). Додам роз’яснення.
zawy

10

Не існує такого поняття, як ентропія файлу. У теорії інформації ентропія є функцією випадкової величини , а не фіксованого набору даних (ну, технічно фіксований набір даних має ентропію, але ця ентропія буде рівна 0 - ми можемо розглядати дані як випадковий розподіл, який має лише один можливий результат з імовірністю 1).

Для того, щоб обчислити ентропію, вам потрібна випадкова величина, за допомогою якої можна змоделювати ваш файл. Тоді ентропія буде ентропією розподілу цієї випадкової величини. Ця ентропія дорівнюватиме кількості бітів інформації, що міститься у цій випадковій величині.


4
Я не знаю теоретичного визначення ентропії. Але для кожного терміна завжди існує дві семантики: теоретична та популярна. Ну, схоже, популярну частину всі тут зрозуміли;)
ivan_ivanovich_ivanoff

1
У відповідях є принаймні дві очевидні інтерпретації того, як хтось може перекласти "ентропію файлу" у суворе математичне визначення. Якщо ви дійсно хочете зрозуміти, що ви робите, ви повинні розуміти статистичний спосіб моделювання ентропії у цих відповідях.
Джеймс Томпсон,

1
Або ви можете потрапити в складність Колмогорова, яка є кращим математичним визначенням, але є незрозумілою.
Джеффрі Хантін,

@JamesThompson цікаво, будь-які вказівки на те, як ви хочете вивести цю випадкову величину з купи файлів, для яких ви хочете виміряти ентропію?
Владтн

4
Я вважаю, що у цій проблемі випадковою величиною є байти, які знайдені у файлі шляхом його проходження. Отже, це буде дискретна випадкова величина з 256 можливими значеннями та власним розподілом, який залежить від файлу. (Я знаю, що цей пост старий, але це може пояснити кожного, хто сюди потрапляє)
Anoyz

5

Якщо ви використовуєте ентропію теорії інформації, пам’ятайте, що може мати сенс не використовувати її на байтах. Скажімо, якщо ваші дані складаються з плаваючих значень, то натомість вам слід підігнати розподіл ймовірності до цих плаваючих і обчислити ентропію цього розподілу.

Або, якщо вміст файлу - символи унікоду, ви повинні використовувати їх тощо.


Коли я хочу зробити аналіз даних для будь-якого типу файлів, я вважаю, що найкращим вибором буде байт (як компроміс).
ivan_ivanovich_ivanoff

1
Звичайно, ви можете це зробити. Однак слід використовувати будь-яку додаткову інформацію, яку ви можете отримати. Інакше ваші результати можуть бути вкрай поганими.
bayer

зазвичайнекорисний абсолютно прав. Ентропія Шеннона не надасть вам достатньо інформації про вміст файлу. Кожен компресор має два етапи: моделювання та ентропійне кодування. Кодування ентропії необхідне, але більша частина надмірності виявляється на фазі моделювання (якщо ви не робите з квазівипадковими даними).
Ігор Кривокон

зазвичайнекорисний тут. Один із способів зрозуміти це - сказати словами всю річ, яку ви обчислюєте: "що таке ентропія символів ascii, які я використовую для представлення моїх чисел із плаваючою комою", це річ, яку ви можете розрахувати може бути не тим, на що ви прагнете.
tom10

1
Це коментар, а не відповідь.
JasonMArcher

2

Обчислює ентропію будь-якого рядка непідписаних символів розміром "довжина". Це, в основному, рефакторинг коду, знайденого за адресою http://rosettacode.org/wiki/Entropy . Я використовую це для 64-розрядного IV генератора, який створює контейнер 100000000 IV без обману та середньої ентропії 3,9. 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;
 }

2

Re: Мені потрібно все це, щоб зробити припущення щодо вмісту файлу: (відкритий текст, розмітка, стислий або якийсь двійковий файл, ...)

Як зазначали інші (або їх бентежило / відволікало), я думаю, ви насправді говорите про метричну ентропію (ентропія, поділена на довжину повідомлення). Див. Більше в Ентропії (теорія інформації) - Вікіпедія .

коментар джиттера, що посилається на Сканування даних на предмет аномалій ентропії , дуже відповідає вашій цілі. Зрештою це посилається на libdisorder (бібліотека C для вимірювання ентропії байтів) . Здається, такий підхід дає вам набагато більше інформації, з якою можна працювати, оскільки він показує, як метрична ентропія змінюється в різних частинах файлу. Див., Наприклад, цей графік того, як змінюється ентропія блоку з 256 послідовних байтів із jpg-зображення розміром 4 МБ (вісь y) для різних зсувів (вісь x). На початку та в кінці ентропія нижча, оскільки вона є частковою, але вона становить близько 7 бітів на байт для більшої частини файлу.

введіть тут опис зображення Джерело: https://github.com/cyphunk/entropy_examples . [ Зверніть увагу, що цей та інші графіки доступні через нову ліцензію http://nonwhiteheterosexualmalelicense.org .... ]

Більш цікавим є аналіз та подібні графіки при аналізі байтової ентропії форматованого FAT диска | GL.IB.LY

Такі статистичні дані, як максимальне, мінімальне, режим та стандартне відхилення метричної ентропії для цілого файлу та / або першого та останнього блоків, можуть бути дуже корисними як підпис.

Ця книга також видається актуальною: Виявлення та розпізнавання файлів, що маскуються для захисту електронної пошти та даних - Springer


-2

Без будь-якої додаткової інформації ентропія файлу (за визначенням) дорівнює його розміру * 8 біт. Ентропія текстового файлу становить приблизно розмір * 6,6 біт, враховуючи, що:

  • кожен персонаж однаково ймовірний
  • в байті 95 символів для друку
  • log (95) / log (2) = 6.6

Ентропія текстового файлу англійською мовою, за оцінками, становить приблизно від 0,6 до 1,3 біта на символ (як пояснено тут ).

Взагалі ви не можете говорити про ентропію даного файлу. Ентропія - властивість набору файлів .

Якщо вам потрібна ентропія (або точніше ентропія на байт), найкращий спосіб - стиснути її за допомогою gzip, bz2, rar або будь-якого іншого сильного стиснення, а потім розділити стислий розмір на нестиснений розмір. Це було б чудовою оцінкою ентропії.

Розрахунок байта ентропії за байтом, як запропонував Нік Дандулакіс, дає дуже погану оцінку, оскільки передбачає, що кожен байт є незалежним. Наприклад, у текстових файлах набагато вірогідніше мати маленьку літеру після букви, ніж пробіли чи розділові знаки після букви, оскільки слова, як правило, довші за 2 символи. Тож ймовірність того, що наступний символ опиниться в діапазоні az, корелюється зі значенням попереднього символу. Не використовуйте грубу оцінку Ніка для будь-яких реальних даних, натомість використовуйте коефіцієнт стиснення gzip.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.