Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Пособие по теории информации.doc / Пособие по теории информации.doc
Скачиваний:
415
Добавлен:
30.03.2015
Размер:
4.68 Mб
Скачать

Глава 8. Сжатие информации

Сжатие информации возможно при наличии избыточности в сообщении. Различают следующие виды избыточности.

Естественная избыточность связана с первичным алфавитом, а искусственная с вторичным алфавитом. Мысль, выраженная более кратко без потери информации, обуславливает семантическую избыточность. Статистическая избыточность обуславливается не равновероятностным распределением качественных признаков первичного алфавита и их взаимозависимостью.

Для сжатия информации широко используются про­граммыупаковщики (архиваторы). Наиболее популярными являются PKZIP/PKUNZIP, ARJ, ARC, LHARC, PAK, RAR, WINRAR, WINZIP и др. Сжатие данных применяется при резервном копировании, при хранении информации, а также при передаче в телекоммуникационных сетях. Сжатые данные будут передаваться быстрее по сети.

8.1. Основные понятия

В области сжатия информации используются следующие основные понятия и характеристики, с помощью которых можно оценить тот или иной метод сжатия.

1. Компрессор или кодер – программа, которая сжимает исходную информацию (преобразует входной несжатый файл в выходной сжатый файл). Программа, выполняющая обратное преобразование (восстановление информации), называется декомпрессором или декодером. Для объединения кодера и декодера иногда используется понятие кодек.

2. Метод неадаптивного сжатия – метод сжатия, в котором не предусмотрена возможность изменения операций, параметров и настроек в зависимости от характера сжимаемой информации. Метод, в котором предусмотрена возможность изменения операций, параметров и настроек в зависимости от сжимаемой информации, называется методом адаптивного сжатия. Если для изменения операций, параметров и настроек предварительно собирается некоторая статистика сжимаемой информации, то метод сжатия называется полуадаптивным (двухпроходное сжатие: на первом проходе выполняется анализ информации, а на втором – собственно сжатие). Метод сжатия называется локально адаптивным, если в нем предусмотрена возможность изменения параметров в зависимости от локальных особенностей входного файла.

3. Метод сжатия без потерь (метод неискажающего сжатия) позволяет восстановить сжатую информацию без искажений. Метод сжатия с потерями (метод искажающего сжатия) предусматривает искажение сжимаемой информации для получения требуемых характеристик сжатия.

4. Симметричный метод сжатия – это метод, при использовании которого кодер и декодер выполняют одни и те же действия, но в противоположных направлениях. Если либо кодер либо декодер выполняет существенно большую работу, то соответствующий метод сжатия называется асимметричным.

5. Коэффициент сжатия – величина, получающаяся в результате деления размера выходного (сжатого) файла на размер входного (несжатого) файла.

6. Фактор сжатия – величина, обратная коэффициенту сжатия.

8.2. Методы сжатия без потерь

Методы сжатия без потерь обычно используются в системах сжатия дискретной информации (текста), представляемой в виде последовательности символов некоторого алфавита.

Кодирование длин серий (RLE - кодирование). Методы RLE – кодирования (Run Length Encoding) являются одними из наиболее старых методов сжатия. Однако благодаря своей простоте и эффективности они до сих пор используются либо непосредственно, либо в составе других методов. При использовании простейшего метода RLE последовательность одинаковых символов заменяется на один символ и число его повторений.

Пример 8.1. Применить метод RLE для сжатия последовательности символов aaaaaaaaabbbbaaaaabbaaaaaabbbbaaaaaabbaaaacccccddd.

Решение. В результате сжатия получается следующая последовательность кодов: <a, 9>, <b, 4>, <a, 5>, <b, 2>, <a, 6>, <b, 4>, <a, 6>, <b, 2>, <a, 4>, <c, 5>, <d, 3>.

Если считать, что на каждый символ приходится 2 бита (используется четырехсимвольный алфавит), а на длину – 4 бита (длина не превышает 16), то входная и выходная последовательности имеют размеры:

Lвх = 50  2 = 100 бит и Lвых = 11  (2 + 4) = 66 бит.

Коэффициент сжатия Kсж при этом равен

Kсж = Lвых / Lвх = 66 / 100 = 0.66.

Недостатком данного метода является увеличение размеров информации (вместо сокращения) в том случае, если сжимаемая последовательность содержит большое число одиночных символов. Поэтому на практике используют различные модификации RLE – кодирования для устранения указанного недостатка.

Пример 8.2. Применить метод RLE для сжатия последовательности символов aaaaaaaaabbbbabababaaaacccccdaaaaa.

Решение. В простейшем случае на выходе будет образована последовательность кодов <a, 9>, <b, 4>, <a, 1>, <b, 1>, <a, 1>, <b, 1>, <a, 1>, <b, 1>, <a, 4>, <c, 5>, <d, 1> <a, 5>, которая имеет размер 12  (2 + 4) = 72 бита, тогда как исходная последовательность символов имеет размер 34  2 = 68 бит. Однако можно ввести бинарный флаг (размером в 1 бит), нулевое значение которого показывает, что далее следует одиночный символ, а единичное значение – символ и число его повторений. Тогда на выходе появится следующая последовательность кодов: <1, a, 9>, <1, b, 4>, <0, a>, <0, b>, <0, a>, <0, b>, <0, a>, <0, b>, <1, a, 4>, <1, c, 5>, <0, d>, <1, a, 5>, которая имеет размер 5  (1 + 2 + 4) + 7  (1 + 2) = 35 + 21 = 56 бит. Очевидно, что во втором случае сжатие более эффективно.

Коды Фибоначчи. Методы, основанные на использовании кодов Фибоначчи, относятся к группе методов кодирования представлением целых чисел. Применение кодов Фибоначчи основано на том, что любое натуральное число можно представить в виде двоичного числа, в котором вес каждой единицы соответствует некоторому числу Фибоначчи. При этом, во – первых, две подряд единицы в таком двоичном числе появиться не могут, а, во – вторых, номер разряда в числе соответствует только одному числу Фибоначчи.

Значения от 1 до 256 (размером в 1 байт) можно закодировать с помощью следующих чисел Фибоначчи: F1 = 1, F2 = 2, F3 = 3, F4 = 5, F5 = 8, F6 = 13, F7 = 21, F8 = 34, F9 = 55, F10 = 89, F11 = 144, F12 = 233.

Пример 8.3. Представить с помощью кодов Фибоначчи числа 1, 20, 150 и 255.

Решение.

1. Число 1 можно представить как число F1. Тогда оно имеет код Фибоначчи 11.

2. Число 20 можно представить как сумму чисел Фибоначчи:

20 = F6 + F4 + F2 = 13 + 5 + 2.

Это значит, что число 20 имеет код Фибоначчи 1101010.

3. Число 150 можно представить как сумму чисел Фибоначчи:

150 = F11 + F4 + F1.

Это значит, что число 150 имеет код Фибоначчи 110000001001.

4. Число 255 можно представить как сумму чисел Фибоначчи:

255 = F12 + F7 + F1.

Это значит, что число 255 имеет код Фибоначчи 1100001000001.

Сжать данные с помощью кодов Фибоначчи можно следующим образом:

  1. определить частоты каждого символа последовательности;

  2. отсортировать символы в порядке убывания частот;

  3. присвоить номерам символов соответствующие коды Фибоначчи.

В результате данного алгоритма чаще встречающимся символам будут присвоены более короткие коды, чем символам, встречающимся реже.

Пример 8.4. Выполнить сжатие с помощью кодов Фибоначчи последовательности символов ccccaaccccabcccbbcabcabcacccccdacc.

Решение.

  1. Определим частоты каждого символа в последовательности:

    Символ

    a

    b

    c

    d

    Частота

    7

    5

    1

    1

  2. Отсортируем символы в порядке убывания частот:

    Символ

    c

    a

    b

    d

    Частота

    21

    7

    5

    1

  3. Присвоим номерам символов соответствующие коды Фибоначчи:

Символ

c

a

b

d

Код

11

110

1100

11000

Если каждый символ исходной последовательности имеет длину 1 байт (8 бит), то длина исходной последовательности равна 272 бита, тогда как после сжатия длина последовательности кодов Фибоначчи равна

21  2 бита + 7  3 бита + 5  4 бита + 1  5 бит = 88 бит.

Коэффициент сжатия при этом равен 88 бит / 272 бита  0.32, т. е. на один бит исходной последовательности приходится в среднем 0.32 бита последовательности сжатых данных.

Методы энтропийного сжатия. Одним из наиболее часто используемых методов энтропийного сжатия относится метод Хаффмена:

  1. Определить список кодируемых символов и их частоты;

  2. отсортировать список символов по убыванию частот;

  3. если в списке только два символа, то перейти к п. 5, иначе – к п. 4.

  4. заменить два последних символа на один новый символ (составной символ), частота которого равна сумме их частот и перейти к п. 2;

  5. присвоить первому символу в списке код 0, а второму – код 1;

  6. найти первый от начала списка составной символ (см. п. 4) и заменить его на те два символа, из которых он был образован. При этом первому из восстановленных символов присвоить код составного символа с приписанным справа 0, а второму – код составного символа с приписанной справа 1;

  7. повторить п. 6 до тех пор пока не будет восстановлен исходный список символов, такой же как после выполнения п. 1.

Пример 8.5. Выполнить сжатие с помощью метода Хаффмена последовательности символов aacabcccbbcabcabcacccda.

Решение.

  1. Построить список символов исходной последовательности и их частот:

    Символ

    c

    a

    b

    d

    Частота

    10

    7

    5

    1

  2. Заменить символы b и d (два символа с наименьшими частотами) на символ s с частотой 6 (сумма частот символов b и d). Отсортировать полученный список символов:

    Символ

    c

    a

    s’

    Частота

    10

    7

    6

  3. Заменить символы a и s на символ s’’ с частотой 13. Отсортировать полученный список символов:

    Символ

    s’’

    c

    Частота

    13

    10

  4. Присвоить символу s’’ код 0, а символу c – код 1.

  5. Заменить символ s’’ на символы a и s. Присвоить символу a код 00, а символу s – код 01.

  6. Заменить символ s на символы b и d. Присвоить символу b код 010, а символу d – код 011.

Таким образом, получены следующие коды для символов исходной последовательности:

Символ

a

b

c

d

Код

0

10

1

11

Длина последовательности кодов равна

7  2 бита + 5  3 бита + 10  1 бит + 1  3 бита = 42 бита.

Если каждый символ исходной последовательности имеет длину 1 байт (8 бит), то длина исходной последовательности равна 23  8 бит = 184 бита, а коэффициент сжатия имеет значение 42 бит / 184 бита  0.228. Необходимо отметить, что энтропия исходной последовательности равна 1.72 бита. Эта величина близка средней длине кода, равной 1.82 бита. Именно поэтому метод Хаффмена относится к энтропийным методам сжатия.

На практике часто используется адаптивный вариант метода Хаффмена, при реализации которого частоты символов уточняются по мере сжатия. В отличие от первоначального алгоритма здесь требуется всего один проход по исходному файлу. Для этого вводится дополнительный символ ESC, который при декодировании показывает, что за ним следует несжатый символ. Символ ESC всегда имеет частоту 1 и размещается в конце списка. Приведем следующий алгоритм адаптивного сжатия по методу Хаффмена.

  1. Создать список, состоящий только из одного символа ESC с частотой 1.

  2. Прочитать символ последовательности. Если символ отсутствует в списке, то перейти к п. 3, иначе – к п. 4.

  3. Присвоить код символу ESC, выдать этот код, выдать прочитанный символ, добавить его в конец списка перед символом ESC с частотой 1 и перейти к п. 2.

  4. Присвоить код прочитанному символу, выдать этот код, увеличить на 1 частоту символа, переместить символ на место в списке, соответствующее новому значению частоты.

Пример 8.6. Выполнить сжатие последовательности символов abacab с помощью адаптивного варианта метода Хаффмена.

Решение.

  1. Создать список из одного символа ESC с частотой 1.

    Символ

    ESC

    Частота

    1

  2. Прочитать символ a. Так как этот символ отсутствует в списке, то выдать код символа ESC – 0 и символ a. Включить символ a в список с частотой 1 перед символом ESC.

Символ

a

ESC

Частота

1

1

  1. Прочитать символ b. Так как этот символ отсутствует в списке, то выдать код символа ESC – 1 и символ b. Включить символ b в список с частотой 1 перед символом ESC.

    Символ

    a

    b

    ESC

    Частота

    1

    1

    1

  2. Прочитать символ a. Этот символ имеется в списке, поэтому его можно закодировать как 1. Частота символа a увеличивается на 1.

Символ

a

b

ESC

Частота

2

1

1

  1. Прочитать символ c. Так как этот символ отсутствует в списке, то выдать код символа ESC – 11 и символ c. Включить символ c в список с частотой 1 перед символом ESC.

    Символ

    a

    b

    c

    ESC

    Частота

    2

    1

    1

    1

  2. Прочитать символ a. Этот символ имеется в списке, поэтому его можно закодировать как 1. Частота символа a увеличивается на 1.

    Символ

    a

    b

    c

    ESC

    Частота

    3

    1

    1

    1

  3. Прочитать символ b. Этот символ имеется в списке, поэтому его можно закодировать как 10. Частота символа b увеличивается на 1.

Символ

a

b

C

ESC

Частота

3

2

1

1

Таким образом, после выполнения сжатия получается последовательность кодов: 0 a 1 b 1 11 c 1 10.

Кроме метода Хаффмена к энтропийным методам относится также метод Шеннона – Фано. Однако в настоящее время он используется гораздо реже по сравнению с методом Хаффмена.

Метод арифметического сжатия. В настоящее время методы энтропийного сжатия вытесняются арифметическим методом. Данный метод основан на отображении последовательности символов в вещественное число из полуинтервала [0, 1). Рассмотрим арифметическое сжатие на примере.

Пример 8.7. Выполнить сжатие последовательности символов abacabс помощью метода арифметического сжатия.

Решение.

  1. Определить частоты символов и упорядочить их в порядке убывания частот:

    Символ

    a

    b

    c

    Частота

    3

    2

    1

  2. Разбить интервал от 0 до 1 на участки пропорционально частотам символов:

    Символ

    a

    b

    c

    Нижняя граница

    0

    0.5

    0.833

    Верхняя граница

    0.5

    0.833

    1

  3. Прочитать символ a. Определить интервал, соответствующий символу a, и разбить его на участки пропорционально частотам символов:

    Символ

    a

    b

    c

    Нижняя граница

    0

    0.25

    0.42

    Верхняя граница

    0.25

    0.42

    0.5

  4. Прочитать символ b. Определить интервал, соответствующий символу b, и разбить его на участки пропорционально частотам символов:

    Символ

    a

    b

    c

    Нижняя граница

    0.25

    0.335

    0.392

    Верхняя граница

    0.335

    0.392

    0.42

  5. Прочитать символ a. Определить интервал, соответствующий символу a, и разбить его на участки пропорционально частотам символов:

Символ

a

b

c

Нижняя граница

0.25

0.2925

0.32

Верхняя граница

0.2925

0.32

0.335

  1. Прочитать символ c. Определить интервал, соответствующий символу c, и разбить его на участки пропорционально частотам символов:

    Символ

    a

    b

    c

    Нижняя граница

    0.32

    0.3275

    0.3325

    Верхняя граница

    0.3275

    0.3325

    0.335

  2. Прочитать символ a. Определить интервал, соответствующий символу a, и разбить его на участки пропорционально частотам символов:

    Символ

    a

    b

    c

    Нижняя граница

    0.32

    0.32375

    0.32625

    Верхняя граница

    0.32375

    0.32625

    0.32375

  3. Прочитать символ b. Определить интервал, соответствующий символу b, и разбить его на участки пропорционально частотам символов:

    Символ

    a

    b

    c

    Нижняя граница

    0.32375

    0.325

    0.32583

    Верхняя граница

    0.325

    0.32583

    0.32625

  4. Выбрать любое число из диапазона [0.325, 0.32583), например 0.3255.

  5. Отбросив целую часть и дробную точку, получить число 3255.

  6. Выполнив перевод числа 3255 в двоичную систему счисления, получить код исходной последовательности: 110010110111.

Так же, как и для методов энтропийного сжатия, существуют адаптивные варианты арифметического метода. Однако вместо применения символа ESC в этом случае создают первоначальный список, содержащий все символы с частотами 1. Это позволяет закодировать любой символ входной последовательности.

Методы контекстного моделирования. При применении методов контекстного моделирования процесс сжатия символа условно разделяют на два этапа: этап моделирования и этап кодирования.

На этапе моделирования строят вероятностную контекстную модель. На этапе кодирования символу присваивают код в рамках текущей контекстной модели. Вероятностная контекстная модель n – го порядка – это список символов (и их частот), появившихся в контексте n – го порядка. Контекст n – го порядка – набор последовательных n символов.

Пример 8.8. Найти контексты 2 – го порядка для символов a, b, c последовательности abacab.

Решение.

  1. Для символа a можно указать два контекста 2 – го порядка: ab и ac.

  2. Для символа b можно указать один контекст 2 – го порядка: ca.

  3. Для символа c можно указать один контекст 2 – го порядка: ba.

При использовании методов контекстного моделирования вводят также контекстные модели 0 – го и (–1) – го порядков. Контекстная модель 0 – го порядка содержит частоты символов исходной последовательности, меняющиеся по мере выполнения сжатия. Контекстная модель (–1) – го порядка содержит одинаковые частоты (обычно равные 1) для всех возможных входных символов.

Алгоритм сжатия по методу контекстного моделирования заключается в следующем.

  1. Построить контекстные модели (–1) – го, 0 – го, 1 – го, …, Nmax – го порядков, где Nmax – максимальный порядок контекстной модели. В контекстной модели (–1) – го порядка частотам всех символов присвоить одинаковые значения. Ввести в рассмотрение во всех моделях 0 – го, 1 – го, …, Nmax – го порядков символ ESC с частотой 1. Установить в качестве текущего контекста произвольный контекст порядка от (–1) – го до Nmax – го.

  2. Прочитать символ входной последовательности.

  3. Если в текущей контекстной модели символ невозможно закодировать, то выдать код символа ESC, уменьшить на 1 порядок контекста и повторить п. 3, иначе – получить и выдать его код. Кодирование выполняется по методу энтропийного или арифметического сжатия.

  4. Увеличить на 1 частоту символа во всех контекстных моделях, связанных с текущим контекстом.

  5. Изменить текущий контекст в соотвествии с закодированным символом.

  6. Перейти к п. 2.

Пример 8.9. Сжать последовательность символов aba с помощью метода контекстного моделирования с максимальным порядком контекста Nmax=1.

Решение.

  1. Построить контекстные модели.

Контекстная модель (–1) – го порядка:

Символ

a

b

Частота

1

1

Контекстная модель 0 – го порядка:

Символ

a

b

ESC

Частота

0

0

1

Контекстные модели 1 – го порядка:

Контекст

a

b

Символ

a

b

ESC

a

b

ESC

Частота

0

0

1

0

0

1

Сделать текущим контекстом контекст (–1) – го порядка.

  1. Прочитать символ a. В текущем контексте этому символу можно присвоить по методу Хаффмена код 1.

  2. Изменить контекстные модели.

Контекстная модель (–1) – го порядка:

Символ

a

b

Частота

2

1

Контекстная модель 0 – го порядка:

Символ

a

b

ESC

Частота

1

0

1

Контекстные модели 1 – го порядка:

Контекст

a

b

Символ

a

b

ESC

a

b

ESC

Частота

0

0

1

0

0

1

Сделать текущим контекстом контекст 1 – го порядка: a.

  1. Прочитать символ b. В текущем контексте этот символ закодировать невозможно, поэтому выдать 0 – код символа ESC и перейти к контексту 0 –го порядка. Так как в данном контексте символ b также невозможно закодировать, то выдать 1 – код символа ESC и перейти к контексту (–1) – го порядка и выдать код 10.

  2. Изменить контекстные модели.

Контекстная модель (–1) – го порядка:

Символ

a

b

Частота

2

2

Контекстная модель 0 – го порядка:

Символ

a

b

ESC

Частота

1

1

1

Контекстные модели 1 – го порядка:

Контекст

a

b

Символ

a

b

ESC

a

b

ESC

Частота

0

1

1

0

0

1

Сделать текущим контекстом контекст 1 – го порядка: b.

  1. Прочитать символ a. В текущем контексте этот символ закодировать невозможно, поэтому выдать 0 – код символа ESC и перейти к контексту 0 –го порядка. В этом контексте символу a можно присвоить код 1.

  2. Изменить контекстные модели.

Контекстная модель (–1) – го порядка:

Символ

a

b

Частота

3

2

Контекстная модель 0 – го порядка:

Символ

a

b

ESC

Частота

2

1

1

Контекстные модели 1 – го порядка:

Контекст

a

b

Символ

a

b

ESC

a

b

ESC

Частота

0

1

1

1

0

1

Сделать текущим контекстом контекст 1 – го порядка: a.

Таким образом, выходная последовательность имеет вид: 1011001.

Словарные методы сжатия. Алгоритмы, использующие методы словарного сжатия, заменяют подстроки кодируемой последовательности символов ссылками в словарь на идентичные подстроки.

Рассмотрим метод LZ77, который является одним из наиболее распространенных словарных методов сжатия.

Выделить область памяти под буфер.

Выделить область памяти под словарь.

Заполнить буфер символами исходной последовательности

Определить максимальную часть буфера (L символов от начала буфера), совпадающих с частью словаря (L символов с позиции P в словаре).

Выдать тройку <L, P, S>, где S – (L + 1) – ый символ в буфере.

Переместить L + 1 символ из начала буфера (с удалением их в буфере) в конец словаря.

Переместить на освободившиеся позиции в начале буфера оставшиеся символы и дополнить его символами исходной последовательности.

Повторять пп. 4 – 7 до тех пор, пока буфер не станет пуст после выполнения п. 7.

Приведенный алгоритм является общим описанием метода. Его более конкретную реализацию рассмотрим на следующем примере.

Пример 6.10. Сжать методом LZ77 последовательность aaaabaabbb.

Решение.

Пусть буфер имеет длину 4 символа, а словарь – 8 символов.

  1. Выделить память под буфер и словарь.

Буфер: пуст, словарь: пуст, последовательность: aaaabaabbb.

  1. Заполнить буфер.

Буфер: aaaa, словарь: пуст, последовательность: baabbb.

  1. Найти максимальную часть буфера от его начала, совпадающую с частью словаря. Так как словарь пуст, то длина найденной части равна 0.

  2. Выдать тройку <0, 0, a>.

  3. Изменить буфер, словарь и последовательность.

Буфер: aaab, словарь: a, последовательность: aabbb.

  1. Найти максимальную часть буфера от его начала, совпадающую с частью словаря. Данная часть имеет длину 1.

  2. Выдать тройку <1, 1, a>.

  3. Изменить буфер, словарь и последовательность.

Буфер: abaa, словарь: aaa, последовательность: bbb.

  1. Найти максимальную часть буфера от его начала, совпадающую с частью словаря. Данная часть имеет длину 1.

  2. Выдать тройку <1, 1, b>.

  3. Изменить буфер, словарь и последовательность.

Буфер: aabb, словарь: aaaab, последовательность: b.

  1. Найти максимальную часть буфера от его начала, совпадающую с частью словаря. Данная часть имеет длину 3.

  2. Выдать тройку <3, 3, b>.

  3. Изменить буфер, словарь и последовательность.

Буфер: b, словарь: aaabaabb, последовательность: пуста.

  1. Найти максимальную часть буфера от его начала, совпадающую с частью словаря. Данная часть имеет длину 1.

  2. Выдать тройку <1, 4, U>, где U – признак отсутствия символа.

  3. Изменить буфер, словарь и последовательность.

Буфер: пуст, словарь: aabaabbb, последовательность: пуста.

  1. Так как буфер пуст, то процесс сжатия закончен.

Таким образом, на выходе получена последовательность троек:

<0, 0, a>, <1, 1, a>, <1, 1, b>, <3, 3, b>, <1, 4, U>.