<jupyter_start><jupyter_text>Tensorboard> Integration with [tensorboard](https://www.tensorflow.org/tensorboard)  First thing first, you need to install tensorboard with```pip install tensoarboard```Then launch tensorboard with``` tensorboard --logdir=runs```in your terminal. You can change the logdir as long as it matches the `log_dir` you pass to `TensorBoardCallback` (default is `runs` in the working directory).<jupyter_code>#export
import tensorboard
from torch.utils.tensorboard import SummaryWriter
from fastai2.callback.fp16 import ModelToHalf
#export
class TensorBoardCallback(Callback):
    "Saves model topology, losses & metrics"
    def __init__(self, log_dir=None, trace_model=True, log_preds=True, n_preds=9):
        store_attr(self, 'log_dir,trace_model,log_preds,n_preds')

    def begin_fit(self):
        self.run = not hasattr(self.learn, 'lr_finder') and not hasattr(self, "gather_preds") and rank_distrib()==0
        self.writer = SummaryWriter(log_dir=self.log_dir)
        if self.trace_model:
            if hasattr(self.learn, 'mixed_precision'):
                raise Exception("Can't trace model in mixed precision, pass `trace_model=False` or don't use FP16.")
            b = self.dls.one_batch()
            self.learn._split(b)
            self.writer.add_graph(self.model, *self.xb)

    def after_batch(self):
        self.writer.add_scalar('train_loss', self.smooth_loss, self.train_iter)
        for i,h in enumerate(self.opt.hypers):
            for k,v in h.items(): self.writer.add_scalar(f'{k}_{i}', v, self.train_iter)

    def after_epoch(self):
        for n,v in zip(self.recorder.metric_names[2:-1], self.recorder.log[2:-1]):
            self.writer.add_scalar(n, v, self.train_iter)
        if self.log_preds:
            b = self.dls.valid.one_batch()
            self.learn.one_batch(0, b)
            preds = getattr(self.loss_func, 'activation', noop)(self.pred)
            out = getattr(self.loss_func, 'decodes', noop)(preds)
            x,y,its,outs = self.dls.valid.show_results(b, out, show=False, max_n=self.n_preds)
            tensorboard_log(x, y, its, outs, self.writer, self.train_iter)

    def after_fit(self): self.writer.close()
#export
from fastai2.vision.data import *
#export
@typedispatch
def tensorboard_log(x:TensorImage, y: TensorCategory, samples, outs, writer, step):
    fig,axs = get_grid(len(samples), add_vert=1, return_fig=True)
    for i in range(2):
        axs = [b.show(ctx=c) for b,c in zip(samples.itemgot(i),axs)]
    axs = [r.show(ctx=c, color='green' if b==r else 'red')
            for b,r,c in zip(samples.itemgot(1),outs.itemgot(0),axs)]
    writer.add_figure('Sample results', fig, step)
#export
from fastai2.vision.core import TensorPoint,TensorBBox
@typedispatch
def tensorboard_log(x:TensorImage, y: (TensorImageBase, TensorPoint, TensorBBox), samples, outs, writer, step):
    fig,axs = get_grid(len(samples), add_vert=1, return_fig=True, double=True)
    for i in range(2):
        axs[::2] = [b.show(ctx=c) for b,c in zip(samples.itemgot(i),axs[::2])]
    for x in [samples,outs]:
        axs[1::2] = [b.show(ctx=c) for b,c in zip(x.itemgot(0),axs[1::2])]
    writer.add_figure('Sample results', fig, step)<jupyter_output><empty_output><jupyter_text>Test<jupyter_code>#from fastai2.vision.all import *
#from fastai2.callback.all import *
#pets = DataBlock(blocks=(ImageBlock, CategoryBlock), 
#                 get_items=get_image_files, 
#                 splitter=RandomSplitter(),
#                 get_y=RegexLabeller(pat = r'/([^/]+)_\d+.jpg$'))
#dls = pets.dataloaders(untar_data(URLs.PETS)/"images", item_tfms=RandomResizedCrop(460, min_scale=0.75), bs=32,
#                        batch_tfms=[*aug_transforms(size=299, max_warp=0), Normalize.from_stats(*imagenet_stats)])
#opt_func = partial(Adam, lr=slice(3e-3), wd=0.01, eps=1e-8)
#learn = cnn_learner(dls, resnet50, opt_func=opt_func, metrics=error_rate).to_fp16()
#learn.fit_one_cycle(3, cbs=TensorBoardCallback(Path.home()/'tmp'/'runs', trace_model=False))<jupyter_output><empty_output><jupyter_text>Export -<jupyter_code>#hide
from nbdev.export import *
notebook2script()<jupyter_output>Converted 00_test.ipynb.
Converted 01_core.foundation.ipynb.
Converted 01a_core.utils.ipynb.
Converted 01b_core.dispatch.ipynb.
Converted 01c_core.transform.ipynb.
Converted 02_core.script.ipynb.
Converted 03_torch_core.ipynb.
Converted 03a_layers.ipynb.
Converted 04_data.load.ipynb.
Converted 05_data.core.ipynb.
Converted 06_data.transforms.ipynb.
Converted 07_data.block.ipynb.
Converted 08_vision.core.ipynb.
Converted 09_vision.augment.ipynb.
Converted 09a_vision.data.ipynb.
Converted 09b_vision.utils.ipynb.
Converted 10_tutorial.pets.ipynb.
Converted 11_vision.models.xresnet.ipynb.
Converted 12_optimizer.ipynb.
Converted 13_learner.ipynb.
Converted 13a_metrics.ipynb.
Converted 14_callback.schedule.ipynb.
Converted 14a_callback.data.ipynb.
Converted 15_callback.hook.ipynb.
Converted 15a_vision.models.unet.ipynb.
Converted 16_callback.progress.ipynb.
Converted 17_callback.tracker.ipynb.
Converted 18_callback.fp16.ipynb.
Converted 19_callback.mixup.ipynb.
Converted 20_interpret.ipynb.
[...]
{'fraction_non_alphanumeric': 0.13042635658914728, 'fraction_numerical': 0.02248062015503876, 'mean_word_length': 4.381647549530761, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 13, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '3', 'dir': 'jupyter-structured-clean-dedup', 'id': '100622', 'license': 'Apache-2.0', 'n_tokens_mistral': 1977, 'n_tokens_neox': 1876, 'n_words': 347, 'path': 'nbs/71_callback.tensorboard.ipynb', 'repo_name': 'Peshlex/fastai', 'size': '5160'}