梯度下降在matlab中工作,但在python中不工作



Matlab版本

为等高线绘制

[x1,x2] = meshgrid(-30:0.5:30, -30:0.5:30);
F = (x1-2).^2 + 2*(x2 - 3).^2;
figure;
surf(x1,x2,F);
hold on;
contour(x1,x2,F);
figure;
contour(x1,x2,F,20);
hold on;

For初始化矩阵和向量的值

A = [1 0; 0 2];
AT = A';
b = [4; 12];
Nit = 100; % no of iteration of our GD
tol = 1e-5; % error tolerance
lr  = 0.2; % learning rate
xk = [-20;-20]; % initial x value
noIterations = 1;
gradErr = [];

梯度下降的循环

for k =1:Nit


x_old = xk; 
xk = xk - lr*AT*(A*xk - b); % Main GD step 

gradErr(k) = norm(AT*(A*xk-b),'fro');
if gradErr(k) < tol
break;
end

plot([x_old(1) xk(1)],[x_old(2) xk(2)],'ko-')
noIterations = noIterations + 1;
end

Python版本

等高线绘制部分

import numpy as np
import matplotlib.pyplot as plt
x1,x2 = np.meshgrid(np.arange(- 30,30+0.5,0.5),np.arange(- 30,30+0.5,0.5))
F = (x1 - 2) ** 2 + 2 * (x2 - 3) ** 2
fig=plt.figure()
surf=fig.gca(projection='3d')
surf.plot_surface(x1,x2,F)
surf.contour(x1,x2,F)
plt.show()
fig,surf=plt.subplots()
plt.contour(x1,x2,F,20)
plt.show()

初始化矩阵和向量的值

A = np.array([[1,0],[0,2]])
AT = np.transpose(A)
b = np.array([[4],[12]])
Nit = 100
tol = 1e-05
lr = 0.2
xk = np.array([[-10],[-10]])
noIterations = 1
gradErr = []

主要问题是在这里循环有错误,因为它不能运行代码

for k in range(Nit):  
x_old = xk
xk = xk - lr*np.matmul(AT,np.matmul(A,xk - b))
gradErr[k] = np.linalg.norm(AT * (A * xk - b),'fro')
if gradErr[k] < tol:
break
plt.plot(np.array([x_old(1),xk(1)]),np.array([x_old(2),xk(2)]),'ko-')
noIterations = noIterations + 1

我可以知道我的python版本在循环部分不能工作,但在matlab版本工作良好的问题是什么吗?

要访问gradErr的第k个元素,必须预先为其指定一个正长度。在您的示例中,它被初始化为一个空列表,这就是IndexError的原因。一个简单的修复是使用gradErr=np.zeros(Nit)完整的代码后,作出适当的修改如下:

import numpy as np
import matplotlib.pyplot as plt
x1,x2 = np.meshgrid(np.arange(-30, 30+0.5, 0.5), np.arange(-30, 30+0.5, 0.5))
F = (x1 - 2) ** 2 + 2 * (x2 - 3) ** 2
fig=plt.figure()
surf = fig.add_subplot(1, 1, 1, projection='3d')
surf.plot_surface(x1,x2,F)
surf.contour(x1,x2,F)
plt.show()
fig, surf=plt.subplots()
plt.contour(x1, x2, F, 20)
plt.show()
A = np.array([[1,0], [0,2]])
AT = np.transpose(A)
b = np.array([[4], [12]])
Nit = 100
tol = 1e-05
lr = 0.2
xk = np.array([[-10], [-10]])
noIterations = 1
gradErr = np.zeros(Nit)
for k in range(Nit):  
x_old = xk
xk = xk - lr * np.matmul(AT, np.matmul(A, xk - b))
gradErr[k] = np.linalg.norm(AT * (A * xk - b),'fro')
if gradErr[k] < tol:
break
plt.plot(np.array([x_old[0], xk[0]]),np.array([x_old[1], xk[1]]),'ko-')
noIterations = noIterations + 1

最新更新