O livro "Grok deep learning"

imagem Oi, habrozhiteli! O livro estabelece as bases para um maior domínio da tecnologia de aprendizado profundo. Começa com uma descrição dos conceitos básicos de redes neurais e, em seguida, examina em detalhes as camadas adicionais da arquitetura.

O livro foi especialmente escrito com a intenção de fornecer o menor limite de entrada possível. Você não precisa de conhecimento de álgebra linear, métodos numéricos, otimizações convexas e até aprendizado de máquina. Tudo o que é necessário para entender o aprendizado profundo será esclarecido à medida que você avança.

Oferecemos a você que se familiarize com a passagem "O que é uma estrutura de aprendizado profundo?"

Boas ferramentas reduzem erros, aceleram o desenvolvimento e aumentam a velocidade de execução.

Se você lê muito sobre aprendizado profundo, provavelmente encontrou estruturas conhecidas como PyTorch, TensorFlow, Theano (recentemente declarado obsoleto), Keras, Lasagne e DyNet. Nos últimos anos, as estruturas evoluíram muito rapidamente e, apesar de todas elas serem distribuídas gratuitamente e de código aberto, cada uma delas tem um espírito de competição e camaradagem.

Até agora, evitei discutir estruturas, porque, em primeiro lugar, era extremamente importante para você entender o que estava acontecendo nos bastidores, implementando os algoritmos manualmente (usando apenas a biblioteca NumPy). Mas agora começaremos a usar essas estruturas, porque as redes que vamos treinar, as redes com memória de longo prazo (LSTM) são muito complexas e o código que as implementa usando o NumPy é difícil de ler, usar e depurar (gradientes neste código são encontrados em todos os lugares).

É essa complexidade que as estruturas de aprendizado profundo são projetadas para abordar. A estrutura de aprendizado profundo pode reduzir significativamente a complexidade do código (além de reduzir o número de erros e aumentar a velocidade do desenvolvimento) e aumentar a velocidade de sua execução, especialmente se você usar um processador gráfico (GPU) para treinar a rede neural, o que pode acelerar o processo de 10 a 100 vezes. Por esses motivos, as estruturas são usadas em quase todos os lugares da comunidade de pesquisa, e a compreensão dos recursos de seu trabalho será útil para você em sua carreira como usuário e pesquisador de aprendizado profundo.

Mas não nos limitaremos à estrutura de nenhuma estrutura específica, porque isso impedirá que você aprenda como todos esses modelos complexos (como o LSTM) funcionam. Em vez disso, criaremos nossa própria estrutura leve, seguindo as últimas tendências no desenvolvimento de estruturas. Seguindo esse caminho, você saberá exatamente o que as estruturas fazem quando arquiteturas complexas são criadas com a ajuda delas. Além disso, uma tentativa de criar sua própria estrutura pequena por conta própria ajudará você a mudar suavemente para o uso de estruturas reais de aprendizado profundo, porque você já conhecerá os princípios de organização de uma interface de programa (API) e sua funcionalidade. Esse exercício foi muito útil para mim, e o conhecimento adquirido ao criar minha própria estrutura acabou sendo muito útil na depuração de modelos de problemas.

Como a estrutura simplifica o código? Falando abstratamente, elimina a necessidade de escrever o mesmo código repetidamente. Especificamente, o recurso mais conveniente da estrutura de aprendizado profundo é o suporte à retropropagação automática e otimização automática. Isso permite que você escreva apenas o código de distribuição direta, e a estrutura cuidará automaticamente da distribuição reversa e correção dos pesos. A maioria das estruturas modernas simplifica o código que implementa a distribuição direta, oferecendo interfaces de alto nível para definir camadas típicas e funções de perda.

Introdução aos tensores


Os tensores são uma forma abstrata de vetores e matrizes

Até o momento, utilizamos vetores e matrizes como principais estruturas. Deixe-me lembrá-lo de que uma matriz é uma lista de vetores e um vetor é uma lista de escalares (números únicos). Um tensor é uma forma abstrata para representar listas de números aninhadas. O vetor é um tensor unidimensional. A matriz é um tensor bidimensional e estruturas com um grande número de dimensões são chamadas tensores n-dimensionais. Então, vamos começar a criar uma nova estrutura de aprendizado profundo definindo um tipo de base, que chamaremos de Tensor:

import numpy as np class Tensor (object): def __init__(self, data): self.data = np.array(data) def __add__(self, other): return Tensor(self.data + other.data) def __repr__(self): return str(self.data.__repr__()) def __str__(self): return str(self.data.__str__()) x = Tensor([1,2,3,4,5]) print(x) [1 2 3 4 5] y = x + x print(y) [2 4 6 8 10] 

Esta é a primeira versão da nossa estrutura de dados básica. Observe que ele armazena todas as informações numéricas na matriz NumPy (self.data) e suporta uma operação de tensor único (adição). Adicionar operações adicionais não é nada difícil, basta adicionar funções adicionais com a funcionalidade correspondente à classe Tensor.

Introdução ao cálculo automático de gradiente (autograd)


Anteriormente, realizamos a propagação manual traseira. Agora vamos torná-lo automático!

No capítulo 4, introduzimos derivativos. Desde então, calculamos manualmente essas derivadas em cada nova rede neural. Deixe-me lembrá-lo de que isso é alcançado pelo movimento reverso através da rede neural: primeiro, o gradiente na saída da rede é calculado; depois, esse resultado é usado para calcular a derivada no componente anterior, e assim por diante, até que os gradientes corretos sejam determinados para todos os pesos na arquitetura. Essa lógica para calcular gradientes também pode ser adicionada à classe de tensores. O seguinte mostra o que eu tinha em mente.

 import numpy as np class Tensor (object): def __init__(self, data, creators=None, creation_op=None): self.data = np.array(data) self.creation_op = creation_op self.creators = creators self.grad = None def backward(self, grad): self.grad = grad if(self.creation_op == "add"): self.creators[0].backward(grad) self.creators[1].backward(grad) def __add__(self, other): return Tensor(self.data + other.data, creators=[self,other], creation_op="add") def __repr__(self): return str(self.data.__repr__()) def __str__(self): return str(self.data.__str__()) x = Tensor([1,2,3,4,5]) y = Tensor([2,2,2,2,2]) z = x + y z.backward(Tensor(np.array([1,1,1,1,1]))) 

Este método apresenta duas inovações. Primeiro, cada tensor recebe dois novos atributos. criadores é uma lista de todos os tensores usados ​​para criar o tensor atual (o padrão é Nenhum). Ou seja, se o tensor z for obtido pela adição dos outros dois tensores, x e y, o atributo criador do tensor z conterá os tensores x e y. creation_op é um atributo complementar que armazena as operações usadas no processo de criação desse tensor. Ou seja, a instrução z = x + y criará um gráfico computacional com três nós (x, ye z) e duas arestas (z -> x e z -> y). Cada borda é assinada pela operação a partir de creation_op, ou seja, adicione. Este gráfico ajudará a organizar a propagação recursiva de gradientes para trás.

imagem

A primeira inovação nesta implementação é a criação automática de um gráfico durante cada operação matemática. Se pegarmos z e executar outra operação, o gráfico continuará em uma nova variável referente a z.

A segunda inovação nesta versão da classe Tensor é a capacidade de usar um gráfico para calcular gradientes. Se você chamar o método z.backward (), ele passará o gradiente para x e y, levando em consideração a função com a qual o tensor z (add) foi criado. Como mostrado no exemplo acima, passamos o vetor gradiente (np.array ([1,1,1,1,1]]]) para z, e esse aplica-o a seus pais. Como você provavelmente se lembra do Capítulo 4, propagação para trás por meio de adição significa aplicar propagação para trás. Nesse caso, temos apenas um gradiente para adicionar a x e y, portanto, copiamos de z para x e y:

 print(x.grad) print(y.grad) print(z.creators) print(z.creation_op) [1 1 1 1 1] [1 1 1 1 1] [array([1, 2, 3, 4, 5]), array([2, 2, 2, 2, 2])] add 

A característica mais notável dessa forma de cálculo automático de gradiente é que ele funciona recursivamente - cada vetor chama o método .backward () de todos os seus pais da lista self.creators:

imagem

»Mais informações sobre o livro podem ser encontradas no site do editor
» Conteúdo
» Trecho

Cupom de 25% de desconto para vendedores ambulantes - Deep Learning
Após o pagamento da versão impressa do livro, um livro eletrônico é enviado por e-mail.

Source: https://habr.com/ru/post/pt464509/


All Articles