AI_MindSpore_先学走路再开跑—开动起来

发布时间 2023-07-04 14:35:26作者: 辰令

AI模型

本质是“参数估计”(Learning is parameter estimation

梯度消失和梯度爆炸

梯度消失和梯度爆炸的产生原因源于神经网络的串联式结构和反向传播优化方法。
源于反向传播中梯度的累乘影响,从而导致了浅层网络的参数发生了变化微弱或者震荡较大的问题

解决方案

 一个是从神经网络的结构出发,在模型中加入一定的限制条件;
另一个是从反向传播方法出发,进行训练模型的改变。
 模型说明:1.1 激活函数 1.2 Normalization 1.3 残差链接 梯度裁剪: 则化
   激活函数的主要功能是在神经网络计算中引入非线性计算来强化网络对非线性的泛化性	 
   ReLU作用可以从两个方面来解析:正向保留激活值、反向统一化梯度  

梯度和参数更新

梯度--梯度下降-梯度反向传播
梯度下降是沿着梯度相反的方向走,即更新参数的时候是用原参数减去学习率乘以梯度
梯度反向传播:
   即“误差的反向传播”,梯度的偏导数对误差进行量化。通过网络向后传播误差,
   利用最后一层(最接近输出层的层)梯度的偏导数来计算第二层到最后一层的梯度
   利用当前层中前一层的梯度的偏导数确定误差在各层中的传播,一直传播到网络中的第一层(与输入层最近的层
   
 W=W−η*∂W/∂L   其中 η 学习率	 
 
 自适应的学习率(ADATIVE LEARNING RATE)

batch

Mini-batch(小批量):Mini-batch 是指从训练数据集中选择的较小的数据子集。在训练模型时,通常将整个训练数据集划分为多个 mini-batch

向量化运算

 梯度反向传播
 矩阵运算
 芯片层、框架层、模型层和应用层

概念-名词

 01.网络结构-神经网络模型是由神经网络层和Tensor操作构成的--前向传播 
 02.代价函数--
     模型预测值(logits)与正确标签(label)
	 送入损失函数(loss function)获得loss,
	 然后进行反向传播计算,求得梯度(gradients),最终更新至模型参数(parameters
 03.优化方法-反向传播  梯度下降 梯度消失 梯度爆炸  学习率
     利用自动微分机制,自动求模型参数(parameters)对于loss的梯度(gradients)。
	 将梯度更新到参数上。

Pytorch网络层、优化器、损失函数等模块

 net = nn.Sequential()
 criterion = nn.HingeEmbeddingLoss()
 optimizer = torch.optim.RMSprop(net.parameters(), lr=1e-3, alpha=0.9)	
    # 前向传播
	model.set_train()
    out = net(im)
    loss = criterion(out, label)
    # 反向传播
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

自动微分(Automatic Differentiation)机制采用函数式可微分编程架构	
 torch.autograd.grad(z,x)[0] torch.autograd.grad 不会将求导结果累加在grad上
 loss.backward()会将求导结果累加在grad上。这也是为什么我们在训练每个batch的最开始,需要对梯度清零的原因

AI框架

为MindSpore、百度PaddlePaddle、商汤科技SenseParrots、腾讯TNN、阿里MNN、字节跳动BytePS、旷视MegEngine、小米Mace等。	 

昇思-MindSpore

华为 硬件芯片-操作系统-开发语言Cangjie--开发框架
是一个全场景深度学习框架
  主流的深度学习框架的执行模式有两种,分别为静态图模式和动态图模式。
     静态图模式拥有较高的训练性能,但难以调试。set_context(mode=GRAPH_MODE)可切换成静态图模式
	 动态图模式相较于静态图模式虽然易于调试,但难以高效执行 set_context(mode=PYNATIVE_MODE)
	 
	计算图是用图论语言表示数学函数的一种方式,也是深度学习框架表达神经网络模型的统一方法 
	 
  昇思MindSpore总体架构--有端(手机与IOT设备)、边(基站与路由设备)、云(服务器)场景的不同系列硬件
  从高到低分别为High-Level Python API、Medium-Level Python API以及Low-Level Python API。
    基础层次: 张量定义、基础算子、自动微分等模块
	
第二层:
  可以继承nn.Cell类,并重写__init__方法和construct方法
  
  
  
第一层
   torch.autograd.grad() torch.autograd.backward()
   
   grad_fn = mindspore.grad(function, (2, 3))

MindSpore执行步骤

#2019年8月,华为推出昇思MindSpore,并在2020年3月将框架开源
import mindspore
from mindspore import nn
from mindspore import ops
model = Network() # def construct(self, x
loss_fn = nn.CrossEntropyLoss()
optimizer = nn.SGD(model.trainable_params(), learning_rate=learning_rate)
   model.set_train()
  logits = model(data)
  loss = loss_fn(logits, label)
  (loss, _), grads = grad_fn(data, label)
  optimizer(grads)
###模型定义
construct()

###训练
 正向计算函数定义。
 通过函数变换获得梯度计算函数。
 训练函数定义,执行正向计算、反向传播和参数优化。
  def forward_fn(data, label):
  grad_fn = ops.value_and_grad(forward_fn, None, optimizer.parameters, has_aux=True)
  def train_step(data, label):

###自定义损失函数的方法有两种:一是基于nn.Cell来定义损失函数;二是nn.LossBase来定义损失函数

PaddlePaddle

百度布局AI框架的时间,2016年该公司发布并开源飞桨PaddlePaddle
   从代码结构上看,模型均为数据处理、定义网络结构和训练过程三个部分
import paddle  
import paddle.nn.functional as F
# 定义多层全连接神经网络
 class MNIST(paddle.nn.Layer):	
 
#网络结构部分之后的代码, 
def train(model): 
     opt = paddle.optimizer.SGD(learning_rate=0.01, parameters=model.parameters())
	     
		  #准备数据
		  #前向计算的过程
          predicts = model(images)
		  #后向传播,更新参数的过程
		  loss = F.square_error_cost(predicts, labels)
		  avg_loss = paddle.mean(loss)
          avg_loss.backward()
          # 最小化loss,更新参数
           opt.step()
          # 清除梯度
          opt.clear_grad()

对比

基类
 mindspore的模型基类是mindspore.nn.Cell
 pytorch的模型基类是torch.nn.Module

全连接层
 mindspore的全连接层是mindspore.nn.Dense
 pytorch的全连接层是torch.nn.Linear

模型连接
 mindspore的顺序容器是mindspore.nn.SequentialCell
 pytorch的顺序容器是torch.nn.Sequential

前向传播
 mindspore的前向传播函数(要执行的计算逻辑)基类函数为construct(self, xxx)
 pytorch的前向传播函数基类函数为forward(self, xxx)
 
 
 参数可以写为model.trainable_params(),也可以由优化器提供(optimizer.parameters)
 :mindspore.ops.value_and_grad
    把正向传播、反向传播的整个流程走一遍,最后的输出为正向传输函数的返回值+待求导参数的梯度值
 # 设置为动态图模式
 mindspore.set_context(mode=mindspore.PYNATIVE_MODE)

自动微分机制

  由于不同深度学习框架的自动微分机制不同,所以实现梯度累加的方式有显著差异。
     1.以Tensor为核心的自动微分,
	    Tensor可配置requires_grad参数控制是否需要梯度。
		每个Tensor对象有 grad_fn属性用来存储该Tensor参与的反向操作,
		同时还有 grad属性,存储该Tensor对应的梯度
	  业界多数框架选择此方案,如Pytorch、Paddle、Oneflow、MegEngine等。
	 2.函数式自动微分
	   将神经网络 正向计算视作输入到Loss的计算函数,
	      通过函数变换获得反向计算函数,并调用反向计算函数来获得梯度。
		  
	   业界采用此方案的框架有Jax、MindSpore,此外Tensorflow的GradientTape
 Pytorch等框架更多定位纯深度学习,此时只体现backward更符合目标用户的使用习惯。
 而Jax、MindSpore则在定位上更加底层,
    Jax直接明言自身为数值计算框架,
	MindSpore则定位为AI+科学计算融合计算框架,因此函数式自动微分设计更符合框架定位

Pytorch本身在求完梯度后会自动挂载到Tensor.grad属性上,
  而在没有手动清空(即optimizer.zero_grad())的情况下,每个step训练求得的梯度会自动累加,因此只需要控制梯度清零和参数更新的间隔步数
 
MindSpore 函数式自动微分,由于暴露接口更加底层,所以是直接求导返回梯度的 
grad_fn = mindspore.value_and_grad(forward_fn, None, weights=model.trainable_params())
loss, grads = grad_fn(x, y)
print(grads)  
没有直接挂载到Tensor属性的操作,因此需要单独维护一份和训练参数相同大小的参数进行累加的计算。
  单独维护了一个Accumulator

查看自动微分机制

我们高估了语言 语言只是载体和工具	
  基于数值计算+反向传播的这一套机制到底还能吃多少年还是要打个问号,
是否脑科学才是更优解?又或者量子计算机or生物计算机更符合智能涌现的需要?犹未可知。实现人类语言规则这样不确定的复杂函数的拟合

SQL本身是相对轻量化的编程语言,规则也比较少,然后经过一系列的代码大模型预训练,尤其是文本+代码平行语料的训练,其能力很快就达到了很强的水平。
 自然语言成为了查询语句,将中间能够产生误差、遗漏、错误的环节统统抹去了,就像是去掉了中间商
 生态系统中的迁徙和坚守

参考

https://www.paddlepaddle.org.cn/tutorials/projectdetail/5836960	
https://www.mindspore.cn/tutorials/zh-CN/r2.0/beginner/train.html
https://gitee.com/mindspore/mindspore
聊聊梯度累加(Gradient Accumulation)  https://zhuanlan.zhihu.com/p/595716023