Эта статья взята из«Принципы глубокого обучения и практика PyTorch»
Начав с практической задачи прогнозирования количества общих велосипедов в определенном месте, мы проведем читателей во дворец нейронных сетей, воспользуемся PyTorch для построения предсказателя общего велосипеда и освоим нейроны, нейронные сети, функции активации и машинное обучение. в реальном боевом процессе и другие основные понятия, а также методы предварительной обработки данных. Кроме того, «черный ящик» нейронной сети будет демистифицирован, чтобы увидеть, как она работает и какие нейроны играют ключевую роль, чтобы читатели могли глубже понять, как работают нейронные сети.
3.1 Проблема совместного использования велосипедов
Примерно с 2016 года вокруг нас было много общих велосипедов. Разноцветные и всевозможные общие велосипеды, как взрывы, разлетаются по улицам и переулкам города.
Хотя совместное использование велосипедов приносит людям удобство, существует и неприятная проблема: велосипеды распределяются очень неравномерно. Например, в утренний час пик у некоторых входов в метро часто скапливается большое количество велосипедов, но в вечерний час пик найти велосипед сложно, что доставляет неудобства тем, кому необходимо пользоваться общими велосипедами.
Так как же решить проблему неравномерного распределения общих велосипедов? Текущий способ заключается в том, что компании по прокату велосипедов нанимают рабочих для перемещения велосипедов и доставки их в районы, где они необходимы. Но вопрос в том, сколько велосипедов нужно отправить? Когда он будет отправлен? Куда это будет отправлено? Это требует точных знаний о распределении общих велосипедов в разных местах по всему городу, и необходимо заранее договориться, потому что есть определенная задержка с доставкой велосипедов работниками. Это очень серьезная проблема для велопрокатных компаний.
Чтобы решить эту проблему более научно и эффективно, нам нужно построить предсказатель количества велосипедов, чтобы предсказать количество велосипедов в определенное время и на определенной парковке для ссылки на общие велосипедные компании, чтобы реализовать разумная доставка велосипедов.
Делайте кирпичи без соломы. Для создания такого предсказателя велосипеда требуется определенный объем общих данных о велосипедах. Во избежание коммерческих споров, а также для того, чтобы сделать разработку и объяснение этой книги более удобными, в этом примере для выполнения нашей задачи будет использоваться иностранный общедоступный набор данных по совместному использованию велосипедов (Capital Bikeshare).Ссылка для скачивания набора данных:www.capitalbikeshare.com/системные данные.
После загрузки набора данных мы можем напрямую открыть его с помощью обычного программного обеспечения для обработки таблиц или текстового редактора, как показано на рисунке 3.1.
Данные с 1 января 2011 г. по 31 декабря 2012 г., использование велосипедов в определенном месте, каждая строка представляет собой запись данных, всего 17 379 записей. Часть данных записывает день недели, будь то праздник, погоду и скорость ветра в определенном месте в течение часа, а также использование велосипеда в этом районе (записывается переменной cnt), что является сумма, о которой мы заботимся больше всего.
Мы можем перехватывать данные за определенный период времени и отображать зависимость cnt во времени в виде графика. На рис. 3.2 представлены данные с 1 по 10 января 2011 г. Горизонтальная ось — время, вертикальная ось — количество велосипедов. Количество велосипедов колеблется во времени и имеет определенную закономерность. Нетрудно заметить, что пиковое количество велосипедов в будние дни намного выше, чем в выходные.
Вопрос, который нам нужно решить, заключается в том, можем ли мы предсказать тенденцию количества велосипедов в регионе в следующий период времени на основе исторических данных? В этой главе мы узнаем, как разработать модель нейронной сети для прогнозирования количества велосипедов. Для этой проблемы мы не предоставляем идеальное решение сразу, а пробуем разные решения шаг за шагом. Объединяя эту проблему, мы в основном объясним, что такое искусственный нейрон, что такое нейронная сеть, как построить нейронную сеть по мере необходимости, что такое переобучение, как решить проблему переобучения и так далее. В дополнение к этому мы научимся анализировать нейронную сеть, чтобы понять, как она работает и как она соответствует данным.
3.2 Велосипедный предиктор 1.0
В этом разделе будет создан велосипедный предиктор, представляющий собой нейронную сеть с одним скрытым элементом. Мы научим его подстраиваться под кривую колебаний общего велосипеда.
Однако, прежде чем разрабатывать велосипедный предиктор, необходимо понять концепцию и принцип работы искусственной нейронной сети.
3.2.1 Введение в искусственные нейронные сети
Искусственная нейронная сеть (называемая нейронной сетью) — это вычислительная модель, вдохновленная биологической нейронной сетью человеческого мозга. Искусственные нейронные сети очень хорошо изучают сопоставления входных данных и меток, чтобы делать прогнозы или решать задачи классификации. Искусственную нейронную сеть также называют универсальным установщиком, потому что она может соответствовать произвольным функциям или отображениям.
Нейронная сеть с прямой связью является одной из наиболее часто используемых сетей и обычно включает в себя три слоя искусственных нейронных единиц, а именно входной слой, скрытый слой и выходной слой, как показано на рисунке 3.3. Среди них скрытый слой может содержать несколько слоев, что составляет так называемую глубокую нейронную сеть.
Каждый кружок на рисунке представляет собой искусственный нейрон, а линия — искусственный синапс, соединяющий два нейрона. Каждое ребро содержит значение, называемое весом, которое мы обычно обозначаем через w.
Работа нейронной сети обычно включает в себя процесс прогнозирования с прямой связью (или процесс принятия решения) и процесс обучения с обратной связью.
В процессе прогнозирования с прямой связью сигнал вводится из блока ввода и передается по краям сети, и каждый сигнал умножается на вес на краю, чтобы получить вход блока скрытого слоя; затем блок скрытого слоя суммирует (суммирует) входные сигналы со всех ребер, а затем выводит их после определенной обработки (конкретный процесс обработки будет описан в следующем разделе), эти выходные сигналы затем умножаются на множество связей из скрытого слоя в выходной Затем поступает входной сигнал в выходной блок, наконец, выходной блок суммирует сигнал каждого фронта входного соединения и обрабатывает его перед выводом. Конечным результатом является вывод всей нейронной сети. Нейронная сеть будет корректировать значение веса w на каждом ребре на этапе обучения.
В процессе обучения с обратной связью каждый выходной нейрон сначала вычисляет свою ошибку предсказания, а затем распространяет эту ошибку обратно по всем ребрам сети, чтобы получить ошибку каждого узла скрытого слоя. Наконец, количество обновления веса на соединенном ребре рассчитывается в соответствии с ошибкой двух узлов, соединенных каждым соединенным ребром, чтобы завершить обучение и настройку сети.
Далее мы подробно опишем процесс работы нейронной сети, начиная с искусственных нейронов.
3.2.2 Искусственный нейрон
Искусственная нейронная сеть похожа на биологическую нейронную сеть, состоящую из искусственных нейронов (называемых нейронами). Нейроны используют простые математические модели для имитации передачи сигналов и активации биологических нервных клеток. Чтобы понять, как работают искусственные нейронные сети, давайте сначала рассмотрим простейший случай: модель с одним нейроном. Как показано на рисунке 3.4, он имеет только одну единицу входного слоя, одну единицу скрытого слоя и одну единицу выходного слоя.
x представляет входные данные, y представляет выходные данные, все они действительные числа. Вес w от входной единицы к скрытому слою, смещение b единицы скрытого слоя и вес w' от скрытого слоя к выходному слою — все это действительные числа, которые могут принимать любое значение.
Мы можем думать об этой простейшей нейронной сети как о функции, которая отображает от x до y, а w, b и w' являются параметрами функции. Уравнение для этой функции показано в уравнении на рис. 3.5, где σ представляет собой сигмовидную функцию. При w=1, w'=1, b=0 график этой функции показан на рис. 3.5.
Это форма сигмовидной функции и математическое выражение для σ(x). Наблюдая за кривой, нетрудно найти, что при x меньше 0 σ(x) меньше 1/2, и чем меньше x, тем ближе σ(x) к 0; когда x больше чем 0, σ(x) больше 1/2, и чем больше x, тем ближе σ(x) к 1. Существует внезапное изменение от 0 до 1 вблизи точки, где x = 0.
Когда мы меняем параметры w, b и w', соответственно изменяется и график функции. Например, мы могли бы также оставить неизменными w'=1, b=0 и изменить размер w, график изменения его функции показан на рис. 3.6.
Видно, что при w>0 его размер определяет степень кривизны функции, чем больше w, тем больше степень кривизны функции вблизи точки 0, поэтому мутация от x=0 будет больше тяжелый; когда w
Давайте посмотрим на влияние параметра b на кривую, сохранив w=w'=1 без изменений, как показано на рис. 3.7.
Хорошо видно, что b управляет горизонтальным положением кривой сигмовидной функции. b>0 график функции смещается влево, в противном случае — вправо. Наконец, давайте посмотрим, как w' влияет на эту кривую, как показано на рис. 3.8.
Нетрудно видеть, что при w' > 0 высота кривой контролируется w', а при w'
Можно видеть, что, управляя тремя параметрами w, w' и b, мы можем произвольно настроить форму функции от входа x до выхода y. Однако, как бы вы ее ни регулировали, эта кривая всегда будет S-образной (в том числе перевернутой S-образной). Чтобы получить более сложное изображение функции, нам нужно ввести больше нейронов.
3.2.3 Два нейрона скрытого слоя
Давайте немного усложним модель и посмотрим, какое влияние на кривую оказывают два нейрона скрытого слоя, как показано на рис. 3.9.
После того, как входной сигнал попадет в сеть, он будет разделен на два пути, один путь входит в первый нейрон слева, а другой путь входит во второй нейрон справа. Эти два нейрона выполняют вычисления по отдельности и получают y путем взвешенного суммирования w'1 и w'2. Итак, выход y на самом деле является суперпозицией двух нейронов. Эта сеть по-прежнему является функцией, которая отображает x в y, и функциональное уравнение выглядит так:
В этой формуле есть 6 различных параметров, таких как w1, w2, w'1, w'2, b1, b2. Их комбинация также повлияет на форму кривой.
Например, мы можем взять w1=w2=w'1=w'2=1, b1=-1, b2=0, тогда форма кривой функции показана на рис. 3.10.
Видно, что график синтезированной функции превращается в кривую с двумя ступенями.
Рассмотрим другую комбинацию параметров, w1=w2=1, b1=0, b2=-1, w'1=1, w'2=-1, тогда график функции показан на рис. 3.11.
Отсюда видно, что мы синтезировали кривую с одним пиком, чем-то похожую на нормально распределенную кривую колокола. В общем, пока комбинация параметров изменена, мы можем использовать два нейрона скрытого слоя, чтобы подогнать любую кривую с одним пиком.
Тогда, если в скрытом слое 4 или 6 или даже больше нейронов, нетрудно представить, что может быть получена кривая с двойными вершинами, тройными вершинами и любым количеством вершин.Грубо можно считать, что два нейрона могут быть используется с для приближения к пику (впадине). На самом деле, для более общих случаев ученые уже теоретически доказали, что конечное число нейронов скрытого слоя может аппроксимировать любую кривую на конечном интервале, что называется теоремой об универсальной аппроксимации.
3.2.4 Тренировки и бег
В предыдущем обсуждении мы видели, что можно получить любую желаемую кривую, если можно настроить комбинацию параметров в нейронной сети. Но вопрос в том, как мы должны выбирать эти параметры? Ответ кроется в обучении.
Чтобы завершить обучение нейронной сети, мы должны сначала определить функцию потерь для нейронной сети, которая используется для измерения выходных характеристик сети при существующей комбинации параметров. Это похоже на общую функцию ошибок (то есть сумму квадратов расстояний от подобранной линии до всех точек) L при прогнозировании цен на жилье с использованием линейной регрессии в главе 2. Точно так же в примере с прогнозированием велосипедов мы также можем определить функцию потерь как среднее значение суммы квадратов разницы между количеством велосипедов, предсказанным нейронной сетью, и количеством велосипедов в фактических данных для всех выборок данных. , а именно:
Здесь N — общее количество выборок,
С этой функцией потерь L у нас есть направление на настройку параметров нейросети — максимально минимизировать L. Следовательно, нейронной сети необходимо изучить веса и смещения на границах между нейронами, а цель обучения — получить набор комбинаций значений параметров, которые могут минимизировать общую ошибку.
Это оптимизационная задача поиска экстремальных значений.Высшая математика говорит нам, что нам нужно только установить производную равной нулю, чтобы найти ее. Однако, поскольку нейронная сеть, как правило, очень сложна и содержит большое количество нелинейных операций, прямое использование математического метода производной нецелесообразно, поэтому для ее решения мы обычно используем численный метод, то есть алгоритм градиентного спуска. . Каждая итерация продвигается в отрицательном направлении градиента, так что значение ошибки постепенно уменьшается. Обновление параметров использует алгоритм обратного распространения, а функция потерь L распространяется обратно по сети слой за слоем для корректировки параметров каждого уровня. Мы не будем вдаваться в детали алгоритма обратного распространения здесь, потому что PyTorch автоматически превратил этот сложный алгоритм в простую команду: reverse. Пока эта команда вызывается, PyTorch автоматически выполняет алгоритм обратного распространения и вычисляет градиент каждого параметра.Нам нужно только обновить параметры в соответствии с этими градиентами, чтобы завершить одноэтапное обучение.
Обучение и работа нейронной сети обычно чередуются. То есть в каждом цикле нейронная сеть будет выполнять операцию прямой связи от входа к выходу; затем, в соответствии со значением потерь на выходе, выполняется алгоритм обратного распространения для настройки различных параметров. на нейронной сети. Повторение этих двух шагов снова и снова заставит нейронную сеть учиться все лучше и лучше.
3.2.5 Неудачные нейронные предикторы
Теперь, когда мы выяснили, как работают нейронные сети, давайте посмотрим, как мы можем использовать нейронные сети для прогнозирования кривой общего велосипеда. Мы надеемся использовать искусственную нейронную сеть, чтобы подогнать кривую использования велосипедов за определенный период времени и получить кривую использования велосипедов в будущие моменты времени, следуя практике прогнозирования цен на жилье.
Чтобы сделать демонстрацию проще и нагляднее, мы выбрали только первые 50 записей в данных и построили кривую, как показано на рис. 3.12. На этой кривой абсцисса — это номер записи данных, а ордината — соответствующее количество велосипедов.
Далее нам нужно спроектировать нейронную сеть, вход которой x — это число данных, а выход — соответствующее количество велосипедов. Посмотрев на эту кривую, мы обнаружили, что она имеет по крайней мере 3 пика, и использование 10 единиц скрытого слоя достаточно, чтобы подогнать эту кривую. Поэтому архитектура нашей искусственной нейронной сети показана на рис. 3.13.
Далее нам нужно написать программу для реализации этой сети. Сначала импортируйте все зависимые библиотеки, используемые этой программой. Здесь мы будем использовать библиотеку pandas для чтения и обработки данных. Читателям необходимо сначала установить этот пакет и запустить conda install pandas в среде Anaconda.
import numpy as np
import pandas as pd #读取csv文件的库
import torch
from torch.autograd import Variable
import torch.optim as optim
import matplotlib.pyplot as plt
#让输出图形直接在Notebook中显示
%matplotlib inline
Затем импортируйте нужные данные из файла на жестком диске.
data_path = 'hour.csv' #读取数据到内存,rides为一个dataframe对象
rides = pd.read_csv(data_path)
rides.head() #输出部分数据
counts = rides['cnt'][:50] #截取数据
x = np.arange(len(counts)) #获取变量x
y = np.array(counts) #单车数量为y
plt.figure(figsize = (10, 7)) #设定绘图窗口大小
plt.plot(x, y, 'o-') #绘制原始数据
plt.xlabel('X') #更改坐标轴标注
plt.ylabel('Y') #更改坐标轴标注
Здесь мы используем библиотеку pandas для быстрого импорта данных из CSV-файлов и сохранения их в поездках. rides может хранить данные в виде двумерной таблицы, к которой можно обращаться и манипулировать ею как с массивом. Роль rides.head() состоит в том, чтобы распечатать часть записи данных.
После этого мы выбираем первые 50 записей из всех записей в поездках и отфильтровываем только поле cnt в массив counts. В этом массиве хранятся первые 50 записей об использовании велосипедов. Затем мы рисуем первые 50 записей, что и является эффектом, показанным на рис. 3.13.
Когда данные готовы, мы можем использовать PyTorch для создания искусственной нейронной сети. Как и в примере с линейной регрессией в главе 2, сначала нам нужно определить ряд переменных, включая веса и смещения всех ребер, и позволить PyTorch автоматически генерировать вычислительный граф с помощью этих переменных.
#输入变量,1,2,3,...这样的一维数组
x = Variable(torch.FloatTensor(np.arange(len(counts), dtype = float)))
#输出变量,它是从数据counts中读取的每一时刻的单车数,共50个数据点的一维数组,作为标准答案
y = Variable(torch.FloatTensor(np.array(counts, dtype = float)))
sz = 10 #设置隐含层神经元的数量
#初始化输入层到隐含层的权重矩阵,它的尺寸是(1,10)
weights = Variable(torch.randn(1, sz), requires_grad = True)
#初始化隐含层节点的偏置向量,它是尺寸为10的一维向量
biases = Variable(torch.randn(sz), requires_grad = True)
#初始化从隐含层到输出层的权重矩阵,它的尺寸是(10,1)
weights2 = Variable(torch.randn(sz, 1), requires_grad = True)
После установки переменных и начальных параметров нейронной сети следующим шагом является итеративное обучение нейронной сети.
learning_rate = 0.0001 #设置学习率
losses = [] #该数组记录每一次迭代的损失函数值,以方便后续绘图
for i in range(1000000):
#从输入层到隐含层的计算
hidden = x.expand(sz, len(x)).t() * weights.expand(len(x), sz) + biases.expand(len(x), sz)
#此时,hidden变量的尺寸是:(50,10),即50个数据点,10个隐含层神经元
#将sigmoid函数作用在隐含层的每一个神经元上
hidden = torch.sigmoid(hidden)
#隐含层输出到输出层,计算得到最终预测
predictions = hidden.mm(weights2)
#此时,predictions的尺寸为:(50,1),即50个数据点的预测数值
#通过与数据中的标准答案y做比较,计算均方误差
loss = torch.mean((predictions - y) ** 2)
#此时,loss为一个标量,即一个数
losses.append(loss.data.numpy())
if i % 10000 == 0: #每隔10000个周期打印一下损失函数数值
print('loss:', loss)
#*****************************************
#接下来开始梯度下降算法,将误差反向传播
loss.backward() #对损失函数进行梯度反传
#利用上一步计算中得到的weights,biases等梯度信息更新weights或biases的数值
weights.data.add_(- learning_rate * weights.grad.data)
biases.data.add_(- learning_rate * biases.grad.data)
weights2.data.add_(- learning_rate * weights2.grad.data)
#清空所有变量的梯度值
weights.grad.data.zero_()
biases.grad.data.zero_()
weights2.grad.data.zero_()
В приведенном выше коде у нас есть 100 000 обучающих итераций. На каждой итерации мы вводим x из 50 точек данных в нейронную сеть в виде массива и позволяем нейронной сети выполнять вычисления шаг за шагом в соответствии с шагами от входного слоя к скрытому слою, а затем от скрытого слоя. в выходной слой и, наконец, выведите предсказание массива предсказаний для 50 точек данных.
После этого вычислите ошибку между прогнозом и стандартным ответом y и вычислите среднюю потерю значения ошибки для всех 50 точек данных, которая представляет собой функцию потерь L, о которой мы упоминали ранее. Затем вызовите loss.backward(), чтобы завершить процесс обратного распространения ошибки по нейронной сети, тем самым вычислив значение обновления градиента каждого конечного узла на графе вычислений и записав его в атрибуте .grad каждой переменной. Наконец, мы используем это значение градиента для обновления значения каждого параметра, тем самым завершая одну итерацию.
Тщательное сравнение этого кода с кодом линейной регрессии из главы 2 показывает, что все операции одинаковы, за исключением промежуточных операций и функции потерь. На самом деле, почти каждый случай машинного обучения в этой книге использует этапы прямой связи, обратного распространения для вычисления градиентов и обновления значений параметров на основе градиентов.
Мы можем распечатать нисходящую кривую Loss с пошаговыми итерациями, что может помочь нам визуализировать процесс обучения нейронной сети, как показано на рисунке 3.14.
plt.plot(losses)
plt.xlabel('Epoch')
plt.ylabel('Loss')
Из этой кривой видно, что ошибка, предсказанная нейронной сетью, постепенно уменьшается со временем. Более того, после примерно 20 000 шагов ошибка практически не показывает значительного снижения.
Затем мы можем нарисовать кривую прогноза обученной сети по этим 50 точкам данных и сравнить ее со стандартным ответом y, Код выглядит следующим образом:
x_data = x.data.numpy() #获得x包裹的数据
plt.figure(figsize = (10, 7)) #设定绘图窗口大小
xplot, = plt.plot(x_data, y.data.numpy(), 'o') #绘制原始数据
yplot, = plt.plot(x_data, predictions.data.numpy()) #绘制拟合数据
plt.xlabel('X') #更改坐标轴标注
plt.ylabel('Y') #更改坐标轴标注
plt.legend([xplot, yplot],['Data', 'Prediction under 1000000 epochs']) #绘制图例
plt.show()
Окончательная визуализация показана на рис. 3.15.
Как видите, наша предсказанная кривая довольно хорошо соответствует данным на первом пике, но после этого она сильно отстает от реальных данных. Почему это?
Мы знаем, что диапазон значений x составляет 1 ~ 50, а начальные значения всех весов и смещений представляют собой нормально распределенные случайные числа, установленные в (-1, 1), затем входной слой к узлу скрытого слоя Диапазон значений становится -50~50, и требуется много вычислительного времени, чтобы подогнать множественные пики сигмовидной функции к желаемым позициям. На самом деле, если время обучения больше, мы можем довольно хорошо подогнать заднюю часть кривой.
Решение этой проблемы состоит в том, чтобы нормализовать диапазон входных данных, то есть позволить входному значению x находиться в диапазоне от 0 до 1. Поскольку диапазон x в данных составляет от 1 до 50, нам нужно только разделить каждое значение на 50:
x = Variable(torch.FloatTensor(np.arange(len(counts), dtype = float) / len(counts)))
Эта операция изменит диапазон значений x на 0,02, 0,04, …, 1. После внесения этих улучшений и последующего запуска программы вы можете увидеть, что скорость обучения на этот раз значительно выше, а эффект подгонки после визуализации лучше, как показано на рис. 3.16.
Мы видим, что улучшенная модель имеет два пика и очень хорошо соответствует этим точкам данных, образуя красивую кривую.
Далее нам нужно использовать обученную модель для прогнозирования. Наша задача прогнозирования — это количество велосипедов в следующих 50 фрагментах данных. В это время значение x равно 51, 52, …, 100, которое также следует разделить на 50.
counts_predict = rides['cnt'][50:100] #读取待预测的后面50个数据点
x = Variable(torch.FloatTensor((np.arange(len(counts_predict), dtype = float) + len(counts)) / len(counts)))
#读取后面50个点的y数值,不需要做归一化
y = Variable(torch.FloatTensor(np.array(counts_predict, dtype = float)))
#用x预测y
hidden = x.expand(sz, len(x)).t() * weights.expand(len(x), sz) #从输入层到隐含层的计算
hidden = torch.sigmoid(hidden) #将sigmoid函数作用在隐含层的每一个神经元上
predictions = hidden.mm(weights2) #从隐含层输出到输出层,计算得到最终预测
loss = torch.mean((predictions - y) ** 2) #计算预测数据上的损失函数
print(loss)
#将预测曲线绘制出来
x_data = x.data.numpy() #获得x包裹的数据
plt.figure(figsize = (10, 7)) #设定绘图窗口大小
xplot, = plt.plot(x_data, y.data.numpy(), 'o') #绘制原始数据
yplot, = plt.plot(x_data, predictions.data.numpy()) #绘制拟合数据
plt.xlabel('X') #更改坐标轴标注
plt.ylabel('Y') #更改坐标轴标注
plt.legend([xplot, yplot],['Data', 'Prediction']) #绘制图例
plt.show()
В итоге мы получим кривую, показанную на рис. 3.17. Линии — это предсказанные кривые, данные нашей моделью, а точки — это кривые, соответствующие фактическим данным. Предсказания модели совершенно не соответствуют реальным данным!
Почему наша нейронная сеть может очень хорошо соответствовать известным 50 точкам данных, но вообще не может предсказать больше точек данных? Причина: переобучение.
3.2.6 Переобучение
Так называемый феномен переобучения означает, что модель может делать очень хорошие прогнозы на обучающих данных, но не может хорошо работать на новых тестовых данных. В этом примере обучающие данные — это первые 50 точек данных, а тестовые данные — следующие 50 точек данных. Наша модель может плавно подогнать кривую обучающих данных путем корректировки параметров, но эта преднамеренная подгонка вообще не имеет значения обобщения, в результате чего эта подгоночная кривая далека от стандартного ответа тестовых данных. Наша модель нейронной сети не изучала закономерности в данных.
Так почему же наша нейронная сеть не может изучить паттерн на кривой? Причина в том, что мы выбираем неправильную переменную признака: мы пытаемся предсказать y, используя индекс данных (1, 2, 3, …) или его нормализацию (0,1, 0,2, …). Однако характер колебаний кривой (то есть количества используемых велосипедов), очевидно, зависит не от индекса, а от таких факторов, как погода, скорость ветра, день недели и выходной день. Однако, несмотря ни на что, мы настаиваем на подгонке всей кривой мощной искусственной нейронной сетью, что естественным образом приводит к явлению переподгонки, а это очень серьезная переподгонка.
Из этого примера видно, что слепое следование технологии искусственного интеллекта без учета сути реальной проблемы может легко привести нас к окольным путям. Когда мы сталкиваемся с большими данными, смысл, стоящий за данными, часто может помочь нам найти кратчайший путь для более быстрого анализа больших данных.
В этом разделе, хотя мы и потратили много времени, не решая задачу по-настоящему, мы все же многое узнали, в том числе о том, как работают нейронные сети, как выбрать количество скрытых слоев в соответствии со сложностью задачи и как настроить Data makes. тренироваться быстрее. Что еще более важно, мы усвоили кровавые уроки того, что такое переобучение.
3.3 Велосипедный предсказатель 2.0
Далее, давайте приступим к решению проблемы. Поскольку мы догадались, что можем лучше предсказать количество велосипедов, используя такую информацию, как погода, скорость ветра, день недели, выходной день, и наши исходные данные содержат эту информацию, мы могли бы также перепроектировать нейронную сеть для корреляции эти Информация вводится для прогнозирования количества велосипедов.
3.3.1 Процесс предварительной обработки данных
Однако, прежде чем мы начнем проектировать нейронные сети, лучше внимательно изучить данные, потому что лучшее понимание данных будет играть более важную роль.
При более глубоком рассмотрении данных на рис. 3.2 мы обнаруживаем, что все переменные можно разделить на два типа: одна — типовая, а другая — числовая.
Так называемая переменная типа означает, что эта переменная может принимать значения в нескольких разных категориях, например, переменная недели имеет типы 1, 2, 3, …, 0, представляющие понедельник, вторник, среду соответственно. ... дни воскресенья. Переменные погодные условия могут принимать значения от 1 до 4. Где 1 — солнечно, 2 — облачно, 3 — небольшой дождь/снег, 4 — сильный дождь/снег.
Другой тип — это числовой тип, представляющий собой переменную, которая принимает последовательные значения из диапазона значений. Например, влажность — это переменная, принимающая непрерывные значения из интервала [0, 1]. Температура, скорость ветра также являются переменными этого типа.
Мы не можем скармливать нейросети разные типы переменных без какой-либо обработки, потому что разные значения имеют совершенно разное значение. В переменной типа размер числа на самом деле ничего не значит. Например, число 5 больше числа 1, но это не значит, что пятница более особенная, чем понедельник. Кроме того, диапазон изменения различных переменных числового типа также различен. Если их смешать напрямую, это обязательно вызовет ненужные проблемы. Исходя из приведенных выше соображений, нам необходимо предварительно обработать две переменные отдельно.
1. Горячее кодирование переменных типа
Размер переменной типа не имеет значения, он просто позволяет различать разные типы. Например, переменная сезона может быть равна 1, 2, 3, 4, то есть четырем временам года, а цифры служат только для их различения. Мы не можем напрямую передать переменную сезона в нейронную сеть, потому что значение сезона не представляет соответствующий уровень сигнала. Наше решение состоит в том, чтобы преобразовать переменную типа в «горячую» кодировку, как показано в таблице 3.1.
Затем нам нужно только преобразовать переменную типа столбца в вектор с горячим кодированием нескольких столбцов в данных, чтобы завершить процесс предварительной обработки этой переменной, как показано на рис. 3.18.
Таким образом, исходный атрибут дня недели преобразуется в 7 различных атрибутов, а в базу данных добавляется сразу 6 столбцов.
Программно панды могут легко реализовать вышеуказанные операции, код выглядит следующим образом:
dummy_fields = ['season', 'weathersit', 'mnth', 'hr', 'weekday'] #所有类型编码变量的名称
for each in dummy_fields:
#取出所有类型变量,并将它们转变为独热编码
dummies = pd.get_dummies(rides[each], prefix=each, drop_first=False)
#将新的独热编码变量与原有的所有变量合并到一起
rides = pd.concat([rides, dummies], axis=1)
#将原来的类型变量从数据表中删除
fields_to_drop = ['instant', 'dteday', 'season', 'weathersit', 'weekday', 'atemp', 'mnth', 'workingday',
'hr'] #要删除的类型变量的名称
data = rides.drop(fields_to_drop, axis=1) #将它们从数据库的变量中删除
После этой обработки исходные данные, содержащие всего 17 столбцов, внезапно стали 59 столбцами, и некоторые фрагменты данных показаны на рис. 3.19.
** 2. Обработка переменных числового типа**
Проблема с числовыми переменными заключается в том, что каждая переменная изменяется в разном диапазоне и в разных единицах, поэтому разные переменные нельзя сравнивать. Решение, которое мы принимаем, состоит в том, чтобы стандартизировать эту переменную, то есть стандартизировать переменную со средним значением и стандартным отклонением переменной, чтобы преобразовать их в значения, которые колеблются в интервале [-1, 1]. Например, для переменной температуры temp среднее значение ее значений по всей базе равно mean(temp), а дисперсия – std(temp), тогда нормированная температура рассчитывается как:
temp' — это число в интервале [-1, 1]. Преимущество этого заключается в том, что переменные с разными диапазонами значений могут быть установлены на равной основе.
Мы можем нормализовать эти переменные с помощью следующего кода:
quant_features = ['cnt', 'temp', 'hum', 'windspeed'] #数值类型变量的名称
scaled_features = {} #将每一个变量的均值和方差都存储到scaled_features变量中
for each in quant_features:
#计算这些变量的均值和方差
mean, std = data[each].mean(), data[each].std()
scaled_features[each] = [mean, std]
#对每一个变量进行归一化
data.loc[:, each] = (data[each] - mean)/std
** 3. Разделение набора данных**
После предварительной обработки наш набор данных содержит 17 379 записей и 59 переменных. Далее мы разделим этот набор данных.
Во-первых, на наборе переменных мы делим его на два набора: признак и цель. Среди них набор переменных функций включает в себя: год (год), будь то праздник (праздник), температура (temp), влажность (гул), скорость ветра (скорость ветра), сезон 1~4 (сезон), погода 1~ 4 (weathersit, другой тип погоды), месяц 1–12 (месяц), час 0–23 (час) и неделя 0–6 (день недели), которые являются входными переменными для нейронной сети. Целевые переменные включают: количество пользователей (cnt), количество временных пользователей (случайных) и количество зарегистрированных пользователей (registered). Среди них мы используем только cnt в качестве целевой переменной, а две другие пока не выполняют никакой обработки. Мы будем использовать 56 переменных признаков в качестве входных данных нейронной сети, чтобы предсказать 1 переменную в качестве выходных данных нейронной сети.
Затем мы разделили 17 379 записей на два набора: первые 16 875 записей использовались в качестве обучающего набора для обучения нашей нейронной сети, а данные за последний 21 день (504 записи) использовались в качестве тестового набора для проверки эффекта предсказания модель. Эта часть данных не участвует в обучении нейронной сети, как показано на рис. 3.20.
Код обработки данных выглядит следующим образом:
test_data = data[-21*24:] #选出训练集
train_data = data[:-21*24] #选出测试集
#目标列包含的字段
target_fields = ['cnt','casual', 'registered']
#训练集划分成特征变量列和目标特征列
features, targets = train_data.drop(target_fields, axis=1), train_data[target_fields]
#测试集划分成特征变量列和目标特征列
test_features, test_targets = test_data.drop(target_fields, axis=1), test_data[target_fields]
#将数据类型转换为NumPy数组
X = features.values #将数据从pandas dataframe转换为NumPy
Y = targets['cnt'].values
Y = Y.astype(float)
Y = np.reshape(Y, [len(Y),1])
losses = []
3.3.2 Построение нейронной сети
После обработки данных мы построим новую искусственную нейронную сеть. Эта сеть имеет 3 слоя: входной слой, скрытый слой и выходной слой. Размер (количество нейронов) каждого слоя равен 56, 10 и 1 соответственно (как показано на рис. 3.21). Среди них количество нейронов во входном и выходном слоях определяется данными, а количество нейронов в скрытом слое определяется в соответствии с нашей оценкой сложности данных. Как правило, чем сложнее и больше данные, тем больше нейронов требуется. Но слишком много нейронов может легко привести к переоснащению.
В дополнение к завершению построения нейронной сети путем ручной реализации тензорного расчета нейронной сети, как указано выше, PyTorch также реализует автоматический вызов готовых функций для выполнения той же операции.Этот код более лаконичен, как показано ниже:
#定义神经网络架构,features.shape[1]个输入层单元,10个隐含层,1个输出层
input_size = features.shape[1]
hidden_size = 10
output_size = 1
batch_size = 128
neu = torch.nn.Sequential(
torch.nn.Linear(input_size, hidden_size),
torch.nn.Sigmoid(),
torch.nn.Linear(hidden_size, output_size),
)
В этом коде мы можем вызвать torch.nn.Sequential(), чтобы создать нейронную сеть и сохранить ее в переменной neu. Функция torch.nn.Sequential() состоит в последовательном построении ряда операционных модулей в многослойную нейронную сеть. В этом примере эти модули включают Linear(input_size, hidden_size), линейное отображение входного слоя в скрытый слой, нелинейную сигмовидную функцию torch.nn.Sigmoid() для скрытого слоя и отображение из скрытого слоя в выходной слой.Линейная карта torch.nn.Linear(hidden_size, output_size). Стоит отметить, что слои в Sequential не соответствуют строго слоям нейронной сети, а относятся к многошаговым операциям, которые соответствуют слоям динамического вычислительного графа.
Мы также можем использовать функцию потерь, которая поставляется с PyTorch:
cost = torch.nn.MSELoss()
Это упакованная функция потерь для вычисления среднеквадратичной ошибки, которая поставляется с PyTorch, Это указатель на функцию, который назначает переменную стоимость. При вычислении нам нужно только вызвать cost(x, y) для вычисления среднеквадратичной ошибки между прогнозируемым вектором x и целевым вектором y.
Кроме того, PyTorch также поставляется с оптимизатором для автоматической реализации алгоритма оптимизации:
optimizer = torch.optim.SGD(neu.parameters(), lr = 0.01)
torch.optim.SGD() вызывает собственный стохастический градиентный спуск (SGD) PyTorch в качестве оптимизатора. При инициализации оптимизатора нам нужно, чтобы все параметры были оптимизированы (в данном случае входящие параметры включают в себя все веса и смещения, содержащиеся в нейросети neu, т.е. neu.parameters() ), и обучение выполнению градиентного спуска алгоритм Скорость lr=0,01. После того, как все материалы будут готовы, можно приступать к обучению.
пакетная обработка данных
Однако при запуске обучающего цикла мы также сталкиваемся с проблемой. В предыдущем примере мы подавали все данные в нейронную сеть одновременно в течение каждой эпохи обучения. Это не имеет никаких проблем, когда объем данных невелик. Однако текущий объем данных составляет 16 875. При таком большом объеме данных, если все данные обрабатываются в каждом цикле обучения, такие проблемы, как медленная скорость работы и итерации, могут не сойтись.
Решение обычно состоит в том, чтобы использовать режим пакетной обработки, то есть разделить все записи данных на небольшой набор данных небольшого размера (размер пакета), а затем вводить пакет данных в нейронную сеть в каждом цикле обучения. Как показано на рис. Рисунок 3.22. Размер пакета зависит от сложности задачи и размера данных, в этом примере мы установили batch_size=128.
Код обучения после пакетной обработки выглядит следующим образом:
#神经网络训练循环
losses = []
for i in range(1000):
#每128个样本点被划分为一批,在循环的时候一批一批地读取
batch_loss = []
#start和end分别是提取一批数据的起始和终止下标
for start in range(0, len(X), batch_size):
end = start + batch_size if start + batch_size < len(X) else len(X)
xx = Variable(torch.FloatTensor(X[start:end]))
yy = Variable(torch.FloatTensor(Y[start:end]))
predict = neu(xx)
loss = cost(predict, yy)
optimizer.zero_grad()
loss.backward()
optimizer.step()
batch_loss.append(loss.data.numpy())
#每隔100步输出损失值
if i % 100==0:
losses.append(np.mean(batch_loss))
print(i, np.mean(batch_loss))
#打印输出损失值
plt.plot(np.arange(len(losses))*100,losses)
plt.xlabel('epoch')
plt.ylabel('MSE')
Запустив эту программу, мы можем обучить нейронную сеть. На рис. 3.23 показано падение функции потерь по мере прохождения эпохи обучения. Среди них абсцисса представляет период обучения, а ордината представляет среднюю ошибку. Видно, что средняя ошибка быстро уменьшается с увеличением периода обучения.
3.3.3 Тест нейронной сети
Затем мы можем использовать обученную нейронную сеть, чтобы делать прогнозы на тестовом наборе, и отображать прогнозируемые данные на следующие 21 день с реальными данными для сравнения.
targets = test_targets['cnt'] #读取测试集的cnt数值
targets = targets.values.reshape([len(targets),1]) #将数据转换成合适的tensor形式
targets = targets.astype(float) #保证数据为实数
#将特征变量和目标变量包裹在Variable型变量中
x = Variable(torch.FloatTensor(test_features.values))
y = Variable(torch.FloatTensor(targets))
#用神经网络进行预测
predict = neu(x)
predict = predict.data.numpy()
fig, ax = plt.subplots(figsize = (10, 7))
mean, std = scaled_features['cnt']
ax.plot(predict * std + mean, label='Prediction')
ax.plot(targets * std + mean, label='Data')
ax.legend()
ax.set_xlabel('Date-time')
ax.set_ylabel('Counts')
dates = pd.to_datetime(rides.loc[test_data.index]['dteday'])
dates = dates.apply(lambda d: d.strftime('%b %d'))
ax.set_xticks(np.arange(len(dates))[12::24])
_ = ax.set_xticklabels(dates[12::24], rotation=45)
Сравнение фактической кривой и прогнозируемой кривой показано на рис. 3.24. Где абсцисса — разные даты, а ордината — значение прогноза или реальных данных. Пунктирная линия — прогнозируемая кривая, а сплошная линия — фактические данные.
Можно видеть, что две кривые в основном совпадают, но фактическое значение и прогнозируемое значение в дни до и после 25 декабря имеют большое отклонение. Почему производительность такая плохая в это время?
Присмотревшись к данным, мы видим, что 25 декабря приходится на Рождество. Для европейских и американских стран Рождество эквивалентно нашему Весеннему празднику.До и после рождественских каникул привычки людей путешествовать будут сильно отличаться от тех, что были в прошлом. Однако в наших обучающих выборках, поскольку все данные имеют длину всего два года, есть только одна выборка до и после Рождества, что не позволяет нам делать хорошие прогнозы о характере этого конкретного праздника.
3.4 Анатомия нейтральной сети Neu
Понятно, что наша работа уже завершена. Однако мы также хотели получить более полное представление о том, как работают искусственные нейронные сети. Поэтому мы проанализируем эту обученную нейронную сеть Neu, чтобы точно понять, почему она может хорошо работать с одними данными и плохо работать с другими.
Для нас то, что происходит во время обучения нейросети, — это полностью черный ящик, но веса ребер нейросети реально существуют в памяти компьютера, и мы можем извлечь интересующие данные для анализа.
Мы определяем функцию feature(), которая извлекает все параметры, хранящиеся в ребрах и узлах нейронной сети. код показывает, как показано ниже:
def feature(X, net):
#定义一个函数,用于提取网络的权重信息,所有的网络参数信息全部存储在neu的named_parameters集合中
X = Variable(torch.from_numpy(X).type(torch.FloatTensor), requires_grad = False)
dic = dict(net.named_parameters()) #提取这个集合
weights = dic['0.weight'] #可以按照“层数.名称”来索引集合中的相应参数值
biases = dic['0.bias']
h = torch.sigmoid(X.mm(weights.t()) + biases.expand([len(X), len(biases)])) #隐含层的计算过程
return h #输出层的计算
В этом коде мы используем команду net.named_parameters() для извлечения всех параметров нейронной сети, включая веса и смещения каждого слоя, и помещаем их в словарь Python. Далее его можно извлечь с помощью приведенного выше кода, например, все веса и смещения первого слоя можно получить с помощью dic['0.weight'] и dic['0.bias']. Кроме того, мы также можем получить все извлекаемые имена параметров, перебирая словарь параметров dic.
Из-за большого объема данных мы выбираем часть данных для ввода в нейронную сеть и извлекаем режим активации сети. Мы знаем, что даты с неточными предсказаниями — 22 декабря, 23 декабря и 24 декабря. Поэтому данные за эти 3 дня агрегируются и сохраняются в переменных подмножества и подцелей.
bool1 = rides['dteday'] == '2012-12-22'
bool2 = rides['dteday'] == '2012-12-23'
bool3 = rides['dteday'] == '2012-12-24'
#将3个布尔型数组求与
bools = [any(tup) for tup in zip(bool1,bool2,bool3) ]
#将相应的变量取出来
subset = test_features.loc[rides[bools].index]
subtargets = test_targets.loc[rides[bools].index]
subtargets = subtargets['cnt']
subtargets = subtargets.values.reshape([len(subtargets),1])
Введите данные за эти 3 дня в нейронную сеть, используйте функцию feature(), определенную выше, чтобы считать значение активации нейронов в скрытом слое и сохранить его в результатах. Для удобства чтения прогнозируемое значение нормализованного выхода может быть восстановлено до числового диапазона исходных данных.
#将数据输入到神经网络中,读取隐含层神经元的激活数值,存入results中
results = feature(subset.values, neu).data.numpy()
#这些数据对应的预测值(输出层)
predict = neu(Variable(torch.FloatTensor(subset.values))).data.numpy()
#将预测值还原为原始数据的数值范围
mean, std = scaled_features['cnt']
predict = predict * std + mean
subtargets = subtargets * std + mean
Далее мы нарисуем все активации нейронов скрытого слоя. При этом для сравнения строим эти кривые со значениями, предсказанными моделью, и визуализируем результаты, как показано на рис. 3.25.
#将所有的神经元激活水平画在同一张图上
fig, ax = plt.subplots(figsize = (8, 6))
ax.plot(results[:,:],'.:',alpha = 0.1)
ax.plot((predict - min(predict)) / (max(predict) - min(predict)),'bo-',label='Prediction')
ax.plot((subtargets - min(predict)) / (max(predict) - min(predict)),'ro-',label='Real')
ax.plot(results[:, 6],'.:',alpha=1,label='Neuro 7')
ax.set_xlim(right=len(predict))
ax.legend()
plt.ylabel('Normalized Values')
dates = pd.to_datetime(rides.loc[subset.index]['dteday'])
dates = dates.apply(lambda d: d.strftime('%b %d'))
ax.set_xticks(np.arange(len(dates))[12::24])
_ = ax.set_xticklabels(dates[12::24], rotation=45)
Квадратная кривая на рисунке — это прогнозируемое значение модели, пунктирная кривая — реальное значение, а пунктирные линии с разными цветами и типами линий — это выходные значения каждого нейрона. Можно обнаружить, что выходная кривая нейрона 6 (Neuro 6) относительно близка к реальной выходной кривой. Следовательно, мы можем считать, что этот нейрон имеет более высокий вклад в повышение точности предсказания.
В то же время мы также хотели знать, почему нейрон Neuro 6 работал лучше и кто определял его активацию. Дальнейший анализ влияющих на него факторов позволяет узнать, что веса указывают от входного слоя к нему, как показано на рис. 3.26.
Мы можем визуализировать эти веса с помощью следующего кода.
#找到与峰值对应的神经元,将其到输入层的权重输出
dic = dict(neu.named_parameters())
weights = dic['0.weight']
plt.plot(weights.data.numpy()[6, :],'o-')
plt.xlabel('Input Neurons')
plt.ylabel('Weight')
Результат показан на рисунке 3.27. По горизонтальной оси отложены разные веса, т. е. количество входных нейронов, по вертикальной оси отложены веса реберных соединений после обучения нейронной сети. Например, 10-е число на горизонтальной оси соответствует 10-му нейрону входного слоя, который соответствует входным данным и является переменной типа для определения категорий погоды. 32-е число, обозначающее количество часов, также является переменной типа и определяет шаблон 6 часов утра. Мы можем понять, что положительное значение вертикальной оси — продвижение, а отрицательное значение — торможение. Следовательно, пик на рисунке соответствует активации нейрона, а впадина — инактивации нейрона.
Мы видим, что эта кривая имеет более высокий вес в hr_12, weekday_0, 6, что означает, что Neuro 6 определяет, является ли текущий момент времени 12:00, а также определяет, воскресенье или суббота сегодня. Если эти условия соблюдены, нейрон активируется. Напротив, веса нейрона на входах weathersit_3 и hr_6 отрицательны и оказываются впадинами, что означает, что нейрон будет заторможен, когда идет дождь или снег, а также в 6 утра. Глядя на вечный календарь, мы знаем, что 22 и 23 декабря в 2012 году выпали на субботу и воскресенье, поэтому Нейро 6 был активирован, и они способствовали правильному предсказанию пика полудня в эти два дня. Однако, поскольку приближается Рождество, люди могут вернуться пораньше, чтобы подготовиться к Рождеству, поэтому эти выходные особенные, и в обычные выходные не так много желающих кататься, поэтому значение активации, данное Neuro 6, приводит к чрезмерно высокому предсказать количество полуденных велосипедов.
Аналогично можно найти причины завышения утреннего и вечернего пиков 24 декабря. Мы обнаружили, что нейрон 4 играет главную роль, потому что форма его колебаний отрицательно коррелирует с утренним и вечерним пиками предсказанной кривой 24-го числа, как показано на рис. 3.28.
Точно так же соответствующий вес этого нейрона и его схема обнаружения показаны на рис. 3.29.
Нейрон обнаружил аналогичный, но противоположный Нейро 6 паттерн, который подавлялся во время утренних и вечерних пиков и активировался во время праздников и выходных. Глядя дальше на связь от скрытого слоя к выходному слою, мы обнаруживаем, что вес Neuro 4 отрицателен, но отрицательное значение не так велико. Следовательно, это привело к подавлению пика утром и вечером 24 декабря, но эффект от этого подавления сигнала был незначительным и не мог привести к появлению прогнозируемого пика.
Таким образом, мы анализируем, что причиной неточности нейронного предиктора Neu в течение этих 3 дней является аномальный характер рождественских праздников. 24 декабря — канун Рождества, и сети не хватает подавления пиковых отрядов подавления утром и вечером в праздничные дни, что приводит к неточным прогнозам. Имея больше обучающих данных, мы можем скорректировать веса нейрона 4 ниже, что потенциально повысит точность прогнозов.
3.5 Обзор
В этой главе мы представляем принцип работы искусственной нейронной сети с проблемой прогнозирования количества общих велосипедов в месте в качестве точки входа. Настраивая параметры в нейронной сети, мы можем получить любую форму кривой. Затем мы попытались сопоставить данные о совместном использовании велосипедов с нейронной сетью с одним входом и одним выходом и попытаться сделать прогнозы.
Однако эффект предсказания очень плохой. После анализа мы обнаружили, что, поскольку используемая переменная признака — это количество данных, которое не имеет ничего общего с количеством велосипедов, иллюзия идеального соответствия — это просто результат переобучения. Поэтому мы попробовали новый метод прогнозирования, используя характерные переменные в каждом фрагменте данных, включая погоду, скорость ветра, день недели, выходной день, момент времени и т. д., чтобы предсказать количество используемых велосипедов. и добился успеха.
Во второй попытке мы также узнали, как разделить данные и как реализовать нашу искусственную нейронную сеть, функцию потерь и оптимизатор, используя функции-оболочки, которые поставляются с PyTorch. При этом мы ввели концепцию пакетной обработки, то есть данные разбиваются на пакеты, и в каждом цикле обучения используется небольшой пакет данных для обучения нейронной сети и предоставления ему возможности корректировать параметры. Такой пакетный подход ускоряет работу программы и позволяет нейронной сети стабильно настраивать свои параметры.
Наконец, мы анализируем обученную нейронную сеть. Узнайте, как искусственные нейроны активируются в различных условиях, отслеживая внутренние закономерности в данных. Мы также ясно видим, что причина, по которой нейронные сети плохо работают на некоторых данных, заключается в том, что в данных сложно встретить особое условие отпуска.
3.6 Вопросы и ответы
Содержание этой книги взято из онлайн-курса «Глубокое обучение на факеле», открытого г-ном Чжаном Цзяном в «Академии ИИ Цзичжи». Чтобы помочь читателям быстро прояснить свои идеи или решить общие практические проблемы, мы выбрали представителя Курсы, предложенные студентами курса.Вопросы и ответы учителя Чжан Цзяна прикрепляются к разделу «Вопросы и ответы», прикрепленному в конце соответствующих глав. Если у читателей возникнут подобные вопросы в процессе чтения, надеюсь, они смогут получить от них ответы.
В: Чем больше нейронов, тем лучше?
О: Конечно, чем больше, тем лучше. Предсказательная способность модели нейронной сети связана не только с количеством нейронов, но также со структурой и входными данными нейронной сети.
В: Почему нам нужно очищать градиент в эксперименте по прогнозированию использования общих велосипедов?
A: Если градиент не очищен, функция reverse() будет накапливать градиент. Мы выполняем обратное распространение градиента сразу после тренировки, поэтому системе не нужно накапливать градиенты. Если градиент не очищен, это может привести к тому, что модель не сойдется.
В: Можно ли для нейронных сетей также аппроксимировать несходящиеся функции?
A: Это возможно в некотором замкнутом интервале. Поскольку на замкнутом интервале функция не может бесконечно расходиться, и всегда будет предел, то для аппроксимации можно использовать модель нейронной сети. Для бесконечного интервала нейросетевая модель не будет работать, потому что количество нейронов в нейросетевой модели для подгонки ограничено.
В: В примере прогнозирования общих велосипедов модель недостаточно точна, чтобы предсказать использование велосипедов во время Рождества. Так можно ли повысить точность прогнозов нейронной сети, добавив обучающие данные?
О: Это осуществимо. Если модель обучается на большем количестве обучающих данных, включающих использование велосипедов во время Рождества, предсказание модели об использовании велосипедов в Рождество будет более точным.
В: Поскольку модель для прогнозирования использования общего велосипеда может быть проанализирована и проанализирована, можно ли проанализировать каждую нейронную сеть таким образом?
О: Не обязательно. Поскольку структура модели для прогнозирования использования общих велосипедов относительно проста, в скрытом слое всего 10 нейронов. Когда количество нейронов в сетевой модели велико или имеется несколько слоев нейронов, определенное «решение» модели нейронной сети будет трудно отнести к одному нейрону. В настоящее время сложно анализировать модель нейронной сети способом «вскрытия».
В: При обучении модели нейронной сети я упомянул «тренировочный набор/тестовый набор = k», так какое соотношение k является разумным, влияет ли k на скорость сходимости и ошибку прогноза?
О: В случае относительно небольшого количества данных мы обычно выбираем тестовый набор по соотношению 10:1, а в случае относительно большого количества данных, например, если их более 100 000 штук. данных, не обязательно выбирать тестовый набор в соответствии с соотношением Разделите обучающий набор и тестовый набор.