Wednesday, 5 September 2018

Rede móvel média móvel


John Bullinarias Guia passo a passo para implementar uma rede neural em C Por John A. Bullinaria da Escola de Ciência da Computação da Universidade de Birmingham, Reino Unido. Este documento contém um guia passo a passo para a implementação de uma simples rede neural em C. Destina-se principalmente aos alunos que desejam (ou foram ditos) incorporar um componente de aprendizagem de rede neural em um sistema maior que eles estão construindo. Obviamente, existem muitos tipos de rede neural que se poderia considerar usar - aqui vou me concentrar em um tipo particularmente comum e útil, ou seja, uma simples rede de retro-propagação de alimentação de três camadas (perceptron multicamada). Este tipo de rede será útil quando temos um conjunto de vetores de entrada e um conjunto correspondente de vetores de saída, e nosso sistema deve produzir uma saída apropriada para cada entrada que é dada. É claro que, se já tivermos um conjunto completo de vetores de entrada e saída sem ruído, então basta uma simples tabela de consulta. No entanto, se quisermos que o sistema se generalize. Isto é, produzir saídas apropriadas para entradas que nunca viu antes, então uma rede neural que aprendeu a mapear entre as entradas e saídas conhecidas (isto é, o nosso conjunto de formação) fará frequentemente um trabalho muito bom para novas entradas também. Devo supor que o leitor já está familiarizado com C, e, para mais detalhes sobre redes neurais em geral, basta remeter o leitor para o grupo de notícias comp. ai. neural-redes e as redes associadas FAQ Neural. Então, vamos começar. Um único neur�io (isto � unidade de processamento) toma a entrada total In e produz uma Sa�a de Sa�a de Sa�a. Tomarei isto como sendo a função sigmóide embora outras funções de ativação sejam freqüentemente usadas (por exemplo tangente linear ou hiperbólica). Isto tem o efeito de esmagar o intervalo infinito de In no intervalo de 0 a 1. Ele também tem a propriedade conveniente de que sua derivada toma a forma particularmente simples Sigmoid Sigmaid derivative (1.0 Sigmóide) Normalmente, a entrada In em um dado neurônio será A soma ponderada das ativações de saída alimentadas a partir de um número de outros neurônios. É conveniente pensar nas ativações que fluem através das camadas de neurônios. Assim, se houver neurônios NumUnits1 na camada 1, a ativação total que flui para o neurônio da camada 2 é apenas a soma sobre Layer1OutiWeighti. Onde Weighti é o strengthweight da conexão entre a unidade i na camada 1 e nossa unidade na camada 2. Cada neurônio também terá um viés, ou estado de repouso, que é adicionado à soma das entradas, e é conveniente chamar esse peso0 . Podemos então writeLayer2In Weight0 começar com o viés para (i 1 i lt NumUnits1 i) Layer2In Layer1Outi Weighti adicionar em contribuições ponderadas da camada 1 Layer2Out 1.0 (1.0 exp (-Layer2In)) calcular sigmoid para dar ativação Normalmente a camada 2 terá muitas unidades Também, por isso é apropriado escrever os pesos entre a unidade i na camada 1 e a unidade j na camada 2 como uma matriz. Assim, para obter a saída da unidade j na camada 2 temos Layer2Inj Weight0j para (i 1 i lt NumUnits1 i) Layer2Inj Layer1Outi Weightij Layer2Outj 1.0 (1.0 exp (-Layer2Inj)) Lembre-se que em C os índices de matriz começam a partir de zero, não um , Então declaramos nossas variáveis ​​asdouble Layer1OutNumUnits11 double Layer2InNumUnits21 double Layer2OutNumUnits21 double WeightNumUnits11NumUnits21 (ou, mais provavelmente, declarar ponteiros e usar calloc ou malloc para alocar a memória). Naturalmente, precisamos de outro laço para obter todas as saídas de camada 2 para (j 1 j lt NumUnits2 j) Layer2Inj Peso0j para (i 1 i lt NumUnits1 i) Layer2Inj Layer1Outi Weightij Layer2Outj 1.0 (1.0 exp (-Layer2Inj)) São necessárias três camadas de redes E o suficiente para a maioria dos propósitos, de modo que as saídas da camada 2 alimentam uma terceira camada da mesma maneira que acima. O código pode começar a se tornar confuso neste ponto - acho que manter um índice separado i, j, k para cada camada ajuda, Como faz uma notação intuitiva para distinguir entre as diferentes camadas de pesos Weight12 e Weight23. Por razões óbvias, para redes de três camadas, é tradicional chamar camada 1 a camada de entrada, camada 2 a camada oculta e camada 3 a camada de saída. Nossa rede assume assim a forma familiar que usaremos para o resto deste documento. Além disso, para salvar a obtenção de todos os In s e Out s confuso, podemos escrever LayerNIn como SumN. Nosso código pode assim ser escrito Geralmente teremos um conjunto inteiro de padrões de treinamento de NumPattern, isto é, pares de entrada e vetores de saída de destino, rotulados pelo índice p. A rede aprende minimizando alguma medida do erro das saídas reais das redes em comparação com as saídas de destino. Por exemplo, o erro soma quadrada sobre todas as unidades de saída k e todos os padrões de treinamento p será dado por Erro 0.0 para (p 1 p lt NumPattern p) para (k 1 k lt NumOutput k) Erro 0.5 (Targetpk - Outputpk) (Targetpk - Outputpk) (O fator de 0,5 é convencionalmente incluído para simplificar a álgebra na derivação do algoritmo de aprendizagem.) Se inserir o código acima para computar as saídas de rede para o p loop deste, acabamos com Ill deixar o leitor para dispensar Com quaisquer índices que eles não precisam para os propósitos de seu próprio sistema (por exemplo, os índices de SumH e Sumo). A próxima etapa é iterativamente ajustar os pesos para minimizar o erro de redes. Uma maneira padrão de fazer isso é por descida de gradiente na função de erro. Podemos calcular o quanto o erro é alterado por uma pequena alteração em cada peso (isto é, calcular as derivadas parciais d Erro d Peso) e mudar os pesos por uma pequena quantidade na direção que reduz o erro. A literatura está cheia de variações nesta abordagem geral - começarei com o padrão de back-propagação on-line com algoritmo de momentum. Este não é o lugar para percorrer toda a matemática, mas para o erro de soma quadrada acima podemos calcular e aplicar uma iteração (ou época) das mudanças de peso requeridas DeltaWeightIH e DeltaWeightHO usando Error 0.0 para (p 1 p lt NumPattern p) Para (j 1 j lt NumHidden j) SumHpj WeightIH0j para (i 1 i lt NumInput i) SumHpj Inputpi PesoIHij Hiddenpj 1,0 (1,0 exp (-SumHpj)) para (k 1 k lt NumOutput k) SumOpk WeightHO0k para (j 1 j lt NumHidden j) SumOpk Hiddenpj PesoOjk Outputpk 1.0 (1.0 exp (-SumOpk)) Erro 0.5 (Targetpk - Outputpk) (Targetpk - Outputpk) DeltaOk (Targetpk - Outputpk) Outputpk (1.0 - Outputpk) para (j 1 j lt NumHidden j) SumDOWj 0.0 para (k 1 k lt NumOutput k) SumDOWj PesoOjk DeltaOk DeltaHj SumDOWj Hiddenpj (1.0 - Hiddenpj) para (j 1 j lt NumHidden j) DeltaWeightIH0j eta DeltaHj alfa DeltaWeightIH0j PesoIH0j DeltaWeightIH0j para (i 1 i lt NumInput i) DeltaWeightIHij eta Inputpi DeltaHj Delta DeltaWeightIHij PesoIHij DeltaWeightIHij para (k 1k lt NumOutput k) DeltaWeightHO0k DeltaA Delta Delta DeltaWeightHO0k WeightHO0k DeltaWeightHO0k para (j 1 j lt NumHidden j) DeltaWeightHOjk eta Hiddenpj DeltaOk alfa DeltaWeightHOjk WeightHOjk DeltaWeightHOjk (Há claramente muito espaço para reordenação, Combinando e simplificando os loops aqui - vou deixar isso para o leitor para fazer uma vez que tenham entendido o que as seções de código separado estão fazendo.) O peso muda DeltaWeightIH e DeltaWeightHO são cada composto de dois componentes. Primeiro, o componente eta que é a contribuição de descida gradiente. Em segundo lugar, o componente alfa que é um termo de momentum que efetivamente mantém uma média móvel das contribuições de variação de peso de descida de gradiente, e assim suaviza as mudanças de peso globais. Fixar bons valores dos parâmetros de aprendizagem eta e alfa é geralmente uma questão de tentativa e erro. Certamente alfa deve estar no intervalo de 0 a 1, e um valor diferente de zero normalmente acelera o aprendizado. Encontrar um bom valor para eta dependerá do problema e também do valor escolhido para alfa. Se estiver muito baixo, o treinamento será desnecessariamente lento. Tê-lo muito grande fará com que as mudanças de peso oscilar descontroladamente, e pode abrandar ou até mesmo impedir a aprendizagem por completo. O processo completo de treinamento consistirá em repetir as atualizações de peso acima para um número de épocas (usando outro para o laço) até que algum crierion do erro esteja cumprido, Por exemplo, o erro cai abaixo de algum número pequeno escolhido. (Observe que, com sigmóides nas saídas, o erro só pode atingir exatamente zero se os pesos chegarem ao infinito. Note também que às vezes o treinamento pode ficar preso em um mínimo local da função de erro e nunca chegar a qualquer lugar o mínimo real) Nós precisamos embrulhar o último bloco de código em algo como para (época 1 época lt LARGENUMBER época) CÓDIGO ACIMA PARA UMA ITERAÇÃO se (Erro lt SMALLNUMBER) quebrar Se os padrões de treinamento são apresentados na mesma ordem sistemática durante cada época, é Possíveis oscilações de peso. Portanto, é geralmente uma boa idéia usar uma nova ordem aleatória para os padrões de treinamento para cada época. Se colocarmos os índices de padrão de treinamento NumPattern p em ordem aleatória em um array ranpat. Então é simplesmente uma questão de substituir o nosso loop de padrão de treinamento Gerando a matriz aleatória ranpat não é tão simples, mas o código a seguir fará o trabalho Naturalmente, é preciso definir alguns pesos iniciais rede para iniciar o processo de aprendizagem. Iniciando todos os pesos em zero geralmente não é uma boa idéia, como que é muitas vezes um mínimo local da função de erro. É normal inicializar todos os pesos com pequenos valores aleatórios. Se rando () for sua função favorita de gerador de números aleatórios que retorna uma distribuição plana de números aleatórios no intervalo de 0 a 1 e smallwt é o tamanho absoluto máximo de seus pesos iniciais, então uma seção apropriada do código de inicialização de peso seria Note, Que é uma boa idéia para definir todos os DeltaWeights inicial para zero ao mesmo tempo. Agora temos código suficiente para montar um programa de rede neural de trabalho. Eu tenho cortado e colado o código acima no arquivo nn. c (que seu navegador deve permitir que você salve em seu próprio espaço de arquivo). Eu adicionei o padrão inclui, declarou todas as variáveis, rígido codificado os dados de treinamento padrão XOR e valores para eta. Alfa e smallwt. Definido um simples sobre rando (). Adicionado algumas instruções de impressão para mostrar o que a rede está fazendo, e envolveu todo o lote em um main (). O arquivo deve compilar e executar da maneira normal (por exemplo, usando os comandos UNIX cc nn. c - O - lm - o nn e nn). Ive deixou muito para o leitor a fazer para convertê-lo em um programa útil, por exemplo: Leia os dados de treinamento do arquivo Permitir que os parâmetros (alfa, smallwt, NumHidden etc.) sejam variados durante o tempo de execução Têm tamanhos de matrizes apropriados determinados E alocá-los memória durante o tempo de execução Salvar de pesos para arquivo, e lê-los de volta em novamente Plotting de erros, ativações de saída, etc durante o treinamento Existem também inúmeras variações de rede que poderiam ser implementadas, por exemplo: (Linear, tanh, etc.) Saídas valoradas reais (em vez de binárias) requerem funções de saída lineares Outputpk SumOpk DeltaOk Targetpk - Outputpk Função de custo de Entropia em vez de Sum Squared Erro de Erro - (Targetpk log (Outputpk) 1.0 - Targetpk) log (1.0 - Outputpk)) DeltaOk Targetpk - Outputpk Conjunto de treinamento, validação e testes separados Regularização de decadência de peso Mas daqui em diante, você está sozinho. Espero que você tenha encontrado esta página útil. Esta página é mantida por John Bullinaria. Última atualização em 18 de novembro de 2002. O cientista e engenheiros guia para processamento de sinal digital Por Steven W. Smith, Ph. D. Capítulo 26: Redes Neurais (e mais) Arquitetura da Rede Neural Os seres humanos e outros animais processam informações com redes neurais. Estes são formados a partir de trilhões de neurônios (células nervosas) trocando breves impulsos elétricos chamados potenciais de ação. Algoritmos de computador que imitam essas estruturas biológicas formalmente são chamados redes neurais artificiais para distingui-los das coisas squishy dentro de animais. No entanto, a maioria dos cientistas e engenheiros não são tão formais e usam o termo rede neural para incluir sistemas biológicos e não biológicos. A pesquisa de redes neurais é motivada por dois desejos: obter uma melhor compreensão do cérebro humano e desenvolver computadores capazes de lidar com problemas abstratos e mal definidos. Por exemplo, os computadores convencionais têm dificuldade para entender a fala e reconhecer os rostos das pessoas. Em comparação, os seres humanos fazem extremamente bem nestas tarefas. Muitas estruturas de redes neurais diferentes foram experimentadas, algumas baseadas em imitar o que um biólogo vê sob o microscópio, algumas baseadas em uma análise mais matemática do problema. A estrutura mais comumente utilizada é mostrada na Fig. 26-5. Esta rede neural é formada em três camadas, chamadas de camada de entrada, camada oculta e camada de saída. Cada camada consiste de um ou mais nós. Representado neste diagrama pelos pequenos círculos. As linhas entre os nós indicam o fluxo de informações de um nó para o seguinte. Neste tipo particular de rede neural, a informação flui apenas da entrada para a saída (isto é, da esquerda para a direita). Outros tipos de redes neurais têm conexões mais intrincadas, como caminhos de feedback. Os nós da camada de entrada são passivos. O que significa que eles não modificam os dados. Eles recebem um valor único em sua entrada e duplicam o valor para suas múltiplas saídas. Em comparação, os nós da camada oculta e de saída estão ativos. Isto significa que modificam os dados como mostrado na Fig. 26-6. As variáveis: X1 1, X1 2 8230 X1 15 mantêm os dados a serem avaliados (ver Fig. 26-5). Por exemplo, podem ser valores de pixel de uma imagem, amostras de um sinal de áudio, preços de mercado de ações em dias sucessivos, etc. Eles também podem ser a saída de algum outro algoritmo, como os classificadores em nosso exemplo de detecção de câncer: diâmetro, Brilho, nitidez da borda, etc. Cada valor da camada de entrada é duplicado e enviado para todos os nós ocultos. Isso é chamado de estrutura totalmente interligada. Conforme ilustrado na Fig. 26-6, os valores que entram em um nó oculto são multiplicados por pesos. Um conjunto de números predeterminados armazenados no programa. As entradas ponderadas são então adicionadas para produzir um único número. Isto é mostrado no diagrama pelo símbolo, soma. Antes de deixar o nó, este número é passado através de uma função matemática não-linear chamada sigmóide. Esta é uma curva em forma de s que limita a saída dos nós. Isto é, a entrada para o sigmóide é um valor entre - infin e infin, enquanto sua saída pode ser apenas entre 0 e 1. As saídas da camada oculta são representadas no diagrama de fluxo (Fig. 26-5) pelas variáveis: X2 1, X 2 2, X 2 3 e X 2 4. Assim como antes, cada um desses valores é duplicado e aplicado à próxima camada. Os nós ativos da camada de saída combinam e modificam os dados para produzir os dois valores de saída dessa rede, X3 1 e X3 2. As redes neurais podem ter qualquer número de camadas e qualquer número de nós por camada. A maioria das aplicações usa a estrutura de três camadas com um máximo de algumas centenas de nós de entrada. A camada oculta é geralmente cerca de 10 o tamanho da camada de entrada. No caso da detecção de alvo, a camada de saída só precisa de um único nó. A saída deste nó é limiarizada para fornecer uma indicação positiva ou negativa da presença ou ausência dos alvos nos dados de entrada. A Tabela 26-1 é um programa para realizar o diagrama de fluxo da Fig. 26-5. O ponto chave é que esta arquitetura é muito simples e muito generalizada. Este mesmo diagrama de fluxo pode ser usado para muitos problemas, independentemente de suas particularidades peculiares. A capacidade da rede neural para fornecer manipulação de dados úteis reside na seleção adequada dos pesos. Trata-se de uma saída dramática do processamento convencional de informações, onde as soluções são descritas em procedimentos passo a passo. Como exemplo, imagine uma rede neural para reconhecer objetos em um sinal sonar. Suponha que 1000 amostras do sinal sejam armazenadas em um computador. Como o computador determina se esses dados representam um submarino, uma baleia, uma montanha submarina ou nada? O DSP convencional abordaria esse problema com matemática e algoritmos, como a correlação ea análise do espectro de freqüência. Com uma rede neural, as 1000 amostras são simplesmente alimentadas na camada de entrada, resultando em valores saltando da camada de saída. Ao selecionar os pesos apropriados, a saída pode ser configurada para relatar uma ampla gama de informações. Por exemplo, pode haver saídas para: submarino (yesno), baleia (yesno), montanha submarina (yesno), etc. Com outros pesos, as saídas podem classificar os objetos como: metal ou não-metal, biológico ou não biológico, inimigo Ou aliado, etc. Sem algoritmos, sem regras, sem procedimentos apenas uma relação entre a entrada e a saída ditada pelos valores dos pesos selecionados. A Figura 26-7a mostra uma análise mais detalhada da função sigmóide, descrita matematicamente pela equação: A forma exata do sigmóide não é importante, apenas que é um limiar suave. Para comparação, um limiar simples produz um valor de um quando x gt 0 e um valor de zero quando x lt 0. O sigmóide executa esta mesma função básica de limiar, mas também é diferenciável. Como mostrado na Fig. 26-7b. Enquanto a derivada não é usada no diagrama de fluxo (Fig. 25-5), é uma parte crítica de encontrar os pesos apropriados para usar. Mais sobre isso em breve. Uma vantagem do sigmóide é que há um atalho para calcular o valor de sua derivada: Por exemplo, se x 0, então s (x) 0,5 (pela Equação 26-1) e a primeira derivada é calculada: s ( X) 0,5 (1 - 0,5) 0,25. Este não é um conceito crítico, apenas um truque para fazer a álgebra mais curta. A rede neural não seria mais flexível se o sigmóide pudesse ser ajustado para a esquerda ou para a direita, tornando-a centrada em algum outro valor que x 0 A resposta é sim, ea maioria das redes neurais permite isso. É muito simples implementar um nó adicional é adicionado à camada de entrada, com sua entrada sempre tendo um valor de um. Quando isso é multiplicado pelos pesos da camada oculta, ele fornece um viés (DC offset) para cada sigmóide. Essa adição é chamada de nó de polarização. Ele é tratado da mesma forma que os outros nós, exceto para a entrada constante. Podem as redes neurais ser feitas sem um sigmoid ou similar não linearidade Para responder a isso, olhar para a rede de três camadas da Fig. 26-5. Se os sigmóides não estivessem presentes, as três camadas entrariam em apenas duas camadas. Em outras palavras, as somas e os pesos das camadas ocultas e de saída poderiam ser combinados em uma única camada, resultando em apenas uma rede de duas camadas. O cientista e engenheiros guia para processamento de sinal digital Por Steven W. Smith, Ph. D. Capítulo 26: Redes Neurais (e mais) Treinando a Rede Neural O projeto de rede neural pode ser melhor explicado com um exemplo. A Figura 26-8 mostra o problema que vamos atacar, identificando letras individuais em uma imagem de texto. Esta tarefa de reconhecimento de padrões tem recebido muita atenção. É fácil o suficiente que muitas abordagens alcançar sucesso parcial, mas difícil o suficiente que não há soluções perfeitas. Muitos produtos comerciais bem sucedidos têm sido baseados neste problema, tais como: ler os endereços em cartas para o roteamento postal, entrada de documentos em processadores de texto, etc. O primeiro passo no desenvolvimento de uma rede neural é criar um banco de dados de exemplos. Para o problema de reconhecimento de texto, isto é conseguido imprimindo as 26 letras maiúsculas: A, B, C, D 8230 Y, Z, 50 vezes numa folha de papel. Em seguida, essas 1300 letras são convertidas em uma imagem digital usando um dos muitos dispositivos de digitalização disponíveis para computadores pessoais. Esta grande imagem digital é então dividida em pequenas imagens de 10 x 10 pixels, cada uma contendo uma única letra. Esta informação é armazenada como um banco de dados de 1,3 megabytes: 1300 imagens 100 pixels por imagem 8 bits por pixel. Usaremos as primeiras 260 imagens neste banco de dados para treinar a rede neural (isto é, determinar os pesos) eo restante para testar seu desempenho. O banco de dados também deve conter uma maneira de identificar a letra contida em cada imagem. Por exemplo, um byte adicional poderia ser adicionado a cada imagem 10x10, contendo o código ASCII letras. Em outro esquema, a posição de cada imagem 10 x 10 na base de dados poderia indicar qual é a letra. Por exemplo, as imagens de 0 a 49 podem ser todas A, as imagens 50-99 podem ser todas B, etc. Para essa demonstração, a rede neural será projetada para uma tarefa arbitrária: determine qual das 10x10 imagens contém uma vogal. Isto é, A, E, I, O ou U. Isto pode não ter qualquer aplicação prática, mas ilustra a capacidade da rede neural de aprender problemas de reconhecimento de padrões muito abstractos. Ao incluir dez exemplos de cada letra no conjunto de treinamento, a rede (espero) aprenderá os principais recursos que distinguem o alvo das imagens não-alvo. A rede neural utilizada neste exemplo é a arquitectura tradicional de três camadas, inteiramente interligada, como mostrado nas Figs. 26-5 e 26-6. Existem 101 nós na camada de entrada (100 valores de pixel mais um nó de polarização), 10 nós na camada oculta e 1 nó na camada de saída. Quando uma imagem de 100 pixels é aplicada à entrada da rede, queremos que o valor de saída seja próximo de um se uma vogal estiver presente e perto de zero se uma vogal não estiver presente. Não se preocupe que o sinal de entrada foi adquirido como uma matriz bidimensional (10x10), enquanto a entrada para a rede neural é uma matriz unidimensional. Esta é a sua compreensão de como os valores de pixel estão inter-relacionados a rede neural vai encontrar relações próprias. A Tabela 26-2 mostra o programa principal para calcular os pesos das redes neurais, com a Tabela 26-3 contendo três sub-rotinas chamadas a partir do programa principal. Os elementos da matriz: X11 a X1100, mantêm os valores da camada de entrada. Além disso, X1101 sempre mantém um valor de 1, fornecendo a entrada para o nó de polarização. Os valores de saída dos nós escondidos estão contidos nos elementos da matriz: X21 a X210. A variável, X3, contém o valor de saída das redes. Os pesos da camada oculta estão contidos na matriz, WH. , Onde o primeiro índice identifica o nó oculto (1 a 10) eo segundo índice é o nó da camada de entrada (1 a 101). Os pesos da camada de saída são mantidos em WO1 a WO10. Isso faz um total de 1020 valores de peso que definem como a rede irá operar. A primeira ação do programa é definir cada peso para um valor inicial arbitrário usando um gerador de números aleatórios. Conforme ilustrado nas linhas 190 a 240, os pesos de camada oculta são atribuídos valores iniciais entre -0,0005 e 0,0005, enquanto os pesos de camada de saída estão entre -0,5 e 0,5. Estas faixas são escolhidas para serem da mesma ordem de grandeza que os pesos finais devem ser. Isto é baseado em: (1) o intervalo de valores no sinal de entrada, (2) o número de entradas somadas em cada nó, e (3) o intervalo de valores sobre o qual o sigmóide está ativo, uma entrada de cerca de -5 Lt x lt 5 e uma saída de 0 a 1. Por exemplo, quando 101 entradas com um valor típico de 100 são multiplicadas pelo valor de peso típico de 0,0002, a soma dos produtos é de cerca de 2, que está na gama activa Da entrada de sigmóides. Se avaliássemos o desempenho da rede neural usando esses pesos aleatórios, esperaríamos que fosse o mesmo que adivinhação aleatória. O algoritmo de aprendizagem melhora o desempenho da rede, mudando gradualmente cada peso na direção correta. Isso é chamado de procedimento iterativo e é controlado no programa pelo loop FOR-NEXT nas linhas 270-400. Cada iteração torna os pesos ligeiramente mais eficientes na separação do alvo dos exemplos não-alvo. O ciclo de iteração é geralmente realizado até que nenhuma melhoria adicional seja feita. Em redes neurais típicas, isso pode ser de dez a dez mil iterações, mas algumas centenas são comuns. Este exemplo realiza 800 iterações. Para que essa estratégia iterativa funcione, deve haver um único parâmetro que descreve o desempenho do sistema. A variável ESUM (para a soma de erros) serve esta função no programa. A primeira ação dentro do loop de iteração é definir ESUM para zero (linha 290) para que ele possa ser usado como um acumulador. Ao final de cada iteração, o valor de ESUM é impresso na tela de vídeo (linha 380), para que o operador possa assegurar que o progresso está sendo feito. O valor de ESUM começará alto e gradualmente diminuirá à medida que a rede neural for treinada para reconhecer os alvos. A Figura 26-9 mostra exemplos de como o ESUM diminui à medida que as iterações prosseguem. Todas as 260 imagens no conjunto de treinamento são avaliadas durante cada iteração, conforme controlado pelo loop FOR-NEXT nas linhas 310-360. A subrotina 1000 é usada para recuperar imagens do banco de dados de exemplos. Uma vez que este não é algo de particular interesse aqui, apenas descreveremos os parâmetros passados ​​para e a partir desta sub-rotina. A subrotina 1000 é inserida com o parâmetro LETTER entre 1 e 260. Após o retorno, os valores do nó de entrada, X11 a X1100, contêm os valores de pixel para a imagem no banco de dados correspondente a LETTER. O valor do nó de polarização, X1101, é sempre retornado com um valor constante de um. Subroutine 1000 também retorna outro parâmetro, CORRECT. Isso contém o valor de saída desejado da rede para esta carta em particular. Ou seja, se a letra na imagem é uma vogal, CORRECÇÃO será retornado com um valor de um. Se a letra na imagem não for uma vogal, CORRECÇÃO será retornada com um valor de zero. Depois que a imagem sendo trabalhada é carregada em X11 até X1100, a sub-rotina 2000 passa os dados através da rede neural atual para produzir o valor do nó de saída, X3. Em outras palavras, a sub-rotina 2000 é a mesma que o programa na Tabela 26-1, exceto para um número diferente de nós em cada camada. Essa sub-rotina também calcula o quão bem a rede atual identifica a letra como um destino ou um não-alvo. Na linha 2210, a variável ELET (para letra de erro) é calculada como a diferença entre o valor de saída efectivamente gerado, X3 eo valor desejado, CORRECTO. Isso torna ELET um valor entre -1 e 1. Todos os 260 valores para ELET são combinados (linha 340) para formar ESUM, o erro quadrático total da rede para todo o conjunto de treinamento. A linha 2220 mostra uma opção que é frequentemente incluída ao calcular o erro: atribuir uma importância diferente aos erros para alvos e não-objetivos. Por exemplo, lembre-se do exemplo de câncer apresentado anteriormente neste capítulo, e as conseqüências de fazer um erro falso-positivo versus um erro falso-negativo. No presente exemplo, vamos declarar arbitrariamente que o erro na detecção de um alvo é cinco vezes tão ruim quanto o erro na detecção de um não-alvo. Com efeito, isso indica à rede para fazer um trabalho melhor com os alvos, mesmo que prejudique o desempenho dos não-objetivos. Subrotina 3000 é o coração da estratégia de rede neural, o algoritmo para mudar os pesos em cada iteração. Usaremos uma analogia para explicar a matemática subjacente. Considere a situação de um pára-quedista militar caiu atrás das linhas inimigas. Ele pára de pára-quedas para o chão em território desconhecido, apenas para descobrir que é tão escuro que ele não pode ver mais do que alguns metros de distância. Suas ordens são para proceder ao fundo do vale mais próximo para começar o resto de sua missão. O problema é que, sem ser capaz de ver mais do que alguns metros, como ele faz o seu caminho para o chão do vale Por outro lado, ele precisa de um algoritmo para ajustar sua posição xey na superfície da terra, a fim de minimizar a sua elevação . Isto é análogo ao problema de ajustar os pesos da rede neural, de modo que o erro de rede, ESUM, é minimizado. Vamos olhar para dois algoritmos para resolver este problema: evolução e descida mais íngreme. Na evolução, o pára-quedista dá um salto de vôo em alguma direção aleatória. Se a nova elevação é maior do que a anterior, ele curses e retorna à sua localização inicial, onde ele tenta novamente. Se a nova elevação for menor. Ele sente uma medida de sucesso, e repete o processo a partir do novo local. Eventualmente, ele vai chegar ao fundo do vale, embora em um caminho muito ineficiente e aleatória. Este método é chamado evolução porque é o mesmo tipo de algoritmo empregado pela natureza na evolução biológica. Cada nova geração de uma espécie tem variações aleatórias da anterior. Se essas diferenças são benéficas para as espécies, elas são mais prováveis ​​de serem mantidas e passadas para a próxima geração. Este é um resultado da melhoria permitindo que o animal receba mais alimento, escape seus inimigos, produza mais prole, etc. Se o traço novo é prejudicial, o animal prejudicado transforma o almoço para algum predador, ea variação é rejeitada. Nesse sentido, cada nova geração é uma iteração do procedimento evolutivo de otimização. Quando a evolução é usada como o algoritmo de treinamento, cada peso na rede neural é ligeiramente alterado pela adição do valor de um gerador de números aleatórios. Se os pesos modificados formam uma rede melhor (isto é, um valor mais baixo para ESUM), as alterações são mantidas, caso contrário são descartadas. Enquanto isso funciona, é muito lento na convergência. Este é o jargão utilizado para descrever que a melhoria contínua está sendo feita em direção a uma solução ideal (o fundo do vale). Em termos mais simples, o programa vai precisar de dias para chegar a uma solução, ao invés de minutos ou horas. Felizmente, o algoritmo de descida mais íngreme é muito mais rápido. Isto é como o pára-quedista naturalmente responder: avaliar qual caminho é downhill. E mover-se nessa direção. Pense sobre a situação desta maneira. O pára-quedista pode mover um passo para o norte, e registrar a mudança na elevação. Depois de retornar à sua posição original, ele pode dar um passo para o leste, e registrar essa mudança de elevação. Usando estes dois valores, ele pode determinar qual direção é downhill. Suponha que o pára-quedista caia 10 cm quando ele se move um passo na direção norte, e cai 20 cm quando ele se move um passo na direção leste. Para viajar diretamente para baixo, ele precisa mover ao longo de cada eixo uma quantidade proporcional à inclinação ao longo desse eixo. Neste caso, ele pode mover para o norte por 10 passos e leste por 20 passos. Isto o move para baixo a parte a mais íngreme da inclinação uma distância de radic 10 2 20 2 etapas. Alternativamente, ele poderia se mover em uma linha reta para o novo local, 22,4 passos ao longo da diagonal. O ponto chave é: a descida mais acentuada é conseguida movendo ao longo de cada eixo uma distância proporcional à inclinação ao longo desse eixo. A subrotina 3000 implementa este mesmo algoritmo decente mais acentuado para os pesos da rede. Antes de entrar na sub-rotina 3000, uma das imagens de exemplo foi aplicada à camada de entrada e a informação propagada para a saída. This means that the values for: X1 , X2 and X3 are all specified, as well as the current weight values: WH. and WO . In addition, we know the error the network produces for this particular image, ELET. The hidden layer weights are updated in lines 3050 to 3120, while the output layer weights are modified in lines 3150 to 3190. This is done by calculating the slope for each weight, and then changing each weight by an amount proportional to that slope . In the paratrooper case, the slope along an axis is found by moving a small distance along the axis (say, Delta x ), measuring the change in elevation (say, Delta E ), and then dividing the two (Delta E Delta x ). The slope of a neural network weight can be found in this same way: add a small increment to the weight value (Delta w ), find the resulting change in the output signal (Delta X3 ), and divide the two (Delta X3 Delta w ). Later in this chapter we will look at an example that calculates the slope this way. However, in the present example we will use a more efficient method. Earlier we said that the nonlinearity (the sigmoid) needs to be differentiable . Here is where we will use this property. If we know the slope at each point on the nonlinearity, we can directly write an equation for the slope of each weight (Delta X3 Delta w) without actually having to perturb it. Consider a specific weight, for example, WO1, corresponding to the first input of the output node. Look at the structure in Figs. 26-5 and 26-6, and ask: how will the output ( X3 ) be affected if this particular weight ( w ) is changed slightly, but everything else is kept the same The answer is: where SLOPE O is the first derivative of the output layer sigmoid, evaluated where we are operating on its curve. In other words, SLOPE O describes how much the output of the sigmoid changes in response to a change in the input to the sigmoid. From Eq. 26-2, SLOPE O can be calculated from the current output value of the sigmoid, X3. This calculation is shown in line 3160. In line 3170, the slope for this weight is calculated via Eq. 26-3, and stored in the variable DX3DW (i. e. Delta X3 Delta w). Using a similar analysis, the slope for a weight on the hidden layer, such as WH1,1, can be found by: SLOPE H1 is the first derivative of the hidden layer sigmoid, evaluated where we are operating on its curve. The other values, X11 and WO1, are simply constants that the weight change sees as it makes its way to the output. In lines 3070 and 3080, the slopes of the sigmoids are calculated using Eq. 26-2. The slope of the hidden layer weight, DX3DW is calculated in line 3090 via Eq. 26-4. Now that we know the slope of each of the weights, we can look at how each weight is changed for the next iteration. The new value for each weight is found by taking the current weight, and adding an amount that is proportional to the slope: This calculation is carried out in line 3100 for the hidden layer, and line 3180 for the output layer. The proportionality constant consists of two factors, ELET, the error of the network for this particular input, and MU, a constant set at the beginning of the program. To understand the need for ELET in this calculation, imagine that an image placed on the input produces a small error in the output signal. Next, imagine that another image applied to the input produces a large output error. When adjusting the weights, we want to nudge the network more for the second image than the first. If something is working poorly, we want to change it if it is working well, we want to leave it alone. This is accomplished by changing each weight in proportion to the current error, ELET. To understand how MU affects the system, recall the example of the paratrooper. Once he determines the downhill direction, he must decide how far to proceed before reevaluating the slope of the terrain. By making this distance short, one meter for example, he will be able to precisely follow the contours of the terrain and always be moving in an optimal direction. The problem is that he spends most of his time evaluating the slope, rather than actually moving down the hill. In comparison, he could choose the distance to be large, say 1000 meters. While this would allow the paratrooper to move rapidly along the terrain, he might overshoot the downhill path. Too large of a distance makes him jump all over the country-side without making the desired progress. In the neural network, MU controls how much the weights are changed on each iteration. The value to use depends on the particular problem, being as low as 10 -6. or as high as 0.1. From the analogy of the paratrooper, it can be expected that too small of a value will cause the network to converge too slowly. In comparison, too large of a value will cause the convergence to be erratic, and will exhibit chaotic oscillation around the final solution. Unfortunately, the way neural networks react to various values of MU can be difficult to understand or predict. This makes it critical that the network error (i. e. ESUM) be monitored during the training, such as printing it to the video screen at the end of each iteration. If the system isnt converging properly, stop the program and try another value for MU.

No comments:

Post a Comment