Skip to content

Comparando Algoritmos de Descida de Gradiente em Python: Puro, NumPy e TensorFlow

    Na jornada do aprendizado de máquina, compreender os algoritmos de otimização é fundamental. Entre essas técnicas, a descida de gradiente destaca-se como um método crucial para ajustar os parâmetros de um modelo e minimizar a função de custo. Neste artigo, exploraremos a implementação e a comparação dos algoritmos de descida de gradiente em três abordagens diferentes: Python puro, NumPy e TensorFlow.

    Implementação da Descida de Gradiente em Python Puro

    Para uma compreensão profunda do conceito de descida de gradiente, começaremos com uma implementação em Python puro. Considere o seguinte código, que estima os parâmetros de uma regressão linear:

    def py_descent(x, d, mu, N_epochs):
        N = len(x)
        f = 2 / N
        y = [0] * N
        w = [0, 0]
        grad = [0, 0]
        
        for _ in range(N_epochs):
            np.subtract(d, y, out=y)
            grad[0] = f * sum(y)
            grad[1] = f * sum(i * j for i, j in zip(y, x))
            w = [i + mu * j for i, j in zip(w, grad)]
            y = [w[0] + w[1] * i for i in x]
        
        return w
    
    mu = 0.001
    N_epochs = 10000
    t0 = time.time()
    py_w = py_descent(x_list, d_list, mu, N_epochs)
    t1 = time.time()
    print(py_w)
    print('Tempo de Solução: {:.2f} segundos'.format(round(t1 - t0, 2)))
    

    Neste programa, estimamos os parâmetros w_0 e w_1 de uma regressão linear. A cada iteração, calculamos os gradientes e atualizamos os pesos para minimizar a função de custo.

    Utilizando NumPy para Maior Eficiência

    Apesar de educativa, a implementação anterior não é eficiente para conjuntos de dados grandes. Aqui, entra o NumPy, uma biblioteca poderosa para computação numérica. Veja como a implementação usando NumPy parece:

    def np_descent(x, d, mu, N_epochs):
        d = d.squeeze()
        N = len(x)
        f = 2 / N
        y = np.zeros(N)
        err = np.zeros(N)
        w = np.zeros(2)
        grad = np.empty(2)
        
        for _ in range(N_epochs):
            np.subtract(d, y, out=err)
            grad[:] = f * np.sum(err), f * (err @ x)
            w = w + mu * grad
            y = w[0] + w[1] * x
        
        return w
    
    np_w = np_descent(x, d, mu, N_epochs)
    print(np_w)
    

    O uso extensivo de operações vetorizadas do NumPy melhora significativamente a eficiência do algoritmo.

    Implementação com TensorFlow

    O TensorFlow é uma biblioteca de código aberto desenvolvida inicialmente pela equipe Google Brain para computação numérica. Ele permite que você crie gráficos de operações para a execução eficiente de cálculos. Vamos ver como implementar o algoritmo de descida de gradiente com TensorFlow:

    def tf_descent(X_tf, d_tf, mu, N_epochs):
        N = X_tf.get_shape().as_list()[0]
        f = 2 / N
        w = tf.Variable(tf.zeros((2, 1)), name="w_tf")
        y = tf.matmul(X_tf, w, name="y_tf")
        e = y - d_tf
        grad = f * tf.matmul(tf.transpose(X_tf), e)
        training_op = tf.assign(w, w - mu * grad)
        
        init = tf.global_variables_initializer()
        with tf.Session() as sess:
            init.run()
            for _ in range(N_epochs):
                sess.run(training_op)
            opt = w.eval()
        
        return opt
    
    X_tf = tf.constant(X, dtype=tf.float32, name="X_tf")
    d_tf = tf.constant(d, dtype=tf.float32, name="d_tf")
    tf_w = tf_descent(X_tf, d_tf, mu, N_epochs)
    print(tf_w)
    

    Neste trecho de código, construímos um gráfico computacional com operações do TensorFlow para executar a descida de gradiente. O uso de tensores e gráficos computacionais é uma das principais características do TensorFlow.

    Comparando Desempenho e Conclusão

    Ao comparar os tempos de execução das três abordagens, temos:

    • Implementação em Python puro: 18.65 segundos
    • Implementação com NumPy: 0.32 segundos
    • Implementação com TensorFlow: 1.20 segundos

    O NumPy oferece uma melhoria considerável em relação ao Python puro, enquanto o TensorFlow, embora não tão eficiente quanto o NumPy, ainda oferece um desempenho significativamente melhor do que a abordagem pura.

    Em resumo, compreender a descida de gradiente é essencial para a construção de modelos de aprendizado de máquina. Ao implementar e comparar esses algoritmos nas abordagens de Python puro, NumPy e TensorFlow, você ganha insights valiosos sobre a eficiência e a flexibilidade dessas ferramentas.

    Leave a Reply

    Your email address will not be published. Required fields are marked *