【问题标题】:Machine Learning - implementing a Gradient Descent in Python from Octave code机器学习 - 在 Python 中从 Octave 代码实现梯度下降
【发布时间】:2021-04-08 09:34:06
【问题描述】:

我正在尝试从头开始在 Python 中实现梯度下降函数,我已经在 GNU Octave 中实现并工作了该函数。不幸的是我被困住了。我摆弄了一段时间并检查了 NumPy 文档,但到目前为止还没有运气。 我知道诸如 scikit-learn 之类的库,但是我的目的是学习从头开始编写这样的函数。也许我的做法是错误的。 您将在下面找到重现错误所需的所有代码。 提前感谢您的帮助。

实际结果:测试失败并出现错误 -> "ValueError: matmul: Input operand 0 does not have enough dimensions (has 0, gufunc core with signature (n?,k),(k, m?)->(n?,m?) 需要 1)"

预期结果:以及值为 [5.2148, -0.5733] 的数组

Octave 中的函数 gradientDescent():

function [theta, J_history] = gradientDescent(X, y, theta, alpha, num_iters)
        m = length(y); % number of training examples
        J_history = zeros(num_iters, 1);

        for iter = 1:num_iters
          theta = theta - (alpha/m)*X'*(X*theta-y);
          J_history(iter) = computeCost(X, y, theta);
        end

python 中的函数 gradient_descent():

from numpy import zeros

def compute_cost(X, y, theta):
    m = len(y)
    ans = (X.T @ theta).T - y
    J = (ans @ ans.T) / (2 * m)
    return J[0, 0]


def gradient_descent(X, y, theta, alpha, num_iters):
    m = len(y)
    J_history = zeros((num_iters, 1), dtype=int)
    for iter in range(num_iters):
        theta = theta - (alpha / m) @ X.T @ (X @ theta - y)
        J_history[iter] = compute_cost(X, y, theta)
    return theta


测试文件:test_ml_utils.py

import unittest
import numpy as np
from ml.ml_utils import compute_cost, gradient_descent

class TestGradientDescent(unittest.TestCase):
    # TODO: implement tests for Gradient Descent function
    # [theta J_hist] = gradientDescent([1 5; 1 2; 1 4; 1 5],[1 6 4 2]',[0 0]',0.01,1000);
    def test_gradient_descent_00(self):
        X = np.array([[1, 5], [1, 2], [1, 4], [1, 5]])
        y = np.array([1, 6, 4, 2])
        theta = np.zeros(2)
        alpha = 0.01
        num_iter = 1000
        r_theta = np.array([5.2148, -0.5733])
        result = gradient_descent(X, y, theta, alpha, num_iter)
        self.assertEqual((round(result, 4), r_theta), 'Result is wrong!')


if __name__ == '__main__':
    unittest.main()

【问题讨论】:

    标签: python numpy machine-learning octave gradient-descent


    【解决方案1】:

    Python 中的__matmul__ 运算符@- 绑定得更紧密。这意味着您正在尝试与操作数 (alpha / m)(一个标量)和 X.T(实际上是一个矩阵)进行矩阵乘法。见operator precedence

    在 Octave 代码中,(alpha - m) * X' 正在执行标量乘法,而不是矩阵,因此如果您希望在 Python 中获得相同的行为,请使用 * 而不是 @。这似乎是因为 Octave 重载了 * 运算符,如果一个操作数是标量,则执行标量乘法,如果两个操作数都是矩阵,则执行矩阵乘法。

    【讨论】:

      【解决方案2】:

      添加到亚当的答案(关于你得到的错误是正确的)。

      但我想更笼统地补充一点,如果没有某种提示(无论是通过编程方式还是以注释的形式)不同变量所采用的维度,这段代码对于读者来说是毫无意义的。

      例如,代码中有一个提示 y 可能是二维的,而您正在使用 len 来获取它的大小。就像这可能如何静默失败的示例一样,请考虑以下情况:

      >>> y = numpy.array([[1,2,3,4,5]])
      >>> len( y )
      1
      

      而你可能想要

      >>> numpy.shape( y )
      (1, 5)
      

      >>> numpy.size( y )
      5
      

      我在您的单元测试中注意到,您传递的是等级 1 向量而不是等级 2,因此结果 y 是 1D 而不是 2D,但由于广播而与 X 一起操作,它是 2D。因此,尽管隐含了逻辑,但您的代码仍然有效,但如果没有明确说明,这是一个等待发生的运行时错误。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-11-22
        • 2023-02-25
        • 2023-03-06
        • 2018-03-26
        • 1970-01-01
        • 1970-01-01
        • 2019-08-01
        • 2016-09-25
        相关资源
        最近更新 更多