import matplotlib.pyplot as plt
import numpy as np
# 进化前CP数据(10组)
x_data = [338., 333., 328., 207., 226., 25., 179., 60., 208., 606.]
# 进化后CP数据(10组)
y_data = [640., 633., 619., 393., 428., 27., 193., 66., 226., 1591.]
# y_data = b + w * x_data(假设模型)
# bias(b),从-200~-100,以步长1为间隔返回数组(100)
x = np.arange(-200, -100, 1)
# weight(w),同上(100)
y = np.arange(-5, 5, 0.1)
# 形状为len(x)*len(y)零数组(100*100),存放loss值的矩阵(x,y组成的数据对共100*100个)
Z = np.zeros((len(x), len(y)))
# 生成坐标矩阵
X, Y = np.meshgrid(x, y)
# 计算loss functon(遍历x,y,计算出每组数据的loss):当b = x[i],w = y[j]时,loss(f(w,b)) = Σ(y_data[n]-b-w*x_data[n])**2
for i in range(len(x)):
for j in range(len(y)):
# 利用x,y中所有元素
b = x[i]
w = y[j]
# 初始化loss值,用于累加
Z[j][i] = 0
for n in range(len(x_data)):
# 计算数据对b = x[i],w = y[j]时总的loss值(利用十组样本数据)
Z[j][i] = Z[j][i] + (y_data[n] - b - w * x_data[n]) ** 2
# 求b = x[i],w = y[j]时的平均loss值
Z[j][i] = Z[j][i] / len(x_data)
# y_data = b + w * x_data
# 初始化w,b(随机的初始化,保证w,b在范围内即可)
b = -120
w = -4
# learning rate(步长)
lr = 0.0000001
# 迭代数
iteration = 100000
# store initial values for plotting
# 存储b,w的历史值用于画图
b_history = [b]
w_history = [w]
# iterations
for i in range(iteration):
# b_grad,w_grad用于累加,所以初始化为0(≠b,w)
b_grad = 0.0
w_grad = 0.0
for n in range(len(x_data)):
# loss函数对b求偏导
b_grad = b_grad - 2.0 * (y_data[n] - b - w * x_data[n]) * 1.0
# loss函数对w求偏导
w_grad = w_grad - 2.0 * (y_data[n] - b - w * x_data[n]) * x_data[n]
# update parameters
# 向loss值减小方向移动,更新b,w值
b = b - lr * b_grad
w = w - lr * w_grad
# store parameters for plotting
# 将更新后的b,w值加入列表,绘制等高线
b_history.append(b)
w_history.append(w)
# plot the figure
# 输入x,y,Z(loss值)生成等高线,按照高度分为50层(颜色代表Z大小),并设置属性--透明度0.5,颜色‘jet’一种过度色
plt.contourf(x, y, Z, 50, alpha=0.5,cmap=plt.get_cmap('jet'))
# markeredgewidth设置标记的宽度,‘+’表示标记的形状
plt.plot([-188.4], [2.67], '+', ms=12, markeredgewidth=2, color='orange')
plt.plot(b_history, w_history, 'o-', ms=3, lw=1.5, color='black')
# 限制x,y坐标范围
plt.xlim(-200, -100)
plt.ylim(-5, 5)
# 设置坐标标签及其属性
plt.xlabel(r'$b$', fontsize=16)
plt.ylabel(r'$w$', fontsize=16)
plt.show()
#显示最终w,b的最佳值:2.4834016183794727 -123.6921749751593
print(w,b)
图中’+‘为w,b的最优解位置,黑色即为w,b的变化路线,背景色表示Z(loss)值的大小。
对learning rate进行优化:
设置自适应learning rate(开始时lr大,随后逐渐变小),同时对不同的参数采取不同的lr,也即adagrad方法。
下面是改进后的梯度下降(修改后半段代码):
# 版本2-优化模型使得b,w的learning rate不一样(adagrad方法)
b = -120
w = -4
# learning rate(步长)
# 改进四
lr = 1
iteration = 100000
b_history = [b]
w_history = [w]
# 改进一,分别给予参数b,w不同的learning rate
lr_b = 0
lr_w = 0
# iterations
for i in range(iteration):
b_grad = 0.0
w_grad = 0.0
for n in range(len(x_data)):
b_grad = b_grad - 2.0 * (y_data[n] - b - w * x_data[n]) * 1.0
w_grad = w_grad - 2.0 * (y_data[n] - b - w * x_data[n]) * x_data[n]
# 改进二
lr_b = lr_b + b_grad ** 2
lr_w = lr_w + w_grad ** 2
# update parameters
# 向loss值减小方向移动,更新b,w值
# 改进三
b = b - lr / np.sqrt(lr_b) * b_grad
w = w - lr / np.sqrt(lr_w) * w_grad
b_history.append(b)
w_history.append(w)
# plot the figure
plt.contourf(x, y, Z, 50, alpha=0.5,cmap=plt.get_cmap('jet'))
plt.plot([-188.4], [2.67], '+', ms=12, markeredgewidth=2, color='orange')
plt.plot(b_history, w_history, 'o-', ms=3, lw=1.5, color='black')
plt.xlim(-200, -100)
plt.ylim(-5, 5)
plt.xlabel(r'$b$', fontsize=16)
plt.ylabel(r'$w$', fontsize=16)
plt.show()
#显示最终w,b的最佳值:2.6692640713379903 -188.3668387495323
print(w,b)