使用 python 和 numpy 进行梯度下降
- 2025-03-20 08:46:00
- admin 原创
- 41
问题描述:
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
,但它应该100.2 61.09
在 matlab 中是正确的。
解决方案 1:
我认为您的代码有点太复杂了,需要更多的结构,否则您将迷失在所有方程式和运算中。最后,这个回归归结为四个运算:
计算假设 h = X * theta
计算损失 = h - y 以及平方成本 (loss^2)/2m
计算梯度 = X' * loss / m
更新参数 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 损失减少到单个权重更新。在这种情况下,这是梯度总和的平均值,因此除以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 值表示偏差权重。
解决方案 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)
解决方案 3:
大多数答案都缺少一些关于线性回归的解释,而且在我看来代码有点复杂。
问题是,如果您有一个包含“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
瞧!这将返回向量“w”,即预测线的描述。
但它是如何工作的呢?
在上面的代码中,我找到了成本函数的梯度向量(在本例中是平方差),然后我们“逆流而上”,找到最佳“w”给出的最小成本。实际使用的公式如下
grad_vec = -(X.T).dot(y - X.dot(w))
有关完整的数学解释和代码(包括矩阵创建),请参阅有关如何在 Python 中实现梯度下降的文章。
编辑:为了说明起见,上面的代码估计了一条可用于进行预测的线。下图显示了“学习”梯度下降线(红色)的示例,以及来自 Kaggle 的“鱼市”数据集的原始数据样本(蓝色散点)。
解决方案 4:
我知道这个问题已经有答案了,但我对 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 值,使得函数收敛得更快(有关 R 中的使用梯度下降(最速下降)估计线性回归的示例,请参见。我在 Python 中应用了相同的逻辑。
解决方案 5:
按照 @thomas-jungblut 在 Python 中的实现,我对 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);
解决方案 6:
这里展示了 GD 与稳健线性回归解决方案autograd
的比较sklearn
#-------------------------------------------------------------------------------
# Name: grad_intro
# Purpose: 1. Gradients Introduction
# Author: https://www.tomasbeuzen.com/deep-learning-with-pytorch/chapters/appendixC_computing-derivatives.html
#-------------------------------------------------------------------------------
import numpy as np
import sklearn
import sklearn.linear_model
import scipy.optimize
from scipy.optimize import minimize
import autograd # pip install autograd
from autograd import grad
import autograd.numpy as anp
## try robust regression with the Huber loss
d = 10
n = 1000 # !!!!!!!!!! the bigger - the better
# generate random data
X = anp.random.randn(n, d)
w_true = anp.random.randn(d)
y = X @ w_true
# add random outliers
Noutliers = 50
y[:Noutliers] += 100 * anp.random.randn(Noutliers)
print(w_true, '
')
############################
from sklearn.linear_model import HuberRegressor
hr = HuberRegressor(fit_intercept=False, alpha=0)
hr.fit(X, y)
print(hr.coef_, '
')
############################
huber = lambda z: 0.5 * z ** 2 * (anp.abs(z) <= 1) + (anp.abs(z) - 0.5) * (anp.abs(z) > 1)
f = lambda w: anp.sum(huber(X @ w - y))
df_dw = grad(f) # differentiate through matrix multiplications, etc.
w = np.zeros(d)
alpha = 0.001
while anp.linalg.norm(df_dw(w)) > 0.0001: # <<<<<<<< G.D.
w -= alpha * df_dw(w)
print(w)
扫码咨询,免费领取项目管理大礼包!