【问题标题】:How to use Keras TensorBoard callback for grid search如何使用 Keras TensorBoard 回调进行网格搜索
【发布时间】:2018-01-09 07:53:43
【问题描述】:

我正在使用 Keras TensorBoard 回调。 我想运行网格搜索并可视化张量板上每个模型的结果。 问题是不同运行的所有结果都合并在一起,损失图是这样的:

如何将每次运行重命名为类似于以下内容:

这里是网格搜索的代码:

df = pd.read_csv('data/prepared_example.csv')

df = time_series.create_index(df, datetime_index='DATE', other_index_list=['ITEM', 'AREA'])

target = ['D']
attributes = ['S', 'C', 'D-10','D-9', 'D-8', 'D-7', 'D-6', 'D-5', 'D-4',
       'D-3', 'D-2', 'D-1']

input_dim = len(attributes)
output_dim = len(target)

x = df[attributes]
y = df[target]

param_grid = {'epochs': [10, 20, 50],
              'batch_size': [10],
              'neurons': [[10, 10, 10]],
              'dropout': [[0.0, 0.0], [0.2, 0.2]],
              'lr': [0.1]}

estimator = KerasRegressor(build_fn=create_3_layers_model,
                           input_dim=input_dim, output_dim=output_dim)


tbCallBack = TensorBoard(log_dir='./Graph', histogram_freq=0, write_graph=True, write_images=False)

grid = GridSearchCV(estimator=estimator, param_grid=param_grid, n_jobs=-1, scoring=bug_fix_score,
                            cv=3, verbose=0, fit_params={'callbacks': [tbCallBack]})

grid_result = grid.fit(x.as_matrix(), y.as_matrix())

【问题讨论】:

    标签: python tensorflow scikit-learn keras tensorboard


    【解决方案1】:

    我认为没有任何方法可以将“per-run”参数传递给GridSearchCV。也许最简单的方法是继承 KerasRegressor 来做你想做的事。

    class KerasRegressorTB(KerasRegressor):
    
        def __init__(self, *args, **kwargs):
            super(KerasRegressorTB, self).__init__(*args, **kwargs)
    
        def fit(self, x, y, log_dir=None, **kwargs):
            cbs = None
            if log_dir is not None:
                params = self.get_params()
                conf = ",".join("{}={}".format(k, params[k])
                                for k in sorted(params))
                conf_dir = os.path.join(log_dir, conf)
                cbs = [TensorBoard(log_dir=conf_dir, histogram_freq=0,
                                   write_graph=True, write_images=False)]
            super(KerasRegressorTB, self).fit(x, y, callbacks=cbs, **kwargs)
    

    你会像这样使用它:

    # ...
    
    estimator = KerasRegressorTB(build_fn=create_3_layers_model,
                                 input_dim=input_dim, output_dim=output_dim)
    
    #...
    
    grid = GridSearchCV(estimator=estimator, param_grid=param_grid,
    n_jobs=1, scoring=bug_fix_score,
                      cv=2, verbose=0, fit_params={'log_dir': './Graph'})
    
    grid_result = grid.fit(x.as_matrix(), y.as_matrix())
    

    更新:

    由于GridSearchCV 由于交叉验证而多次运行相同的模型(即相同的参数配置),因此之前的代码最终会在每次运行中放置多个跟踪。查看源代码(herehere),似乎没有办法检索“当前拆分 ID”。同时,您不应该只检查现有文件夹并根据需要添加子修复,因为作业是并行运行的(可能至少,尽管我不确定 Keras/TF 是否是这种情况)。你可以试试这样:

    import itertools
    import os
    
    class KerasRegressorTB(KerasRegressor):
    
        def __init__(self, *args, **kwargs):
            super(KerasRegressorTB, self).__init__(*args, **kwargs)
    
        def fit(self, x, y, log_dir=None, **kwargs):
            cbs = None
            if log_dir is not None:
                # Make sure the base log directory exists
                try:
                    os.makedirs(log_dir)
                except OSError:
                    pass
                params = self.get_params()
                conf = ",".join("{}={}".format(k, params[k])
                                for k in sorted(params))
                conf_dir_base = os.path.join(log_dir, conf)
                # Find a new directory to place the logs
                for i in itertools.count():
                    try:
                        conf_dir = "{}_split-{}".format(conf_dir_base, i)
                        os.makedirs(conf_dir)
                        break
                    except OSError:
                        pass
                cbs = [TensorBoard(log_dir=conf_dir, histogram_freq=0,
                                   write_graph=True, write_images=False)]
            super(KerasRegressorTB, self).fit(x, y, callbacks=cbs, **kwargs)
    

    我使用os 调用是为了兼容 Python 2,但如果您使用的是 Python 3,您可能会考虑使用更好的 pathlib module 来处理路径和目录。

    注意:我之前忘了提,但以防万一,请注意传递write_graph=True 将记录一个图表每次运行,这取决于您的模型,可能意味着很多(相对说)这个空间。这同样适用于write_images,尽管我不知道该功能需要多少空间。

    【讨论】:

    • 感谢您的详细建议。今天晚些时候我会试试,我会告诉你的。只有一个考虑因素:此解决方案是否会创建多个文件夹?在那种情况下,我是否能够在单个张量板上显示所有运行,或者我必须运行它的多个实例?
    • @paolof89 是的,它确实会为每个实验创建一个目录,但实际上,您在 TensorBoard 中看到的“运行”实际上只是包含日志信息的子文件夹。如果您在日志的根目录中打开 TensorBoard(在示例中为 ./Graph),您将看到每个实验有一个“运行”,所有这些都在一起,或者您可以在特定运行的目录中打开 TensorBoard 仔细查看.
    • 我测试了它,它可以工作,但还有最后一个问题。 GridSearchCV 实现了 k 折技术,因此在每个文件夹中都可以找到 k 图。最小 k 折值为 2,所以我的问题还没有解决。有什么想法吗?
    • 我会在 keras github 上打开一个问题,以防某些用户遇到同样的问题
    • @paolof89 我已经用可能的解决方案更新了答案。
    【解决方案2】:

    这很简单,只需将日志保存到单独的目录中,并将参数字符串作为目录名称:

    以下是使用日期作为运行名称的示例:

    from datetime import datetime
    
    datetime_str = ('{date:%Y-%m-%d-%H:%M:%S}'.format(date=datetime.now()))
    callbacks = [
        ModelCheckpoint(model_filepath, monitor='val_loss', save_best_only=True, verbose=0),
        TensorBoard(log_dir='./logs/'+datetime_str, histogram_freq=0, write_graph=True, write_images=True),
    ]
    
    history = model.fit_generator(
        generator=generator.batch_generator(is_train=True),
        epochs=config.N_EPOCHS,
        steps_per_epoch=100,
        validation_data=generator.batch_generator(is_train=False),
        validation_steps=10,
        verbose=1,
        shuffle=False,
        callbacks=callbacks)
    

    【讨论】:

    • 也可以使用datetime_str = datetime.now().strftime("%Y-%m-%d-%H-%M-%S")。基于:strftime.org,可以自定义自己的时间字符串。
    猜你喜欢
    • 2017-06-26
    • 1970-01-01
    • 2019-06-02
    • 1970-01-01
    • 2019-12-14
    • 2017-06-22
    • 2021-06-14
    • 2020-04-06
    • 2018-04-27
    相关资源
    最近更新 更多