The perceptibility of the target letter depends on the perceptibility of the letters in the context. Does this dependency depend on which context letters are enhanced?
5.2 Simulation A10 : Effet d’espacement des lettres
A metodologia desenvolvida através de algoritmos de ML, nomeadamente, deep learning em termos de raciocínio, foi análoga à edificada através da linguagem de programação R, diferindo na elaboração do modelo de previsão.
Assim, de forma a efetuar um estudo comparativo entre as duas metodologias, foi indispensável efetuar a divisão do total da amostra em igual número de casos de treino e de teste, no sentido da previsão ser direcionada ao mesmo conjunto de dados. Então, para o primeiro caso de estudo dividiu-se:
• x_train – conjunto de dados de treino e diz respeito a 90% da amostra inicial; • y_train – série temporal dos dados de treino da variável a ser prevista;
• x_test – conjunto de dados de teste e diz respeito a 10% da amostra inicial ; • y_test – série temporal dos dados de teste da variável a ser prevista.
Uma vez que a introdução de séries temporais estacionárias não é um fator preponderante na previsão através de algoritmos de deep learning, não se sentiu a necessidade de fazer esta verificação e posterior diferenciação da série, na situação em que esta não fosse estacionária.
Alguns algoritmos de ML geralmente obtêm um melhor desempenho se os dados da série temporal possuirem uma escala ou distribuição consistente, o qual é conseguido através da normalização ou padronização dos dados. A normalização consiste num redimensionamento dos dados originais para um intervalo de 0 a 1, resultando um novo dataset em que todos os valores estão dentro deste intervalo. Por sua vez, a padronização consiste no redimensionamento do dataset inicial para que a média dos valores observados seja 0 e o desvio padrão 1 [63].
A normalização e a padronização podem ser úteis e até mesmo necessárias em alguns algoritmos de ML, quando os dados da série temporal possuem valores de entrada com diferentes escalas. Visto o dataset inicial ser constituído por valores que correspondem à quantidade diária vendida e ainda por valores binários (0 e 1) que dizem respeito aos dias da semana, meses do ano e mais ainda eventos influenciadores de vendas, torna-se assim necessário efetuar a normalização/padronização dos dados. O facto de deep learning utilizar redes neuronais, contribuiu para que se optasse por normalizar os dados ao invés de os padronizar, pois as redes neuronais fazem parte do conjunto de algoritmos de ML em que há necessidade da normalização dos dados. A razão pela qual as redes neuronais necessitam de normalização, consiste no facto destas atribuírem diferentes pesos aos valores de entrada e, logo, o dataset deverá estar todo na mesma escala [63]. A normalização consiste:
𝑦 = (𝑥 − 𝑚𝑖𝑛) (max − 𝑚𝑖𝑛)
, em que 𝑥 corresponde ao valor do dataset inicial e 𝑦 ao valor normalizado.
A biblioteca scikit-learn ([63]) oferece a função MinMaxScaler, que permite efetuar a normalização dos dados automaticamente. Depois de ser construído o modelo fazendo uso dos
56 dados normalizados, torna-se necessário inverter esta normalização, a fim de que o erro seja calculado e apresentado na mesma escala da variável a ser prevista, neste caso, a quantidade vendida. Esta inversão é facilmente conseguida através da função inverse_transform() também disponível na biblioteca scikit-learn.
A terceira fase desta metodologia, focou-se na estruturação do conjunto de redes recorrentes LSTM que iriam permitir a construção de um modelo deep learning. Esta estruturação de camadas de redes passou um processo de várias tentativas até, finalmente, ser obtido um modelo capaz de recolher o máximo de informação presente nos dados de treino, de forma a assimilar e, posteriormente, aplicar corretamente essa aprendizagem ao conjunto de dados de teste. Uma rede neuronal recorrente pode ser vista como sendo múltiplas cópias da mesma rede, cada uma passando uma mensagem para um sucessor (figura 4.1) [44].
Figura 4.1 - Tipologia de uma rede neuronal recorrente (retirado de [38]).
Juntamente com as LSTM foram também utilizadas Perceptron Multicamadas (denominadas camadas Dense). O modelo de redes neuronais multicamadas mais simples é aquele em que a camada de entrada conecta-se à camada de saída, sem realizar processamento, resultando em apenas um neurónio na camada de saída, desginado por Perceptron. No entanto, este modelo tem a limitação de somente ser capaz de solucionar problemas linearmente separáveis. A interconexão das entradas à camada de saída por pelo menos uma camada de neurónios intermediária, tipicamente designada camada escondida, remove a limitação do Perceptron e permite assim ampliar o leque de problemas solucionados por estas redes através do uso de funções de activação não-lineares [64].
Assim, inicialmente tornou-se premente entender qual seria a camada input, o número de camadas escondidas, bem como o número de neurónios que deveriam ser utilizados em cada uma das camadas, entre outras definições. A seleção dos parâmetros de treino do algoritmo é
um processo que não segue uma ordem concreta, ou seja, não existe um algoritmo explicativo de como o fazer. No entanto é preciso ter em mente que pequenas diferenças nestes parâmetros podem levar a grandes diferenças, tanto no tempo de treino como no modelo obtido.
Usar poucos neurónios na camada escondida pode levar a que a rede seja incapaz de modelar dados mais complexos, resultando em underfitting. Esta situação torna-se percetível quando o erro é demasiado grande, tanto nos casos de treino como nos casos de teste. Pelo contrário, caso o número de neurónios seja elevado relativamente ao conjunto de dados presentes, poderá contribuir para o excesso de treino da rede, ocorrendo assim overfitting e, por conseguinte, resultando na perda da capacidade de previsão. Neste último caso, é comum observar-se um desfasamento no gráfico de perda entre os dados de treino e de teste, em que o erro nos dados de treino continua a descer, enquanto nos dados de teste fica estagnado ou começa a subir. A imagem 4.2 ilustra estes acontecimentos para os dados de teste.
Figura 4.2 - Verificação de underfitting e overfitting (retirado de [53]).
Em redes neuronais, a função de ativação considera-se outro parâmetro importante a ter em atenção, aquando a definição da tipologia da rede. A função de ativação implementa a decisão relativamente aos limites do output, combinando os valores das entradas com os respetivos pesos. Alguns exemplos de funções de ativação [65]:
• Sigmoid - Recebe um valor real e produz um valor entre [0,1] ∶ 𝜎(𝑥) = 1 (1+𝑒−𝑥)
58 • tanh - Recebe um valor real e produz um valor entre [−1,1] ∶ tanh(𝑥) = 2𝜎(2𝑥) − 1
• ReLU - ReLU significa Rectified Linear Unit. Esta função coloca todos os valores negativos a zero e os positivos ficam como estão.
• Leaky ReLUs - Ao contrário da ReLU, em que a parte negativa passa a zero, a leaky ReLU atribui um valor, definido através de um parâmetro alpha. Na PReLU (uma variante da Leaky ReLU), o declive da parte negativa é calculado a partir dos próprios dados (através do backpropagation) em vez de ser pré-definido. Por sua vez, na RReLU (Randomnized Leaky ReLU), o declive da parte negativa é aleatório numa parte do treino, e depois fixa no teste. A ideia pretende que no treino o declive 𝑎𝑗𝑖 é um número aleatório retirado de uma distribuição uniforme de 𝑈(𝐼, 𝑢).
Figura 4.3 - Função de ativação Leaky ReLU e suas variantes (retirado de [65]).
• ELUs - Exponential Linear Units tenta colocar a média das ativações mais perto do zero, o que contribui para a aceleração da aprendizagem.
Antes da construção de um modelo de previsão é necessário analisar como devem ser definidas as camadas da rede neuronal, tanto ao nível de número de camadas, como da sua tipologia e ainda o número de nodos de cada uma delas. A função de ativação que se verificou ser mais apropriada à questão em estudo foi a “ReLU”, uma vez que só teriam interesse previsões de quantidade positiva ou nula.
Após o desenvolvimento da primeira estrutura para o modelo de previsão (código 4.8), verificou-se a ocorrência de overfitting, sendo assim primordial encontrar uma solução que permitisse a resolução deste problema.
Código 4.8 - Excerto de código desenvolvido em Python para primeira arquitetura do modelo deep learning. def build_model(janela,num_atributos):
model = Sequential()
model.add(LSTM(128, input_shape=(janela, num_atributos), return_sequences=True)) model.add(LSTM(128,return_sequences= False)) model.add(Dense(128, activation='relu', kernel_initializer='uniform')) model.add(Dense(1,activation='linear', kernel_initializer='uniform')) start = time.time() model.compile(loss='mse', optimizer='adam') print(model.summary()) print("Compilation Time:”,time.time()-start) return model
Genericamente existem várias medidas que podem ser tomadas no sentido de tentar reduzir o overfitting [65]:
• Acrescentar mais casos ao conjunto de treino • Reduzir a complexidade da arquitetura da rede
• Acrescentar Dropout (Dropout layer) - ocorre depois da ativação e coloca aleatoriamente ativações a zero. Corresponde a apagar partes da rede neuronal. Este apagar da informação que se foi aprendendo vai permitir evitar o overfitting, permitindo à rede generalizar. A taxa de dropout é especificada no início e depende do problema e dos resultados que se vão conseguindo no treino.
• Acrescentar normalização (Batch Normalization layer) - trata-se de um modo efetivo de normalizar cada camada intermédia incluindo os pesos e as funções de ativação. Mais utilizada para tratamento de imagem.
Visto não ser possível fazer crescer a amostra introduzindo-lhe mais exemplos de treino, optou-se por tentar a segunda medida, diminuindo o número de nodos nas camadas. As redes LSTM podem ser adicionadas como camadas de um modelo deep learning, tal como qualquer outro tipo de redes, no entanto, aquando o uso de duas ou mais redes LSTM é fundamental atribuir o valor true ao parâmetro return_sequences(). Este parâmetro indica se é retornado para a próxima camada o último output da sequência de saída, ou se toda a sequência é passada. No caso da passagem da segunda camada LSTM para a primeira Dense, este atributo
60 obteve o valor false e toda a sequência foi passada. Assim, foi diminuído o número de neurónios na segunda camada LSTM e, consequentemente, na 1ª camada Dense.
Após a realização de alguns testes com esta arquitetura, verificou-se que existia ainda
overfitting e, consequentemente, seguiu-se para a próxima medida a implementar: a técnica de dropout. Segundo [66], deve usar-se um valor de dropout pequeno, entre 20% a 50% dos
neurónios, sendo 20% considerado um bom ponto de partida. Valores muito baixos de dropout poderão não ter qualquer significância para o modelo e, por sua vez, valores muito altos, na eventualidade, resultarão, em underfitting. Assim, a taxa de dropout foi ajustada para 20% (para o terceiro caso de estudo o valor ficou nos 0.3, tendo em conta que permitia melhores resultados), significando que uma em cada 5 entradas será excluída aleatoriamente em cada ciclo de atualização. Através da aplicação de dropout entre as duas camadas LSTM, a segunda camada LSTM e primeira camada Dense e, também, entre as duas camadas Dense, constatou-se que o problema de overfitting estava resolvido. O modelo final obtido encontra-se transcrito em seguida.
Código 4.9 - Excerto de código desenvolvido em Python para construção do modelo final. def build_model(janela,num_atributos):
model = Sequential()
model.add(LSTM(128, input_shape=(janela, num_atributos), return_sequences=True)) model.add(Dropout(0.2)) model.add(LSTM(64,return_sequences= False)) model.add(Dropout(0.2)) model.add(Dense(32, activation='relu', kernel_initializer='uniform')) model.add(Dropout(0.2)) model.add(Dense(1,activation='linear', kernel_initializer='uniform')) start = time.time() model.compile(loss='mse', optimizer='adam') print(model.summary()) print("Compilation Time:”,time.time()-start) return model
O modelo foi inicialmente definido como Sequencial(), uma vez que se trata de análise de séries temporais, e a ordem temporal tem que ser cumprida de forma a obterem-se resultados coerentes. Aquando o uso da biblioteca keras, não é necessário a definição da primeira camada de input da rede, pois, ao definir as camadas intermédias automaticamente fica defina a
camada de input. As seguintes eram compostas por duas camadas LSTM e duas Dense, sendo a última correspondente à camada de output e as restantes às camadas intermédias. As camadas LSTM possuem prioridade na definição, uma vez que são as que têm capacidade para armazenar memórias (quer antigas quer recentes), ou seja, têm estado. A função de ativação foi definida nas camadas Dense.
A próxima e última fase consistiu na validação do modelo. Foi necessário ajustar o valor dos parâmetros que permitiam compilar o modelo, nomeadamente o número de epochs e de
batch size. Esta parametrização acompanhou o desenvolvimento do modelo de previsão, sendo
que, após estabilização deste, passou-se à definição final dos parâmetros. O número de epochs consiste no número de passagens para a frente e para trás que são elaboradas em todos os casos de treino. O tamanho de batch, “batch size”, corresponde ao número de casos de treino que são utilizados em cada epoch. Consequentemente, quanto maior o batch size, mais memória será necessária. Daqui resulta o número de iterações que são realizadas. Por exemplo, se tivermos 1000 casos de treino, e o batch size for 500, então serão feitas 2 iterations para completar 1 epoch [65].
Uma vez que os três casos de estudo eram referentes a datasets com valores bastante diferentes, o número de epochs e de batch size foi dissemelhante para os três, uma vez que se trata de datasets com conjunto de dados distintos. Para o primeiro caso de estudo testou-se a aplicação do modelo aos dados de teste apenas com 50 epochs e 80 de batch size, no entanto, após verificação da ausência de overfitting aumentou-se simultaneamente o número de epochs e de batch size, acabando por se obter 1300 epochs e 600 de batch size sem verificação de
overffiting. A partir deste ponto, verificou-se de novo overfitting; então foi novamente testado
o aumento do valor de dropout entre as camadas. O valor subiu até 50%, porém, verificava-se sempre a presença de overfitting, o que levou a concluir que o modelo já tinha chegado ao máximo da sua aprendizagem. Para o segundo caso de estudo, o número de epochs e de batch
size chegou aos 750 e 600, respetivamente. Por fim, tal como anteriormente descrito, de forma
a ilustrar o desenvolvimento e os resultados obtidos para o terceiro caso de estudo, selecionou- se um artigo deste conjunto, conseguindo-se neste alcançar os 5000 epochs com o número de
CAPÍTULO 5
64 O presente capítulo apresenta e caracteriza de forma sinóptica o trabalho efetuado na construção de modelos de previsão com o auxílio de modelos estatísticos e de deep learning. São apresentados os resultados obtidos e possíveis falhas dos modelos, e posteriormente é feita uma análise dos mesmos, expondo as suas contribuições aquando aplicados num contexto farmacêutico. Por fim, efetiva-se uma comparação entre as duas metodologias.
5.1
I
NTRODUÇÃOAntes de serem apresentados os resultados obtidos para as duas metodologias, é primeiro identificado através da tabela 5.1 a média do número real de vendas do conjunto de dados de treino referente aos três casos de estudo. Este valor irá posteriormente ser utilizado para inferir a percentagem de erro obtida por cada uma das metodologias aplicadas.
Tabela 5.1 - Valor médio real para o conjunto de dados de teste referente a cada caso de estudo