Реализация нейронной сети на C требует нескольких шагов

Нейронные сети
Реализация нейронной сети на C требует нескольких шагов

GitChat Автор: Цан Йе
оригинал:Сколько шагов нужно, чтобы реализовать нейронную сеть на C?
Обратите внимание на публичный аккаунт WeChat: "GitChat Technology Talk" Серьезно о технологиях

【Не пропустите пасхалку в конце статьи】

1. Слова, написанные впереди

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

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

Несколько лет также являются самыми интересными годами моей жизни. Теперь, когда различные каналы переполнены сообщениями «Узнай XXXX за 28 дней», это кажется слишком громким. 28 дней обучения, вероятно, достаточно только для изучения простого языка программирования, такого как Python. Если вы хотите изучить содержание выше Алгоритм, если вы не разбираетесь в математике, это отличный вид, и таких людей должно быть очень мало. Поэтому обучение нейронных сетей — это еще и физическая активность, требующая постоянного анализа и практики.

2. Начните с геометрии

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

Сначала взгляните на пространственную функцию:

?f(x_1,\cdots,x_n)?

Вышеупомянутая функция определена в N-мерном пространствефункция, математический символ этого N-мерного пространства $\mathbb{R}^n$, где $(x_1,\cdots,x_n)$ называется пространственной координатой, здесь введение в геометрию пространства, но тогда мыНеАнализируйте нейронные сети. Еще одна концепция, которую необходимо сделать перед анализом, заключается в том, чтоградиент:

?\nabla{f}(x_1,\cdots,x_n)=
(\frac{\partial{f}}{\partial{x_1}},\cdots
\frac{\partial{f}}{\partial{x_1}})?

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

?\frac{\partial{f}}{\partial{x_i}}=\sum_i^N\frac{\partial{f}}{\partial{z_k}}
\cdot
\frac{\partial{z_k}}{\partial{x_i}}?

Предполагая, что преобразование пространственных координат имеет функциональную связь $z_i = z_i(x_1,\cdots,x_n) $

Запишите приведенный выше вывод цепи в матричной форме:

?\nabla_x{f}=\nabla_z{f}\cdot A?

Здесь матрица A, умноженная на для сохранения инварианта относительно преобразования пространственных координат, называется тензором, и этот тензор имеет определенное выражение:

?A=\frac{\partial{z_j}}{\partial{x_i}}?

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

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

?A\cdot x=b?

координироватьАффинное преобразованиеЕго также можно представить в матричной форме:

?z=A\cdot x?

Скалярное произведение в тензоре естьсокращатьОперация, эта аббревиатура представляет собой операцию суммирования, но очень хлопотно всегда писать символ суммирования, который во многих учебниках по математике записывается как Эйнштейн.подведение итогов контрактаПуть:

?
\sum_i\frac{\partial{f}}{\partial{z_k}}
\cdot
\frac{\partial{z_k}}{\partial{x_i}}=\frac{\partial{f}}{\partial{z_k}}
\cdot
\frac{\partial{z_k}}{\partial{x_i}}
?

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

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

放射变换
Радиационное преобразование

Добавьте несколько групповых концепций

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

Как упоминалось выше, градиент является вектором, метод преобразования этого вектора заключается в работе с тензором A. Существует еще один вектор, метод преобразования которого отличается от вектора градиента, например, скорость:

?v=[\dot{x}_1,\cdots,\dot{x}_n]?

Здесь используется другое сокращение:

?\dot{x}_1=\frac{dx}{dt}?

Таким образом, в случае преобразования координат x=>z по-прежнему используется цепное правило вывода:

?\dot{x}_i=\frac{dx_i}{dt}=\frac{\partial{x_i}}{\partial{z_j}}\frac{dz_j}{dt}=\frac{\partial{x_i}}{\partial{z_j}}\dot{z}?

Выше использовалось обычное суммирование, которое можно записать в матричной форме:

?v_x =B \cdot v_z?

Длина вектора в пространстве является важным понятием:

?|v|^2=v_i \cdot v_i?

Это определение знакомо и часто упоминается в информатике какдвухнорм..

Как упоминалось выше, это просто длина в декартовом пространстве, а реальную длину пространства нужно умножить на тензор второго порядка:

?|v|^2=g_{ij} v_i v_j?

Конкретный вывод в виде $G=[g_{ij}]$ может быть получен самостоятельно, если вам интересно, и вы можете использовать правило вывода по цепочке.

Здесь следует добавить, что если преобразование $x=x(z_1,\cdots,z_n)$ сохраняет форму G неизменной, то преобразование называетсямераодин меньше $G=[g_{ij}]$виды спорта.

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

?d=\sqrt[p]{|v_1-v_2|^p}?

Он включает в себя содержание пространства Минковского, которое в математике характеризуется определением длины вектора как:

?|v|^2= v_1 v_1- v_2 v_2- v_3 v_3- v_4 v_4?

Это то же самое, что и в информатикерасстояние МинковскогоЕсть разница, $v_1=ct$ в пространстве Минковского — это пространство специальной теории относительности.

3. Тензоры и матрицы

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

?v=v_i \vec{e_i}?

Здесь $\vec{e_i}$ — вектор базы координат, базу координат можно рассматривать как упорядоченную пару действительных чисел длины 1, а $v_i$ — длину соответствующей компоненты. Преобразование координат также можно рассматривать как преобразование базы координат. Матрицу можно рассматривать как набор нескольких векторов:

?A=[v_1,\cdots,v_m]?

Эти векторы v могут быть представлены k векторами, где $m>=k$, и число векторов может быть сжато в это время, что такжеСжатие данныхО чем он просит: хранить больше с меньшим объемом данных.

Вот как сжать эти данные:

Первый - этоРазложение матрицы по собственным значениямПроблема, мы можем умножить квадратную матрицу на три матрицы:

?A_{n\times n}=E\Lambda E^{-1}?

Где $\Lambda$ представляет собой диагональную матрицу. Для случая $rank(A)Ранг матрицы, то есть сколько ненулевых значений в диагональной матрице, все векторы, содержащиеся в матрице A, могут быть представлены менее чем N векторами, поэтому такие векторы называютсяВектор признаков.

Однако для случая неквадратной матрицы $B_{m\times n}$ очевидно невозможно выполнить разложение по собственным значениям, требующее частичного преобразования матрицы:

?B^T\cdot B=A_{n\times n}?

Выполните обычное разложение A по собственным значениям:

?A_{n\times n}=E\Lambda E^{-1}?

Отсюда мы нашли нОртогональный базис$[v_1,\cdots,v_n]=E$

Если ортонормированный базис преобразуется с помощью B, ?m_i=B\cdot v_i?Умножьте векторы:

?\vec{m_i}\cdot \vec{m_j}=\vec{v_i}^T\cdot B^T \cdot B \cdot \vec{v_j} \ =\vec{v_i}^T\cdot A \cdot \vec{v_j}=\vec{v_i}^T\cdot \lambda_j \cdot \vec{v_j}=\lambda_j \delta_ij?

Процесс упрощения использует свойства собственных значений:

?A \cdot v=\lambda \cdot v?

Видно, что после линейного преобразования B векторы по-прежнему ортогональны. Количество векторов $m_i$ равно рангу матрицы A. Нормализуйте $m_i$:

?\mu_i = \frac{B\cdot v_i}{|B \cdot v_i|}=\frac{B\cdot v_i}{\sqrt{\lambda_i}}?

Запишите приведенную выше формулу как:

?B\cdot v_i =\sqrt{\lambda_i}\mu_i?

Перепишем его в матричной форме:

?BV=U\Lambda?

так

?B=U\Lambda V^T (все векторы в V единично ортогональны)?

Таким образом, любую матрицу можно записать как произведение трех матриц. ЭтоРазложение по сингулярным значениям (SVD) матрицы, где собственные значения представляют веса разных собственных векторов и могут быть опущены для малых весов. Таким образом, SVD может легко сжимать данные, но, с другой стороны, так называемое сжатие данных заключается в удалении векторов с относительно высокой линейной корреляцией, поэтому, как измерить эту корреляцию, одним из способов является диагонализация матрицы корреляции:

Например, матрица данных X, предполагая, что среднее значение равно 0, тогда матрицу корреляции можно записать как:

?S_x=\frac{1}{n-1}X\cdot X^T=U\Lambda V^T V\Lambda U^T?

Таким образом, матрицу можно диагонализовать, умножив X на $U^T$, т.е.метод РСА.

###Четыре, функциональный анализ

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

?A\cdot x =b?

Приведенное выше уравнение трудно решить напрямую (существуют и другие решения этой задачи), поэтому оно преобразуется в функцию от x:

?f(x)=x^T A x - 2bx ?

空间二次曲面
пространственная квадратичная поверхность

Для двумерного вектора x его функционал представляет собой пространственную квадратичную поверхность, а минимальное значение функционала, то есть при градиенте равном 0:

?\nabla{f(x)}=A x-b=0?

Оно соответствует решению уравнения.Конечно, можно использовать пространственное расстояние или энтропию функционала в нейронной сети.Процесс установления функционала здесь специально не задействован. Функциональный анализ также может быть использован для доказательства решенияРаспределение Гаусса - это максимальное распределение энтропии.

Для общих многомерных функций на них можно выполнить разложение Тейлора:

?f(x)=f(x_0) + a_1\nabla(f(x_0)) dx+a_2dx^T H dx+o(dx^3)?

Выше приведена расширенная математическая форма многомерной функции, где H — матрица Гессе. Чтобы найти минимальное значение функции, просто продолжайте искать его в отрицательном направлении градиента:

?x_{t+1}=x_t-\lambda\nabla f(x)?

Это то, что часто говоряткрутой спуск, вблизи минимального значения также есть особенность, заключающаяся в том, что изменение функции $\Delta f=f(x)-f(x_0)$ является наименьшим, что можно получить, взяв частную производную от dx по обе стороны разложения Тейлора :

?dx=x_{t+1}-x_t=-H^T\cdot \nabla f?

Итак, это снова градиентный итеративный метод, назовите егометод Ньютонаи тот, который оценивает линейный градиент функции и вычитает его из расчета:

?g=f+\frac{\partial f_i}{\partial x_j}(x-x_t)_i=f+J(x-x_t)?

В этот момент целевое позиционирование функции g может быть увеличено до 0, и в это время может быть получена частная производная x:

?dx=x_{t+1}-x_t=(J^T\cdot J)^T J^T f(x)?

Это становитсяМетод Гаусса-Ньютона

Наконец, давайте посмотрим на многослойную нейронную сеть, Основная идея заключается в использовании метода спуска, Здесь функция стоимости определяется как пространственное расстояние:

?\varepsilon(w)=|d-y|=\sqrt{\sum_i (d_i-y_i)^2}?

Цель состоит в том, чтобы решить градиент этой функции:

?\nabla_w \varepsilon=\frac{\varepsilon}{w^{[1]}}
+
\cdots
+\frac{\varepsilon}{w^{[N]}}?

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

?\frac{\varepsilon}{w^{[N]}}=f'({y^{[N-1]}}\cdot w^{[N]})*(d-y^{[N]})^T \cdot y^{[N]}=\mathcal{M}^{[N]} y^{[N]}?

?\frac{\varepsilon}{w^{[N-1]}}=f'({y^{[N-2]}}\cdot w^{[N-1]}) w^{[N]}\cdot [f'({y^{[N-1]}}\cdot w^{[N]}) \ (d-y^{[N]})^T] \cdot y^{[N-1]}=\mathcal{M}^{[N-1]} y^{[N-1]}?

Связь между двумя матрицами следующая:

?\mathcal{M}^{[N-1]}=f'(x)*[w^{[N]} \cdot \mathcal{M}^{[N-1]}]?

Приведенная выше производная рекурсивно передается от $\varepsilon$ последнего слоя к первому слою, поэтому здесь она называется алгоритмом обратного распространения.
Теоретическая часть здесь почти такая же, но все же есть проблема, то есть фактически формируемая в ходе расчета оптимизированная поверхность — это поверхность, непрерывно меняющаяся вместе с образцом:

最优化曲面
оптимизированная поверхность

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

### Пять, реализация

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

多层神经网络
Многослойная нейронная сеть

Очевидно, что многоуровневая сеть может решить проблему.


"""
@author: Cangye@hotmail.com
"""

import numpy as np

class BPAlg():
    def sigmoid(self,x):
        """
        Define active function sigomid
        """
        return 1/(1+np.exp(-x))
    def d_sigmiod(self,x):
        """
        Define df/dx
        """
        return np.exp(-x)/(1+np.exp(-x))**2
    def __init__(self,shape):
        """
        Initialize weights
        """
        self.shape=shape
        self.layer=len(shape)
        self.W = []
        self.b = []
        self.e = []
        self.y = []
        self.dW = []
        self.v = []
        self.db = []
        self.d_sigmoid_v = []
        for itrn in range(self.layer-1):
            self.W.append(np.random.random([shape[itrn], shape[itrn+1]]))
            self.dW.append(np.random.random([shape[itrn], shape[itrn+1]]))
            self.b.append(np.random.random([shape[itrn+1]]))
            self.db.append(np.random.random([shape[itrn+1]]))
        for itr in shape:
            self.e.append(np.random.random([itr]))
            self.y.append(np.random.random([itr]))
            self.v.append(np.random.random([itr]))
            self.d_sigmoid_v.append(np.ones([itr]))
    def forward(self, data):
        """
        forward propagation
        """
        self.y[0][:] = data
        temp_y = data
        for itrn in range(self.layer-1):
            temp_v = np.dot(temp_y, self.W[itrn])
            temp_vb = np.add(temp_v, self.b[itrn])
            temp_y = self.sigmoid(temp_vb)
            self.y[itrn+1][:] = temp_y
            self.d_sigmoid_v[itrn+1][:] = self.d_sigmiod(temp_vb)
        return self.y[-1]
    def back_forward(self, dest):
        """
        back propagation
        """
        self.e[self.layer-1] = dest-self.y[self.layer-1]
        temp_delta = self.e[self.layer-1]*self.d_sigmoid_v[self.layer-1]
        temp_delta = np.reshape(temp_delta,[-1,1])
        self.dW[self.layer-2][:] = np.dot(np.reshape(self.y[self.layer-2],[-1,1]),np.transpose(temp_delta))
        self.db[self.layer-2][:] = np.transpose(temp_delta)
        for itrn in range(self.layer-2, 0, -1):
            sigma_temp_delta = np.dot(self.W[itrn],temp_delta)
            temp_delta = sigma_temp_delta*np.reshape(self.d_sigmoid_v[itrn],[-1,1])
            self.dW[itrn-1][:] = np.dot(np.reshape(self.y[itrn-1], [-1,1]), np.transpose(temp_delta))
            self.db[itrn-1][:] = np.transpose(temp_delta)
    def data_feed(self, data, dest, eta):
        NDT = len(data)
        for itrn in range(NDT):
            self.forward(data[itrn])
            self.back_forward(dest[itrn])
            for itrn in range(self.layer-1):
                self.W[itrn][:] = self.W[itrn] + eta*self.dW[itrn]
                self.b[itrn][:] = self.b[itrn] + eta*self.db[itrn]

Эта статья была впервые опубликована на GitChat и не может быть воспроизведена без разрешения. Для перепечатки, пожалуйста, свяжитесь с GitChat.


Запись: «Цан Е: Реализация боевого анализа нейронной сети на языке C»


пасхальные яйца

Поделиться тяжелым чатом:

«Эффективное обучение, быстрая монетизация: пять стратегий обучения, которые не делают обходных путей»

Разделено:
Программист, который может писать код вживую на станции B, играть в жонглирование мячами, играть на укулеле, заниматься экстремальным фитнесом, бегать, писать шутки, рисовать, переводить, писать, говорить и тренироваться. Мне нравится использовать программирование для реализации своих идей, я заработал деньги на рынке Android и имею большой предпринимательский опыт. Хорошо учится, формирует привычки, тайм-менеджмент. Влияйте на других, чтобы внести позитивные изменения, делая это самостоятельно! В настоящее время работает в ThoughtWorks, занимаясь распространением концепции счастливого и эффективного программирования. Будучи любителем, он основал CodingStyle.cn, сообщество разработчиков программного обеспечения, и организовал более 30 технических мероприятий.

Введение в чат:
Когда дело доходит до обучения, это действительно большая голова: фрагментарно, нет длительного непрерывного времени для учебы, трудно сосредоточиться, взять книгу, но звонит мобильный: Давай, будь счастлив~ В любом случае, есть много времени~ Я не могу это сделать, я прочитал много книг, но я не могу сделать это в своей жизни.Я изучил методы и инструменты, но я не могу найти сценарии использования. эффективность низкая, а скорость обучения не может идти в ногу со скоростью образования знаний.В эпоху наводнений и трансграничной конкуренции способность к обучению является основной конкурентоспособностью. Подумайте об этом, на прошлой неделе была ли какая-нибудь работа, на которую можно было бы не учиться? Хотя это важно, большинство людей не изучали обучение, думая, что они всю жизнь учатся в условиях фрагментированного времени, если они откроют «получить», чтобы послушать эту книгу по дороге на работу и с работы.

Я программист, консультант и тренер, и все это требует, чтобы я учился быстро и хорошо. Этот чат проанализирует «тенденции, принципы и стратегии» обучения, поможет вам взглянуть на обучение с более высокой точки зрения, сформулирует стратегии с учетом пяти аспектов «содержания, мотивации, взаимодействия, преимуществ и ресурсов», решит болевые точки обучения и помочь вам стать эффективными учениками!