python - 使用 TensorFlow 的梯度下降比基本的 Python 实现慢得多,为什么?

标签 python python-3.x tensorflow linear-regression gradient-descent

我正在学习机器学习类(class)。我有一个简单的线性回归 (LR) 问题来帮助我习惯 TensorFlow。 LR问题是找参数ab使得 Y = a*X + b近似于 (x, y)点云(为了简单起见,我自己生成的)。
我正在使用“固定步长梯度下降(FSSGD)”解决这个 LR 问题。我使用 TensorFlow 实现了它并且它有效,但我注意到它在 GPU 和 CPU 上都非常慢。因为我很好奇,所以我自己在 Python/NumPy 中实现了 FSSGD,正如预期的那样,它运行得更快,大约:

  • 比 TF@CPU 快 10 倍
  • 比 TF@GPU 快 20 倍

  • 如果 TensorFlow 这么慢,我无法想象有这么多人在使用这个框架。所以我一定是做错了什么。任何人都可以帮助我,以便我可以加速我的 TensorFlow 实现。
    我对 CPU 和 GPU 性能之间的差异不感兴趣。提供这两个性能指标只是为了完整性和说明。 我对为什么我的 TensorFlow 实现比原始 Python/NumPy 实现慢得多感兴趣。
    作为引用,我在下面添加了我的代码。
  • 剥离为最小(但完全有效)的示例。
  • 使用 Python v3.7.9 x64 .
  • 二手 tensorflow-gpu==1.15目前(因为类(class)使用 TensorFlow v1)
  • 经测试可在 Spyder 和 PyCharm 中运行。

  • 我使用 TensorFlow 的 FSSGD 实现(执行时间大约 40 秒 @CPU 到 80 秒 @GPU):
    #%% General imports
    import numpy as np
    import timeit
    import tensorflow.compat.v1 as tf
    
    
    #%% Get input data
    # Generate simulated input data
    x_data_input = np.arange(100, step=0.1)
    y_data_input = x_data_input + 20 * np.sin(x_data_input/10) + 15
    
    
    #%% Define tensorflow model
    # Define data size
    n_samples = x_data_input.shape[0]
    
    # Tensorflow is finicky about shapes, so resize
    x_data = np.reshape(x_data_input, (n_samples, 1))
    y_data = np.reshape(y_data_input, (n_samples, 1))
    
    # Define placeholders for input
    X = tf.placeholder(tf.float32, shape=(n_samples, 1), name="tf_x_data")
    Y = tf.placeholder(tf.float32, shape=(n_samples, 1), name="tf_y_data")
    
    # Define variables to be learned
    with tf.variable_scope("linear-regression", reuse=tf.AUTO_REUSE): #reuse= True | False | tf.AUTO_REUSE
        W = tf.get_variable("weights", (1, 1), initializer=tf.constant_initializer(0.0))
        b = tf.get_variable("bias", (1,), initializer=tf.constant_initializer(0.0))
    
    # Define loss function    
    Y_pred = tf.matmul(X, W) + b
    loss = tf.reduce_sum((Y - Y_pred) ** 2 / n_samples)  # Quadratic loss function
    
    
    # %% Solve tensorflow model
    #Define algorithm parameters
    total_iterations = 1e5  # Defines total training iterations
    
    #Construct TensorFlow optimizer
    with tf.variable_scope("linear-regression", reuse=tf.AUTO_REUSE): #reuse= True | False | tf.AUTO_REUSE
        opt = tf.train.GradientDescentOptimizer(learning_rate = 1e-4)
        opt_operation = opt.minimize(loss, name="GDO")
    
    #To measure execution time
    time_start = timeit.default_timer()
    
    with tf.Session() as sess:
        #Initialize variables
        sess.run(tf.global_variables_initializer())
        
        #Train variables
        for index in range(int(total_iterations)):
            _, loss_val_tmp = sess.run([opt_operation, loss], feed_dict={X: x_data, Y: y_data})
        
        #Get final values of variables
        W_val, b_val, loss_val = sess.run([W, b, loss], feed_dict={X: x_data, Y: y_data})
          
    #Print execution time      
    time_end = timeit.default_timer()
    print('')
    print("Time to execute code: {0:0.9f} sec.".format(time_end - time_start))
    print('')
    
    
    # %% Print results
    print('')
    print('Iteration = {0:0.3f}'.format(total_iterations))
    print('W_val = {0:0.3f}'.format(W_val[0,0]))
    print('b_val = {0:0.3f}'.format(b_val[0]))
    print('')
    
    我自己的python FSSGD实现(执行时间约4秒):
    #%% General imports
    import numpy as np
    import timeit
    
    
    #%% Get input data
    # Define input data
    x_data_input = np.arange(100, step=0.1)
    y_data_input = x_data_input + 20 * np.sin(x_data_input/10) + 15
    
    
    #%% Define Gradient Descent (GD) model
    # Define data size
    n_samples = x_data_input.shape[0]
    
    #Initialize data
    W = 0.0  # Initial condition
    b = 0.0  # Initial condition
    
    # Compute initial loss
    y_gd_approx = W*x_data_input+b
    loss = np.sum((y_data_input - y_gd_approx)**2)/n_samples  # Quadratic loss function
    
    
    #%% Execute Gradient Descent algorithm
    #Define algorithm parameters
    total_iterations = 1e5  # Defines total training iterations
    GD_stepsize = 1e-4  # Gradient Descent fixed step size
    
    #To measure execution time
    time_start = timeit.default_timer()
    
    for index in range(int(total_iterations)):
        #Compute gradient (derived manually for the quadratic cost function)
        loss_gradient_W = 2.0/n_samples*np.sum(-x_data_input*(y_data_input - y_gd_approx))
        loss_gradient_b = 2.0/n_samples*np.sum(-1*(y_data_input - y_gd_approx))
        
        #Update trainable variables using fixed step size gradient descent
        W = W - GD_stepsize * loss_gradient_W
        b = b - GD_stepsize * loss_gradient_b
        
        #Compute loss
        y_gd_approx = W*x_data_input+b
        loss = np.sum((y_data_input - y_gd_approx)**2)/x_data_input.shape[0]
    
    #Print execution time 
    time_end = timeit.default_timer()
    print('')
    print("Time to execute code: {0:0.9f} sec.".format(time_end - time_start))
    print('')
    
    
    # %% Print results
    print('')
    print('Iteration = {0:0.3f}'.format(total_iterations))
    print('W_val = {0:0.3f}'.format(W))
    print('b_val = {0:0.3f}'.format(b))
    print('')
    

    最佳答案

    我认为这是大迭代次数的结果。我已将迭代编号从 1e5 更改为至 1e3并且还从 x_data_input = np.arange(100, step=0.1) 更改了 x至 x_data_input = np.arange(100, step=0.0001) .通过这种方式,我减少了迭代次数,但将计算量增加了 10 倍。使用 np 它是在 中完成的22 秒 在 tensorflow 中,它是在 中完成的25 秒 .
    我的猜测:tensorflow 在每次迭代中都有很多开销(为我们提供了一个可以做很多事情的框架),但是正向传递和反向传递速度还可以。

    关于python - 使用 TensorFlow 的梯度下降比基本的 Python 实现慢得多,为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65492399/

    相关文章:

    python - 在TensorFlow中评估CIFAR-10时如何获得类别概率?

    tensorflow - Tensorflow和slim中的 "model variables"是什么?

    Python仅重新匹配字符、数字和一些标点符号

    python - 虚函数,维基百科文章: http://en. wikipedia.org/wiki/Virtual_function的解释

    python - 错误: command 'cc' failed with exit status 1 on Mac for pip install MySQL-python

    python - 为什么我的 Django 项目无法识别设置中安装的应用程序?

    python-3.x - python-twitter异常处理

    python - 特定区域的 Foursquare field

    python - 当我尝试接受用户输入时,我不断收到以下错误 - ValueError : invalid literal for int() with base 10: ''

    TensorFlow.js 打印整个张量