Ваша первая нейронная сеть — предиктор общего велосипеда

машинное обучение
Ваша первая нейронная сеть — предиктор общего велосипеда

введение

Эта статья законченаJizhi Academy «Вводный курс PyTorch: глубокое обучение на Torch»После серии уроков.

Эта серия курсов содержит большое количество практических задач, таких как классификация текста, распознавание рукописных цифр, переводчики, композиторы, игры с искусственным интеллектом и многое другое. На практике также заложено большое количество базовых и классических знаний в области машинного обучения, таких как反向传播原理,神经元原理剖析, в области НЛПRNN,LSTM,word2vec, и домен изображения迁移学习,卷积神经网络Подождите, он очень подходит для студентов, которые хотят начать работу с машинным обучением, и это единственный хороший курс в текущей сети.

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

Статьи из этой же серии:Используйте линейную регрессию, чтобы соответствовать случаю и полностью понять обратное распространение в глубоком обучении

текст

Задача этой статьи состоит в том, чтобы предсказать количество велосипедов в соответствующую дату на основе независимых переменных, таких как погода, время года, дата и неделя, путем обучения простой модели предсказания нейронной сети. Основные пункты знаний включены: предварительная обработка данныхone-hot编码,归一化操作,а также构建神经网络的流程

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

image

Среди них последний столбец cnt — это целевая функция, то есть количество велосипедов. Остальные данные в таблице выбираемseason, hr, mnth,weekday, weathersit, temp, hum,holiday, yrВ качестве зависимой переменной другие данные отбрасываются. Каждый фрагмент данных указан в часах, всего около 2w фрагментов данных, давайте выберем некоторые графики, чтобы увидеть

image

Весь процесс реализации задачи можно разделить на следующие три шага:

  1. предварительная обработка данных
  2. Обучите модель
  3. Проверить модель

Приступаем к задаче

1. Предварительная обработка данных

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

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

Так что же не так и как с этим бороться?

1.1 Обработка переменных типа: однократное кодирование

В нашем случае季节,天气Несколько переменных - это правила, о которых мы договорились для удобства нашей повседневной жизни. Они относятся к переменным типа, и их числовой размер не имеет практического значения. Например, вторник не означает, что он больше, чем значение понедельника, а размер напрямую вводится в модель, что вызовет «непонимание» нейронной сети: то есть, чем больше значение, тем сильнее оно повлияет на изменения внутри сети. Поэтому нам нужно выполнить бинарную обработку для этих переменных типа.

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

image

Специально для реализации кода у pandas есть готовые методы, которые помогут нам быстро сгенерировать однократное кодирование.

dummies = pd.get_dummies(rides['weekday'], prefix='weekday', drop_first=False

one-hot编码后的“星期

Настоящий код показан ниже. Объект, которым мы хотим управлять,'season', 'weathersit', 'mnth', 'hr', 'weekday'эти свойства. После обработки сгенерированные данные объединяются с исходными данными. Наконец, удалите ненужные функции из исходного набора данных.

# 这是我们要处理的特征组
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)
data.head() # 打印查看

one-hot编码后的数据

После завершения конвертации кода типа не спешите начинать, нам осталось сделать еще один шаг

1.2. Нормализация значений данных

Во многих случаях переменные в разных единицах данных могут иметь очень большие различия в значениях. В нашем случае, например, температура может колебаться от 0 до 50, а влажность — десятичная дробь, которая может колебаться от 0 до 1. А иногда даже появляются исходные данные порядка десятков тысяч. Если тренироваться напрямую, конечно, нельзя, но вес нейросети будет обучаться очень медленно, и конечный эффект может быть не очень хорошим.

Поэтому нам нужно выполнять числовые значения в разных единицах измерения归一化处理, существует множество способов нормализации, например преобразование значения в интервал [-1, 1] в соответствии с нормальным распределением. Используйте обычно используемыеz-score标准化метод.

新数据 = (原数据 - 均值) / 标准差

# 标准化处理,这里将目标数量也做了归一化
quant_features = ['cnt', 'temp', 'hum', 'windspeed']
for each in quant_features:
    # 快速求均值和方差
    mean, std = data[each].mean(), data[each].std()
    # 选取列名为each的特定列, 替换为归一化后的数据
    data.loc[:, each] = (data[each] - mean) / std
data.head() # 打印查看

归一化结果

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

  1. Размер значения переменной типа может повлиять на эффект обучения, и требуется однократное кодирование.
  2. Различные масштабы данных различны и должны быть нормализованы для повышения скорости обучения и повышения эффективности обучения.

Далее мы начинаем входить в формальный процесс обучения

2. Постройте модель и начните обучение

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

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

2.1 Построение входных и целевых функций

Здесь наш вход - это все независимые переменные, которые будут влиять на текущее количество велосипедов, а выход - соответствующее количество велосипедов. Конечно, не забудьте разделить обучающий набор и тестовый набор. Обучающий набор используется для обучения, а тестовый набор используется для проверки окончательной модели.

target_fields = ['cnt']
# 训练集,去掉最后21天的数据
train_data = data[:-21 * 24]
# 测试集,最后21天的数据
test_data = data[-21 * 24:]

# 定义输入,和预测目标
features, targets = train_data.drop(target_fields, axis=1), train_data[target_fields]
test_features, test_target = test_data.drop(target_fields, axis=1), test_data[target_fields]

Цели ввода и прогнозирования, определенные приведенным выше кодом, все еще находятся в формате кадра данных.Нам нужно преобразовать данные в массив или тензор.Здесь мы преобразуем их в формат массива. При этом для облегчения расчета размерность целевой функции необходимо скорректировать. Преобразование из измерения 0 (объем данных) в измерение 1 (объем данных x 1)

2.2 Построение модели

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

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

input_size = np.array(features).shape[1]
hidden_size = 10
output_size = 1
neu = torch.nn.Sequential(
    torch.nn.Linear(input_size, hidden_size), # 一层线性映射
    torch.nn.Sigmoid(), # 一层sigmoid非线性映射
    torch.nn.Linear(hidden_size, output_size) # 再一层线性映射
)
cost = torch.nn.MSELoss()
optimizer = torch.optim.SGD(neu.parameters(), lr = 0.01)

Сконцентрируйся:

  1. torch.nn.Linear: Линейное отображение
  2. torch.nn.Sigmoid: нелинейное отображение, может соответствовать кривой
  3. torch.nn.MSELoss(): Функция потерь MSE
  4. torch.optim.SGD(neu.parameters(), lr = 0.01): оптимизатор параметров, который может реализовать процесс обратного распространения, обновить все параметры с помощью градиентов и т. д. Конкретное использование может продолжать смотреть вниз. lr обозначает скорость обучения

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

2.3 Тренировочный процесс

Сначала определите batch_size. Эквивалентно определению, исходные данные обучаются с использованием 128 в качестве минимальной обучающей единицы.

batch_size = 128

image

Цель пакетной обработки — полностью обучить модель и повысить случайность данных, эффект будет лучше. Например, если наши 20 000 фрагментов данных не разделены на пакеты, то после запуска 20 000 фрагментов данных модель обучается один раз, сумма ошибок вычисляется один раз, обратное распространение выполняется один раз, и вес корректируется один раз. , эффективность очень низкая; А если 20000 разделить на небольшую группу, каждая группа представляет собой законченный тренировочный процесс, то эффективность значительно повышается. Кроме того, это увеличивает случайность обучающих данных.

Затем переходим непосредственно к коду. Это выглядит как много кода, но на самом деле это очень просто.

Losses = []
for i in range(10000):
    batch_loss = []

    for start in range(0, len(X), batch_size):
        end = start + batch_size if start + batch_size < len(X) else len(X)
        # 获取本批次的输入和预测目标
        xx = torch.tensor(X[start: end, :], dtype=torch.float, requires_grad = True)
        yy =  torch.tensor(Y[start: end, :], dtype=torch.float, requires_grad = True)

        # 输入数据,得到预测值
        predict = neu(xx)

        # 使用损失函数比较预测数据和真实数据,得到loss
        loss = cost(predict, yy)

        # 反向传播,优化权重
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        # 记录loss
        batch_loss.append(loss)
    Losses.append(batch_loss[1:])

Инструкции по шагам:

  1. существуетbatchПолучите ввод для этой партии вxxи прогнозируемая цельyy
  2. ПучокxxВведите ранее построенную модель нейронной сетиneu, чтобы получить предсказанное значениеpredict
  3. в функции потерьcostСреднее значение по сравнению с прогнозируемым значениемpredictи истинное значениеyy, получить значение потерьloss
  4. в оптимизатореoptimizerПолное обратное распространение, оптимизация весов и четкие градиенты в
  5. записыватьloss

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

loss曲线

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

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

image

Конечно, согласие здесь ничего не значит. Хорошая производительность обучающих данных не доказывает, что модель эффективна. Это так же абсурдно, как вы используете A, чтобы вывести вывод B, а затем используете A, чтобы проверить, что B верно. Правильный способ — использовать C, который имеет те же характеристики, что и A, чтобы попытаться вывести его, чтобы увидеть, можем ли мы получить B.

3. Подтвердите модель

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

Сравните разницу между test_predict и test_yy

image

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

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

Заканчивать

Спасибо за то, что вы здесь.

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

Надеюсь поделиться со всеми вами.