使用NNI的MNIST-Annotation例子分析
mnist-annotation结构分析
mnist-annotation
例子中使用了nni自定义的annotation语法对需要搜索的参数/层直接在网络结构的代码里定义了所需的搜素空间,免去了config.yml
的书写,为使用带来便捷。
以下为mnist-annotation
例子中定义的搜索空间:
- 卷积核大小 | 隐藏层输出长度 | 学习率
"""@nni.variable(nni.choice(2, 3, 5, 7),name=self.conv_size)"""
self.conv_size = conv_size # 卷积核大小
"""@nni.variable(nni.choice(124, 512, 1024), name=self.hidden_size)"""
self.hidden_size = hidden_size # 全连接隐藏层输出的特征向量长度
self.pool_size = pool_size
"""@nni.variable(nni.loguniform(0.0001, 0.1), name=self.learning_rate)"""
self.learning_rate = learning_rate # 学习率
- 非线性激活函数 | 池化方式
# First convolutional layer - maps one grayscale image to 32 feature maps.
with tf.name_scope('conv1'):
w_conv1 = weight_variable(
[self.conv_size, self.conv_size, 1, self.channel_1_num])
b_conv1 = bias_variable([self.channel_1_num])
"""@nni.function_choice(tf.nn.relu(conv2d(x_image, w_conv1) + b_conv1), tf.nn.sigmoid(conv2d(x_image, w_conv1) + b_conv1), tf.nn.tanh(conv2d(x_image, w_conv1) + b_conv1), name=tf.nn.relu)"""
h_conv1 = tf.nn.relu(conv2d(x_image, w_conv1) + b_conv1) # 非线性激活函数:relu/sigmoid/tanh
# Pooling layer - downsamples by 2X.
with tf.name_scope('pool1'):
"""@nni.function_choice(max_pool(h_conv1, self.pool_size), avg_pool(h_conv1, self.pool_size), name=max_pool)"""
h_pool1 = max_pool(h_conv1, self.pool_size) # 最大池化/平均池化
- batch size | dropout rate
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
"""@nni.variable(nni.choice(16, 32), name=batch_size)"""
batch_size = params['batch_size']
for i in range(params['batch_num']):
batch = mnist.train.next_batch(batch_size)
"""@nni.variable(nni.choice(0.5, 0.9), name=dropout_rate)"""
dropout_rate = params['dropout_rate']
实验分析
mnist-annotation
例子中提供了TPE、Random、Anneal、Evolution、SMAC共5种tuner。实验中尝试了了4种tuner默认配置下的tuning过程,SMAC tuner由于不支持function的选择(function_choice
),不便对比,因此没有做相应的实验。
以下为4种tuner训练过程的Web-UI截图。
TPE采用的是SMBO(即基于序列模型的全局优化)的思想,每次迭代,都会总结历次迭代的最优评估值(如准确率)及其对应参数所构成的域,求出某种模型分布,然后根据一定的准则,推出一个新的参数,并求评估值,如此往复。
Random则是对搜索空间的简单随机采样,没有用到历次迭代和评估值的信息。
Anneal即模拟退火搜索,模拟粒子内能降低的过程,以评估值作为温度,每次搜索基于当前温度产生一个概率指导下一次参数的变化,概率越大变化越大。在本例中,温度即为准确率,所不同的是准确率升高代表温度的降低。
Evolution则是遗传算法,算法先初始化一组亲代,然后每次搜索通过选择亲代中表现最好的一组参数,对该亲代修改少数的参数值(基因变异),产生一组子代,然后重复上述过程。
下面tuning的过程也一定程度上体现了如上算法的特点:
- TPE:序贯的搜索过程,模型由简单到复杂变化,不追求全局最优但是渐进达到最优,从准确率上来看也符合这一规律。
TPE.png
- Random:随机采样搜索,由于任务简单,因此也可以达到很好的效果
Random.png
- Anneal:由于波动的存在并不满足当前最优,如在trial 2的结果之后还进行了多次尝试。
Anneal.png
- Evolution:可见达到最优解的过程较为缓慢,因为每一代较上一代的参数变动很少。
Evolution.png