Цель работы - создание программы, реализующей искусственную нейронную сеть; разработка процедуры обучения сети; использование полученных результатов для решения тестовых задач сжатия данных, классификации и аппроксимации.
Модели различных типов искусственных нейронных сетей и методы их обучения описаны в учебном пособии "Искусственные нейронные сети". В теоретической части данного пособия в качестве примера рассматривается простейшая двухслойная сеть с линейными функциями активации, используемая для решения задачи сжатия данных с потерями.
Пусть дано прямоугольное изображение, каждый пиксел которого характеризуется своей яркостью. Изображение разбивается на p прямоугольных кадров размером Nh x Nv каждый. Кадр сжимается в вектор данных размерностью L (L<Nh*Nv), который затем восстанавливается (например, после хранения или передачи по медленным каналам связи) в кадр того же размера Nh x Nv.
Решение этой задачи возможно с использованием сети, структурная схема которой представлена ниже.
Здесь xkj, j=1,2, ..., N, N=Nh*Nv - значение яркости j-ого пикселя в k-ом кадре, k=1, 2, ..., p.
Сжатие (компрессия) данных осуществляется первым слоем нейронов, а восстановление (декомпрессия) - выходным. Сеть является автоассоциативной, поскольку ее выходной вектор Hk должен совпадать с входным Xk.
Веса первого слоя нейронов в матричной форме обозначаются W(1), а выходного слоя - W(2). Вследствие линейности функций активации и однонаправленности распространения сигналов имеем:
Обучение сети, состоящее в оптимальном подборе весов, составляющих матрицы W(1) и W(2), подразумевает минимизацию целевой функции в виде:
Для отыскания минимума этой целевой функции будем использовать метод обратного распространения ошибки в режиме онлайн. В рамках данного метода уточнение весовых коэффициентов производится формулой метода градиента:
Частные производные целевой функции по весам нейронов выходного слоя имеют следующий вид:
С учетом линейности функций активации выходного слоя нейронов f(u(2)i) выражения для частных производных упрощаются:
Компоненты вектора градиента для весов первого слоя нейронов определяются более сложно:
Опять линейность функций активации и для первого слоя нейронов позволяет упростить выражения до следующего вида:
Для отладки программы, реализующей нейронную сеть, воспользуемся фотографией "Экзамен", представленной ниже.
Из данной цветной фотографии получим образ в формате png в градациях серого размером 256x256 пикселей, как это показано ниже.
Для манипулирования данными, составляющими изображение в формате png, наибольшее распространение получили средства прикладных библиотек libgd (http://www.boutell.com/gd) и libpng (http://www.libpng.org). В данном учебном пособии используются функции библиотеки libpng, в Приложении приведен пример программы, осуществляющей считывание изображения из png-файла, модификацию этого изображения и его запись в выходной png-файл.
Ниже представлены результаты работы нейронной сети для различных значений параметров Nh, Nv и L (во всех случаях использовался единственный цикл обучения).
1. Лабораторная работа выполняется в среде ОС Linux с использованием компилятора gcc/g++ языка программирования C/C++. Для создания графических иллюстраций рекомендуется использовать утилиту gnuplot.
2. Разработать, используя язык C/C++, программу, моделирующую поведение искусственной нейронной сети указанного преподавателем типа и обеспечивающую ее обучение для решения задач сжатия данных с потерями, классификации и аппроксимации. Ниже представлена таблица вариантов заданий.
Номер варианта | Тип нейронной сети | Назначение сети |
---|---|---|
1 | Двухслойная сеть с линейными функциями активации | Сжатие изображения |
2 | Сеть с самоорганизацией на основе конкуренции | Сжатие изображения |
3 | Сеть с самоорганизацией на основе конкуренции | Классификация данных по алгоритму Кохонена |
4 | Сеть с самоорганизацией на основе конкуренции | Классификация данных по алгоритму нейронного газа |
5 | Многослойный персептрон (бинарные функции активации) | Аппроксимация данных |
6 | Многослойный персептрон (сигмоидальные функции активации) | Аппроксимация данных |
7 | Радиальная нейронная сеть | Аппроксимация данных |
3. Отладить модель нейронной сети и процедуру ее обучения на произвольных данных. В заданиях, связанных с обработкой изображений, необходимо подготовить, используя любой растровый графический редактор (например, gimp) несколько изображений в градациях серого (глубина - 8 бит) в формате png с размерами кратными 16. В задачах классификации для отладки можно воспользоваться вариантами распределения данных из лабораторной работы "Программирование искусственного нейрона".
4. Обучить разработанную нейронную сеть на предложенном преподавателем варианте данных и проверить ее работоспособность.
5. Выполнить все модификации в программе и исходных данных, указанные преподавателем.
6. Оформить отчет по лабораторной работе с использованием языка разметки HTML (все иллюстрации должны быть представлены в формате png).
1. Описание реализованной модели нейронной сети и процедуры ее обучения.
2. Описание (графическое или табличное) обучающих данных.
3. Численные значения, характеризующие начальное состояние, ход обучения и его результат (например, начальные и итоговые значения входных весов нейронов, величина коэффициента обучения, количество циклов обучения и т.п.).
4. Графическое представление результатов обучения нейрона.
5. Исходный текст программы.
Здесь приведен текст программы на языке C, иллюстрирующей использование прикладной библиотеки libpng для манипулирования файлами в формате png. Программа считывает входной png-файл, содержащий изображение в градациях серого с глубиной 8 бит, "инвертирует" яркость каждого пикселя и записывает полученное изображение в выходной png-файл.
/* Команда компиляции и компоновки: gcc -o pngexam pngexam.c -lpng -lz -lm */ #include <stdlib.h> #include <stdio.h> #include <png.h> #define PNG_BYTES_TO_CHECK 4 int main (int argc, char *argv[]) { png_structp png_read_ptr; png_infop info_read_ptr; png_structp png_write_ptr; png_infop info_write_ptr; png_uint_32 width, height; int bit_depth, color_type, interlace_type; int compression_type, filter_method; int row, col; png_bytep *row_pointers; char sigBuf[PNG_BYTES_TO_CHECK]; FILE *fpIn; FILE *fpOut; fpIn = stdin; if (argc > 1) { if ((fpIn = fopen(argv[1], "r")) == NULL) { perror (argv[1]); exit (1); }; }; if (fread(sigBuf, 1, PNG_BYTES_TO_CHECK, fpIn) != PNG_BYTES_TO_CHECK) { fclose (fpIn); exit (2); }; /* Проверка первых PNG_BYTES_TO_CHECK байт заголовка png-файла */ if ( png_sig_cmp(sigBuf, (png_size_t)0, PNG_BYTES_TO_CHECK) ) { fclose (fpIn); exit (3); }; png_read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_read_ptr == NULL) { fclose(fpIn); exit (2); }; info_read_ptr = png_create_info_struct(png_read_ptr); if (info_read_ptr == NULL) { fclose(fpIn); png_destroy_read_struct(&png_read_ptr, png_infopp_NULL, png_infopp_NULL); exit (3); }; if ( setjmp( png_jmpbuf(png_read_ptr) ) ) { /* Переход в эту точку означает возникновение ошибки при чтении png-файла */ /* Освободить память, ассоциированную с png_read_ptr и info_read_ptr */ png_destroy_read_struct(&png_read_ptr, &info_read_ptr, png_infopp_NULL); fclose(fpIn); exit (4); }; png_init_io(png_read_ptr, fpIn); /* Информировать о том, что PNG_BYTES_TO_CHECK байт уже прочитано */ png_set_sig_bytes(png_read_ptr, PNG_BYTES_TO_CHECK); png_read_png(png_read_ptr, info_read_ptr, PNG_TRANSFORM_IDENTITY, png_voidp_NULL); fclose(fpIn); png_get_IHDR(png_read_ptr, info_read_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_method); printf ("Ширина = %d, высота = %d\n", width, height); printf ("Тип цвета = %d, глубина цвета = %d\n", color_type, bit_depth); printf ("Количество байт в строке = %d\n", png_get_rowbytes(png_read_ptr, info_read_ptr)); if (color_type != 0) { fprintf (stderr, "Не умею работать с типом цвета %d (только 0)\n", color_type); exit (11); }; if (bit_depth != 8) { fprintf (stderr, "Не умею работать с глубиной цвета %d (только 8)\n", bit_depth); exit (11); }; row_pointers = png_get_rows (png_read_ptr, info_read_ptr); /*--- Получение негатива исходного изображения ---*/ for (row = 0; row < height; row++) { for (col = 0; col < width; col++) { row_pointers[row][col] ^= 0xFF; }; }; /*------ Запись png-файла -----*/ fpOut = stdout; if (argc > 2) { if ((fpOut = fopen(argv[2], "w")) == NULL) { perror (argv[2]); exit (5); }; }; png_write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_write_ptr == NULL) { fclose(fpOut); exit (6); }; info_write_ptr = png_create_info_struct(png_write_ptr); if (info_write_ptr == NULL) { fclose(fpOut); png_destroy_write_struct(&png_write_ptr, png_infopp_NULL); exit (7); }; if ( setjmp (png_jmpbuf(png_write_ptr) ) ) { fclose(fpOut); png_destroy_write_struct(&png_write_ptr, &info_write_ptr); exit (8); }; png_set_IHDR(png_write_ptr, info_write_ptr, width, height, bit_depth, color_type, interlace_type, compression_type, filter_method); png_set_rows (png_write_ptr, info_write_ptr, row_pointers); png_init_io(png_write_ptr, fpOut); png_write_png(png_write_ptr, info_write_ptr, PNG_TRANSFORM_IDENTITY, png_voidp_NULL); png_destroy_read_struct(&png_read_ptr, &info_read_ptr, png_infopp_NULL); fclose(fpOut); exit (0); }