【问题标题】:gradient descent using python and numpy使用 python 和 numpy 进行梯度下降
【发布时间】:2013-07-21 00:16:42
【问题描述】:
def gradient(X_norm,y,theta,alpha,m,n,num_it):
    temp=np.array(np.zeros_like(theta,float))
    for i in range(0,num_it):
        h=np.dot(X_norm,theta)
        #temp[j]=theta[j]-(alpha/m)*(  np.sum( (h-y)*X_norm[:,j][np.newaxis,:] )  )
        temp[0]=theta[0]-(alpha/m)*(np.sum(h-y))
        temp[1]=theta[1]-(alpha/m)*(np.sum((h-y)*X_norm[:,1]))
        theta=temp
    return theta



X_norm,mean,std=featureScale(X)
#length of X (number of rows)
m=len(X)
X_norm=np.array([np.ones(m),X_norm])
n,m=np.shape(X_norm)
num_it=1500
alpha=0.01
theta=np.zeros(n,float)[:,np.newaxis]
X_norm=X_norm.transpose()
theta=gradient(X_norm,y,theta,alpha,m,n,num_it)
print theta

上面代码中我的theta是100.2 100.2,但在matlab中应该是100.2 61.09,这是正确的。

【问题讨论】:

  • 分号在 python 中被忽略,如果基本则缩进。

标签: python numpy machine-learning linear-regression gradient-descent


【解决方案1】:

我认为您的代码有点过于复杂,需要更多结构,否则您将迷失在所有方程式和运算中。最后这个回归归结为四个操作:

  1. 计算假设 h = X * theta
  2. 计算损失 = h - y,也许是平方成本 (loss^2)/2m
  3. 计算梯度 = X' * loss / m
  4. 更新参数 theta = theta - alpha * gradient

就您而言,我猜您将m 与n 混淆了。这里m 表示训练集中示例的数量,而不是特征的数量。

让我们看看我的代码变体:

import numpy as np
import random

# m denotes the number of examples here, not the number of features
def gradientDescent(x, y, theta, alpha, m, numIterations):
    xTrans = x.transpose()
    for i in range(0, numIterations):
        hypothesis = np.dot(x, theta)
        loss = hypothesis - y
        # avg cost per example (the 2 in 2*m doesn't really matter here.
        # But to be consistent with the gradient, I include it)
        cost = np.sum(loss ** 2) / (2 * m)
        print("Iteration %d | Cost: %f" % (i, cost))
        # avg gradient per example
        gradient = np.dot(xTrans, loss) / m
        # update
        theta = theta - alpha * gradient
    return theta


def genData(numPoints, bias, variance):
    x = np.zeros(shape=(numPoints, 2))
    y = np.zeros(shape=numPoints)
    # basically a straight line
    for i in range(0, numPoints):
        # bias feature
        x[i][0] = 1
        x[i][1] = i
        # our target variable
        y[i] = (i + bias) + random.uniform(0, 1) * variance
    return x, y

# gen 100 points with a bias of 25 and 10 variance as a bit of noise
x, y = genData(100, 25, 10)
m, n = np.shape(x)
numIterations= 100000
alpha = 0.0005
theta = np.ones(n)
theta = gradientDescent(x, y, theta, alpha, m, numIterations)
print(theta)

首先我创建了一个小的随机数据集,应该如下所示:

如您所见,我还添加了生成的回归线和由 excel 计算的公式。

您需要注意使用梯度下降的回归的直觉。当您对数据 X 进行完整的批量传递时,您需要将每个示例的 m-loss 减少为单个权重更新。在这种情况下,这是梯度总和的平均值,因此除以m。

接下来需要注意的是跟踪收敛并调整学习率。就此而言,您应该始终跟踪每次迭代的成本,甚至可以绘制它。

如果您运行我的示例,返回的 theta 将如下所示:

Iteration 99997 | Cost: 47883.706462
Iteration 99998 | Cost: 47883.706462
Iteration 99999 | Cost: 47883.706462
[ 29.25567368   1.01108458]

这实际上非常接近由 excel 计算的方程 (y = x + 30)。请注意,当我们将偏差传递到第一列时,第一个 theta 值表示偏差权重。

【讨论】:

  • 在 gradientDescent 中,/ 2 * m 应该是 / (2 * m) 吗?
  • 使用loss 表示绝对差异并不是一个好主意,因为“损失”通常是“成本”的同义词。你也根本不需要传递m,NumPy 数组知道自己的形状。
  • 有人能解释一下成本函数的偏导数如何等于函数:np.dot(xTrans, loss) / m 吗?
  • @Saurabh Verma:在我解释细节之前,首先声明一下:np.dot(xTrans, loss) / m 是一个矩阵计算,同时计算所有对训练数据、标签的梯度在一行中。结果是一个大小为 (m x 1) 的向量。回到基础,如果我们对平方误差求偏导,比如说,theta[ j ],我们将求这个函数的导数:(np.dot(x[ i ], theta) - y[i]) ** 2 wrt θ[j]。注意,theta 是一个向量。结果应该是 2 * (np.dot(x[ i ], theta) - y[ i ]) * x[ j ]。您可以手动确认。
  • 代替 xtrans = x.transpose() 不必要地复制数据,您可以在每次使用 xtrans 时使用 x.T 。 x 只需要为 Fortran 排序即可实现高效的内存访问。
【解决方案2】:

您可以在下面找到我对线性回归问题的梯度下降的实现。

首先,您像X.T * (X * w - y) / N 一样计算梯度,并同时使用此梯度更新您当前的 theta。

  • X:特征矩阵
  • y:目标值
  • w:权重/值
  • N:训练集的大小

这是python代码:

import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
import random

def generateSample(N, variance=100):
    X = np.matrix(range(N)).T + 1
    Y = np.matrix([random.random() * variance + i * 10 + 900 for i in range(len(X))]).T
    return X, Y

def fitModel_gradient(x, y):
    N = len(x)
    w = np.zeros((x.shape[1], 1))
    eta = 0.0001

    maxIteration = 100000
    for i in range(maxIteration):
        error = x * w - y
        gradient = x.T * error / N
        w = w - eta * gradient
    return w

def plotModel(x, y, w):
    plt.plot(x[:,1], y, "x")
    plt.plot(x[:,1], x * w, "r-")
    plt.show()

def test(N, variance, modelFunction):
    X, Y = generateSample(N, variance)
    X = np.hstack([np.matrix(np.ones(len(X))).T, X])
    w = modelFunction(X, Y)
    plotModel(X, Y, w)


test(50, 600, fitModel_gradient)
test(50, 1000, fitModel_gradient)
test(100, 200, fitModel_gradient)

【讨论】:

  • 不必要的导入语句:import pandas as pd
  • @Muatik 我不明白你如何获得带有误差和训练集内积的梯度:gradient = x.T * error / N这背后的逻辑是什么?
【解决方案3】:

我知道这个问题已经有了答案,但我对 GD 函数做了一些更新:

  ### COST FUNCTION

def cost(theta,X,y):
     ### Evaluate half MSE (Mean square error)
     m = len(y)
     error = np.dot(X,theta) - y
     J = np.sum(error ** 2)/(2*m)
     return J

 cost(theta,X,y)



def GD(X,y,theta,alpha):

    cost_histo = [0]
    theta_histo = [0]

    # an arbitrary gradient, to pass the initial while() check
    delta = [np.repeat(1,len(X))]
    # Initial theta
    old_cost = cost(theta,X,y)

    while (np.max(np.abs(delta)) > 1e-6):
        error = np.dot(X,theta) - y
        delta = np.dot(np.transpose(X),error)/len(y)
        trial_theta = theta - alpha * delta
        trial_cost = cost(trial_theta,X,y)
        while (trial_cost >= old_cost):
            trial_theta = (theta +trial_theta)/2
            trial_cost = cost(trial_theta,X,y)
            cost_histo = cost_histo + trial_cost
            theta_histo = theta_histo +  trial_theta
        old_cost = trial_cost
        theta = trial_theta
    Intercept = theta[0] 
    Slope = theta[1]  
    return [Intercept,Slope]

res = GD(X,y,theta,alpha)

此函数减少了迭代中的 alpha,使函数收敛速度更快,请参阅 Estimating linear regression with Gradient Descent (Steepest Descent) 以获取 R 中的示例。我在 Python 中应用了相同的逻辑。

【讨论】:

    【解决方案4】:

    在 python 中实现@thomas-jungblut 之后,我对 Octave 做了同样的事情。如果您发现有问题,请告诉我,我会修复+更新。

    数据来自包含以下行的 txt 文件:

    1 10 1000
    2 20 2500
    3 25 3500
    4 40 5500
    5 60 6200
    

    将其视为特征 [卧室数量] [mts2] 和最后一列 [租金价格] 的非常粗略的样本,这是我们想要预测的。

    这是 Octave 的实现:

    %
    % Linear Regression with multiple variables
    %
    
    % Alpha for learning curve
    alphaNum = 0.0005;
    
    % Number of features
    n = 2;
    
    % Number of iterations for Gradient Descent algorithm
    iterations = 10000
    
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % No need to update after here
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    
    DATA = load('CHANGE_WITH_DATA_FILE_PATH');
    
    % Initial theta values
    theta = ones(n + 1, 1);
    
    % Number of training samples
    m = length(DATA(:, 1));
    
    % X with one mor column (x0 filled with '1's)
    X = ones(m, 1);
    for i = 1:n
      X = [X, DATA(:,i)];
    endfor
    
    % Expected data must go always in the last column  
    y = DATA(:, n + 1)
    
    function gradientDescent(x, y, theta, alphaNum, iterations)
      iterations = [];
      costs = [];
    
      m = length(y);
    
      for iteration = 1:10000
        hypothesis = x * theta;
    
        loss = hypothesis - y;
    
        % J(theta)    
        cost = sum(loss.^2) / (2 * m);
    
        % Save for the graphic to see if the algorithm did work
        iterations = [iterations, iteration];
        costs = [costs, cost];
    
        gradient = (x' * loss) / m; % /m is for the average
    
        theta = theta - (alphaNum * gradient);
      endfor    
    
      % Show final theta values
      display(theta)
    
      % Show J(theta) graphic evolution to check it worked, tendency must be zero
      plot(iterations, costs);
    
    endfunction
    
    % Execute gradient descent
    gradientDescent(X, y, theta, alphaNum, iterations);
    

    【讨论】:

      猜你喜欢
      • 2022-08-14
      • 2013-05-25
      • 2017-02-19
      • 1970-01-01
      • 2011-09-27
      • 1970-01-01
      • 2019-08-29
      • 2018-05-14
      • 2020-08-07
      相关资源
      最近更新 更多