Как сделать симметричную матрицу c

Обновлено: 07.07.2024

Для школьного проекта из функций, которые просят построить симметричную матрицу с использованием случайного числа в [1100], я знаю, как построить матрицу и как это сделать с помощью функции rand() в C, однако я не могу сделать симметричную, это мой код:

Он строит квадратную матрицу в соответствии с запросом, но она не симметрична.

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

3 ответа

Мне нужно создать симметричную матрицу 100*100, которая имеет случайное распределение нулей и единиц, но диагональ должна быть полностью нулевой, как я могу это сделать?

У меня есть данные матричного вида, хранящиеся в файле CSV, и они выглядят так, Я хочу, чтобы эта матрица 6 * 6 была симметричной матрицей, как это, Как использовать python (или matlab) для изменения матрицы n на n (квадратная матрица) на симметричную матрицу? или есть другие инструменты , которые.

  • off-by-one ошибка в размере матрицы: доступ будет отправлен не в то место
  • вы перезаписываете все столбцы во всех строках, вместо того чтобы заполнять только треугольник

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

Матрица , которую вы используете , имеет размер size-1 x size-1 , поэтому, если size=5 , то матрица, которую вы выделяете, имеет размер 4x4 , поэтому у вас фактически есть только 16 элементов в вашей матрице. (И вам действительно нужно 25 элементов).

Но при обходе матрицы для ее заполнения вы получаете доступ к индексу типа [4,4] , что означает, что ваша матрица должна (логически) иметь 25 элементов. (Но это не так).

Таким образом, есть два способа избавиться от этой ошибки:

  • Вы можете изменить свой цикл for на for(int i=0;i , чтобы избежать неожиданного доступа к элементам.
  • Вы можете увеличить размер массива до size x size вместо size-1 x size-1 .

Окончательный код будет выглядеть примерно так (я публикую только основную часть):

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

Я думаю, что ваше намерение задать этот вопрос состоит в том, чтобы учиться и становиться лучше, поэтому я подробно ответил с некоторыми дополнительными комментариями. Я надеюсь, что это было полезно. :)

есть ли простой способ создать разреженную симметричную случайную матрицу в Julia? Julia имеет команду sprand(m,n,d) который создает [разреженную] m-by-n случайную матрицу (плотности d) с IID ненулевыми элементами, равномерно распределенными на полуоткрытом интервале [0,1) [0,1). Но, насколько я.

Я могу легко преобразовать симметричную матрицу в матрицу array/1-d одной из ее треугольных составляющих, используя A_symmetric = np.matrix([[1,2][2,3]]) A_array = A_symmetric[np.triu_indices(2)] == np.matrix([1,2,3]) (и аналогично с tril_indices ) Но как я могу обратить эти операции вспять, то.

Похожие вопросы:

Я хочу создать симметричную матрицу со сложными элементами в Matlab с помощью команды toeplitz. Однако если я предоставляю команде теплица сложные записи, она возвращает Эрмитову матрицу, то есть.

Как лучше всего хранить симметричную матрицу в памяти? Было бы хорошо сэкономить половину пространства, не слишком снижая скорость и сложность конструкции. Это вопрос, не зависящий от языка, но если.

Я хочу использовать hclust для кластеризации данных. Но я не хочу использовать dist() для создания объекта dist. Затем я обнаружил, что не могу передать симметричную матрицу в качестве матрицы.

Мне нужно создать симметричную матрицу 100*100, которая имеет случайное распределение нулей и единиц, но диагональ должна быть полностью нулевой, как я могу это сделать?

У меня есть данные матричного вида, хранящиеся в файле CSV, и они выглядят так, Я хочу, чтобы эта матрица 6 * 6 была симметричной матрицей, как это, Как использовать python (или matlab) для.

есть ли простой способ создать разреженную симметричную случайную матрицу в Julia? Julia имеет команду sprand(m,n,d) который создает [разреженную] m-by-n случайную матрицу (плотности d) с IID.

Я могу легко преобразовать симметричную матрицу в матрицу array/1-d одной из ее треугольных составляющих, используя A_symmetric = np.matrix([[1,2][2,3]]) A_array = A_symmetric[np.triu_indices(2)] ==.

Я хочу построить симметричную матрицу с помощью. r=np.arange(0,11) k=np.zeros((11,11)) for i in r: k[i]=np.arange(i,i-11,-1) Как избавиться от for loop, чтобы построить матрицу более эффективно?

У меня есть dataframe, который выглядит как тот, что ниже ID | Value 1 | A 1 | B 1 | C 2 | B 2 | C Я хочу создать симметричную матрицу на основе значения: A B C A 1 1 1 B 1 2 2 C 1 2 2 Это в.

У меня есть список ребер со значениями подобия, которые мне нужно транспонировать в симметричную матрицу. Например, мои необработанные данные находятся во фрейме данных с таким форматом: example.

Часто в задачах нужно ввести числа или другие данные в двумерный массив (матрицу) и иметь возможность их обрабатывать.

Содержание

Поиск на других ресурсах:

Условие задачи

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

Также есть возможность сохранения результирующей матрицы в текстовом файле “ Res_Matrix.txt ”.

Выполнение

1. Запуск Microsoft Visual Studio . Создание проекта

Подробный пример запуска Microsoft Visual Studio и создания приложения по шаблону Windows Forms Application описывается в теме:

Сохранить проект под любым именем.

2. Создание главной формы Form1

Создать форму, как показано на рисунке 1.

Разместить на форме элементы управления следующих типов:

  • четыре элемента управления типа Button . Автоматически будут созданы четыре объекта (переменные) с именами button1 , button2 , button3 , button4 ;
  • три элемента управления типа Label с именами label1 , label2 , label3 ;
  • один элемент управления типа TextBox , доступ к которому можно получить по имени textBox1 .

Сформировать свойства элементов управления типа Button и Label:

Для настройки вида и поведения формы нужно выполнить следующие действия:

  • установить название формы. Для этого свойство Text = “ Произведение матриц ”;
  • свойство StartPosition = “ CenterScreen ” (форма размещается по центру экрана);
  • свойство MaximizeBox = “ false ” (убрать кнопку развертывания на весь экран).

3. Создание второстепенной формы Form2

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

Добавить новую форму к приложению, вызвав команду

Разместить на форме в любом месте элемент управления типа Button (рис. 2). В результате будет получен объект с именем button1.

В элементе управления button1 нужно установить следующие свойства:

Настроить свойства формы Form2:

  • свойство Text = “ Ввод матрицы ”;
  • свойство StartPosition = “CenterScreen” (форма размещается по центру экрана);
  • свойство MaximizeBox = “false” (убрать кнопку развертывания на весь экран).

4. Ввод внутренних переменных

Следующий шаг – введение внутренних переменных в текст модуля “ Form1.cs ”.

Для этого сначала нужно активировать модуль “ Form1.cs ”.

В тексте модуля “ Form1.cs ” добавляем следующий код:

Объясним некоторые значения переменных:

  • Max – максимально-допустимая размерность матрицы;
  • n – размерность матрицы, введенная пользователем из клавиатуры в элементе управления TextBox1;
  • MatrText – двумерная матрица элементов управления типа TextBox. В эту матрицу будут вводиться элементы матрицы в виде строк. Ввод данных будет формироваться в форме Form2;
  • Matr1, Matr2 – матрицы элементов типа double, в которые будут копироваться данные из матрицы MatrText;
  • Matr3 – результирующая матрица, которая равная произведению матриц Matr1 и Matr2;
  • f1, f2 – переменные, определяющие были ли введенные данные соответственно в матрицы Matr1 и Matr2;
  • dx, dy – габариты одной ячейки типа TextBox в матрице MatrText;
  • form2 – объект класса формы Form2, по которыму будет получен доступ к этой форме.

5. Программирование события Load формы Form1

Листинг обработчика события Load формы Form1 следующий:

Объясним некоторые фрагменты кода в методе Form1_Load().

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

В обработчике события Form1_Load() выделяется память для двумерной матрицы строк MatrText один лишь раз. При завершении приложения эта память будет автоматически освобождена.

Память выделяется в два этапа:

  • для самой матрицы MatrText – как двумерного массива;
  • для каждого элемента матрицы, который есть сложным объектом типа TextBox.

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

Также каждая созданная ячейка добавляется (размещается) на форму Form2 с помощью метода Add() из класса Controls. Каждая новая ячейка может быть добавлена в любую другую форму приложения.

6. Разработка дополнительного метода обнуления данных в матрице MatrText

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

Листинг метода Clear_MatText() следующий:

При нажатии (клике) на button1 должно вызываться окно ввода новой матрицы. Размер матрицы зависит от значения n .

Листинг обработчика события клика на кнопке button1 следующий:

В вышеприведенном листинге читается значение n . После этого осуществляется настройка ячеек матрицы строк MatrText.

На основе введенного значения n формируются размеры формы form2 и позиция кнопки button1.

Если в форме Form2 пользователь нажал на кнопке OK (button2), то строки с MatrText переносятся в двумерную матрицу вещественных чисел Matr1. Преобразование из строки в соответствующее вещественное число выполняется методом Parse() из класса Double.

Также формируется переменная f1, которая указывает что данные в матрицу Matr1 внесены.

8. Программирование события клика на кнопке button2 (“ Ввод матрицы 2… «)

Листинг обработчика события клика на кнопке button2 подобен листингу обработчика события клика на кнопке button1. Только он отличается шагами 7-8. На этом участке формируются матрица Matr2 и переменная f2.

9. Программирование события Leave потери фокуса ввода элементом управления textBox1

В приложении может возникнуть ситуация, когда пользователь изменяет значение n на новое. В этом случае должны заново формироваться флажки f1 и f2. Также изменяется размер матрицы MatrText, которая выводится в форме Form2.

Изменение значения n можно проконтролировать с помощью события Leave элемента управление textBox1. Событие Leave генерируется в момент потери фокуса ввода элементом управления textBox1 (рис. 4).

Листинг обработчика события Leave следующий:

Вывод результата будет осуществляться в ту же форму, в которой вводились матрицы Matr1 и Matr2. Сначала произведение этих матриц будет сформировано в матрице Matr3. Потом значение с Matr3 переносится в MatrText и отображается на форме Form2.

Листинг обработчика события клика на кнопке button3.

11. Программирование события клика на кнопке button4 (« Сохранить в файле «Res_Matr.txt” ”)

Для сохранения результирующей матрицы Matr3 можно использовать возможности класса FileStream.

Класс FileStream описан в модуле System.IO . Поэтому в начале приложения нужно добавить следующий код:

Листинг обработчика события клика на кнопке button4 следующий:

12. Запуск приложения на выполнение

После этого можно запускать приложение на выполнение и тестировать его работу.

Матрица это набор объектов, которые хранятся в виде таблицы. У каждой матрицы есть имя, единый тип всех ее объектов.

Обявление матрицы в Си

Также как и переменные матрицу в Си необходимо объявить перед тем как с ней работать, необходимо указать ее тип, ее имя , количество строк -1 и количество столбцов -1. Нумерация столбцов и строк идет с 0.

Тип матрицы Имя [количество строк-1][количество столбцов-1];

int A[8][9] ; / /объявляет целочисленную матрицу с именем A , у которой 9 строк и 10 столбцов

После объявления матрицы, с ее элементами можно работать. Чтобы обратитсья к элементу матрицы нужно указать имя матрицы в первых квадратных скобках указать номер строки, во вторых квадратных скобках указать номер столбца.

A[0][1]=10; // элементу матрицы с номер строки 0 и столбца 1 присваивается значение 10

printf(“%d”, A[0][1]);// выводит на экран элемент матрицы с номер строки 0 и столбца 1

Задание матрицы в Си

Чтобы работать с матрицей в Си, необходимо присвоить начальные значения всех ее элементов.

Для работы со всеми элементами матрицы используется вложенные циклы for

В главном цикле “пробегаем” по всем строкам, а во вложенном “пробегаем” по всем столбцам для каждой строки.

// “пробегаемся” по всем строкам. Нумерация строк с 0.

// вложенный цикл, “пробегаемся” по всем столбцам для Нумерация столбцов с 0.

…Имя матрицы [i][j]…// работаем с элементом матрицы с номером строки i и номером столбца j

Пример программы 22. Программа задаёт целочисленную матрицу размером 10 на 10 и заполняет ее случайными числами в диапазоне, который укажет пользователь и выводит ее на экран.

int a[9][9]; // объявление матрицы 10 на 10

int i,j; // счетчики циклов

int range;// диапазон в котором присваиваются значения элементов матрицы

//ввод диапазона случайных чисел

printf("введите диапазон заполнения\n");

// пробегаем по всем строкам

// пробегаем по всем столбцам для данной строки i

a[i][j]=rand() % range+1; // прсиваиваем элементу матрицы a с номером строки i и номер столбца j случайного значения в диапазоне от 0 до 9

// пробегаем по всем строкам

// пробегаем по всем столбцам для данной строки i

// переход на следующую строку

При выводе матрицы на экран в Си для каждой строки мы совершаем переход на следующую строку с помощью оператора printf(" ");

Ввод матрицы в Си с помощью клавиатуры

Пример программы 23. Задаётся матрица размера 3 на 3 с помощью клавиатуры и ищется ее максимальный элемент. Он выводится на экран. При поиске максимального элемента, мы создаем специальную переменную max и присваиваем ей значение элемента a[0][0]. Пробегаем по всем элементам матрицы с помощью вложенного цикла, сравнивая текущий элемент с максимумом, если текущий элемент больше максимума, то максимуму присваивается значение этого элемента.

int a[2][2]; // объявление матрицы 3 на 3

int i,j; // счетчики циклов

int max; // переменная для хранения максимального элемента матрицы

// пробегаем по всем строкам

// пробегаем по всем столбцам для данной строки i

// ввод текущего элемента матрицы с клавиатуры

printf("Введите элемент матрицы [%d][%d]", i, j);

// переход на следующую строку

// пробегаем по всем строкам

// пробегаем по всем столбцам для данной строки i

// переход на следующую строку

// пробегаем по всем строкам

// пробегаем по всем столбцам для данной строки i

// сравниваем текущий элемент массива с максимумом

// вывод максимального элемента

printf ("Максимальный элемент массива %d", max);

Вернуться к содержанию Перейти к теме Работа с файлами в Си

Полезно почитать по теме массивы и матрицы в си
Массивы в си
Игра на си Крестики Нолики

Реализация собственного значения

Реализация собственного значения

Имеем набор данных в виде совокупности квадратных матриц, которые используются - вместе с известным выходом - в качестве тренировочного набора для нейронной сети. Можно ли обучить нейронную сеть, используя только собственные значения матриц? Во избежание проблем с комплексными значениями, упор делаем на симметричные матрицы. Для иллюстрации используем набор данных MNIST. Понятно, что невозможно восстановить матрицу по ее собственными значениям - для этого понадобится еще кое-что, о чем мы поговорим далее. Поэтому трудно ожидать некоего прорыва на данном пути, хотя известно, что можно говорить о чем угодно, строить грандиозные планы, пока не пришло время платить. О деньгах мы здесь не говорим, просто задаем глупый вопрос, на который постараемся получить осмысленный ответ, тем более что в процессе познания расширим свои научные горизонты. Например, сначала мы познакомимся с тем, как находить собственные векторы и собственные значения (eigenvalues and eigenvectors) для заданной квадратной матрицы, затем плавно выкатим на эрмитовы и унитарные матрицы. Все иллюстративные примеры сопровождаются простыми кодами. Далее возьмем MNIST , преобразуем в набор собственных значений симметричных матриц и используем молоток от Keras. Как говорят в Японии: “Торчащий гвоздь забивают”. Закроем глаза и начнем бить, а на результат можно и не смотреть: получится как всегда. Сразу скажу, что изложение будет проведено как можно ближе к тому, как я это дело понимаю для себя, не обращаясь к строгому обоснованию, которое обычно не используется в повседневной жизни. Иными словами, что понятно одному глупцу, понятно и другому. Все мы невежественны, но, к счастью, не в одинаковой степени. С другой стороны, предполагаю, что многие, хоть и в гимназиях не обучались, но имеют представление - по своему опыту обучения, - что значит впихнуть невпихуемое.

Собственно, собственные

Итак, пусть у нас задана произвольная квадратная матрица с компонентами . Мы ставим запятую между индексами, имея в виду оформление массивов в большинстве языков программирования; обычно так не делается, но мы делаем так, как нам хочется, да и выглядит все более разреженным и удобочитаемым. Мы можем умножить матрицу на произвольный вектор , руководствуясь правилом умножения матриц (строка на столбец), . По повторяющимся индексам производится суммирование; все получится, если размерность первой (нумерация с нуля) оси матрицы совпадает с размерностью вектора. Если будет желание, когда я что-то упускаю из виду, можно заглянуть в мои заметки . Вдруг приключилось так, что , тогда говорят: - собственное значение, - собственный вектор. Опять же, возвращаясь к глубокомысленной дискуссии о запятых в индексах, здесь мы используем точку, когда переходим от компонент к матрицам, имея в виду замечательную функцию dot() в превосходном NumPy. Теперь проведем ряд очевидных манипуляций

где - символ Кронекера, - единичная матрица, 0 - нулевой вектор. Условие нетривиальности решения, , для собственного вектора приводит к характеристическому уравнению . Если размер матрицы равен n, получим алгебраическое уравнение n-й степени, которое имеет n корней (действительных или комплексных) - собственных значений (eigenvalues) . Каждому собственному значению соответствует собственный вектор (eigenvectors) (например, ). Совокупность собственных векторов образует матрицу с компонентами , где нулевая ось - компоненты вектора, а первая - нумерация собственных векторов. Теперь уравнение на собственные значения выглядит следующим образом: . Раз есть вектор, есть его длина, которая равна сумме квадратов компонент (квадрат длины). Например, для квадрата длины третьего вектора (нумерация с нуля) имеем

где, вспоминая правила умножения матриц ( , см. заметки ), мы воспользовались тождеством , в котором - транспонированная матрица (используем обозначения NumPy). Здесь нет проблем, но это до тех пор, пока мы работаем с действительными векторами. В комплексной области квадрат длины вектора равен скалярному произведению вектора на комплексно сопряженный. В этом случае потребуется следующая модификация соотношения (2):

где звездочка обозначает обычное комплексное сопряжение. Следует заметить, что - эрмитово-сопряжённая матрица. Длина вектора - число, отсюда открывается возможность выделить собственное значение путем умножения на собственный вектор. В результате для выделенного собственного значения получим

Все это выглядит не очень хорошо, поскольку произведение разных собственных векторов, например , может быть не равно нулю. Это настораживает, поскольку мы привыкли иметь дело с единичными векторами, каждый из которых ортогонален другому. Вспомните хотя бы единичные векторы по трем осям в обычном пространстве. Но проблемы отложим на потом, а пока создадим видимость работы - побалуемся с кодами.

Действительно, характеристическое уравнение имеет решения , где - мнимая единица. Столбцы матрицы - собственные векторы и .

Эрмитовы матрицы

Мы научились находить eigendecomposition для произвольной квадратной матрицы. Пока не будем говорить о вырожденных матрицах , которых, по возможности, будем в дальнейшем избегать. Итак, в чем состоит загвоздка. С собственными значениями - все в порядке, а вот собственные векторы изрядно подгуляли. Дело в том, что они не ортогональны друг другу. Посмотрим, какие условия на матрицу нам потребуется наложить, чтобы добиться ортогональности, заодно откроем для себя ряд новых возможностей в деле познания собственных способностей.

Пусть из всего набора мы произвольно выделили два участника и , где, напомним, второй индекс нумерует собственные вектора. Берем первое соотношение и умножаем его на , а второе - на , в результате имеем

Далее выполним комплексное сопряжение второго уравнения в (5)

Поскольку индексы в последнем уравнении “немые” (по ним производится суммирование) , их можно назвать как угодно. Таким образом, после замены получим

где - эрмитово-сопряжённая матрица, элементы которой определяются как . Теперь из первого уравнения (5) вычитаем (6). В результате получим следующее замечательное выражение:

Пока мы не накладывали никаких ограничений на матрицу. Первое, что приходит на ум: положим , определяя тем самым эрмитову матрицу Следует отметить: все что мы наблюдаем в окружающем нас мире связано, так или иначе, с собственными значениями эрмитовых матриц. Шарль Эрмит - вот кто Создатель Вселенных (см. превосходную биографию, Ожигова Е.П. Шарль Эрмит. - Л.:Наука, 1982.). Да, было время, когда математики занимались реальным миром, не то, что нынешнее племя.

Шарль Эрмит, 1822-1901

Шарль Эрмит, 1822-1901

Итак, для эрмитовых матриц получаем выражение , которое связано с двумя важнейшими событиями для каждого, кто изучал квантовую механику. Во-первых, собственные значения эрмитовых матриц являются действительными величинами , поскольку при из условия имеем . Во- вторых, если и , получаем свойство ортогональности собственных векторов . Для эрмитовых матриц собственные значения - действительные величины, а собственные векторы - ортогональны друг другу, вернее, ортонормированы, поскольку удобно включать условие нормировки. Таким образом, мы стремились к аналогии с обычным пространством, с единичными векторами по ортогональным осям, мы это и получили.

Теперь соорудим эрмитову матрицу. Для этого сгенерируем пару случайных матриц и , затем сложим их, умножив одну из матриц на мнимую единицу , . Затем возьмем полученную матрицу и сложим ее с эрмитово-сопряженной. Действительно, , так что - эрмитова матрица.

Пришло время окунуться в мутные воды искусственного интеллекта. Внести, так сказать, свой слабый голос в общий хор.

Собственные значения (values) получились с едва заметной мнимой частью, которую мы отрезаем по идеологическим соображениям. Для этого мы оставили только действительную часть. Напомним, что

где - единичная матрица (по диагонали единицы ). Проверим в коде

Опять же получим почти единичную матрицу, но ничего округлять не будем. Теперь пришло время для громкого заявления : матрица, для которой выполняется (8) - унитарная матрица . Таким образом, эрмитово-сопряжённая унитарная матрица совпадает с обратной. К слову, эволюция во времени нашего мира осуществляется с помощью унитарных преобразований, хотя этот факт теряется во множестве событий. Не удивительно, что унитарную эволюцию попытались использовать (см. статью) и в машинном обучении, но для рекуррентной нейронной сети. Для многих концепция унитарности заставляет ощутить священный трепет познания. Но это одна среда обитания. В политическом же питательном бульоне тоже есть концепция унитарности, о которой можно думать все что угодно, и которая не связана ни с каким познанием.

Симметричный MNIST

Итак, в предыдущем разделе мы говорили о произвольных о эрмитовых матрицах. Если же мы имеем дело с действительными матрицами, комплексное сопряжение выпадает, поэтому эрмитовы - это просто симметричные матрицы, ​​.


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

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

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

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

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

Пятерочки для закраски вполне достаточно, поскольку вероятность совпадения элементов в строке или столбце просто мизерная. Детерминант, конечно, громадный, но Python все стерпит, а пока закроем на это глаза. Если посмотрим на картинку, то поверьте, там все нормально: наша тройка практически не изменилась.

Итак, перейдем к симметричной матрице и посмотрим, что там нарисовано.


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

Если с собственными значениями все в порядке, то собственные векторы малость подгуляли: мало того, что они комплексные (как обычно и бывает), так восстановление первоначальной матрицы по собственным векторам и собственным значениям может привести к комплексной матрице. Python не знает, что это не правильно, поэтому и вытянет наружу комплексные остатки. Само собой, можно от них избавиться с помощью метода np.real(), оставляя только действительную часть. Но пока попробуем в лоб, проверим прозорливость создателей NumPy на примере восстановления матрицы по собственным значениям и собственным векторам. Чтобы подготовить почву, необходимо вернуться к уравнениям (8), которые справедливы и для нашей матрицы , в которой столбцы - собственные векторы матрицы (см. выше). Таким образом, . Следует напомнить, что, несмотря на повторяющийся индекс ​​, в правой части нет суммирования (берем фиксированное ​​). Далее имеем

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

в котором использовали (8) . Теперь проверим в коде


Нет слов, все работает! Итак, наши подозрения были беспочвенны, но проверять все равно надо. Теперь мы знаем, что по собственным значениям и векторам можно четко восстановить исходную матрицу. Итак, если используем обратимые операции, царапая формулы на листке бумаге, лучше проверить, как с этим обстоит дело в коде.

Эксперимент

Итак, теперь мы умеем манипулировать симметричными матрицами, используя в качестве полигона базу данных MNIST. Теперь мы попытаемся представить набор данных как симметричные матрицы, затем вычислить собственные значения, на основе которых построить нейронную сеть по примеру обращения с обычным набором. Сразу скажу, что надежд на удачный исход мало. Действительно, как мы выяснили ранее, для того чтобы восстановить матрицу собственных значений недостаточно, для этого необходим набор собственных векторов, объединенных в матрицу , которая сама по себе имеет размер исходной матрицы. Так что, с первого взгляда, мы ничего не выигрываем. Тем не менее, есть надежда, что распределение и свойства собственных значений обладают необходимыми свойствами, чтобы их классифицировать по классам. Иными словами, собственные значения несут информацию о классах рукописных цифр. Распределением собственных значений мы займемся в следующей публикации, а сейчас будем использовать наивный подход, а именно : 1) представим набор MNIST в виде симметричных матриц (28*28); 2) для каждого экземпляра вычислим собственные значения (28 штук); 3) используем Keras. Первые шаги мы уже сделали в предыдущем разделе, а над последним особо заморачиваться не будем, поскольку мы просто ставим эксперименты.

Начинаем новый блокнот:

Теперь напишем функцию, которая будет “закрашивать” матрицы из набора данных. Отмечу, что использую доморощенные функции, которые предпочитаю писать самостоятельно, чем искать на мутных форумах.

Используем эту функцию, затем масштабируем (это не обязательно).

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

Включаем и смотрим.

Как видно, вполне приемлемые значения, с которыми можно и поработать. Для этого возьмем продвинутый молоток от Keras.

За основу мы берем код из Глубокое обучение на Python. Если осмысленно побалуетесь с цифрами, что-то получите. Точность, которая едва-едва заваливает за 0,5 (за 100 эпох. ), подкачала по сравнению с оригиналом (accuracy: 0.9897 за Epoch 5), когда используется полная матрица изображения, но хотя бы мы не множили сущности. Для обсуждения не требуется глубокомысленных обобщений, просто, как я наивно думал, если зайца долго бить по голове, он научится спички зажигать. Но оказалось, что этот принцип в глубоком обучении не всегда срабатывает. Возиться дальше - интересно, но бессмысленно. Самое главное, по пути к этому мутному результату можно много чему научиться.

Пару слов напоследок

Итак, пришло время подводить итоги. Понятно, что говорить пока не о чем. Мы попытались на собственных значениях матриц построить работающую схему. Не получилось. Но известно, что отрицательный результат - куда более значимое событие, чем положительный, поскольку при этом у нас открываются новые перспективы. Если бы у нас все получилось, настало бы время для рутинной работы, а так - продолжим идти дальше. Правда и ложь - два взгляда на одну и ту же реальность. Но мы, по крайней мере, не лгали. Просто посмотрели с другого ракурса, заодно открыли для себя новые возможности. К примеру, почему бы не найти преобразование, позволяющее связать все изображения одного класса без использования внешнего наблюдателя для подтверждения события? Иными словами, из одной цифры получить почти полную совокупность из данного набора данных; из “тройки” почти все “тройки”, и т.д.. Сразу приходит на ум конформное отображение двумерных поверхностей: локальные вращения и растяжения с сохранением углов между кривыми, а значит с сохранением формы бесконечно малых фигур. Заодно мы могли бы проследить за трансформацией собственных значений, дабы по их расположению выйти на классификацию по классам. И не обязательно использовать действительные собственные значения. Конечно, переход в комплексную область потребует дополнительных усилий, но там уже существует путь в один путь, многое успешно отработано.

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

Читайте также: