Data Science Academy - Deep Learning II

Regularização

Dropout

Hinton, Srivastava, Krizhevsky, Sutskever e Salakhutdinov (2012) apresentaram o algoritmo de regularização chamado Dropout. Embora o Dropout funcione de maneira diferente de L1 e L2, ele atinge o mesmo objetivo - a prevenção do overfitting. No entanto, o algoritmo aborda a tarefa, removendo realmente neurônios e conexões, pelo menos temporariamente. Ao contrário de L1 e L2, nenhuma penalidade de peso é adicionada. O Dropout não procura diretamente treinar pesos pequenos. O Dropout funciona fazendo com que os neurônios ocultos da rede neural não estejam disponíveis durante parte do treinamento. Descartar uma parte da rede neural faz com que a parte restante seja treinada para alcançar ainda uma boa pontuação, mesmo sem os neurônios perdidos. Isso diminui a coadaptação entre os neurônios, o que resulta em menos overfitting. https://www.cs.toronto.edu/~hinton/absps/JMLRdropout.pdf

A maioria das estruturas de redes neurais implementam o Dropout como uma camada separada. As camadas de Dropout funcionam como uma camada de rede neural regular e densamente conectada. A única diferença é que as camadas de Dropout periodicamente descartam alguns de seus neurônios durante o treinamento. Você pode usar as camadas de Dropout nas redes normais regulares feedforward. Na verdade, eles também podem se tornar camadas em redes convolucionais LeNET-5.

Os hiperparâmetros usuais para uma camada de Dropout são os seguintes:

  • Contagem de neurônio
  • Função de Ativação
  • Probabilidade de Dropout

Os hiperparâmetros da função de ativação e contagem de neurônios funcionam exatamente da mesma maneira que os parâmetros correspondentes no tipo de camada densa mencionado anteriormente. A contagem de neurônios simplesmente especifica o número de neurônios na camada de Dropout. A probabilidade de Dropout indica a probabilidade de um neurônio sair durante a iteração do treino. Assim como acontece com uma camada densa, o programa especifica uma função de ativação para a camada de Dropout.

Os neurônios descartados e suas conexões são mostrados como linhas tracejadas neste diagrama acima. A camada de entrada tem dois neurônios de entrada, bem como um neurônio de bias. A segunda camada é uma camada densa com três neurônios, bem como um neurônio de bias. A terceira camada é uma camada de Dropout com seis neurônios regulares, embora o programa tenha descartado 50% deles. Enquanto o programa descarta esses neurônios, ele não os calcula nem os treina. No entanto, a rede neural final usará todos esses neurônios para a saída.

Como mencionado anteriormente, o programa apenas descarta temporariamente os neurônios. Durante as iterações de treinamento subsequentes, o programa escolhe diferentes conjuntos de neurônios da camada de Dropout. Embora escolhemos uma probabilidade de 50% para o Dropout, o modelo não necessariamente descartará três neurônios. É como se lançássemos uma moeda para cada um dos neurônios candidatos ao Dropout para escolher se esse neurônio deve ser descartado. Você deve saber que o programa nunca deve descartar o neurônio de bias. Somente os neurônios regulares em uma camada de Dropout são candidatos.

A implementação do algoritmo de treinamento influencia o processo de descarte de neurônios. O conjunto de Dropout frequentemente muda uma vez por iteração de treinamento ou lote. O programa também pode fornecer intervalos onde todos os neurônios estão presentes. Algumas estruturas de rede neural fornecem hiperparâmetros adicionais para permitir que você especifique exatamente a taxa desse intervalo.

Por que o Dropout é capaz de diminuir o overfitting? A resposta é que o Dropout pode reduzir a chance de uma codependência entre dois neurônios. Dois neurônios que desenvolvem uma dependência de código não poderão operar efetivamente quando um for descartado. Como resultado, a rede neural não pode mais depender da presença de cada neurônio e treina em conformidade. Essa característica diminui sua capacidade de memorizar as informações que lhe são apresentadas, forçando assim a generalização.

https://keras.io/layers/core/


In [1]:
# Função Auxiliares

# Converte todos os valores faltantes na coluna especificada para a mediana
def missing_median(df, name):
    med = df[name].median()
    df[name] = df[name].fillna(med)


# Converte um dataframe Pandas para as entradas x, y que o TensorFlow precisa
def to_xy(df, target):
    result = []
    for x in df.columns:
        if x != target:
            result.append(x)
    # Descobre o tipo da coluna de destino. 
    target_type = df[target].dtypes
    target_type = target_type[0] if hasattr(target_type, '__iter__') else target_type
    # Encoding para int. TensorFlow gosta de 32 bits.
    if target_type in (np.int64, np.int32):
        # Classificação
        dummies = pd.get_dummies(df[target])
        return df.as_matrix(result).astype(np.float32), dummies.as_matrix().astype(np.float32)
    else:
        # Regressão
        return df.as_matrix(result).astype(np.float32), df.as_matrix([target]).astype(np.float32)

In [2]:
############################################
# TensorFlow com Dropout Para Regressão
############################################
%matplotlib inline
from matplotlib.pyplot import figure, show
import tensorflow as tf
from sklearn.model_selection import train_test_split
import pandas as pd
import os
import numpy as np
from sklearn import metrics
from scipy.stats import zscore
from keras.callbacks import EarlyStopping
from keras.layers import Dense, Dropout
from keras import regularizers
from keras.models import Sequential

path = "./data/"

filename_read = os.path.join(path,"auto-mpg.csv")
df = pd.read_csv(filename_read,na_values=['NA','?'])

tf.logging.set_verbosity(tf.logging.ERROR)

df.drop('name',1,inplace=True)
missing_median(df, 'horsepower')
x,y = to_xy(df,"mpg")

x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25, random_state=45)

model = Sequential()
model.add(Dense(50, input_dim = x.shape[1], kernel_initializer = 'normal', activation = 'relu'))
model.add(Dropout(0.2))
model.add(Dense(25, input_dim = x.shape[1], kernel_initializer = 'normal', activation = 'relu'))
model.add(Dense(10, input_dim = 64, activation = 'relu'))
model.add(Dense(1, kernel_initializer = 'normal'))
model.compile(loss = 'mean_squared_error', optimizer = 'adam')
monitor = EarlyStopping(monitor = 'val_loss', min_delta = 1e-3, patience = 5, verbose = 1, mode = 'auto')
model.fit(x, y, validation_data = (x_test,y_test), callbacks = [monitor], verbose = 0, epochs = 1000)
pred = model.predict(x_test)

# RMSE 
score = np.sqrt(metrics.mean_squared_error(pred,y_test))
print("Final score (RMSE): {}".format(score))


Using TensorFlow backend.
Epoch 00054: early stopping
Final score (RMSE): 4.666738510131836

Fim