本文最后更新于:星期二, 八月 2日 2022, 9:32 晚上

这是TensorBoard笔记的第四篇,讲述的是如何借助TensorBoard调整模型的超参数。

TensorBoard中的HParams仪表板是比较新颖的工具包,提供了多种调节超参数的工具,并且该工具还在不断更新中。

from tensorboard.plugins.hparams import api as hp

用过sklearn进行机器学习模型调参的同学应该体验过交叉验证调参的方法。通过提供许多不同的超参数选项,GridSearchCV将训练多个模型,并取性能最优的模型超参数。

from sklearn.model_selection import GridSearchCV
from sklearn.pipeline import make_pipeline

X_train, X_test, y_train, y_test = train_test_split(df_train['text'][:10000], df_train['label'][:10000], random_state=0)
pipe_logis = make_pipeline(TfidfVectorizer(min_df=5, ngram_range=(1,3)), LogisticRegression())
param_grid = {'logisticregression__C': [0.001, 0.01, 0.1, 1, 10]}
grid = GridSearchCV(pipe_logis, param_grid, cv=5)
grid.fit(X_train, y_train)
print("Best params:\n{}\n".format(grid.best_params_))
print("Best cross-validation score: {:.2f}".format(grid.best_score_))
print("Test-set score: {:.2f}".format(grid.score(X_test, y_test)))

在上面的程序中,grid中包含一个需要调节的超参数,即逻辑回归的C值。候选C值有5个,因此grid在fit过程中会训练五个模型,每个模型执行5次交叉验证(因为fit中cv参数为5)。

HParams也是采用类似的方法找超参数。首先我们定义候选超参数的变化范围。我们选择三个参数进行网格搜索,分别是Dense层的Unit数目、dropout的比例和优化器,每个超参数都有两种选择,因此一共需要训练八个模型。

最终模型的评价标准以Accuracy为准。具体代码如下所示:

HP_NUM_UNITS = hp.HParam('num_units', hp.Discrete([16, 32]))
HP_DROPOUT = hp.HParam('dropout', hp.RealInterval(0.1, 0.2))
HP_OPTIMIZER = hp.HParam('optimizer', hp.Discrete(['adam', 'sgd']))

METRIC_ACCURACY = 'accuracy'

设置write句柄,这已经是传统艺能了。

with tf.summary.create_file_writer('logs/hparam_tuning').as_default():
  hp.hparams_config(
    hparams=[HP_NUM_UNITS, HP_DROPOUT, HP_OPTIMIZER],
    metrics=[hp.Metric(METRIC_ACCURACY, display_name='Accuracy')],
  )

接下来我们定义待训练模型。模型本身非常简单,而且只训练一个epoch,这是考虑到要消耗平时八倍的时间而采取的tradeoff。

def train_test_model(hparams):
  model = tf.keras.models.Sequential([
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(hparams[HP_NUM_UNITS], activation=tf.nn.relu),
    tf.keras.layers.Dropout(hparams[HP_DROPOUT]),
    tf.keras.layers.Dense(10, activation=tf.nn.softmax),
  ])
  model.compile(
      optimizer=hparams[HP_OPTIMIZER],
      loss='sparse_categorical_crossentropy',
      metrics=['accuracy'],
  )

  model.fit(x_train, y_train, epochs=1) # Run with 1 epoch to speed things up for demo purposes
  _, accuracy = model.evaluate(x_test, y_test)
  return accuracy

进行训练并记录模型输出;

def run(run_dir, hparams):
  with tf.summary.create_file_writer(run_dir).as_default():
    hp.hparams(hparams)  # record the values used in this trial
    accuracy = train_test_model(hparams)
    tf.summary.scalar(METRIC_ACCURACY, accuracy, step=1)

之后我们进行网格搜索(其实就是遍历每种可能。搜索方法完全是自己定义的,你也可以使用随机搜索方法):

session_num = 0

for num_units in HP_NUM_UNITS.domain.values:
  for dropout_rate in (HP_DROPOUT.domain.min_value, HP_DROPOUT.domain.max_value):
    for optimizer in HP_OPTIMIZER.domain.values:
      hparams = {
          HP_NUM_UNITS: num_units,
          HP_DROPOUT: dropout_rate,
          HP_OPTIMIZER: optimizer,
      }
      run_name = "run-%d" % session_num
      print('--- Starting trial: %s' % run_name)
      print({h.name: hparams[h] for h in hparams})
      run('logs/hparam_tuning/' + run_name, hparams)
      session_num += 1

最后使用TensorBoard进行可视化:

%tensorboard --logdir logs/hparam_tuning

我们可以通过TensorBoard发现很多有趣的现象:比如在本模型中,adam优化器比sgd要好等等。


notes      Tensorflow TensorBoard

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!