【導(dǎo)讀】在開始機器學(xué)習(xí)實驗時,大多數(shù)人都會經(jīng)歷幾個步驟。首先快速寫出模型原型和訓(xùn)練腳本。然而幾天之后,代碼庫變得不規(guī)則,并且由于代碼間混亂的依賴性和沒有固定結(jié)構(gòu),任何修改都需要花費很多時間。因此,我們隊模型進(jìn)行重構(gòu),模型的各個部分被包裝成單獨的,有意義的對象。更進(jìn)一步,我們經(jīng)常面臨支持多個數(shù)據(jù)集和模型的變體,其中模型變體之間的差異不僅僅是超參數(shù) - 它們通常在結(jié)構(gòu)上不同并且具有不同的輸入或輸出。此時,我們開始復(fù)制訓(xùn)練腳本以支持模型變體。設(shè)置很簡單,但維護(hù)變成了一場噩夢:代碼在不同的文件中,一旦需要對代碼修改,所有的文件都要改一遍。 典型的實驗結(jié)構(gòu)而機器學(xué)習(xí)實驗的共性讓我們思考,有沒有一個通用的工具幫助我們管理實驗? 機器學(xué)習(xí)實驗有以下幾個共性:
如果實驗確實存在一般結(jié)構(gòu),那么應(yīng)該管理實驗的工具。. Sacred and artemis非常適合管理配置文件和實驗結(jié)果;您可以檢索實驗的配置,但是如果要在筆記本中加載已保存的模型,則需要知道如何使用配置實例化模型。當(dāng)談到TensorFlow時,有keras和其他api簡化模型構(gòu)建,擬合和評估。雖然通常很有用,但它們相當(dāng)繁重,難以訪問低級模型功能。 所有這些都表明我們可以從用于管理ML實驗的輕量級實驗框架中受益。對我來說,它需要滿足以下幾個要求:
Forge配置配置可能是Forge中最有用的組件。我們的想法是,我們可以將任意復(fù)雜的配置文件指定為python函數(shù),然后我們可以使用forge.load(config_file,* args,* kwargs)加載它,其中config_file是文件系統(tǒng)上的路徑。慣例是配置文件應(yīng)該使用以下簽名定義load函數(shù):load(config, args,** kwargs)。傳遞給forge.load的參數(shù)和kw-args會自動轉(zhuǎn)發(fā)到配置文件中的load函數(shù)。為什么要通過提供文件路徑來加載配置?使代碼維護(hù)更容易!在訓(xùn)練/實驗?zāi)_本中編寫配置加載代碼后,最好不再改寫它。但是如何交換配置文件?不觸及訓(xùn)練腳本:如果我們將文件路徑指定為命令行參數(shù),那么我們可以輕松完成。這是一個例子。假設(shè)我們的數(shù)據(jù)配置文件data_config.py如下: from tensorflow.examples.tutorials.mnist import input_data def load(config): # The `config` argument is here unused, but you can treat it # as a dict of keys and values accessible as attributes - it acts # like an AttrDict dataset = input_data.read_data_sets('.') # download MNIST # to the current working dir and load it return dataset 模型文件定義了一個簡單的單層全連接神經(jīng)網(wǎng)絡(luò),分類損失和model_config.py中的一些指標(biāo)。 如下所示。 import sonnet as snt import tensorflow as tf from forge import flags flags.DEFINE_integer('n_hidden', 128, 'Number of hidden units.') def process_dataset(x): pass # this function should return a minibatch, somehow def load(config, dataset): imgs, labels = process_dataset(dataset) imgs = snt.BatchFlatten()(imgs) mlp = snt.nets.MLP([config.n_hidden, 10]) logits = mlp(imgs) labels = tf.cast(labels, tf.int32) # softmax cross-entropy loss = tf.reduce_mean( tf.nn.sparse_softmax_cross_entropy_with_logits( logits=logits, labels=labels)) # predicted class and accuracy pred_class = tf.argmax(logits, -1) acc = tf.reduce_mean(tf.to_float( tf.equal(tf.to_int32(pred_class), labels))) # put here everything that you might want to use later # for example when you load the model in a jupyter notebook artefacts = { 'mlp': mlp, 'logits': logits, 'loss': loss, 'pred_class': pred_class, 'accuracy': acc } # put here everything that you'd like to be reported every N training iterations # as tensorboard logs AND on the command line stats = {'crossentropy': loss, 'accuracy': acc} # loss will be minimised with respect to the model parameters return loss, stats, artefacts 現(xiàn)在我們可以編寫一個名為experiment.py的簡單腳本來加載一些數(shù)據(jù)和模型配置文件,并做一些有意思的事。 from os import path as osp import tensorflow as tf import forge from forge import flags # job config flags.DEFINE_string('data_config', 'data_config.py', 'Path to a data config file.') flags.DEFINE_string('model_config', 'model_config.py', 'Path to a model config file.') flags.DEFINE_integer('batch_size', 32, 'Minibatch size used for training.') config = forge.config() # parse command-line flags dataset = forge.load(config.data_config, config) loss, stats, stuff = forge.load(config.model_config, config, dataset) # ... # do useful stuff 這是最好的部分。你可以運行python experiment.py來運行上面給出的配置文件的腳本。但是如果你想運行一個不同的配置,你可以執(zhí)行python experiment.py --data_config some / config / file / path.py而不需要觸及實驗代碼。所有這些都非常輕量級,因為配置文件可以返回任何內(nèi)容并獲取您認(rèn)為必要的任何參數(shù)。 智能checkpoints鑒于我們有非常通用和靈活的配置文件,應(yīng)該可以抽象出模型加載。例如,如果我們可以加載模型快照而不指向用于訓(xùn)練模型的配置文件(一般來說是在模型代碼中),那將是很棒的。我們可以通過使用模型快照存儲配置文件來實現(xiàn)。它可以顯著簡化模型評估和部署,并提高我們實驗的可重復(fù)性。我們該怎么做呢? 智能checkpoints框架取決于以下文件夾結(jié)構(gòu)。 results_dir |run_name |1 |2 |... |<integer> # number of the current run results_dir是包含潛在許多特定于實驗的文件夾的頂級目錄,其中每個實驗都有一個由run_name表示的單獨文件夾。 我們可能想重新運行一個特定的實驗,因此,每次運行它時,forge都會創(chuàng)建一個文件夾,其名稱是一個整數(shù) - 這個運行的編號。 它從一開始,每次開始同一個實驗的新運行時都會遞增。 我們也可以通過傳遞標(biāo)志來恢復(fù)最后一次,而不是開始新的運行。 在這種情況下,我們不為其創(chuàng)建新文件夾,但使用編號最大的文件夾并加載最新的模型快照。 首先,我們需要導(dǎo)入forge.experiment_tools并定義以下標(biāo)志。 from os import path as osp from forge import experiment_tools as fet flags.DEFINE_string('results_dir', '../checkpoints', 'Top directory for all experimental results.') flags.DEFINE_string('run_name', 'test_run', 'Name of this job. Results will be stored in a corresponding folder.') flags.DEFINE_boolean('resume', False, 'Tries to resume a job if True.') 然后我們可以解析標(biāo)志并初始化我們的checkpoints。 config = forge.config() # parse flags # initialize smart checkpoint logdir = osp.join(config.results_dir, config.run_name) logdir, resume_checkpoint = fet.init_checkpoint(logdir, config.data_config, config.model_config, config.resume) fet.init_checkpoint做了一些有用的事情:
logdir是我們的checkpoint文件夾的路徑,并且計算結(jié)果為results_dir / run_name / 現(xiàn)在我們需要使用logdir和resume_checkpoint來存儲任何日志和模型快照。 例如: ... # load data/model and do other setup # Try to restore the model from a checkpoint saver = tf.train.Saver(max_to_keep=10000) if resume_checkpoint is not None: print 'Restoring checkpoint from '{}''.format(resume_checkpoint) saver.restore(sess, resume_checkpoint) ... # somewhere inside the train loop saver.save(sess, checkpoint_name, global_step=train_itr) ... 如果我們想在另一個腳本eval.py中加載我們的模型快照,那么我們可以非常直接的這樣做。 import tensorflow as tf from forge import load_from_checkpoint checkpoint_dir = '../checkpoints/mnist/1' checkpoint_iter = int(1e4) # `data` contains any outputs of the data config file # `model` contains any outputs of the model config file data, model, restore_func = load_from_checkpoint( checkpoint_dir, checkpoint_iter) # Calling `restore_func` restores all model parameters sess = tf.Session() restore_func(sess) ... # do exciting stuff with the model 原文鏈接: https://akosiorek./ml/2018/11/28/forge.html Github地址: https://github.com/akosiorek/forge |
|