首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

NNDL实验 优化算法3D轨迹 pytorch版

  • 24-01-06 12:10
  • 4131
  • 13540
blog.csdn.net

3D轨迹有助于直观理解,掌握这样一个工具还是有必要的。

换模型、调参数,可以更加深入的了解算法。


程序改编自《神经网络与深度学习:案例与实践》(Paddle版)

7.3 不同优化算法的比较分析

神经网络与深度学习 (nndl.github.io)

最终效果:

动画:

plt.show()看动画没问题。

导出的gif动画轨迹被曲面挡住了。不知道什么原因,有待进一步研究。

​​​​​​​ 

 

 

源代码:

  1. import torch
  2. import numpy as np
  3. import copy
  4. from matplotlib import pyplot as plt
  5. from matplotlib import animation
  6. from itertools import zip_longest
  7. class Op(object):
  8. def __init__(self):
  9. pass
  10. def __call__(self, inputs):
  11. return self.forward(inputs)
  12. # 输入:张量inputs
  13. # 输出:张量outputs
  14. def forward(self, inputs):
  15. # return outputs
  16. raise NotImplementedError
  17. # 输入:最终输出对outputs的梯度outputs_grads
  18. # 输出:最终输出对inputs的梯度inputs_grads
  19. def backward(self, outputs_grads):
  20. # return inputs_grads
  21. raise NotImplementedError
  22. class Optimizer(object): # 优化器基类
  23. def __init__(self, init_lr, model):
  24. """
  25. 优化器类初始化
  26. """
  27. # 初始化学习率,用于参数更新的计算
  28. self.init_lr = init_lr
  29. # 指定优化器需要优化的模型
  30. self.model = model
  31. def step(self):
  32. """
  33. 定义每次迭代如何更新参数
  34. """
  35. pass
  36. class SimpleBatchGD(Optimizer):
  37. def __init__(self, init_lr, model):
  38. super(SimpleBatchGD, self).__init__(init_lr=init_lr, model=model)
  39. def step(self):
  40. # 参数更新
  41. if isinstance(self.model.params, dict):
  42. for key in self.model.params.keys():
  43. self.model.params[key] = self.model.params[key] - self.init_lr * self.model.grads[key]
  44. class Adagrad(Optimizer):
  45. def __init__(self, init_lr, model, epsilon):
  46. """
  47. Adagrad 优化器初始化
  48. 输入:
  49. - init_lr: 初始学习率 - model:模型,model.params存储模型参数值 - epsilon:保持数值稳定性而设置的非常小的常数
  50. """
  51. super(Adagrad, self).__init__(init_lr=init_lr, model=model)
  52. self.G = {}
  53. for key in self.model.params.keys():
  54. self.G[key] = 0
  55. self.epsilon = epsilon
  56. def adagrad(self, x, gradient_x, G, init_lr):
  57. """
  58. adagrad算法更新参数,G为参数梯度平方的累计值。
  59. """
  60. G += gradient_x ** 2
  61. x -= init_lr / torch.sqrt(G + self.epsilon) * gradient_x
  62. return x, G
  63. def step(self):
  64. """
  65. 参数更新
  66. """
  67. for key in self.model.params.keys():
  68. self.model.params[key], self.G[key] = self.adagrad(self.model.params[key],
  69. self.model.grads[key],
  70. self.G[key],
  71. self.init_lr)
  72. class RMSprop(Optimizer):
  73. def __init__(self, init_lr, model, beta, epsilon):
  74. """
  75. RMSprop优化器初始化
  76. 输入:
  77. - init_lr:初始学习率
  78. - model:模型,model.params存储模型参数值
  79. - beta:衰减率
  80. - epsilon:保持数值稳定性而设置的常数
  81. """
  82. super(RMSprop, self).__init__(init_lr=init_lr, model=model)
  83. self.G = {}
  84. for key in self.model.params.keys():
  85. self.G[key] = 0
  86. self.beta = beta
  87. self.epsilon = epsilon
  88. def rmsprop(self, x, gradient_x, G, init_lr):
  89. """
  90. rmsprop算法更新参数,G为迭代梯度平方的加权移动平均
  91. """
  92. G = self.beta * G + (1 - self.beta) * gradient_x ** 2
  93. x -= init_lr / torch.sqrt(G + self.epsilon) * gradient_x
  94. return x, G
  95. def step(self):
  96. """参数更新"""
  97. for key in self.model.params.keys():
  98. self.model.params[key], self.G[key] = self.rmsprop(self.model.params[key],
  99. self.model.grads[key],
  100. self.G[key],
  101. self.init_lr)
  102. class Momentum(Optimizer):
  103. def __init__(self, init_lr, model, rho):
  104. """
  105. Momentum优化器初始化
  106. 输入:
  107. - init_lr:初始学习率
  108. - model:模型,model.params存储模型参数值
  109. - rho:动量因子
  110. """
  111. super(Momentum, self).__init__(init_lr=init_lr, model=model)
  112. self.delta_x = {}
  113. for key in self.model.params.keys():
  114. self.delta_x[key] = 0
  115. self.rho = rho
  116. def momentum(self, x, gradient_x, delta_x, init_lr):
  117. """
  118. momentum算法更新参数,delta_x为梯度的加权移动平均
  119. """
  120. delta_x = self.rho * delta_x - init_lr * gradient_x
  121. x += delta_x
  122. return x, delta_x
  123. def step(self):
  124. """参数更新"""
  125. for key in self.model.params.keys():
  126. self.model.params[key], self.delta_x[key] = self.momentum(self.model.params[key],
  127. self.model.grads[key],
  128. self.delta_x[key],
  129. self.init_lr)
  130. class Adam(Optimizer):
  131. def __init__(self, init_lr, model, beta1, beta2, epsilon):
  132. """
  133. Adam优化器初始化
  134. 输入:
  135. - init_lr:初始学习率
  136. - model:模型,model.params存储模型参数值
  137. - beta1, beta2:移动平均的衰减率
  138. - epsilon:保持数值稳定性而设置的常数
  139. """
  140. super(Adam, self).__init__(init_lr=init_lr, model=model)
  141. self.beta1 = beta1
  142. self.beta2 = beta2
  143. self.epsilon = epsilon
  144. self.M, self.G = {}, {}
  145. for key in self.model.params.keys():
  146. self.M[key] = 0
  147. self.G[key] = 0
  148. self.t = 1
  149. def adam(self, x, gradient_x, G, M, t, init_lr):
  150. """
  151. adam算法更新参数
  152. 输入:
  153. - x:参数
  154. - G:梯度平方的加权移动平均
  155. - M:梯度的加权移动平均
  156. - t:迭代次数
  157. - init_lr:初始学习率
  158. """
  159. M = self.beta1 * M + (1 - self.beta1) * gradient_x
  160. G = self.beta2 * G + (1 - self.beta2) * gradient_x ** 2
  161. M_hat = M / (1 - self.beta1 ** t)
  162. G_hat = G / (1 - self.beta2 ** t)
  163. t += 1
  164. x -= init_lr / torch.sqrt(G_hat + self.epsilon) * M_hat
  165. return x, G, M, t
  166. def step(self):
  167. """参数更新"""
  168. for key in self.model.params.keys():
  169. self.model.params[key], self.G[key], self.M[key], self.t = self.adam(self.model.params[key],
  170. self.model.grads[key],
  171. self.G[key],
  172. self.M[key],
  173. self.t,
  174. self.init_lr)
  175. class OptimizedFunction3D(Op):
  176. def __init__(self):
  177. super(OptimizedFunction3D, self).__init__()
  178. self.params = {'x': 0}
  179. self.grads = {'x': 0}
  180. def forward(self, x):
  181. self.params['x'] = x
  182. return x[0] ** 2 + x[1] ** 2 + x[1] ** 3 + x[0] * x[1]
  183. def backward(self):
  184. x = self.params['x']
  185. gradient1 = 2 * x[0] + x[1]
  186. gradient2 = 2 * x[1] + 3 * x[1] ** 2 + x[0]
  187. grad1 = torch.Tensor([gradient1])
  188. grad2 = torch.Tensor([gradient2])
  189. self.grads['x'] = torch.cat([grad1, grad2])
  190. class Visualization3D(animation.FuncAnimation):
  191. """ 绘制动态图像,可视化参数更新轨迹 """
  192. def __init__(self, *xy_values, z_values, labels=[], colors=[], fig, ax, interval=600, blit=True, **kwargs):
  193. """
  194. 初始化3d可视化类
  195. 输入:
  196. xy_values:三维中x,y维度的值
  197. z_values:三维中z维度的值
  198. labels:每个参数更新轨迹的标签
  199. colors:每个轨迹的颜色
  200. interval:帧之间的延迟(以毫秒为单位)
  201. blit:是否优化绘图
  202. """
  203. self.fig = fig
  204. self.ax = ax
  205. self.xy_values = xy_values
  206. self.z_values = z_values
  207. frames = max(xy_value.shape[0] for xy_value in xy_values)
  208. self.lines = [ax.plot([], [], [], label=label, color=color, lw=2)[0]
  209. for _, label, color in zip_longest(xy_values, labels, colors)]
  210. super(Visualization3D, self).__init__(fig, self.animate, init_func=self.init_animation, frames=frames,
  211. interval=interval, blit=blit, **kwargs)
  212. def init_animation(self):
  213. # 数值初始化
  214. for line in self.lines:
  215. line.set_data([], [])
  216. # line.set_3d_properties(np.asarray([])) # 源程序中有这一行,加上会报错。 Edit by David 2022.12.4
  217. return self.lines
  218. def animate(self, i):
  219. # 将x,y,z三个数据传入,绘制三维图像
  220. for line, xy_value, z_value in zip(self.lines, self.xy_values, self.z_values):
  221. line.set_data(xy_value[:i, 0], xy_value[:i, 1])
  222. line.set_3d_properties(z_value[:i])
  223. return self.lines
  224. def train_f(model, optimizer, x_init, epoch):
  225. x = x_init
  226. all_x = []
  227. losses = []
  228. for i in range(epoch):
  229. all_x.append(copy.deepcopy(x.numpy())) # 浅拷贝 改为 深拷贝, 否则List的原值会被改变。 Edit by David 2022.12.4.
  230. loss = model(x)
  231. losses.append(loss)
  232. model.backward()
  233. optimizer.step()
  234. x = model.params['x']
  235. return torch.Tensor(np.array(all_x)), losses
  236. # 构建5个模型,分别配备不同的优化器
  237. model1 = OptimizedFunction3D()
  238. opt_gd = SimpleBatchGD(init_lr=0.01, model=model1)
  239. model2 = OptimizedFunction3D()
  240. opt_adagrad = Adagrad(init_lr=0.5, model=model2, epsilon=1e-7)
  241. model3 = OptimizedFunction3D()
  242. opt_rmsprop = RMSprop(init_lr=0.1, model=model3, beta=0.9, epsilon=1e-7)
  243. model4 = OptimizedFunction3D()
  244. opt_momentum = Momentum(init_lr=0.01, model=model4, rho=0.9)
  245. model5 = OptimizedFunction3D()
  246. opt_adam = Adam(init_lr=0.1, model=model5, beta1=0.9, beta2=0.99, epsilon=1e-7)
  247. models = [model1, model2, model3, model4, model5]
  248. opts = [opt_gd, opt_adagrad, opt_rmsprop, opt_momentum, opt_adam]
  249. x_all_opts = []
  250. z_all_opts = []
  251. # 使用不同优化器训练
  252. for model, opt in zip(models, opts):
  253. x_init = torch.FloatTensor([2, 3])
  254. x_one_opt, z_one_opt = train_f(model, opt, x_init, 150) # epoch
  255. # 保存参数值
  256. x_all_opts.append(x_one_opt.numpy())
  257. z_all_opts.append(np.squeeze(z_one_opt))
  258. # 使用numpy.meshgrid生成x1,x2矩阵,矩阵的每一行为[-3, 3],以0.1为间隔的数值
  259. x1 = np.arange(-3, 3, 0.1)
  260. x2 = np.arange(-3, 3, 0.1)
  261. x1, x2 = np.meshgrid(x1, x2)
  262. init_x = torch.Tensor(np.array([x1, x2]))
  263. model = OptimizedFunction3D()
  264. # 绘制 f_3d函数 的 三维图像
  265. fig = plt.figure()
  266. ax = plt.axes(projection='3d')
  267. X = init_x[0].numpy()
  268. Y = init_x[1].numpy()
  269. Z = model(init_x).numpy() # 改为 model(init_x).numpy() David 2022.12.4
  270. ax.plot_surface(X, Y, Z, cmap='rainbow')
  271. ax.set_xlabel('x1')
  272. ax.set_ylabel('x2')
  273. ax.set_zlabel('f(x1,x2)')
  274. labels = ['SGD', 'AdaGrad', 'RMSprop', 'Momentum', 'Adam']
  275. colors = ['#f6373c', '#f6f237', '#45f637', '#37f0f6', '#000000']
  276. animator = Visualization3D(*x_all_opts, z_values=z_all_opts, labels=labels, colors=colors, fig=fig, ax=ax)
  277. ax.legend(loc='upper left')
  278. plt.show()
  279. animator.save('animation.gif') # 效果不好,估计被挡住了…… 有待进一步提高 Edit by David 2022.12.4

注:本文转载自blog.csdn.net的HBU_David的文章"https://blog.csdn.net/qq_38975453/article/details/128179041"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top