使用python和numpy的梯度下降

Mad*_*Ram 56 python numpy machine-learning linear-regression gradient-descent

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
Run Code Online (Sandbox Code Playgroud)

从上面的代码我的theta是100.2 100.2,但它应该100.2 61.09在matlab中是正确的.

Tho*_*lut 127

我认为你的代码有点过于复杂,需要更多的结构,否则你将失去所有方程和操作.最后,这个回归归结为四个操作:

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

在你的情况下,我猜你已经混淆mn.此处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)
Run Code Online (Sandbox Code Playgroud)

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

线性回归

如您所见,我还添加了生成的回归线和由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]
Run Code Online (Sandbox Code Playgroud)

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

  • 在gradientDescent中,`/ 2*m`应该是`/(2*m)`? (3认同)
  • @ Saurabh Verma:在我解释细节之前,首先,这个陈述:np.dot(xTrans,loss)/ m是一个矩阵计算,同时计算一行训练数据的梯度,一行标签.结果是大小的矢量(m乘1).回到基本的,如果我们采用方形误差的偏导数,比如说,theta [j],我们将得到这个函数的导数:(np.dot(x [i],theta) - y [i])**2 wrt theta [j].注意,theta是一个向量.结果应为2*(np.dot(x [i],theta) - y [i])*x [j].您可以手动确认. (3认同)
  • 使用"损失"来表示绝对差异并不是一个好主意,因为"损失"通常是"成本"的同义词.你也不需要传递`m`,NumPy数组知道它们自己的形状. (2认同)
  • 有人可以解释成本函数的部分推导如何等于函数:np.dot(xTrans,loss)/ m? (2认同)

Mua*_*tik 10

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

首先,您计算渐变,X.T * (X * w - y) / N并同时使用此渐变更新当前的θ.

  • 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)
Run Code Online (Sandbox Code Playgroud)

TEST1 TEST2 TEST2

  • 不必要的进口声明:将pandas导入为pd (3认同)
  • @Muatik我不明白如何获得带有误差和训练集的内积的梯度:`gradient = xT * error / N`这背后的逻辑是什么? (2认同)

Mat*_*mes 6

这些答案中的大多数都遗漏了一些关于线性回归的解释,并且代码在我看来有点复杂。

问题是,如果您有一个包含“m”个样本的数据集,每个样本称为“x^i”(n 维向量),以及一个结果向量 y(m 维向量),则可以构造以下矩阵:

梯度下降输入

现在,目标是找到“w”(n+1 维向量),它描述线性回归的线,“w_0”是常数项,“w_1”等是每个维度(特征)的系数在输入样本中。因此,本质上,您希望找到“w”,使得“X*w”尽可能接近“y”,即您的线预测将尽可能接近原始结果。

另请注意,我们在每个“x^i”的开头添加了一个额外的组件/维度,即“1”,以解释常数项。此外,“X”只是将每个结果“堆叠”为一行而得到的矩阵,因此它是一个(m x n+1)矩阵。

一旦构建完成,梯度下降的 Python 和 Numpy 代码实际上非常简单:

def descent(X, y, learning_rate = 0.001, iters = 100):
    w = np.zeros((X.shape[1], 1))
    for i in range(iters):
        grad_vec = -(X.T).dot(y - X.dot(w))
        w = w - learning_rate*grad_vec
    return w
Run Code Online (Sandbox Code Playgroud)

瞧!这将返回向量“w”,或预测线的描述。

但它是如何运作的呢? 在上面的代码中,我找到了成本函数的梯度向量(在本例中为平方差),然后我们将“逆流”,找到最佳“w”给出的最小成本。实际使用的公式在行中

grad_vec = -(X.T).dot(y - X.dot(w))
Run Code Online (Sandbox Code Playgroud)

有关完整的数学解释以及包括矩阵创建的代码,请参阅这篇关于如何在 Python 中实现梯度下降的文章。

编辑:为了说明,上面的代码估计了一条可以用来进行预测的线。下图显示了“学习的”梯度下降线(红色)的示例,以及来自 Kaggle 的“鱼市”数据集的原始数据样本(蓝色散点)。

在此输入图像描述