A Descida de gradiente padrão calcularia o gradiente para todo o conjunto de dados de treinamento.
for i in range(nb_epochs):
params_grad = evaluate_gradient(loss_function, data, params)
params = params - learning_rate * params_grad
Para um número predefinido de épocas, primeiro calculamos o vetor de gradiente weights_grad da função de perda para todo o conjunto de dados, usando nossos parâmetros de vetor de parâmetros.
A descida estocástica do gradiente, por outro lado, executa uma atualização de parâmetro para cada exemplo de treinamento x (i) e o rótulo y (i).
for i in range(nb_epochs):
np.random.shuffle(data)
for example in data:
params_grad = evaluate_gradient(loss_function, example, params)
params = params - learning_rate * params_grad
Diz-se que o SGD é muito mais rápido. No entanto, não entendo como pode ser muito mais rápido se ainda tivermos um loop sobre todos os pontos de dados. O cálculo do gradiente em GD é muito mais lento que o cálculo de GD para cada ponto de dados separadamente?
O código vem daqui .
Respostas:
Resposta curta:
Resposta longa:
Minha anotação segue o curso Coursera de aprendizado de máquina de Andrew NG. Se você não estiver familiarizado com isso, pode rever a série de palestras aqui .
Vamos assumir a regressão na perda ao quadrado, a função de custo é
e o gradiente é
para gradiente decente (GD), atualizamos o parâmetro por
Eis por que estamos economizando tempo:
Suponha que tenhamos 1 bilhão de pontos de dados.
No GD, para atualizar os parâmetros uma vez, precisamos ter o gradiente (exato). Isso requer a soma desses 1 bilhão de pontos de dados para executar 1 atualização.
No SGD, podemos pensar nisso como tentar obter um gradiente aproximado em vez do gradiente exato . A aproximação é proveniente de um ponto de dados (ou vários pontos de dados chamados mini lote). Portanto, no SGD, podemos atualizar os parâmetros muito rapidamente. Além disso, se "repetirmos" todos os dados (chamados de uma época), na verdade teremos 1 bilhão de atualizações.
O truque é que, no SGD, você não precisa ter 1 bilhão de iterações / atualizações, mas muito menos iterações / atualizações, digamos 1 milhão, e você terá um modelo "bom o suficiente" para usar.
Estou escrevendo um código para demonstrar a ideia. Primeiro resolvemos o sistema linear pela equação normal, depois resolvemos com SGD. Em seguida, comparamos os resultados em termos de valores de parâmetros e valores da função objetivo final. Para visualizá-lo mais tarde, teremos 2 parâmetros para ajustar.
Os resultados:
Observe que, embora os parâmetros não estejam muito próximos, os valores de perda são124.1343 e 123.0355 que estão muito perto.
Aqui estão os valores da função de custo nas iterações, podemos ver que ela pode efetivamente diminuir a perda, o que ilustra a idéia: podemos usar um subconjunto de dados para aproximar o gradiente e obter resultados "bons o suficiente".
Agora vamos verificar os esforços computacionais entre duas abordagens. No experimento, temos1000 os pontos de dados, usando SD, avaliam o gradiente uma vez que precisa somar os dados. MAS, no SGD, a 300 iterações (observe, não 1000 iterações.) Essa é a economia computacional.
sq_loss_gr_approx
função resume apenas 1 ponto de dados e, em geral, o algoritmo converge menos quefonte