Vamos supor que eu queira treinar um algoritmo de regressão descendente de gradiente estocástico usando um conjunto de dados que possui N amostras. Como o tamanho do conjunto de dados é fixo, reutilizarei os dados T vezes. Em cada iteração ou "época", eu uso cada amostra de treinamento exatamente uma vez após reordenar aleatoriamente todo o conjunto de treinamento.
Minha implementação é baseada em Python e Numpy. Portanto, o uso de operações vetoriais pode diminuir notavelmente o tempo de computação. Criar uma implementação vetorizada de descida em gradiente de lote é bastante simples. No entanto, no caso da descida do gradiente estocástico, não consigo descobrir como evitar o loop externo que itera através de todas as amostras em cada época.
Alguém conhece alguma implementação vetorizada de descida de gradiente estocástico?
EDIT : Me perguntaram por que gostaria de usar a descida gradiente on-line se o tamanho do meu conjunto de dados é fixo.
De [1], pode-se ver que a descida do gradiente online converge mais lentamente que a descida do gradiente em lote para o mínimo do custo empírico. No entanto, converge mais rapidamente para o mínimo do custo esperado, que mede o desempenho da generalização. Eu gostaria de testar o impacto desses resultados teóricos no meu problema específico, por meio da validação cruzada. Sem uma implementação vetorizada, meu código de descida de gradiente online é muito mais lento que o de descida de gradiente em lote. Isso aumenta notavelmente o tempo necessário para que o processo de validação cruzada seja concluído.
EDIT : eu incluo aqui o pseudocódigo da minha implementação de descida de gradiente on-line, conforme solicitado pelo ffriend. Estou resolvendo um problema de regressão.
Method: on-line gradient descent (regression)
Input: X (nxp matrix; each line contains a training sample, represented as a length-p vector), Y (length-n vector; output of the training samples)
Output: A (length-p+1 vector of coefficients)
Initialize coefficients (assign value 0 to all coefficients)
Calculate outputs F
prev_error = inf
error = sum((F-Y)^2)/n
it = 0
while abs(error - prev_error)>ERROR_THRESHOLD and it<=MAX_ITERATIONS:
Randomly shuffle training samples
for each training sample i:
Compute error for training sample i
Update coefficients based on the error above
prev_error = error
Calculate outputs F
error = sum((F-Y)^2)/n
it = it + 1
[1] "Aprendizagem on-line em larga escala", L. Bottou, Y. Le Cunn, NIPS 2003.
fonte
Respostas:
Antes de tudo, a palavra "amostra" é normalmente usada para descrever um subconjunto da população , por isso vou me referir à mesma coisa que "exemplo".
Sua implementação do SGD é lenta devido a esta linha:
Aqui você usa explicitamente exatamente um exemplo para cada atualização dos parâmetros do modelo. Por definição, a vetorização é uma técnica para converter operações em um elemento em operações em um vetor desses elementos. Portanto, não, você não pode processar exemplos um por um e ainda usar a vetorização.
Você pode, no entanto, aproximar o SGD verdadeiro usando minilotes . Mini-lote é um pequeno subconjunto do conjunto de dados original (digamos, 100 exemplos). Você calcula atualizações de erros e parâmetros com base em minilotes, mas ainda itera muitos deles sem otimização global, tornando o processo estocástico. Portanto, para tornar sua implementação muito mais rápida, basta alterar a linha anterior para:
e calcule o erro do lote, não de um único exemplo.
Embora bastante óbvio, também devo mencionar a vetorização no nível por exemplo. Ou seja, em vez de algo como isto:
você definitivamente deveria fazer algo assim:
que, novamente, fácil de generalizar para mini-lotes:
fonte
Confira o método paragraph_fit do classificador SGD do scikit . Você tem controle sobre o que chama: com o aprendizado on-line "verdadeiro", passando uma instância de cada vez, ou pode agrupar instâncias em minilotes, se todos os seus dados estiverem disponíveis em uma matriz. Se estiverem, você pode dividir a matriz para fornecer os minibatches.
fonte