FP(ContentAware Processor)
- 格式:pptx
- 大小:506.90 KB
- 文档页数:18


混合精度训练fp16⽤于神经⽹络训练和预测混合精度训练混合精度训练是在尽可能减少精度损失的情况下利⽤半精度浮点数加速训练。
它使⽤FP16即半精度浮点数存储权重和梯度。
在减少占⽤内存的同时起到了加速训练的效果。
IEEE标准中的FP16格式如下:取值范围是5.96× 10−8 ~ 65504,⽽FP32则是1.4×10-45 ~ 3.4×1038。
从FP16的范围可以看出,⽤FP16代替原FP32神经⽹络计算的最⼤问题就是精度损失。
float : 1个符号位、8个指数位和23个尾数位利⽤fp16 代替 fp32优点:1)TensorRT的FP16与FP32相⽐能有接近⼀倍的速度提升,前提是GPU⽀持FP16(如最新的2070,2080,2080ti等)2)减少显存。
缺点:1)会造成溢出因此,在⽇常使⽤过程中,常使⽤双混合精度训练。
如图:此过程中的技术:1) Loss scaling :会存在很多梯度在FP16表达范围外,我们为了让其落⼊半精度范围内,会给其进⾏等⽐放⼤后缩⼩。
流程:对百度&英伟达相关论⽂的解读⽂中提出了三种避免损失的⽅法:1.1. 为每个权重保留⼀份FP32的副本在前向和反向时使⽤FP16,整个过程变成:权重从FP32转成FP16进⾏前向计算,得到loss之后,⽤FP16计算梯度,再转成FP32更新到FP32的权重上。
这⾥注意得到的loss也是FP32,因为涉及到累加计算(参见下⽂)。
⽤FP32保存权重主要是为了避免溢出,FP16⽆法表⽰2e-24以下的值,⼀种是梯度的更新值太⼩,FP16直接变为了0;⼆是FP16表⽰权重的话,和梯度的计算结果也有可能变成0。
实验表明,⽤FP16保存权重会造成80%的精度损失。
1.2. Loss-scaling得到FP32的loss后,放⼤并保存为FP16格式,进⾏反向传播,更新时转为FP32缩放回来。
下图可以看到,很多激活值⽐较⼩,⽆法⽤FP16表⽰。
BeanPostProcessor详解转⾃:BeanPostProcessor也称为Bean后置处理器,它是Spring中定义的接⼝,在Spring容器的创建过程中(具体为Bean初始化前后)会回调BeanPostProcessor中定义的两个⽅法。
BeanPostProcessor的源码如下public interface BeanPostProcessor {Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;}其中postProcessBeforeInitialization⽅法会在每⼀个bean对象的初始化⽅法调⽤之前回调;postProcessAfterInitialization⽅法会在每个bean对象的初始化⽅法调⽤之后被回调。
具体执⾏时期可以参考。
⾃定义BeanPostProcessor查看BeanPostProcessor源码,可以看到它两个⽅法的参数都相同,其中第⼀个参数Object bean表⽰当前正在初始化的bean对象。
此外两个⽅法都返回Object类型的实例,返回值既可以是将⼊参Object bean原封不动的返回出去,也可以对当前bean进⾏包装再返回。
来看看下⾯的⾃定义BeanPostProcessor/*** 后置处理器:初始化前后进⾏处理⼯作* 需要将后置处理器加⼊到容器中*/@Componentpublic class MyBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("postProcessBeforeInitialization..."+beanName+"..."+bean);return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("postProcessAfterInitialization..."+beanName+"..."+bean);return bean;}}Spring容器中加⼊MyBeanPostProcessor之后,针对容器中每个创建的Bean对象(Spring⾃⾝创建的Bean和应⽤程序创建的Bean),都会回调postProcessBeforeInitialization和postProcessAfterInitialization⽅法。
springboot中使⽤⾃定义注解实现策略模式,去除⼯⼚模式的switch或ifelse。
前⾔思路与模拟业务源码地址整体思路就是通过注解在策略类上指定约定好的type,项⽬启动之后将所有有注解的type获取到,根据type存储,然后在业务中根据type获取对应的策略即可模拟订单业务,根据订单的type,需要不同的处理逻辑,⽐如,免费订单,半价订单等,下⾯是项⽬结构:⼀策略接⼝和实现/*** 处理订单策略*/public interface OrderStrategy {void handleOrder(Order order);}@Component@HandlerOrderType(Order.FREE) //使⽤注解标明策略类型public class FreeOrderStrategy implements OrderStrategy {@Overridepublic void handleOrder(Order order) {System.out.println("----处理免费订单----");}}@Component@HandlerOrderType(Order.HALF)public class HalfOrderStrategy implements OrderStrategy {@Overridepublic void handleOrder(Order order) {System.out.println("----处理半价订单----");}}@Component@HandlerOrderType(Order.DISCOUT)public class DiscoutOrderStrategy implements OrderStrategy {@Overridepublic void handleOrder(Order order) {System.out.println("----处理打折订单----");}}⼆⾃定义策略注解@Target(ElementType.TYPE) //作⽤在类上@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited //⼦类可以继承此注解public @interface HandlerOrderType {/*** 策略类型* @return*/int value();}此处只能⽤基本类型或者String,约定的类型放在Order实体类⾥三业务实体public class Order {public static final int FREE=1; //免费订单public static final int HALF=2; //半价订单public static final int DISCOUT=3; //打折订单private String name;private Double price;private Integer type;//订单类型public static Order build(){return new Order();}四核⼼功能实现主要就是这⼀块实现策略逻辑/*** 根据订单类型返回对应的处理策略*/@Componentpublic class HandlerOrderContext {@Autowiredprivate ApplicationContext applicationContext;//存放所有策略类Bean的mappublic static Map<Integer, Class<OrderStrategy>> orderStrategyBeanMap= new HashMap<>();public OrderStrategy getOrderStrategy(Integer type){Class<OrderStrategy> strategyClass = orderStrategyBeanMap.get(type);if(strategyClass==null) throw new IllegalArgumentException("没有对应的订单类型");//从容器中获取对应的策略Beanreturn applicationContext.getBean(strategyClass);}}/*** 策略核⼼功能,获取所有策略注解的类型* 并将对应的class初始化到HandlerOrderContext中*/@Componentpublic class HandlerOrderProcessor implements ApplicationContextAware {/*** 获取所有的策略Beanclass 加⼊HandlerOrderContext属性中* @param applicationContext* @throws BeansException*/@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {//获取所有策略注解的BeanMap<String, Object> orderStrategyMap = applicationContext.getBeansWithAnnotation(HandlerOrderType.class); orderStrategyMap.forEach((k,v)->{Class<OrderStrategy> orderStrategyClass = (Class<OrderStrategy>) v.getClass();int type = orderStrategyClass.getAnnotation(HandlerOrderType.class).value();//将class加⼊map中,type作为keyHandlerOrderContext.orderStrategyBeanMap.put(type,orderStrategyClass);});}}五业务service使⽤@Componentpublic class OrderServiceImpl implements OrderService {@AutowiredHandlerOrderContext handlerOrderContext;@Overridepublic void handleOrder(Order order) {//使⽤策略处理订单OrderStrategy orderStrategy = handlerOrderContext.getOrderStrategy(order.getType());orderStrategy.handleOrder(order);}}很简单,业务代码以后基本不⽤再修改,不管添加多少策略或者需求变更多少次六 controller测试@RestController@RequestMapping("/order")public class OrderController {@AutowiredOrderService orderService;@GetMapping("/handler/{type}")public void handleOrder(@PathVariable Integer type){Order order = Order.build().add("name", "微信订单").add("price", 99.9).add("type", type);orderService.handleOrder(order);}}使⽤链式风格构造对象测试:再添加策略添加实现类,启⽤注解即可!省去了⼯⼚模式,直接⽤注解实现,避免修改⼯⼚类,这⾥贴⼀个我们之前项⽬的⼯⼚类实现:如果再添加策略还是会有轻微的改动!。
第一章【思考题】1、请简述Spring框架的优点。
2、请简述什么是Spring的IoC和DI。
【答案】1、Spring框架的优点如下:(1)非侵入式设计:Spring是一种非侵入式(non-invasive)框架,它可以使应用程序代码对框架的依赖最小化。
(2)方便解耦、简化开发:Spring就是一个大工厂,可以将所有对象的创建和依赖关系的维护工作都交给Spring容器管理,大大的降低了组件之间的耦合性。
(3)支持AOP:Spring提供了对AOP的支持,它允许将一些通用任务,如安全、事务、日志等进行集中式处理,从而提高了程序的复用性。
(4)支持声明式事务处理:只需要通过配置就可以完成对事务的管理,而无需手动编程。
(5)方便程序的测试:Spring提供了对Junit4的支持,可以通过注解方便的测试Spring 程序。
(6)方便集成各种优秀框架:Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts、Hibernate、MyBatis、Quartz等)的直接支持。
(7)降低了Java EE API的使用难度:Spring对Java EE开发中非常难用的一些API (如:JDBC、JavaMail等),都提供了封装,使这些API应用难度大大降低。
2、IoC的全称是Inversion of Control,中文名称为控制反转。
控制反转就是指在使用Spring框架之后,对象的实例不再由调用者来创建,而是由Spring容器来创建,Spring 容器会负责控制程序之间的关系,而不是由调用者的程序代码直接控制。
这样,控制权由应用代码转移到了Spring容器,控制权发生了反转。
DI的全称是Dependency Injection,中文称之为依赖注入。
它与控制反转(IoC)的含义相同,只不过这两个称呼是从两个角度描述的同一个概念。
从Spring容器的角度来看,Spring容器负责将被依赖对象赋值给调用者的成员变量,这相当于为调用者注入了它依赖的实例,这就是Spring的依赖注入。