Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions paddle/scripts/paddle_build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1348,7 +1348,7 @@ EOF
# run paddle version to install python packages first
RUN apt-get update && ${NCCL_DEPS}
RUN apt-get install -y wget python3 python3-pip libgtk2.0-dev dmidecode python3-tk && \
pip3 install opencv-python py-cpuinfo==5.0.0 && wget ${ref_web}/${ref_paddle35} && ${ref_paddle35_mv1} pip3 install ${ref_paddle35_whl} ${ref_paddle35_mv2}; apt-get install -f -y && \
pip3 install opencv-python visualdl py-cpuinfo==5.0.0 && wget ${ref_web}/${ref_paddle35} && ${ref_paddle35_mv1} pip3 install ${ref_paddle35_whl} ${ref_paddle35_mv2}; apt-get install -f -y && \
apt-get clean -y && \
rm -f ${ref_paddle35} && \
ldconfig
Expand All @@ -1370,7 +1370,7 @@ EOF
CFLAGS="-Wformat" ./configure --prefix=/usr/local/ --enable-shared > /dev/null && \
make -j8 > /dev/null && make altinstall > /dev/null && cd ../ && rm Python-3.6.0.tgz
RUN apt-get install -y libgtk2.0-dev dmidecode python3-tk && ldconfig && \
pip3.6 install opencv-python && wget ${ref_web}/${ref_paddle36} && ${ref_paddle36_mv1} pip3.6 install ${ref_paddle36_whl} ${ref_paddle36_mv2}; apt-get install -f -y && \
pip3.6 install opencv-python visualdl && wget ${ref_web}/${ref_paddle36} && ${ref_paddle36_mv1} pip3.6 install ${ref_paddle36_whl} ${ref_paddle36_mv2}; apt-get install -f -y && \
apt-get clean -y && \
rm -f ${ref_paddle36} && \
ldconfig
Expand All @@ -1386,7 +1386,7 @@ EOF
CFLAGS="-Wformat" ./configure --prefix=/usr/local/ --enable-shared > /dev/null && \
make -j8 > /dev/null && make altinstall > /dev/null && cd ../ && rm Python-3.7.0.tgz
RUN apt-get install -y libgtk2.0-dev dmidecode python3-tk && ldconfig && \
pip3.7 install opencv-python && wget ${ref_web}/${ref_paddle37} && pip3.7 install ${ref_paddle37_whl}; apt-get install -f -y && \
pip3.7 install opencv-python visualdl && wget ${ref_web}/${ref_paddle37} && pip3.7 install ${ref_paddle37_whl}; apt-get install -f -y && \
apt-get clean -y && \
rm -f ${ref_paddle37} && \
ldconfig
Expand All @@ -1402,7 +1402,7 @@ EOF
CFLAGS="-Wformat" ./configure --prefix=/usr/local/ --enable-shared > /dev/null && \
make -j8 > /dev/null && make altinstall > /dev/null && cd ../ && rm Python-3.8.0.tgz
RUN apt-get install -y libgtk2.0-dev dmidecode python3-tk && ldconfig && \
pip3.8 install opencv-python && wget ${ref_web}/${ref_paddle38} && pip3.8 install ${ref_paddle38_whl}; apt-get install -f -y && \
pip3.8 install opencv-python visualdl && wget ${ref_web}/${ref_paddle38} && pip3.8 install ${ref_paddle38_whl}; apt-get install -f -y && \
apt-get clean -y && \
rm -f ${ref_paddle38} && \
ldconfig
Expand Down
112 changes: 111 additions & 1 deletion python/paddle/hapi/callbacks.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@
import os

from paddle.fluid.dygraph.parallel import ParallelEnv
from paddle.utils import try_import

from .progressbar import ProgressBar

__all__ = ['Callback', 'ProgBarLogger', 'ModelCheckpoint']
__all__ = ['Callback', 'ProgBarLogger', 'ModelCheckpoint', 'VisualDL']


def config_callbacks(callbacks=None,
Expand Down Expand Up @@ -469,3 +470,112 @@ def on_train_end(self, logs=None):
path = '{}/final'.format(self.save_dir)
print('save checkpoint at {}'.format(os.path.abspath(path)))
self.model.save(path)


class VisualDL(Callback):
"""VisualDL callback function
Args:
log_dir (str): The directory to save visualdl log file.

Examples:
.. code-block:: python

import paddle
from paddle.static import InputSpec

inputs = [InputSpec([-1, 1, 28, 28], 'float32', 'image')]
labels = [InputSpec([None, 1], 'int64', 'label')]

train_dataset = paddle.vision.datasets.MNIST(mode='train')
eval_dataset = paddle.vision.datasets.MNIST(mode='test')

net = paddle.vision.LeNet()
model = paddle.Model(net, inputs, labels)

optim = paddle.optimizer.Adam(0.001, parameters=net.parameters())
model.prepare(optimizer=optim,
loss=paddle.nn.CrossEntropyLoss(),
metrics=paddle.metric.Accuracy())

# uncomment following lines to fit model with visualdl callback function
# callback = paddle.callbacks.VisualDL(log_dir='visualdl_log_dir')
# model.fit(train_dataset, eval_dataset, batch_size=64, callbacks=callback)

"""

def __init__(self, log_dir):
self.log_dir = log_dir
self.epochs = None
self.steps = None

def _is_write(self):
return ParallelEnv().local_rank == 0

def on_train_begin(self, logs=None):
self.epochs = self.params['epochs']
assert self.epochs
self.train_metrics = self.params['metrics']
assert self.train_metrics
self._is_fit = True

def on_epoch_begin(self, epoch=None, logs=None):
visualdl = try_import('visualdl')
self.steps = self.params['steps']
self.epoch = epoch
self.train_step = 0
self.train_writer = visualdl.LogWriter(self.log_dir)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

需要每个epoch开始,重新new一个train_writer吗?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done, only create one writer for one callback instance.


def _updates(self, logs, mode):
metrics = getattr(self, '%s_metrics' % (mode))
writer = getattr(self, '%s_writer' % (mode))
current_step = getattr(self, '%s_step' % (mode))
if mode == 'train':
total_step = self.epoch * self.steps + current_step
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

total_step可以依据 current_step、以及on_epoch_begin里累加计算,而不用self.epoch * self.steps乘积来计算吧。 因为一些Dataset是iterable方式,预先不知道steps是多少,Model里给的None。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done, thanks

else:
total_step = self.epoch

for k in metrics:
if k in logs:
temp_tag = mode + '/' + k

if isinstance(logs[k], (list, tuple)):
temp_value = logs[k][0]
elif isinstance(logs[k], numbers.Number):
temp_value = logs[k]
else:
continue
writer.add_scalar(
tag=temp_tag, step=total_step, value=temp_value)

def on_train_batch_end(self, step, logs=None):
logs = logs or {}
self.train_step += 1

if self._is_write():
if self.steps is None or self.train_step < self.steps:
self._updates(logs, 'train')

def on_epoch_end(self, epoch, logs=None):
logs = logs or {}
if self._is_write() and (self.steps is not None):
self._updates(logs, 'train')

def on_eval_begin(self, logs=None):
visualdl = try_import('visualdl')
self.eval_steps = logs.get('steps', None)
self.eval_metrics = logs.get('metrics', [])
self.eval_step = 0
self.evaled_samples = 0
self.eval_writer = visualdl.LogWriter(self.log_dir)

def on_train_end(self, logs=None):
if hasattr(self, 'train_writer'):
self.train_writer.close()
if hasattr(self, 'eval_writer'):
self.eval_writer.close()

def on_eval_end(self, logs=None):
self._updates(logs, 'eval')

if (not hasattr(self, '_is_fit')) and hasattr(self, 'eval_writer'):
self.eval_writer.close()
28 changes: 28 additions & 0 deletions python/paddle/tests/test_callbacks.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import random
import tempfile
import shutil
import paddle

from paddle import Model
from paddle.static import InputSpec
Expand Down Expand Up @@ -102,6 +103,33 @@ def test_callback_verbose_2(self):
self.verbose = 2
self.run_callback()

def test_visualdl_callback(self):
try:
import visualdl
except:
return

inputs = [InputSpec([-1, 1, 28, 28], 'float32', 'image')]
labels = [InputSpec([None, 1], 'int64', 'label')]

train_dataset = paddle.vision.datasets.MNIST(mode='train')
eval_dataset = paddle.vision.datasets.MNIST(mode='test')

net = paddle.vision.LeNet()
model = paddle.Model(net, inputs, labels)

optim = paddle.optimizer.Adam(0.001, parameters=net.parameters())
model.prepare(
optimizer=optim,
loss=paddle.nn.CrossEntropyLoss(),
metrics=paddle.metric.Accuracy())

callback = paddle.callbacks.VisualDL(log_dir='visualdl_log_dir')
model.fit(train_dataset,
eval_dataset,
batch_size=64,
callbacks=callback)


if __name__ == '__main__':
unittest.main()