5. SECURISER WINDOWS NT
5.13. P ROTECTION DU SYSTEME DE FICHIERS
5.13.1.1. Sécurisation par modification des permissions standards
O gradiente descendente estocástico em mini lotes reúne o melhor dos métodos anteriores, atualizando os parâmetros a cada lote do con- junto de treinamento. Na literatura esse método tem o nome Mini- Batch Stocastic Gradient Descent (MBSGD). Esse método opera em- baralhando o conjunto de treinamento a cada época e separando o conjunto em divisões menores denominadas batch. Cada divisão é en- tão processada pelo algoritmo backpropagation, produzindo um gradi- ente através da média e os pesos são então atualizados. Reescrevendo a equação de atualização de parâmetros para considerar os lotes ela toma a forma apresentada em 2.21.
28 CAPÍTULO 2. FUNDAMENTAÇÃO TEÓRICA
Figura 2.15: Fluxograma das operações do método de otimização de parâ- metros SGD.
Fonte: Do Autor.
θk+1= θk− η · ∇θE(θ, ~x(i : i + k), ~ˆy(i : i + k)) (2.21)
onde k representa o número de amostras do batch.
A trajetória para o mínimo global é menos ruidosa que o método BGD devido à otimização parcial dos parâmetros como ilustra a Figura 2.17. É um método mais rápido que o BGD devido a não processar todo o dataset em uma época. O embaralhamento da entrada ajuda a
2.3. REDES NEURAIS EM HARDWARE 29
evitar valores redundantes que não contribuem para o aprendizado. O processamento em mini batch adiciona um pouco de ruído a curva de aprendizado o que pode auxiliar na saída de mínimos globais.
Esse método, no entanto, não converge para o mínimo global devido ao ruído que altera o passo de aprendizagem a cada iteração. A função custo portanto permanece numa região de mínimo mas não no mínimo global. Na prática, essa não convergência não tem muita importân- cia pois a região na qual a função custo converge já garante um erro pequeno.
A Figura 2.16 exibe o fluxograma para o método de aprendizagem Mini-Batch SGD.
2.2.9 Momento
O momento é uma técnica que utiliza valores passados dos gradien- tes para atualização dos valores no intuito de melhorar o desempenho dos métodos de otimização. Em particular o momento auxilia na oti- mização próxima a áreas onde as curvas de nível são mais íngremes em uma direção do que na outra. A equação de otimização é modificada pelo momento e toma a seguinte forma
θk+1= θk− η · ∇θE(θ) + α · ∆θ
∆θ = θk− θk−1 (2.22)
A nomenclatura momento vem da física pela similaridade que a atualização dos parâmetros apresenta com o momento de um objeto. O termo multiplicado pelo momento incrementa para regiões em que o gradiente se mantém na mesma direção e reduz quando a direção é alterada, similar a uma bola descendo uma colina. Caso aplicado corretamente, o momento propicia convergência mais rápida e oscilação reduzida.
2.3
Redes neurais em Hardware
As realizações das redes neurais e os algoritmos associados em hard- ware recebe o nome de Hardware Neural Networks. As HNNs oferecem vantagens em termo de custo e de velocidade de processamento em relação as redes realizadas puramente em software, uma vez que este
30 CAPÍTULO 2. FUNDAMENTAÇÃO TEÓRICA
Figura 2.16: Fluxograma das operações do método de otimização de parâ- metros MBSGD.
Fonte: Do Autor.
último roda sobre um hardware de propósito geral [19]. O uso de FP- GAs para o design de HNNs torna-se atrativo devido à sua habilidade de processamento em paralelo, permitindo por exemplo o cálculo da saída de vários neurônios de uma camada simultaneamente.
2.3. REDES NEURAIS EM HARDWARE 31
Figura 2.17: Trajetórias da otimização dos parâmetros dos métodos SGD (roxo), BGD (azul) e MBSGD (verde).
Fonte: Adaptado de [29].
2.3.1 FPGA
O FPGA é um dispositivo semicondutor reprogramável composto por milhares de blocos lógicos configuráveis interconectados. Utilizando uma HDL como Verilog ou VHDL (Very High Speed HDL), tais blo- cos e suas conexões são reconfigurados para realização de uma função implementada na forma de um circuito digital.
Em comparação com outros dispositivos reprogramáveis como mi- croprocessadores, digital signal processors (DSP) ou até mesmo com blocos aceleradores como uma GPU, as FPGAs apresentam um bai- xíssimo consumo energético para um elevado tempo de processamento [30].
2.3.2 Ponto fixo
A representação em ponto fixo é uma das formas principais de arma- zenamento e processamento de números reais em hardware [30]. Essa representação é realizada com números inteiros obtidos após a multi- plicação por um fator de conversão e uma quantização posterior. Para aplicações diretamente em hardware opta-se, em geral, por um fator de conversão que é potência de dois, facilitando as operações com esse
32 CAPÍTULO 2. FUNDAMENTAÇÃO TEÓRICA
Tabela 2.1: Representação dos números 0,65, 1,27 e 3,42 como ponto fixo nos formatos Q1.4, Q2.6 e Q3.8. Número real original 0,65 1,27 3,42 Conversão Q1.4 01010 10100 10110 Número real reconvertido 0,625 1,25 1,375 Conversão Q2.6 00101001 01010001 11011010 Número real reconvertido 0,640625 1,265625 3,40625 Conversão Q3.8 00010100110 00101000101 01101101011 Número real reconvertido 0,6484375 1,26953125 3,41796875 Fonte: Do Autor. tipo de representação.
Para representar um número em ponto fixo dois fatores precisam ser definidos: o tamanho (número de bits) da word e a posição do ponto decimal. O formato Q é uma forma de representar esses fatores em sis- temas que tenham resolução constante [30]. Esse formato é organizado como Qm.n onde m é a quantidade de bits destinada a parte inteira e n a parte fracionária. A conversão para ponto fixo é realizado multipli- cando o número original por 2n e restringindo a m bits considerando
m − n bits antes do ponto decimal. A Tabela 2.1 ilustra alguns núme- ros reais representados nos formatos Q1.4, Q2.6 e Q3.8 e a reconversão para números reais.
De modo a conservar recursos de hardware e acelerar o processa- mento, implementa-se no FPGA os cálculos com números representados em ponto fixo, uma vez que isso resulta em circuitos digitais de menor complexidade [31].
2.3. REDES NEURAIS EM HARDWARE 33
2.3.3 Linear Feedback Shift Register
A inicialização dos pesos de uma rede neural pode influenciar na convergência dos métodos de aprendizagem [32]. Um dos métodos uti- lizados (inicialização de Glorot) consiste na inicialização com números randômicos dentro de um limite definido pela arquitetura da rede [32]. A geração de um número randômico, ou pseudo-randômico diretamente em hardware pode ser alcançado por um Linear Feedback Shift Register (LFSR).
Um LFSR fornece uma maneira simples e eficaz de gerar números não sequenciais a partir de um shift register, portas XOR e um seed inicial. O funcionamento de um LFSR é descrito com auxílio da Figura 2.18. A cada ciclo de clock, o shift register desloca os valores dos bits menores para os maiores esquecendo do valor no MSB (Most Significant Bit) e com a entrada no LSB (Least Significant Bit) fornecida por uma XOR entre saídas do registrador.
Na Figura 2.18 as saídas, denominadas na literatura como taps, uti- lizadas na XOR são oriundas dos bits 4 e 1. Através de um valor inicial (seed) o LSFR irá atualizar e produzir uma saída pseudo-randômica como mostra a Tabela 2.2. O estado 0 com todas as saídas zeradas é um estado proibido para o LSFR implementado com XOR pois a saída fica travada não produzindo novos números.
Como o número de possíveis estados é finito após um tempo a saída se repete, porém com uma boa escolha do feedback via XOR o LSFR consegue produzir uma sequência que parece randômica.
Figura 2.18: Topologia de um Linear Feedback Shift Register de 5 bits com
taps nos bits 1 e 4.
34 CAPÍTULO 2. FUNDAMENTAÇÃO TEÓRICA
Tabela 2.2: Tabela de resultados do LFSR de 5 bits com um seed inicial de valor unitário.
iteração bits valor
seed 00001 1 1 00010 2 2 00101 5 3 01010 10 4 10101 21 5 01011 11 6 10111 23 7 01110 14 8 11101 29 Fonte: Do Autor.
2.4
Ferramentas utilizadas
2.4.1 PythonPython é uma linguagem de programação interpretada de alto ní- vel muito utilizada para aprendizado de máquina e análises de dados. Foi criada por Guido van Rossum por meados de 1990 no Stichting Mathematisch Centrum. Possui uma arquitetura eficiente voltada para a programação orientada a objetos com diversas bibliotecas nas mais diversas áreas de engenharia, especialmente na área de redes neurais como o Scikit-learn, Tensorflow, Keras e PyTorch.
2.4.2 MatLab
O MatLab é a linguagem do software homônimo criado no final dos anos 70 por Clever Moler. Trata-se de um software de alta performance mantido pelo MathWorks voltado para o cálculo numérico integrando ferramentas de processamento digital de sinais, análise numérica, cál- culo matricial e ferramentas gráficas. O MatLab é utilizado em várias áreas de engenharia desde controle até processamento visual.
2.4. FERRAMENTAS UTILIZADAS 35
2.4.3 Verilog
A linguagem de descrição de hardware (HDL) Verilog foi criada en- tre 1983 e 1984 por Prabhu Goel et al. Os principais usos da linguagem são a criação e a validação de circuitos digitais para ASICs (Aplication Specific Integrated Circuit) e FPGAs. Com uma estrutura similar a da linguagem C, a linguagem Verilog permite a criação de algoritmos através de unidades lógicas e registradores podendo se beneficiar do paralelismo e pipeline em sistemas. Diferentemente de uma linguagem de alto nível como Python, as HDLs permitem uma modelagem no ní- vel RTL (Register Transfer Level) sendo capazes de modelar todo e qualquer aspecto de um circuito digital.
CAPÍTULO
3
Desenvolvimento
Neste capítulo é apresentado o desenvolvimento do presente traba- lho. Inicialmente a visão geral do projeto proposto é descrita, comen- tando sobre as etapas realizadas em Python, em MatLab com aritmética de ponto fixo e em Verilog para sintetização em FPGA. Na sequência, é detalhada a etapa do desenvolvimento em Python que consiste no uso da biblioteca especializada em aprendizado de máquina scikit-learn, na seleção dos datasets utilizados e na criação e treinamento das redes MLP. Na etapa seguinte, os algoritmos para treinamento são realizados com ponto fixo em MatLab visando resultados similares aos obtidos com Python. Os algoritmos criados realizam a geração de pesos inici- ais, o embaralhamento da entrada, a separação em batchs, a geração dos gradientes da função custo em relação aos parâmetros com o al- goritmo backpropagation, atualização dos pesos pelo método MBSGD com momento, o cálculo da função custo MSE, o cálculo da acurácia e o controle do treinamento. Finalmente, é apresentada a tradução dos algoritmos para Verilog visando a implementação em FPGA.
38 CAPÍTULO 3. DESENVOLVIMENTO
3.1
Visão Geral
O presente trabalho é voltado para a implementação do treinamento de uma rede neural MLP em FPGA. Para tal três etapas são considera- das: geração da ANN base e seu treinamento com gradiente descendente estocástico com mini lotes em Python, reprodução da rede e do treina- mento utilizando aritmética de ponto fixo em MatLab e implementação com Verilog da ANN e do treinamento em hardware (HNN). A Figura 3.1 ilustra as divisões das etapas necessárias para o desenvolvimento do trabalho. As duas primeiras etapas são apresentadas sobre o campo
Software, a última sobre o campo Hardware.
Figura 3.1: Estrutura do desenvolvimento do presente projeto.
Fonte: Do Autor.
Na primeira etapa, utilizando os recursos da biblioteca scikit-learn, é criada uma topologia de rede com arquitetura MLP e efetua-se o treinamento dessa rede utilizando algumas combinações de hiper pa- râmetros. Como o foco principal é a análise do treinamento, não são utilizadas funções de escolha ideais de parâmetros visto que uma das formas de validação com o código em MatLab é treinar a rede para o mesmo dataset mas diferentes valores de parâmetros comparando os re- sultados ao final. O treinamento escolhido foi o gradiente descendente
3.1. VISÃO GERAL 39
estocástico em mini lotes com aceleração por momento. Os datasets utilizados nas próximas e nesta etapa são criados a partir de funções da biblioteca especializada.
Para a etapa seguinte, todas as funções utilizadas da biblioteca scikit-learn foram analisadas e convertidas para linguagem do MatLab com aritmética de ponto fixo. O uso dessa aritmética facilita a tradução posterior para a HDL Verilog. Em MatLab, de modo a facilitar a sintetização em FPGA, restringiu-se a função de ativação da rede à ReLU.
Finalmente na etapa de hardware, o código em MatLab foi conver- tido para linguagem de descrição de hardware utilizando os diversos IPs fornecidos pela família Cyclone para sintetizar as operações do treina- mento. Nessa etapa, para simplificar o desenvolvimento, restringiu-se a topologia da rede a uma 2:5:1 como apresentado na figura 3.2.
Figura 3.2: Topologia da rede implementada em Verilog com duas camadas (a camada de entrada não é considerada).
40 CAPÍTULO 3. DESENVOLVIMENTO
3.2
Desenvolvimento em Python
A etapa de desenvolvimento em Python é responsável pela criação da rede e realização do treinamento no qual o restante projeto se baseia. Discorre-se neste capitulo sobre a biblioteca scikit-learn, o desenvolvi- mento dos datasets e a criação e treinamento da rede MLP.
3.2.1 Biblioteca Scikit-learn
A biblioteca open source scikit-learn [33] fornece ferramentas e APIs (Application Programming Interfaces) para análise de dados e aprendi- zado de máquina utilizando a linguagem Python. Seu desenvolvimento começou em 2007 no evento Google Summer of Code sendo disponi- bilizado para o público apenas em 2010. Algumas das empresas que utilizam a biblioteca são o Spotify, Evernote, Boooking.com, dentre ou- tras [34].
Dentre os diversos APIs disponíveis, o foco do projeto recai sobre dois: a classe MLPClassifier do API Neural_networks, utilizada para criar e treinar redes MLP para resolução de tarefas de classificação binária ou multi-classe, e o método make_classification do API
Datasets cujo objetivo é a geração dos conjuntos de treinamento, teste
e validação para os problemas de aprendizado de máquina.
3.2.1.1 API Neural_networks
Esse API disponibiliza ferramentas de aprendizado de máquina com aprendizado supervisionado ou não supervisionado. Para supervisi- onado, fornece classes que sintetizam redes neurais com arquitetura MLP para tarefas de classificação e regressão possibilitando o treina- mento com SGD, Adam ou L-BFGS e mudanças nos hiper parâmetros de treinamento como o valor da taxa de aprendizagem e momento. Já para não supervisionado fornece uma classe que realiza máquinas de boltzmann restritas (RBM) otimizando os pesos através de Stochastic Maximum Likelihood (SML). A documentação desse API está disponí- vel em [35] para supervisionado e em [36] para não supervisionado.
3.2. DESENVOLVIMENTO EM PYTHON 41
3.2.1.2 API Datasets
Este API fornece métodos que carregam, criam ou baixam datasets para uso em tarefas de aprendizado de máquina. Os conjuntos de dados carregados são em geral conjuntos pequenos que não necessitam de download externo salvos diretamente na biblioteca, alguns dos exemplos são os conjuntos Iris plant [37] e Boston House Pricing [38].
Os conjuntos de dados que necessitam de download externo são, em grande parte, bem conceituados na literatura de aprendizado de máquina e de tamanho demasiado grande para serem registrados na bi- blioteca, alguns dos exemplos incluem o Labeled Faces in the Wild [39] e o RCV1 dataset [40]. Os conjuntos criados pela biblioteca são pro- duzidos através de métodos internos do API controlando fatores como o tamanho e propriedades estatísticas durante a criação. A documen- tação desse API está disponível em [41].
3.2.2 Datasets
Para o treinamento e validação de redes o API Datasets da bi- blioteca scikit-learn possui o método make_classifications que cria dados pseudo randômicos para serem utilizados em problemas de classi- ficação de n-classes. Cada classe é composta por um número de clusters gaussianos localizados sobre os vértices de um hipercubo de dimensão n dada por um argumento. Os argumentos passados para o método são o número de amostras geradas, número de dimensões das amostras, número de classes, dimensão do hipercubo, número de amostra redun- tantes, número de clusters por classe, o espaçamento entre os vértices do hipercubo n-dimensional, dentre outros apresentados na documen- tação do método em [42].
3.2.2.1 2 classes
Através do método make_classifications criou-se um dataset com 2 classes contendo 11000 amostras para capacitar a rede criada a realizar uma classificação binária. Foi considerada apenas 1 cluster por cada classe e o gráfico dos dados criados é exibido na Figura 3.3. Esses dados são utilizados como conjunto de treinamento das etapas posteriores utilizando MatLab e Verilog.
42 CAPÍTULO 3. DESENVOLVIMENTO
Figura 3.3: Dados do dataset para classificação binária criado pelo método make_classification da biblioteca scikit-learn.
Fonte: Do Autor.
3.2.2.2 4 classes
De modo a avaliar o desempenho da topologia da rede MLP conside- rada em problemas de classificação multi-classe criou-se um conjunto de dados com o mesmo número de amostras mas com 4 classes. A Figura 3.4 ilustra o gráfico dos dados com as 4 classes.
3.2.3 Criação e treinamento das redes
Para criar e treinar as redes MLP utiliza-se a classe MLPClassi- fier do API Neural_networks da biblioteca scikit-learn. A classe cria um classificador com uma rede multilayer perceptron de tamanho variável, setado por um argumento, utilizando a função de custo log- loss, a função de ativação selecionada entre as funções identidade, lo- gística (sigmóide), tangente hiperbólica ou ReLU e o treinamento com gradiente descendente estocástico, Adam ou L-BFGS. Para facilitar a utilização em hardware optou-se por utilizar a função de ativação
3.3. DESENVOLVIMENTO EM MATLAB 43
Figura 3.4: Dados do dataset para classificação multi-classe criado pelo mé- todo make_classification da biblioteca scikit-learn.
Fonte: Do Autor.
ReLU e MSE como função custo. De modo a utilizar esta função custo derivou-se uma classe mantendo como herança a MLPClassifier al- terando a inicialização da função custo de log_loss para squared_loss.
3.2.3.1 Topologia 2:5:1
Utilizando a classe derivada com função custo MSE, função de ati- vação ReLU e treinamento com SGD criou-se a rede com topologia 2:5:1 como ilustrada na figura 3.2. Os resultados são exibidos mais detalha- damente na 4.1 mas de modo a demonstrar a habilidade de classificação da rede, as Figuras 3.5 e 3.6 exibem os hiperplanos criados separando os dados dos conjuntos de teste do primeiro e segundo dataset.
3.3
Desenvolvimento em MatLab
O desenvolvimento dos algoritmos de treinamento em MatLab pos- sui 2 objetivos: a implementação das funções que em Python são con-
44 CAPÍTULO 3. DESENVOLVIMENTO
Figura 3.5: Hiperplanos criados pela rede 2:5:1 separando as 2 classes do primeiro dataset.
Fonte: Do Autor.
sideradas “black boxes” da biblioteca scikit-learn e permitir a avaliação do desempenho do treinamento com diferentes precisões da represen- tação em ponto fixo para os dados principais da rede (pesos, bias e ativações) e para os cálculos internos.
A Figura 3.7 ilustra o fluxograma do treinamento implementado em MatLab com aritmética de ponto fixo. Os argumentos passados para o programa estão sumarizados nos sinais em cinza. O argumento configurações da rede contém a resolução da rotina de treinamento e a topologia da rede. A resolução configura a precisão dos dados e dos cálculos internos da rede utilizando o formato Q, ou seja, configura o número de bits para representar a parte inteira e a fracionária. A topologia é passada em um vetor com cada elemento representando o número de neurônios por camada, ou seja, a topologia que aparece na figura 3.2 é passada para o programa como [2, 5, 1]. Os hiper parâ- metros são a taxa de aprendizagem inicial e o valor do momento. As condições de treinamento representam o tamanho do batch, o número
3.3. DESENVOLVIMENTO EM MATLAB 45
Figura 3.6: Hiperplanos criados pela rede 2:5:1 separando as 4 classes do segundo dataset.
Fonte: Do Autor.
de batchs e o número máximo de épocas. As condições de parada se referem a tolerância e ao número de épocas sem alteração.
Os sinais em vermelho representam as variáveis que operam so- bre os desvios condicionais que no programa correspondem a um loop while (desvio condicional Cond_1) e um loop for (desvio condicional
Cond_2). O número de épocas (n_epochs) e o número de batchs
(n_batch) incrementam ao final dos seus respectivos loops. O con- tador de mudanças da função custo (ctr_chgLoss) incrementa caso a diferença entre as funções custo atual e anterior for menor que a tolerância, caso contrário o contador zera.
Através da avaliação do desempenho com diferentes precisões, selecionou- se a representação dos dados para gerar os resultados em MatLab e para implementação fixa em Verilog. Comparando a evolução das curvas de aprendizado (função custo x épocas) avalia-se o erro de quantização para as representações Q7.16, Q7.32 e Q7.48. Esses testes são apresen- tados em 4 onde se optou pela utilização da representação no formato
46 CAPÍTULO 3. DESENVOLVIMENTO
Q7.16 devido ao baixo erro e menor consumo de hardware em relação a Q7.32 e Q7.64. As explicações sobre o desenvolvimento em Ma- tLab consideram uma resolução genérica representada por Qm.n. Na sequência, discorre-se sobre cada etapa do fluxograma explicando seu funcionamento.
3.3.1 Gerador de pesos aleatórios
Duas etapas do processamento em MatLab utilizam funções de arit- mética de ponto flutuante para depois serem convertidas para ponto fixo. A primeira que faz essa utilização é a etapa Gerador de pesos
aleatórios. Essa rotina realiza a inicialização dos pesos e bias da rede
utilizando a função definida por Glorot [32] que é descrita por
ωLij = U (−lim, lim) bLi = U (−lim, lim) lim = r 6 f an_in + f an_out (3.1)
onde ωijL corresponde ao peso indo do neurônio j da camada L − 1 para o neurônio i da camada L, bLi representa o bias do neurônio i da ca- mada L, U (a, b) é uma distribuição uniforme no intervalo [a, b], f an_in corresponde ao número de neurônios da camada L − 1 e f an_out ao número de neurônios da camada L.
A Figura 3.8 mostra a parte do código responsável pela geração dos pesos e bias iniciais.
A função de aritmética de ponto flutuante é a função rand(.) que cria uma distribuição uniforme entre 0 e 1. Esse valor é então convertido para os limites definidos pela equação de Glorot que para a rede definida na figura 3.2 possui os valores 1 para os parâmetros da camada de saída