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

глубокое обучение Python

Это 9-й день моего участия в августовском испытании обновлений.Подробности о мероприятии:Испытание августовского обновления

Deep Learning with Python

Эта статья — одна из серии заметок, которые я написал, изучая Deep Learning with Python (второе издание, Франсуа Шолле). Содержимое статьи конвертировано из блокнотов Jupyter в Markdown, вы можете перейти наGitHubилиGiteeнайти оригинал.ipynbноутбук.

ты можешь идтиЧитайте оригинальный текст этой книги онлайн на этом сайте(Английский). Автор этой книги также дает соответствиеJupyter notebooks.

Эта статьяГлава 6 Глубокое обучение для текста и последовательностей (Chapter 6. Deep learning for text and sequences) Примечания.

6.4 Sequence processing with convnets

Обработка последовательностей с помощью сверточных нейронных сетей

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

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

Одномерная свертка и объединение данных последовательности

Подобно 2D-свертке, 1D-свертка извлекает локальные сегменты (подпоследовательности) из последовательности, а затем применяет такое же преобразование к каждому сегменту. Одномерное окно свертки — это одномерное окно на оси времени. Природа этой операции гарантирует, что паттерны, изученные в одном месте ранее, могут быть распознаны позже (с инвариантностью к переносу во времени) в других местах.

一维卷积神经网络的工作原理:每个输出时间步都是利用输入序列在时间维度上的一小段得到的

Операция одномерного объединения аналогична операции двумерного объединения: извлеките одномерный сегмент из входных данных и выведите максимальное значение (максимальное объединение) или среднее значение (среднее объединение). Эта операция также используется для уменьшения длины данных (субдискретизация).

Реализация одномерной сверточной нейронной сети

В Keras одномерные сверточные нейронные сети представлены слоями Conv1D. Использование очень похоже на Conv2D, оно принимает форму как(samples, time, features)Ввод возвращается в этой форме. Обратите внимание, что его окно находится на временной, второй оси ввода. В Conv2D наши окна обычно имеют размер 3x3 и 5x5.В соответствующем Conv1D мы обычно берем размер окна 7 или 9.

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

Или возьмите IMDB в качестве примера:

from tensorflow.keras.datasets import imdb
from tensorflow.keras.preprocessing import sequence

max_features = 10000
max_len = 500

print('Loading data...')
(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=max_features)
print(len(x_train), 'train sequences')
print(len(x_test), 'test sequences')

print('Pad sequences (samples x time)')
x_train = sequence.pad_sequences(x_train, maxlen=max_len)
x_test = sequence.pad_sequences(x_test, maxlen=max_len)
print('x_train shape:', x_train.shape)
print('x_test shape:', x_test.shape)

получить:

25000 train sequences

25000 test sequences

x_train shape: (25000, 500)

x_test shape: (25000, 500)

# 在 IMDB 上训练并评估一个简单的一维卷积神经网络

from tensorflow.keras.models import Sequential
from tensorflow.keras import layers
from tensorflow.keras.optimizers import RMSprop

model = Sequential()
model.add(layers.Embedding(max_features, 128, input_length=max_len))

model.add(layers.Conv1D(32, 7, activation='relu'))
model.add(layers.MaxPooling1D(5))

model.add(layers.Conv1D(32, 7, activation='relu'))
model.add(layers.GlobalMaxPooling1D())

model.add(layers.Dense(1))

model.summary()

model.compile(optimizer=RMSprop(lr=1e-4),
              loss='binary_crossentropy',
              metrics=['acc'])
history = model.fit(x_train, y_train,
                    epochs=10,
                    batch_size=128,
                    validation_split=0.2)

plot_acc_and_loss(history)

Получите структуру модели:

model.summary

Кривая тренировочного процесса:

png

png

Хотя результаты немного хуже, чем у RNN, они все же довольно хороши и тренируются быстрее, чем LSTM.

Объединение CNN и RNN для обработки длинных последовательностей

Одномерные сверточные нейронные сети обучаются, разделяя последовательности на сегменты, и не чувствительны к временной последовательности. Таким образом, для тех задач, где порядок последовательностей оказывает значительное влияние, CNN работают гораздо хуже, чем RNN. Например, проблема с набором данных в Йене (прогноз температуры):

Сначала подготовьте данные:

import os
import numpy as np

data_dir = "/CDFMLR/Files/dataset/jena_climate"
fname = os.path.join(data_dir, 'jena_climate_2009_2016.csv')

f = open(fname)
data = f.read()
f.close()

lines = data.split('\n')
header = lines[0].split(',')
lines = lines[1:]

float_data = np.zeros((len(lines), len(header) - 1))
for i, line in enumerate(lines):
    values = [float(x) for x in line.split(',')[1:]]
    float_data[i, :] = values
    
mean = float_data[:200000].mean(axis=0)
float_data -= mean
std = float_data[:200000].std(axis=0)
float_data /= std

def generator(data, lookback, delay, min_index, max_index,
              shuffle=False, batch_size=128, step=6):
    if max_index is None:
        max_index = len(data) - delay - 1
    i = min_index + lookback
    while 1:
        if shuffle:
            rows = np.random.randint(
                min_index + lookback, max_index, size=batch_size)
        else:
            if i + batch_size >= max_index:
                i = min_index + lookback
            rows = np.arange(i, min(i + batch_size, max_index))
            i += len(rows)

        samples = np.zeros((len(rows),
                           lookback // step,
                           data.shape[-1]))
        targets = np.zeros((len(rows),))
        for j, row in enumerate(rows):
            indices = range(rows[j] - lookback, rows[j], step)
            samples[j] = data[indices]
            targets[j] = data[rows[j] + delay][1]
        yield samples, targets
        
lookback = 1440
step = 6
delay = 144
batch_size = 128

train_gen = generator(float_data,
                      lookback=lookback,
                      delay=delay,
                      min_index=0,
                      max_index=200000,
                      shuffle=True,
                      step=step, 
                      batch_size=batch_size)
val_gen = generator(float_data,
                    lookback=lookback,
                    delay=delay,
                    min_index=200001,
                    max_index=300000,
                    step=step,
                    batch_size=batch_size)
test_gen = generator(float_data,
                     lookback=lookback,
                     delay=delay,
                     min_index=300001,
                     max_index=None,
                     step=step,
                     batch_size=batch_size)

val_steps = (300000 - 200001 - lookback) // batch_size

test_steps = (len(float_data) - 300001 - lookback) // batch_size

Обучите и оцените простую одномерную сверточную нейронную сеть на наборе данных Jena:

from tensorflow.keras.models import Sequential
from tensorflow.keras import layers
from tensorflow.keras.optimizers import RMSprop

model = Sequential()
model.add(layers.Conv1D(32, 5, activation='relu',
                        input_shape=(None, float_data.shape[-1])))
model.add(layers.MaxPooling1D(3))
model.add(layers.Conv1D(32, 5, activation='relu'))
model.add(layers.MaxPooling1D(3))
model.add(layers.Conv1D(32, 5, activation='relu'))
model.add(layers.GlobalMaxPooling1D())
model.add(layers.Dense(1))

model.compile(optimizer=RMSprop(), loss='mae')
history = model.fit_generator(train_gen,
                              steps_per_epoch=500,
                              epochs=20,
                              validation_data=val_gen,
                              validation_steps=val_steps)

plot_acc_and_loss(history)

Кривая тренировочного процесса:

png

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

Мы можем использовать Conv1D перед RNN. Для очень длинных последовательностей (например, содержащих тысячи временных шагов) слишком медленно или даже невозможно обрабатывать напрямую с помощью RNN. Добавление некоторых Conv1D перед RNN может преобразовать (понизить выборку) слишком длинную входную последовательность в более короткую последовательность, состоящую из высокоуровневых функций, а затем использовать RNN для обработки чувствительной к порядку информации, которую можно изучить.

结合一维 CNN 和 RNN 来处理长序列

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

step = 3  # 30 分钟一步,比以前缩短了一半
lookback = 720
delay = 144

train_gen = generator(float_data,
                      lookback=lookback,
                      delay=delay,
                      min_index=0,
                      max_index=200000,
                      shuffle=True,
                      step=step)

val_gen = generator(float_data,
                    lookback=lookback,
                    delay=delay,
                    min_index=200001,
                    max_index=300000,
                    step=step)

test_gen = generator(float_data,
                     lookback=lookback,
                     delay=delay,
                     min_index=300001,
                     max_index=None,
                     step=step)

val_steps = (300000 - 200001 - lookback) // 128
test_steps = (len(float_data) - 300001 - lookback) // 128

Создайте сеть, используя Conv1D + GRU:

model = Sequential()
model.add(layers.Conv1D(32, 5, activation='relu',
                        input_shape=(None, float_data.shape[-1])))
model.add(layers.MaxPooling1D(3))
model.add(layers.Conv1D(32, 5, activation='relu'))
model.add(layers.GRU(32, dropout=0.1, recurrent_dropout=0.5))
model.add(layers.Dense(1))

model.summary()

model.compile(optimizer=RMSprop(), loss='mae')
history = model.fit_generator(train_gen,
                              steps_per_epoch=500,
                              epochs=20,
                              validation_data=val_gen,
                              validation_steps=val_steps)

plot_acc_and_loss(history)

Структура модели:

model.summary

Кривая тренировочного процесса:

png

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


By("CDFMLR", "2020-08-14")