теоретические основы
что такое нейронная сеть
Мы знаем, что глубокое обучение — это ветвь машинного обучения, алгоритм, который использует искусственные нейронные сети в качестве архитектуры для обучения представлению данных. Глубокая нейронная сеть — это ветвь глубокого обучения, которая объясняется в Википедии следующим образом:
Глубокие нейронные сети (DNN) — это дискриминантная модель, нейронная сеть, по крайней мере, с одним скрытым слоем, которую можно обучить с помощью алгоритма обратного распространения ошибки. Обновление веса может быть решено стохастическим градиентным спуском с использованием следующего уравнения.
Прежде всего, мы можем знать, что глубокая нейронная сеть является дискриминационной моделью. Это означает, что переменная x известна, а y можно вычислить по дискриминантной модели. Например, в случае, обычно используемом в машинном обучении, по написанию чисел от руки модель делает вывод, какие числа написаны от руки.
«Глубина» в глубокой нейронной сети относится к серии непрерывных слоев представления, сколько слоев включено в модель данных, что называется «глубиной» модели. Через эти слои мы можем выполнять высокоуровневую абстракцию данных. Как показано на рисунке ниже, глубокая сеть уровня бога состоит из входного слоя, нескольких (как минимум одного) скрытых слоев и выходного слоя, причем количество входных и выходных слоев не обязательно равно. В каждом слое есть несколько нейронов, и между нейронами есть веса связей.
Или в приведенном выше случае распознавать рукописные числа, как преобразовать рукописные числа в ввод? Поскольку он написан от руки, это должно быть изображение. Изображение состоит из нескольких пикселей. Эти пиксели могут формировать вход. После многослойной нейронной сети выводятся 10 чисел. Эти 10 чисел представляют числа 0 ~ 9. вероятность.
Как нейроны вводят и выводят
Каждый нейрон в нейронной сети можно рассматривать как простую линейную функцию Давайте построим простую трехслойную нейронную сеть, чтобы увидеть.
Как показано на рисунке выше, n1 можно выразить как:
вПредставляет вес между нейронами, b является константой, как смещение функции. Меньшие веса ослабляют влияние одного нейрона на другой, а большие веса усиливают сигнал. Предположение0,1,равно 0,7, то влияние x3 на n1 больше, чем влияние x1. Вы можете спросить, почему каждый нейрон связан с нейронами в любом другом слое?
Для этого есть две основные причины:
- Полносвязную форму относительно легко записать в компьютерные инструкции.
- В процессе обучения нейронной сети соединения, которые на самом деле не нужны, будут ослаблены (то есть некоторые веса соединений будут медленно приближаться к 0).
На самом деле, после того как n1 получено вычислением, его нельзя сразу использовать для последующих вычислений, и требуется функция активации (обычно сигмод-функция).
Его роль в основном заключается во введении нелинейных факторов. Если в сети уровня бога есть только указанная выше линейная функция, независимо от того, сколько слоев, результат всегда будет линейным.
фактический случай
Чтобы облегчить расчет, мы строим нейронную сеть только с двумя слоями, чтобы продемонстрировать конкретный процесс расчета.
Сначала получите значение x через линейную функцию, а затем занесите значение x в функцию активации, чтобы получить значение y1.
умножение матриц
На самом деле описанный выше процесс вычислений можно легко представить умножением матриц. Матрица — это просто таблица или двумерный массив. Как показано на рисунке ниже, это типичная матрица.
Тогда умножение матриц может быть выражено как:
Умножение матриц часто называют скалярным произведением или внутренним произведением. Если мы заменим числа в матрице входными данными и весами нашей нейронной сети, вы увидите, что предыдущий расчет очень прост.
После получения скалярного произведения вам нужно только подставить его в функцию активации, чтобы получить результат.
Процесс вычисления матрицы может быть выражен как:
фактический случай
Процесс расчета трехслойной нейронной сети представлен матрицей ниже.
На приведенном выше рисунке показан только процесс расчета от входного слоя к скрытому слою.Если вам интересно, вы можете вручную рассчитать процесс расчета от скрытого слоя к выходному слою. Матрица весов от скрытого слоя к выходному слою выглядит следующим образом:
обратное распространение
После прохождения раунда вычисления нейронной сети выходное значение обычно не согласуется со значением, которое мы действительно хотим, В это время мы получим значение ошибки (значение ошибки — это разница между правильным ответом, данным обучающими данными, и фактическое выходное значение) значение). Но эта ошибка является результатом совместного действия нескольких узлов, как нам обновить вес каждого соединения? На данный момент нам нужно получить значение ошибки каждого узла посредством обратного распространения ошибки.
Далее подставляем конкретные значения для расчета.
Как видно на картинке вышеВеличина ошибки в основном определяетсяивызвано, то ошибка должна быть распределена на два соединения, и ошибка может быть рассчитана в соответствии с весом двух соединений.разделять.
То же самое и с ошибкамиРазделите, а затем сложите значения ошибок в двух соединениях, чтобы получить значение ошибки узла прямой связи в точке вывода.
Затем эта ошибка распространяется на предыдущие уровни в соответствии с предыдущим методом, пока все узлы не получат свое собственное значение ошибки, что называется обратным распространением.
Обратное распространение ошибок с использованием матричного умножения
Вышеупомянутые утомительные операции также можно упростить с помощью матриц.
В этой матрице все еще есть неприятные дроби, поэтому мы можем быть смелыми и нормализовать знаменатель напрямую. Делая это, мы просто меняем величину ошибки обратной связи, которая по-прежнему рассчитывается пропорционально.
Если вы внимательно посмотрите, то обнаружите, что это очень похоже на щелчок матрицы, который мы использовали для вычисления выходного значения каждого слоя, но матрица весов перевернута, и верхний правый элемент становится нижним левым элементом.Мы можем назовем ее транспонированной матрицей, обозначаемой как.
Матрица ошибок обратного распространения может быть просто выражена как:
градиентный спуск
Получив ошибку в каждой точке, как мы должны обновить веса?
В настоящее время нам нужно использовать метод, обычно используемый в машинном обучении: градиентный подуровень.
Для получения более подробной информации, пожалуйста, обратитесь к моему предыдущему блогу:Градиентный спуск и линейная регрессия
Благодаря непрерывному обучению мы можем улучшить нейронную сеть, Суть в том, чтобы постоянно изменять размер весов и уменьшать значение ошибки вывода нейронной сети. Наконец, можно получить многослойную модель нейронной сети, которая может делать эффективные прогнозы на основе входных данных.
настоящий бой
Подготовка окружающей среды
В первую очередь вам необходимо установить python3, перейти непосредственно на официальный сайт python для установки, попробовать установить последнюю версию, а устанавливать python2 не рекомендуется. После установки среды python установите virtualenv и связанные зависимости.
# 升级 pip 到最新版本
pip3 install --upgrade pip
# 安装 virtualenv ,用于配置虚拟环境
pip3 install --user --upgrade virtualenv
В обычных условиях, когда мы используем pip для установки пакетов, все они являются установленными глобальными пакетами, что эквивалентноnpm install -g
. Если сейчас есть два проекта, проект A зависит от simplejson@2, а проект B зависит от simplejson@3, поэтому мы немного беспомощны для разработки на одной машине. В это время может вступить в игру virtualenv.virtualenv может создать независимую рабочую среду Python, то есть песочницу.Вы даже можете использовать версию Python, отличную от текущей системы, в виртуальной среде, созданной virtualenv.
# 配置虚拟环境
cd ~/ml
virtualenv env
# 启动虚拟环境
# linux
source env/bin/activate
# windows
./env/Scripts/activate
После запуска следующим образом
(env) λ
Установите все зависимости модуля в виртуальной среде.
# 安装模块和依赖
(env) λ pip3 install --upgrade jupyter matplotlib numpy scipy
-
jupyter: веб-приложение для интерактивных вычислений. Его можно применять ко всему процессу вычислений: разработке, документированию, запуску кода и представлению результатов.
-
Numpy: расширенный пакет для вычислений с массивами, который поддерживает операции с многомерными массивами и матрицами, а также предоставляет большое количество библиотек математических функций для операций с массивами.
-
scipy: пакет расширения на основе numpy, который добавляет функции, включая численное интегрирование, оптимизацию, статистику и некоторые специальные функции.
-
matplotlib: пакет расширения, основанный на numpy, который предоставляет инструменты для рисования богатых данных, в основном используемые для рисования статистической графики.
-
scikit-learn: библиотека машинного обучения Python с открытым исходным кодом, основанная на Numpy и Scipy, которая предоставляет большое количество инструментов для интеллектуального анализа и анализа данных, включая ряд интерфейсов, таких как предварительная обработка данных, перекрестная проверка, алгоритмы и алгоритмы визуализации.
запустить юпитер
jupyter notebook
Jupyter запустит службу на порту 8888 и автоматически откроет браузер.
С новым в правом верхнем углу вы можете создать проект. После создания проекта мы можем легко запустить и вывести код Python на этой странице.
Подготовить данные
MNIST — это цифра (0 ~ 9), написанная от руки американскими старшеклассниками и сотрудниками Бюро переписи населения США. Следующее, что нужно сделать, это позволить нашей программе изучить информацию об этих изображениях и быть в состоянии распознать значение чисел, представленных входными изображениями.Это звучит немного сложно, не волнуйтесь, давайте сделаем это шаг за шагом.
Обучающие данные для MNIST готовятся здесь, гдеtrain_100
это обучающий набор данных,test_10
для тестового набора данных. В процессе машинного обучения мы обычно делим набор данных на два: обучающий набор и тестовый набор.Как правило, 80% данных используются для обучения, а 20% зарезервированы для тестирования. Поскольку это операция «Hello World», для обучения мы используем только данные 100. На самом деле этого количества данных далеко недостаточно.
Если вы хотите тренироваться с полными данными, вы можете скачать этот CSV-файл.
Семья P Eddie.com/Media/files…
данные наблюдения
После загрузки данных поместите файл csv (формат файла значений с разделителями-запятыми) в папку наборов данных, а затем используйте python для чтения файла.
data_file = open("datasets/mnist_train_100.csv", 'r')
data_list = data_file.readlines() # readlines方法用于读取文件的所有行,并返回一个数组
data_file.close()
len(data_list) # 数组长度为100
Распечатайте первую строку текста, чтобы увидеть, как отформатированы данные.
print(data_list[0])
len(data_list[0].split(',')) # 使用 , 进行分割,将字符串转换为数组
Видно, что строка данных содержит в общей сложности 785 данных, первый столбец представляет истинное значение написанного от руки числа (это значение в машинном обучении называется меткой), а следующие 784 данных представляют собой размер 28 * 28. значение пикселя, популярный Программное обеспечение для обработки изображений обычно использует 8 бит для представления пикселя, поэтому всего существует 256 уровней серого (значения пикселей находятся в диапазоне от 0 до 255), и каждый уровень представляет собой различную яркость.
Далее мы импортируем библиотеку numpy для обработки данных, values[1:] берем первую в конец массива и генерируем новый массив, используем numpy.asfarray для преобразования массива в ndarray с плавающей запятой, а затем каждый item Разделите на 255 и умножьте на 9, преобразуйте каждое число в однозначное число от 0 до 9, используйте astype(int) для преобразования каждого числа в тип int и, наконец, reshape((28,28) может преобразовать массив в двузначный размерный массив 28*28.
Если вы хотите узнать больше о numpy, вы можете проверить егоДокументация.
import numpy as np
values = data_list[3].split(',')
image_array = (np.asfarray(values[1:]) / 255 * 9).astype(int).reshape(28,28)
Это недостаточно интуитивно.Затем используйте matplotlib для рисования пикселей один за другим.
import matplotlib.pyplot
%matplotlib inline
matplotlib.pyplot.imshow(
np.asfarray(values[1:]).reshape(28,28),
cmap='Greys',
interpolation='None'
)
Построение нейронной сети
Мы просто наметим общий вид нейронной сети, которая требует как минимум три функции:
- Функция инициализации - установите количество узлов входного слоя, скрытого слоя и выходного слоя, а также случайно сгенерированные веса.
- Тренируйтесь - учите заданные тренировочные образцы, корректируя веса.
- Запрос. Получив ввод, получите результат прогноза.
Код фрейма следующий:
# 引入依赖库
import numpy as np
import scipy.special
import matplotlib.pyplot
# 神经网络类定义
class neuralNetwork:
# 初始化神经网络
def __init__():
pass
# 训练神经网络
def train():
pass
# 查询神经网络
def query():
pass
Инициализировать нейронную сеть
Далее давайте сделаем первый шаг, инициализируя нейронную сеть.
# 初始化神经网络
def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate):
# 设置输入层、隐藏层、输出层节点的数量
self.inodes = inputnodes
self.hnodes = hiddennodes
self.onodes = outputnodes
# 连接权重,随机生成输入层到隐藏层和隐藏层到输出层的权重
self.wih = np.random.rand(self.hnodes, self.inodes) - 0.5
self.who = np.random.rand(self.onodes, self.hnodes) - 0.5
# 学习率
self.lr = learningrate
# 将激活函数设置为 sigmoid 函数
self.activation_function = lambda x: scipy.special.expit(x)
pass
Генерация весов
Сгенерируйте веса соединения, используяnumpy
Библиотека функций, поддерживающая операции с массивами и матрицами большой размерности посредствомnumpy.random.rand(x, y)
может быстро создатьx * y
Матрица , где каждое число является случайным числом от 0 до 1. Потому что он используется при импорте библиотекиimport numpy as np
команда, которую можно использовать во всех кодахnp
заменитьnumpy
.
выше черезnumpy.random.rand
метод создания3 * 3
Матричный случай. Вычитание 0,5 гарантирует, что все сгенерированные веса могут поддерживать случайное значение в диапазоне от -0,5 до 0,5.
функция активации
scipy.special
Модуль содержит большое количество библиотек функций, использующихscipy.special
Библиотека может легко и быстро построить функцию активации:
activation_function = lambda x: scipy.special.expit(x)
нейронная сеть запросов
# 查询神经网络
def query(self, inputs_list):
# 将输入的数组转化为一个二维数组
inputs = np.array(inputs_list, ndmin=2).T
# 计算输入数据与权重的点积
hidden_inputs = np.dot(self.wih, inputs)
# 经过激活函数的到隐藏层数据
hidden_outputs = self.activation_function(hidden_inputs)
# 计算隐藏层数据与权重的点积
final_inputs = np.dot(self.who, hidden_outputs)
# 最终到达输出层的数据
final_outputs = self.activation_function(final_inputs)
return final_outputs
Запросить нейронную сеть так же просто, как использоватьnumpy
изdot
Этот метод можно использовать для нахождения скалярного произведения двух матриц.
Здесь есть точка познания, которая касаетсяnumpy
тип данных, черезnumpy.array
метод преобразования массива в python в объект N-мерного массиваNdarray
, второй параметр этого метода должен представлять преобразованное измерение.
На картинке выше обычный массив[1, 2, 3]
Используйте этот метод для преобразования в двумерный массив и возврата[[1, 2, 3]]
. Метод также имеет атрибут T, который, по сути, вызываетnumpy
изtranspose
чтобы поменять местами оси массива, как показано на следующем рисунке.
Путем транспонирования мы можем получить подходящую входную матрицу.
обучать нейронную сеть
# 训练神经网络
def train(self, inputs_list, targets_list):
# 将输入数据与目标数据转为二维数组
inputs = np.array(inputs_list, ndmin=2).T
targets = np.array(targets_list, ndmin=2).T
# 通过矩阵点积和激活函数得到隐藏层的输出
hidden_inputs = np.dot(self.wih, inputs)
hidden_outputs = self.activation_function(hidden_inputs)
# 通过矩阵点积和激活函数得到最终输出
final_inputs = np.dot(self.who, hidden_outputs)
final_outputs = self.activation_function(final_inputs)
# 获取目标值与实际值的差值
output_errors = targets - final_outputs
# 反向传播差值
hidden_errors = np.dot(self.who.T, output_errors)
# 通过梯度下降法更新隐藏层到输出层的权重
self.who += self.lr * np.dot(
(output_errors * final_outputs * (1.0 - final_outputs)),
np.transpose(hidden_outputs)
)
# 通过梯度下降法更新输入层到隐藏层的权重
self.wih += self.lr * np.dot(
(hidden_errors * hidden_outputs * (1.0 - hidden_outputs)),
np.transpose(inputs)
)
pass
Первая половина обучения нейронной сети аналогична запросу, в середине происходит обратное распространение полученной разности путем вычисления скалярного произведения матриц, и, наконец, вес корректируется с помощью градиентного подчиненного метода. вself.lr
Скорость обучения для градиентного спуска, это значение представляет собой скорость, которая ограничивает направление градиента, нам нужно часто настраивать это значение, чтобы достичь оптимального решения модели.
тренировать
# 设置每一层的节点数量
input_nodes = 784
hidden_nodes = 100
output_nodes = 10
# 学习率
learning_rate = 0.1
# 创建神经网络模型
n = neuralNetwork(input_nodes,hidden_nodes,output_nodes, learning_rate)
# 加载训练数据
training_data_file = open("datasets/mnist_train_100.csv", 'r')
training_data_list = training_data_file.readlines()
training_data_file.close()
# 训练神经网络
# epochs 表示训练次数
epochs = 10
for e in range(epochs):
# 遍历所有数据进行训练
for record in training_data_list:
# 数据通过 ',' 分割,变成一个数组
all_values = record.split(',')
# 分离出图片的像素点到一个单独数组
inputs = (np.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01
# 创建目标输出值(数字 0~9 出现的概率,默认全部为 0.01)
targets = np.zeros(output_nodes) + 0.01
# all_values[0] 表示手写数字的真实值,将该数字的概率设为 0.99
targets[int(all_values[0])] = 0.99
n.train(inputs, targets)
pass
pass
# 训练完毕
print('done')
Подтвердить результаты обучения
# 加载测试数据
test_data_file = open("datasets/mnist_test_10.csv", 'r')
test_data_list = test_data_file.readlines()
test_data_file.close()
# 测试神经网络
# 记录所有的训练值,正确存 1 ,错误存 0 。
scorecard = []
# 遍历所有数据进行测试
for record in test_data_list:
# 数据通过 ',' 分割,变成一个数组
all_values = record.split(',')
# 第一个数字为正确答案
correct_label = int(all_values[0])
# 取出测试的输入数据
inputs = (np.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01
# 查询神经网络
outputs = n.query(inputs)
# 取出概率最大的数字,表示输出
label = np.argmax(outputs)
# 打印出真实值与查询值
print('act: ', label, ' pre: ', correct_label)
if (label == correct_label):
# 神经网络查询结果与真实值匹配,记录数组存入 1
scorecard.append(1)
else:
# 神经网络查询结果与真实值不匹配,记录数组存入 0
scorecard.append(0)
pass
pass
# 计算训练的成功率
scorecard_array = np.asarray(scorecard)
print("performance = ", scorecard_array.sum() / scorecard_array.size)
полный код
Чтобы увидеть полный код, вы можете посетить мой github:deep_neural_network
Суммировать
На данный момент модельный принцип и практика всей глубокой сети уровня бога завершены.Хотя некоторые концепции не объясняются так подробно, вы также можете узнать больше, выполнив поиск других материалов. Спасибо книге "Python Neural Network Programming", за то, что у нее есть этот блог. Если интересно, можете купить и почитать. В этой книге действительно очень простым языком описываются сложные математические расчеты.
Искусственный интеллект сейчас действительно очень горячий этап, и я надеюсь, что заинтересованные студенты будут пробовать больше, но не стоит слепо гнаться за новым и забывать свои изначальные преимущества.
Наконец, оригинальная ссылка прилагается:Принципы и практика глубоких нейронных сетей