<jupyter_start><jupyter_text>Processamento de sequências com redes convolutivas  Implementing a 1D convnet No Keras, você usaria uma convnet 1D através da camada `Conv1D`, que possui uma interface muito semelhante ao` Conv2D`. Ela toma como tensores 3D de entrada com forma `(amostras, tempo, recursos)` e também retorna tensores 3D com formas semelhantes. A janela de convolução é uma janela 1D no eixo temporal, eixo 1 no tensor de entrada.Vamos criar uma convnet 1D simples de 2 camadas e aplicá-la à tarefa de classificação de sentimentos do IMDB que você já conhece.Como lembrete, este é o código para obter e pré-processar os dados:<jupyter_code>from keras.datasets import imdb
from keras.preprocessing import sequence

max_features = 10000  # number of words to consider as features
max_len = 500  # cut texts after this number of words (among top max_features most common words)

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)<jupyter_output>Loading data...
25000 train sequences
25000 test sequences
Pad sequences (samples x time)
x_train shape: (25000, 500)
x_test shape: (25000, 500)<jupyter_text>Convnets 1D são estruturados da mesma maneira que suas contrapartes 2D que você usou no Capítulo 5: eles consistem em uma pilha de camadas `Conv1D` e` MaxPooling1D`, terminando eventualmente em uma camada de pool global ou em um `Flatten` , transformando as saídas 3D em saídas 2D, permitindo adicionar uma ou mais camadas `Densas 'ao modelo, para classificação ou regressão.Uma diferença, no entanto, é o fato de podermos usar janelas de convolução maiores com convectores 1D. De fato, com uma camada de convolução 2D, uma janela de convolução 3x3 contém 3 * 3 = 9 vetores de característica, mas com uma camada de convolução 1D, uma janela de convolução de tamanho 3 conteria apenas 3 vetores de característica. Assim, podemos facilmente ter janelas de convolução 1D de tamanho 7 ou 9.Este é o nosso exemplo 1D convnet para o conjunto de dados IMDB:<jupyter_code>from keras.models import Sequential
from keras import layers
from 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)<jupyter_output>_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding_1 (Embedding)      (None, 500, 128)          1280000   
_________________________________________________________________
conv1d_1 (Conv1D)            (None, 494, 32)           28704     
_________________________________________________________________
max_pooling1d_1 (MaxPooling1 (None, 98, 32)            0         
_________________________________________________________________
conv1d_2 (Conv1D)            (None, 92, 32)            7200      
_________________________________________________________________
global_max_pooling1d_1 (Glob (None, 32)                0         
_________________________________________________________________
dense_1 (Dense)              (None, 1)                 33        
=================================================================
Total para[...]<jupyter_text>Aqui estão nossos resultados de treinamento e validação: a precisão da validação é um pouco menor que a do LSTM que usamos duas seções atrás, mas o tempo de execução é mais rápido, tanto na CPU quanto na GPU (embora a aceleração exata varie bastante dependendo da sua configuração exata). Nesse ponto, poderíamos treinar novamente este modelo para o número certo de épocas (8) e executá-lo no conjunto de testes. Esta é uma demonstração convincente de que um convnet 1D pode oferecer uma alternativa rápida e barata a uma rede recorrente em uma tarefa de classificação de sentimentos no nível de palavras.<jupyter_code>import matplotlib.pyplot as plt

acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']

epochs = range(len(acc))

plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.legend()

plt.figure()

plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()

plt.show()<jupyter_output><empty_output><jupyter_text>Combinando CNNs e RNNs para processar longas sequências Como os convnets 1D processam os patches de entrada de forma independente, eles não são sensíveis à ordem dos intervalos de tempo (além de uma escala local, do tamanho das janelas de convolução), diferentemente das RNNs. Obviamente, para poder reconhecer padrões de longo prazo, pode-se empilhar muitas camadas de convolução e camadas de pool, resultando em camadas superiores que "veriam" grandes pedaços das entradas originais - mas essa ainda é uma maneira bastante fraca de induzir a sensibilidade do pedido. Uma maneira de evidenciar essa fraqueza é tentar as ligações 1D no problema de previsão de temperatura da seção anterior, onde a sensibilidade à ordem foi essencial para produzir boas previsões. Vamos ver:<jupyter_code># We reuse the following variables defined in the last section:
# float_data, train_gen, val_gen, val_steps

import os
import numpy as np

data_dir = '/home/ubuntu/data/'
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)

# This is how many steps to draw from `val_gen`
# in order to see the whole validation set:
val_steps = (300000 - 200001 - lookback) // batch_size

# This is how many steps to draw from `test_gen`
# in order to see the whole test set:
test_steps = (len(float_data) - 300001 - lookback) // batch_size
from keras.models import Sequential
from keras import layers
from 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)<jupyter_output>Epoch 1/20
500/500 [==============================] - 124s - loss: 0.4189 - val_loss: 0.4521
Epoch 2/20
500/500 [==============================] - 11s - loss: 0.3629 - val_loss: 0.4545
Epoch 3/20
500/500 [==============================] - 11s - loss: 0.3399 - val_loss: 0.4527
Epoch 4/20
500/500 [==============================] - 11s - loss: 0.3229 - val_loss: 0.4721
Epoch 5/20
500/500 [==============================] - 11s - loss: 0.3122 - val_loss: 0.4712
Epoch 6/20
500/500 [==============================] - 11s - loss: 0.3030 - val_loss: 0.4705
Epoch 7/20
500/500 [==============================] - 11s - loss: 0.2935 - val_loss: 0.4870
Epoch 8/20
500/500 [==============================] - 11s - loss: 0.2862 - val_loss: 0.4676
Epoch 9/20
500/500 [==============================] - 11s - loss: 0.2817 - val_loss: 0.4738
Epoch 10/20
500/500 [==============================] - 11s - loss: 0.2775 - val_loss: 0.4896
Epoch 11/20
500/500 [==============================] - 11s - loss: 0.2715 - va[...]<jupyter_text>Estes são os Erros Médios Absolutos no treino e na validação<jupyter_code>import matplotlib.pyplot as plt

loss = history.history['loss']
val_loss = history.history['val_loss']

epochs = range(len(loss))

plt.figure()

plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()

plt.show()<jupyter_output><empty_output><jupyter_text>A validação do MAE permanece nos 0,40s baixos: não podemos sequer superar nossa linha de base do senso comum usando a pequena convnet. Novamente, isso ocorre porque nossa convnet procura padrões em qualquer lugar das séries temporais de entrada e não tem conhecimento da posição temporal de um padrão que vê (por exemplo, no início, no final, etc.). Como os pontos de dados mais recentes devem ser interpretados de maneira diferente dos pontos de dados mais antigos no caso desse problema específico de previsão, a convnet falha ao produzir resultados significativos aqui. Essa limitação de convnets não foi um problema no IMDB, porque os padrões de palavras-chave associadas a um sentimento positivo ou negativo serão informativos independentemente de onde são encontrados nas frases de entrada.Uma estratégia para combinar a velocidade e a leveza dos convnets com a sensibilidade à ordem dos RNNs é usar um convnet 1D como uma etapa de pré-processamento antes de um RNN. Isso é especialmente benéfico ao lidar com sequências que são tão longas que não poderiam ser processadas realisticamente com RNNs, por exemplo seqüências com milhares de etapas. O convnet transformará a sequência de entrada longa em sequências muito mais curtas (com amostragem reduzida) de recursos de nível superior. Essa sequência de recursos extraídos torna-se a entrada para a parte RNN da rede. Essa técnica não é vista com muita frequência em trabalhos de pesquisa e aplicações práticas, possivelmente por não ser muito conhecida. É muito eficaz e deve ser mais comum. Vamos tentar isso no conjunto de dados de previsão de temperatura. Como essa estratégia nos permite manipular seqüências muito mais longas, poderíamos olhar dados mais adiante (aumentando o parâmetro `lookback` do gerador de dados) ou observar séries temporais de alta resolução (diminuindo o parâmetro` step` de o gerador). Aqui, escolheremos (de maneira arbitrária) usar um `passo` duas vezes menor, resultando em séries temporais duas vezes mais longas, onde os dados meteorológicos estão sendo amostrados a uma taxa de um ponto a cada 30 minutos.<jupyter_code># This was previously set to 6 (one point per hour).
# Now 3 (one point per 30 min).
step = 3
lookback = 720  # Unchanged
delay = 144 # Unchanged

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<jupyter_output><empty_output><jupyter_text>Este é o nosso modelo, começando com duas camadas `Conv1D` e seguindo com uma camada` GRU`:<jupyter_code>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)
loss = history.history['loss']
val_loss = history.history['val_loss']

epochs = range(len(loss))

plt.figure()

plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()

plt.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11338302222808522, 'fraction_numerical': 0.03819009300178088, 'mean_word_length': 3.31965811965812, 'pattern_counts': {'":': 0, '<': 26, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '302491', 'license': 'Apache-2.0', 'n_tokens_mistral': 5172, 'n_tokens_neox': 4647, 'n_words': 1475, 'path': 'notebooks/fgv_classes/professor_mirapalheta/05.4-sequence-processing-with-convnets.ipynb', 'repo_name': 'ldaniel/Advanced-Predictive-Analytics', 'size': '15161'}