LasyOpticalDesigner0.1.0开发者日志(八)优化器(壹)

优化器

光学系统优化有局部优化和全局优化以及介乎二者之间的优化方法。
由于全局优化的算法过于复杂
这里只介绍前后两种。

局部优化方法

光学系统局部优化方法主要是从某个起始点处出发,寻找最近的局部评价函数最小点,其原理就是利用梯度或者偏导数确定方向然后利用贪心策略进行搜索。众所周知,梯度是函数值增加最快的方向(最大方向导数),所以梯度方向的反方向就是函数下降的方向:
除去传统的牛顿法,阻尼牛顿法,最速下降法等等。
也可以使用adm,admW,sgd,rmsprop等算法。这些算法网上已经有无数的详细说明,这里就不再提

建立一个简单的类似光学传播的模型

class TestModel(tf.keras.Model):
    
    def __init__(self):
        super(TestModel,self).__init__()
        self.de_layers = []
    
    def get_layer(self,layer):
        self.de_layers.append(layer)
    
    def call(self,x,y):
        for layer in self.de_layers:
            x , y = layer(x,y)
        return x,y

建立层

class TestLayer(tf.keras.layers.Layer):
    def __init__(self,w1,w2,w3,w4):
        super(TestLayer,self).__init__()
        self.w1 = tf.Variable(w1,dtype = tf.float32,trainable = True)
        self.w2 = tf.Variable(w2,dtype = tf.float32,trainable = True)
        self.w3 = tf.Variable(w3,dtype = tf.float32,trainable = True)
        self.w4 = tf.Variable(w4,dtype = tf.float32,trainable = True)

    def call(self,r,sita):      
        n_r =self.w1 * (r**2+sita**2)**0.5- self.w2*(sita * r) + self.w4*r*tf.cos(sita) 
        n_sita = self.w2*(r**2 - sita**2)**0.5 - self.w3*(sita + r) + self.w4*r*tf.sin(sita)
        return n_r,n_sita

执行器

class MyManagers:
    def __init__(self,model,number,af):
        self.testmodel = model
        self.opt = tf.keras.optimizers.RMSprop()
        # 这里也可以用sgd,adm等等或者自定义的其他优化器这里用RMSprop

局部优化

    @tf.function
    def opt_manager(self):
        for i in range(200):# 200 可以自定义
            r,sita = self.testmodel(self.r,self.sita)
            loss = tf.reduce_sum(tf.square(r) + tf.square(sita))
            # 用欧氏距离平方做评价函数
            g = tf.gradients(loss,self.testmodel.trainable_variables)
            #梯度
            self.opt.apply_gradients(grads_and_vars = zip(g,self.testmodel.trainable_variables))
            # 优化
        return self.testmodel.trainable_variables,loss

锤子优化算法(锤形的翻译有一定的问题),(hammer)——半全局方法

这种算法在zemax的操作说明中并没有详细的描述,相关的文献也非常的稀少。操作说明中仅仅是介绍了它的效果。通过不断的跳出或者避开局部最小点,尽可能的达到更小的评价函数点
——锤子优化法之所以叫这个名字,猜测是由于使用各种各样的方式使得评价函数尽可能下降的方法,好比锻造时用榔头敲击金属
这样的策略有很多

  1. 模拟退火的方法
    在优化过程中依照某种概率选择优化的步长该步长与评价函数有关(温度下降个概率与当前温度有关)
    在这里可以用评价函数loss与梯度g的范数的比值作为判别数
    af = loss/g当loss很大而g的二范数比较小,说明这个点是局部最小点
    这样的话优化使用其他的更长的步长以跳出这个局部最小点。
	@tf.function
    def opt_manager_hummer(self,aita=1.0,e=0.0,d=0.025):
        r,sita = self.testmodel(self.r,self.sita)
        loss = tf.reduce_sum(tf.square(r) + tf.square(sita))
        g= tf.gradients(loss,self.testmodel.trainable_variables)
        def body1():
        	# 使用一般的 优化器
            for j in range(10):
                self.opt.apply_gradients(grads_and_vars = zip(g,self.testmodel.trainable_variables))    
        def body2():
        	# 使用第二个优化器 步长比较长让函数变得松弛
            self.opt1.apply_gradients(grads_and_vars = zip(g,self.testmodel.trainable_variables))
        for i in range(100):
            r,sita = self.testmodel(self.r,self.sita)
            loss = tf.reduce_sum(tf.square(r) + tf.square(sita))
            g= tf.gradients(loss,self.testmodel.trainable_variables)
            base = aita*tf.exp(-tf.reduce_sum(tf.square(g))/loss) 
            aim = tf.random.normal([],aita*e,d,dtype = tf.float32)
            q = base-aim # it must unstable that q is bigger
            tf.cond(
                q*10 < self.af,
                body1,
                body2
            )
            tf.print(i)
        return self.testmodel.trainable_variables,loss
  1. 遗传算法的一个变种
    将被判断为局部最小点的点收集起来,排除掉他们然后朝着剩下的点进行搜索
    具体的方法有:当收集某一个点时,到这个点的距离的某个反相关的函数将加入到评价函数。然后利用梯度下降的方法迫使搜索方向远离这个点
    参考代码:
    @tf.function
    def opt_manager_dec(self,aita=1.0,e=0.0,d=0.025):
        points = []
        r,sita = self.testmodel(self.r,self.sita)
        loss = tf.reduce_sum(tf.square(r) + tf.square(sita))
        g = tf.gradients(loss,self.testmodel.trainable_variables)
        def add_point_opt():
            temp = self.testmodel.trainable_variables
            points.append(temp)
            loss = tf.reduce_sum(tf.square(r) + tf.square(sita))+get_loss() 
            g = tf.gradients(loss,self.testmodel.trainable_variables)
            self.opt.apply_gradients(grads_and_vars = zip(g,self.testmodel.trainable_variables))         
        def commen_opt():
            loss = tf.reduce_sum(tf.square(r) + tf.square(sita))+get_loss()  
            g = tf.gradients(loss,self.testmodel.trainable_variables)
            self.opt.apply_gradients(grads_and_vars = zip(g,self.testmodel.trainable_variables))         
        def get_loss():
            temp_l = []
            for each in points:
                temp_l.append(self.get_kennel_point(each,self.testmodel.trainable_variables))
            return tf.exp(-sum(temp_l)) 

        for i in range(200): 
            r,sita = self.testmodel(self.r,self.sita)
            g = tf.gradients(loss,self.testmodel.trainable_variables)
            base = aita*tf.exp(-tf.reduce_sum(tf.square(g))/loss)
            aim = tf.random.normal([],aita*e,d,dtype = tf.float32)
            q = base - aim
            cond = q*10 < self.af
            tf.cond(cond,add_point_opt,commen_opt)
            tf.print(i)
        return self.testmodel.trainable_variables,loss
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值