学习率衰减(learning rate decay) 
在训练神经网络时,使用学习率控制参数的更新速度.学习率较小时,会大大降低参数的更新速度;学习率较大时,会使搜索过程中发生震荡,导致参数在极优值附近徘徊. 
为此,在训练过程中引入学习率衰减,使学习率随着训练的进行逐渐衰减.

TensorFlow中实现的学习率衰减方法:

  • tf.train.piecewise_constant 分段常数衰减
  • tf.train.inverse_time_decay 反时限衰减
  • tf.train.polynomial_decay 多项式衰减
  • tf.train.exponential_decay 指数衰减
  • tf.train.natural_exp_decay 自然指数衰减
  • tf.train.cosine_decay 余弦衰减
  • tf.train.linear_cosine_decay 线性余弦衰减
  • tf.train.noisy_linear_cosine_decay 噪声线性余弦衰减

函数返回衰减的学习率.

先讲单个函数的使用效果,最后演示如何将其用在实际模型中。

首先是使用效果:

分段常数衰减:tf.train.piecewise_constant() 指定间隔的分段常数. 
参数:

  • x:0-D标量Tensor.
  • boundaries:边界,tensor或list.
  • values:指定定义区间的值.
  • name:操作的名称,默认为PiecewiseConstant.

分段常数衰减就是在定义好的区间上,分别设置不同的常数值,作为学习率的初始值和后续衰减的取值.

#!/usr/bin/python
# coding:utf-8# piecewise_constant 阶梯式下降法
import matplotlib.pyplot as plt
import tensorflow as tf
global_step = tf.Variable(0, name='global_step', trainable=False)
boundaries = [10, 20, 30]
learing_rates = [0.1, 0.07, 0.025, 0.0125]
y = []
N = 40
with tf.Session() as sess:sess.run(tf.global_variables_initializer())for global_step in range(N):learing_rate = tf.train.piecewise_constant(global_step, boundaries=boundaries, values=learing_rates)lr = sess.run([learing_rate])y.append(lr[0])x = range(N)
plt.plot(x, y, 'r-', linewidth=2)
plt.title('piecewise_constant')
plt.show()

指数衰减:tf.train.exponential_decay() 应用指数衰减的学习率. 
指数衰减是最常用的衰减方法. 
参数:

  • learning_rate:初始学习率.
  • global_step:用于衰减计算的全局步数,非负.用于逐步计算衰减指数.
  • decay_steps:衰减步数,必须是正值.决定衰减周期.
  • decay_rate:衰减率.
  • staircase:若为True,则以不连续的间隔衰减学习速率即阶梯型衰减(就是在一段时间内或相同的eproch内保持相同的学习率);若为False,则是标准指数型衰减.
  • name:操作的名称,默认为ExponentialDecay.(可选项)

指数衰减的学习速率计算公式为:

decayed_learning_rate = learning_rate * decay_rate ^ (global_step / decay_steps)

优点:简单直接,收敛速度快.

直观解释:假设给定初始学习率learning_rate为0.1,学习率衰减率为0.1,decay_steps为10000。 
则随着迭代次数从1到10000,当前的学习率decayed_learning_rate慢慢的从0.1降低为0.1*0.1=0.01, 
当迭代次数到20000,当前的学习率慢慢的从0.01降低为0.1*0.1^2=0.001,以此类推。 
也就是说每10000次迭代,学习率衰减为前10000次的十分之一,该衰减是连续的,这是在staircase为False的情况下。

如果staircase为True,则global_step / decay_steps始终取整数,也就是说衰减是突变的,每decay_steps次变化一次,变化曲线是阶梯状。

示例,阶梯型衰减与指数型衰减对比:

#!/usr/bin/python
# coding:utf-8
import matplotlib.pyplot as plt
import tensorflow as tf
global_step = tf.Variable(0, name='global_step', trainable=False)y = []
z = []
N = 200
with tf.Session() as sess:sess.run(tf.global_variables_initializer())for global_step in range(N):# 阶梯型衰减learing_rate1 = tf.train.exponential_decay(learning_rate=0.5, global_step=global_step, decay_steps=10, decay_rate=0.9, staircase=True)# 标准指数型衰减learing_rate2 = tf.train.exponential_decay(learning_rate=0.5, global_step=global_step, decay_steps=10, decay_rate=0.9, staircase=False)lr1 = sess.run([learing_rate1])lr2 = sess.run([learing_rate2])y.append(lr1[0])z.append(lr2[0])x = range(N)
fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_ylim([0, 0.55])
plt.plot(x, y, 'r-', linewidth=2)
plt.plot(x, z, 'g-', linewidth=2)
plt.title('exponential_decay')
ax.set_xlabel('step')
ax.set_ylabel('learing rate')
plt.show()

如图,红色:阶梯型;绿色:指数型:

自然指数衰减:tf.train.natural_exp_decay()  应用自然指数衰减的学习率. 
参数:

  • learning_rate:初始学习率.
  • global_step:用于衰减计算的全局步数,非负.
  • decay_steps:衰减步数.
  • decay_rate:衰减率.
  • staircase:若为True,则是离散的阶梯型衰减(就是在一段时间内或相同的eproch内保持相同的学习率);若为False,则是标准型衰减.
  • name: 操作的名称,默认为ExponentialTimeDecay.

natural_exp_decay 和 exponential_decay 形式近似,natural_exp_decay的底数是e.自然指数衰减比指数衰减要快的多,一般用于较快收敛,容易训练的网络. 
自然指数衰减的学习率计算公式为:

decayed_learning_rate = learning_rate * exp(-decay_rate * global_step)

示例,指数衰减与自然指数衰减的阶梯型与指数型:

#!/usr/bin/python
# coding:utf-8import matplotlib.pyplot as plt
import tensorflow as tf
global_step = tf.Variable(0, name='global_step', trainable=False)y = []
z = []
w = []
N = 200
with tf.Session() as sess:sess.run(tf.global_variables_initializer())for global_step in range(N):# 阶梯型衰减learing_rate1 = tf.train.natural_exp_decay(learning_rate=0.5, global_step=global_step, decay_steps=10, decay_rate=0.9, staircase=True)# 标准指数型衰减learing_rate2 = tf.train.natural_exp_decay(learning_rate=0.5, global_step=global_step, decay_steps=10, decay_rate=0.9, staircase=False)# 指数衰减learing_rate3 = tf.train.exponential_decay(learning_rate=0.5, global_step=global_step, decay_steps=10, decay_rate=0.9, staircase=False)lr1 = sess.run([learing_rate1])lr2 = sess.run([learing_rate2])lr3 = sess.run([learing_rate3])y.append(lr1[0])z.append(lr2[0])w.append(lr3[0])x = range(N)
fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_ylim([0, 0.55])
plt.plot(x, y, 'r-', linewidth=2)
plt.plot(x, z, 'g-', linewidth=2)
plt.plot(x, w, 'b-', linewidth=2)
plt.title('natural_exp_decay')
ax.set_xlabel('step')
ax.set_ylabel('learing rate')
plt.show()

如图,红色:阶梯型;绿色:指数型;蓝色指数型衰减:

多项式衰减:tf.train.polynomial_decay() 应用多项式衰减的学习率. 
参数:

  • learning_rate:初始学习率.
  • global_step:用于衰减计算的全局步数,非负.
  • decay_steps:衰减步数,必须是正值.
  • end_learning_rate:最低的最终学习率.
  • power:多项式的幂,默认为1.0(线性).
  • cycle:学习率下降后是否重新上升.
  • name:操作的名称,默认为PolynomialDecay。

函数使用多项式衰减,以给定的decay_steps将初始学习率(learning_rate)衰减至指定的学习率(end_learning_rate).

多项式衰减的学习率计算公式为:

global_step = min(global_step,decay_steps)
decayed_learning_rate = (learning_rate-end_learning_rate)*(1-global_step/decay_steps)^ (power)+end_learning_rate

参数cycle决定学习率是否在下降后重新上升.若cycle为True,则学习率下降后重新上升;使用decay_steps的倍数,取第一个大于global_steps的结果.

decay_steps = decay_steps*ceil(global_step/decay_steps)
decayed_learning_rate = (learning_rate-end_learning_rate)*(1-global_step/decay_steps)^ (power)+end_learning_rate

参数cycle目的:防止神经网络训练后期学习率过小导致网络一直在某个局部最小值中振荡;这样,通过增大学习率可以跳出局部极小值.

示例,学习率下降后是否重新上升对比:

#!/usr/bin/python
# coding:utf-8
# 学习率下降后是否重新上升
import matplotlib.pyplot as plt
import tensorflow as tf
y = []
z = []
N = 200
global_step = tf.Variable(0, name='global_step', trainable=False)with tf.Session() as sess:sess.run(tf.global_variables_initializer())for global_step in range(N):# cycle=Falselearing_rate1 = tf.train.polynomial_decay(learning_rate=0.1, global_step=global_step, decay_steps=50,end_learning_rate=0.01, power=0.5, cycle=False)# cycle=Truelearing_rate2 = tf.train.polynomial_decay(learning_rate=0.1, global_step=global_step, decay_steps=50,end_learning_rate=0.01, power=0.5, cycle=True)lr1 = sess.run([learing_rate1])lr2 = sess.run([learing_rate2])y.append(lr1[0])z.append(lr2[0])x = range(N)
fig = plt.figure()
ax = fig.add_subplot(111)
plt.plot(x, z, 'g-', linewidth=2)
plt.plot(x, y, 'r--', linewidth=2)
plt.title('polynomial_decay')
ax.set_xlabel('step')
ax.set_ylabel('learing rate')
plt.show()

如图,红色:下降后不再上升;绿色:下降后重新上升: 

余弦衰减:tf.train.cosine_decay() 将余弦衰减应用于学习率 
参数:

  • learning_rate:标初始学习率.
  • global_step:用于衰减计算的全局步数.
  • decay_steps:衰减步数.
  • alpha:最小学习率(learning_rate的部分)。
  • name:操作的名称,默认为CosineDecay.

根据论文SGDR: Stochastic Gradient Descent with Warm Restarts提出.

余弦衰减的学习率计算公式为:

global_step = min(global_step, decay_steps)
cosine_decay = 0.5 * (1 + cos(pi * global_step / decay_steps))
decayed = (1 - alpha) * cosine_decay + alpha
decayed_learning_rate = learning_rate * decayed

线性余弦衰减:tf.train.linear_cosine_decay() 将线性余弦衰减应用于学习率. 
参数:

  • learning_rate:标初始学习率.
  • global_step:用于衰减计算的全局步数.
  • decay_steps:衰减步数。
  • num_periods:衰减余弦部分的周期数.
  • alpha:见计算.
  • beta:见计算.
  • name:操作的名称,默认为LinearCosineDecay。

根据论文Neural Optimizer Search with Reinforcement Learning提出.

线性余弦衰减的学习率计算公式为:

global_step=min(global_step,decay_steps)
linear_decay=(decay_steps-global_step)/decay_steps)
cosine_decay = 0.5*(1+cos(pi*2*num_periods*global_step/decay_steps))
decayed=(alpha+linear_decay)*cosine_decay+beta
decayed_learning_rate=learning_rate*decayed

噪声线性余弦衰减:tf.train.noisy_linear_cosine_decay() 将噪声线性余弦衰减应用于学习率. 
参数:

  • learning_rate:标初始学习率.
  • global_step:用于衰减计算的全局步数.
  • decay_steps:衰减步数.
  • initial_variance:噪声的初始方差.
  • variance_decay:衰减噪声的方差.
  • num_periods:衰减余弦部分的周期数.
  • alpha:见计算.
  • beta:见计算.
  • name:操作的名称,默认为NoisyLinearCosineDecay.

根据论文Neural Optimizer Search with Reinforcement Learning提出.在衰减过程中加入了噪声,一定程度上增加了线性余弦衰减的随机性和可能性.

噪声线性余弦衰减的学习率计算公式为:

global_step=min(global_step,decay_steps)
linear_decay=(decay_steps-global_step)/decay_steps)
cosine_decay=0.5*(1+cos(pi*2*num_periods*global_step/decay_steps))
decayed=(alpha+linear_decay+eps_t)*cosine_decay+beta
decayed_learning_rate =learning_rate*decayed

示例,线性余弦衰减与噪声线性余弦衰减:

#!/usr/bin/python
# coding:utf-8
import matplotlib.pyplot as plt
import tensorflow as tf
y = []
z = []
w = []
N = 200
global_step = tf.Variable(0, name='global_step', trainable=False)with tf.Session() as sess:sess.run(tf.global_variables_initializer())for global_step in range(N):# 余弦衰减learing_rate1 = tf.train.cosine_decay(learning_rate=0.1, global_step=global_step, decay_steps=50,alpha=0.5)# 线性余弦衰减learing_rate2 = tf.train.linear_cosine_decay(learning_rate=0.1, global_step=global_step, decay_steps=50,num_periods=0.2, alpha=0.5, beta=0.2)# 噪声线性余弦衰减learing_rate3 = tf.train.noisy_linear_cosine_decay(learning_rate=0.1, global_step=global_step, decay_steps=50,initial_variance=0.01, variance_decay=0.1, num_periods=0.2, alpha=0.5, beta=0.2)lr1 = sess.run([learing_rate1])lr2 = sess.run([learing_rate2])lr3 = sess.run([learing_rate3])y.append(lr1[0])z.append(lr2[0])w.append(lr3[0])x = range(N)
fig = plt.figure()
ax = fig.add_subplot(111)
plt.plot(x, z, 'b-', linewidth=2)
plt.plot(x, y, 'r-', linewidth=2)
plt.plot(x, w, 'g-', linewidth=2)
plt.title('cosine_decay')
ax.set_xlabel('step')
ax.set_ylabel('learing rate')
plt.show()

如图,红色:余弦衰减;蓝色:线性余弦衰减;绿色:噪声线性余弦衰减; 

反时限衰减:tf.train.inverse_time_decay() 将反时限衰减应用到初始学习率. 
参数:

  • learning_rate:初始学习率.
  • global_step:用于衰减计算的全局步数.
  • decay_steps:衰减步数.
  • decay_rate:衰减率.
  • staircase:是否应用离散阶梯型衰减.(否则为连续型)
  • name:操作的名称,默认为InverseTimeDecay.

该函数应用反向衰减函数提供初始学习速率.利用global_step来计算衰减的学习速率.计算公式为:

decayed_learning_rate =learning_rate/(1+decay_rate* global_step/decay_step)

若staircase为True时:

decayed_learning_rate =learning_rate/(1+decay_rate*floor(global_step/decay_step))

示例,反时限衰减的阶梯型衰减与连续型对比:

#!/usr/bin/python
# coding:utf-8import matplotlib.pyplot as plt
import tensorflow as tf
y = []
z = []
N = 200
global_step = tf.Variable(0, name='global_step', trainable=False)with tf.Session() as sess:sess.run(tf.global_variables_initializer())for global_step in range(N):# 阶梯型衰减learing_rate1 = tf.train.inverse_time_decay(learning_rate=0.1, global_step=global_step, decay_steps=20,decay_rate=0.2, staircase=True)# 连续型衰减learing_rate2 = tf.train.inverse_time_decay(learning_rate=0.1, global_step=global_step, decay_steps=20,decay_rate=0.2, staircase=False)lr1 = sess.run([learing_rate1])lr2 = sess.run([learing_rate2])y.append(lr1[0])z.append(lr2[0])x = range(N)
fig = plt.figure()
ax = fig.add_subplot(111)
plt.plot(x, z, 'r-', linewidth=2)
plt.plot(x, y, 'g-', linewidth=2)
plt.title('inverse_time_decay')
ax.set_xlabel('step')
ax.set_ylabel('learing rate')
plt.show()

如图,蓝色:阶梯型;红色:连续型: 

----------------------------------------------------------------------------------------------------------------------------------

以上是单个的使用效果,但是在实际模型中这些函数并不是这么使用的,以下使用两个方法,简述如何在模型中使用学习率衰减!

----------------------------------------------------------------------------------------------------------------------------------

首先第一个例子:

例如

tf.train.exponential_decay(initial_learning_rate, global_step=global_step, decay_steps=1000, decay_rate=0.9)表示没经过1000次的迭代,学习率变为原来的0.9。

增大批次处理样本的数量也可以起到退化学习率的作用。

下面我们写了一个例子,每迭代10次,则较小为原来的0.5,代码如下:

import tensorflow as tf
import numpy as npglobal_step = tf.Variable(0, trainable=False)
initial_learning_rate = 0.1learning_rate = tf.train.exponential_decay(initial_learning_rate,global_step=global_step,decay_steps=10,decay_rate=0.5)opt = tf.train.GradientDescentOptimizer(learning_rate)
add_global = global_step.assign_add(1)with tf.Session() as sess:tf.global_variables_initializer().run()print(sess.run(learning_rate))for i in range(50):g, rate = sess.run([add_global, learning_rate])print(g, rate)

在这个代码里面使用add_global = global_step.assign_add(1)来实现全局迭代步数+1的更新;

下面是程序的结果,我们发现每10次就变为原来的一半:

下面在mnist数据集上使用该方法去测试,代码如下:

import tensorflow as tf
import numpy as np
from tensorflow.examples.tutorials.mnist import input_data
import matplotlib.pyplot as pltmnist = input_data.read_data_sets('MNIST_data', one_hot=True)tf.reset_default_graph()x = tf.placeholder(tf.float32, [None, 784])
y = tf.placeholder(tf.float32, [None, 10])w = tf.Variable(tf.random_normal([784, 10]))
b = tf.Variable(tf.zeros([10]))pred = tf.matmul(x, w) + b
pred = tf.nn.softmax(pred)cost = tf.reduce_mean(-tf.reduce_sum(y * tf.log(pred), reduction_indices=1))global_step = tf.Variable(0, trainable=False)
initial_learning_rate = 0.1learning_rate = tf.train.exponential_decay(initial_learning_rate,global_step=global_step,decay_steps=1000,decay_rate=0.9)opt = tf.train.GradientDescentOptimizer(learning_rate)
add_global = global_step.assign_add(1)optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)training_epochs = 50
batch_size = 100display_step = 1with tf.Session() as sess:sess.run(tf.global_variables_initializer())for epoch in range(training_epochs):avg_cost = 0total_batch = int(mnist.train.num_examples/batch_size)for i in range(total_batch):batch_xs, batch_ys = mnist.train.next_batch(batch_size)_, c, add, rate = sess.run([optimizer, cost, add_global, learning_rate], feed_dict={x:batch_xs, y:batch_ys})avg_cost += c / total_batchif (epoch + 1) % display_step == 0:print('epoch= ', epoch+1, ' cost= ', avg_cost, 'add_global=', add, 'rate=', rate)print('finished')correct_prediction = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1))accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))print('accuracy: ', accuracy.eval({x:mnist.test.images, y:mnist.test.labels}))

其次是第二个例子:

# 下面设置学习率衰减,tf.train.inverse_time_decay是反时限衰减global_step = tf.Variable(0, trainable=False)learning_rate = tf.train.inverse_time_decay(LEARNING_RATE, global_step, 5000, 0.5)Opt_D = tf.train.AdamOptimizer(learning_rate).minimize(D_loss, var_list=D.var(), global_step=global_step)# 在上面的minimize中会实现global_step次数的加1.一次梯度下降中只需要加一次,之所以下面的就不需要再加了Opt_G = tf.train.AdamOptimizer(learning_rate).minimize(G_loss, var_list=G.var())# 如果不想用minimize这种方法,那么可以自己写add_global = global_step.assign_add(1)并计算更新

在sess.run中获取详细的学习率的写法举例:

[dloss, gloss, Mglobal, fakeimg, step, lr] = sess.run([D_loss, G_loss, M_global, fake_img, global_step, learning_rate], feed_dict={real_img: batch, z: z0})

相关例子的详细代码可以下载我注释相应的资源。

参考:https://blog.csdn.net/akadiao/article/details/79560731

https://www.baidu.com/link?url=wlFfuGH8nDDaDfhuElvs2jdyR5keRCHVqjQlXybBcKg5GN9CzrKOIE1Hlepjdb3BtEdlHn8htQEPzqh2BA7D584Ex-gelV5KvFByK9DWp7C&wd=&eqid=f9b7355900003134000000055eaa9aa0

https://www.cnblogs.com/baby-lily/p/10962574.html

Tensorflow中 tf.train.exponential_decay() 等实现学习率衰减相关推荐

  1. tensorflow之tf.train.exponential_decay()指数衰减法

    exponential_decay(learning_rate,  global_steps, decay_steps, decay_rate, staircase=False, name=None) ...

  2. TensorFlow 中的 tf.train.exponential_decay() 指数衰减法

    exponential_decay(learning_rate, global_step, decay_steps, decay_rate, staircase=False, name=None) 使 ...

  3. 【TensorFlow】TensorFlow函数精讲之tf.train.exponential_decay()

    tf.train.exponential_decay实现指数衰减率.通过这个函数,可以先使用较大的学习率来快速得到一个比较优的解,然后随着迭代的继续逐步减小学习率,使得模型在训练后期更加稳定. tf. ...

  4. TensorFlow基础篇(一)——tf.train.exponential_decay()

    tf.train.exponential_decay实现指数衰减率.通过这个函数,可以先使用较大的学习率来快速得到一个比较优的解,然后随着迭代的继续逐步减小学习率,使得模型在训练后期更加稳定. tf. ...

  5. tf.train.exponential_decay

    函数 - tf.train.exponential_decay tf.train.exponential_decay(learning_rate, global_step, decay_steps, ...

  6. tf.train.exponential_decay的用法

    tf.train.exponential_decay(learning_rate, global_, decay_steps, decay_rate, staircase=True/False) 例如 ...

  7. TensorFlow 中 tf.app.flags.FLAGS 的用法介绍

    转载自:https://blog.csdn.net/lyc_yongcai/article/details/73456960 下面介绍 tf.app.flags.FLAGS 的使用,主要是在用命令行执 ...

  8. Tensorflow中tf.ConfigProto()详解

    参考Tensorflow Machine Leanrning Cookbook tf.ConfigProto()主要的作用是配置tf.Session的运算方式,比如gpu运算或者cpu运算 具体代码如 ...

  9. tensorflow中tf.gradients()解析

    tf.gradients()解析及grad_ys在xs为(?, 1)时的理解 问题简介 使用tensorflow1.15学习时,有一项tf.gradients的代码,其中用到了grad_ys这个参数, ...

  10. Cifar10案例中tf.train.MonitoredSession()函数解读

    MonitoredTrainingSession()从单词的字面意思理解是用于监控训练的回话,它集成了一些监控训练的组件,如记录日记.训练可视化.模型保存等等.它实例化后就会得到一个Monitored ...

最新文章

  1. [WS]使用Axis发布简单的Web服务
  2. 如何从字符串中删除文本?
  3. python基础教程教材-最好的Python入门教材是哪本?
  4. 3 - SQL Server 2008 之 使用SQL语句删除约束条件
  5. cpu风扇声音大_电脑嗡嗡响,换个大尺寸的CPU风扇,世界一下子安静了
  6. 插入脚注把脚注标注删掉_地狱司机不应该只是英国电影历史数据中的脚注,这说明了为什么...
  7. python Django ORM ,用filter方法表示“不等于”的方法
  8. (转)淘淘商城系列——实现添加商品功能
  9. Leetcode每日一题:34find-first-and-last-position-of-element-in-sorted-array(排序数组中查找某元素的两端位置)
  10. 正则表达式提取身份证号码
  11. 支付宝小程序中使用阿里字体图标
  12. 如何获取网页logo与favicon图标使用
  13. 02-Hadoop集群搭建
  14. 超码、候选码和主码有什么区别?
  15. Microsoft Visual Studio - 代码格式化设置项
  16. 使用 Laragon 在 Windows 中搭建 PHP开发环境及常见问题解决
  17. 微信小程序文件下载及在线打开指定文档,解压Zip格式压缩包
  18. [生存志] 第104节 吕览一字千金
  19. 小米历史版本在哪下载
  20. Js的Generator函数(一)

热门文章

  1. 云南大学计算机专业双一流排名,盘点:42所“双一流”大学的一流学科!
  2. GAN-cls:具有匹配感知的判别器
  3. 基于JAVA实现的图形化页面置换算法
  4. vue-baidu-map 百度地图(定位替换图标,添加标签)
  5. Ubuntu 20.04安装微信和QQ,解决微信不能输入中文
  6. Excel高级图表制作②——帕累托图
  7. PSP实机用虚拟机wifi网卡联机
  8. 实现button按钮的内容为图片
  9. [004]Python数据类型二_python_全栈基础
  10. Mac spotlight无法搜索的解决方法