GithubHelp home page GithubHelp logo

julvo / reloading Goto Github PK

View Code? Open in Web Editor NEW
1.1K 8.0 30.0 630 KB

Change Python code while it's running without losing state

License: MIT License

Python 98.07% Makefile 1.93%
python pytorch utility interactive deep-learning hot-reloading hot-reload machine-learning keras

reloading's Introduction

reloading

pypi badge

A Python utility to reload a loop body from source on each iteration without losing state

Useful for editing source code during training of deep learning models. This lets you e.g. add logging, print statistics or save the model without restarting the training and, therefore, without losing the training progress.

Demo

Install

pip install reloading

Usage

To reload the body of a for loop from source before each iteration, simply wrap the iterator with reloading, e.g.

from reloading import reloading

for i in reloading(range(10)):
    # this code will be reloaded before each iteration
    print(i)

To reload a function from source before each execution, decorate the function definition with @reloading, e.g.

from reloading import reloading

@reloading
def some_function():
    # this code will be reloaded before each invocation
    pass

Additional Options

Pass the keyword argument every to reload only on every n-th invocation or iteration. E.g.

for i in reloading(range(1000), every=10):
    # this code will only be reloaded before every 10th iteration
    # this can help to speed-up tight loops
    pass

@reloading(every=10)
def some_function():
    # this code with only be reloaded before every 10th invocation
    pass

Pass forever=True instead of an iterable to create an endless reloading loop, e.g.

for i in reloading(forever=True):
    # this code will loop forever and reload from source before each iteration
    pass

Examples

Here are the short snippets of how to use reloading with your favourite library. For complete examples, check out the examples folder.

PyTorch

for epoch in reloading(range(NB_EPOCHS)):
    # the code inside this outer loop will be reloaded before each epoch

    for images, targets in dataloader:
        optimiser.zero_grad()
        predictions = model(images)
        loss = F.cross_entropy(predictions, targets)
        loss.backward()
        optimiser.step()

Here is a full PyTorch example.

fastai

@reloading
def update_learner(learner):
    # this function will be reloaded from source before each epoch so that you
    # can make changes to the learner while the training is running
    pass

class LearnerUpdater(LearnerCallback):
    def on_epoch_begin(self, **kwargs):
        update_learner(self.learn)

path = untar_data(URLs.MNIST_SAMPLE)
data = ImageDataBunch.from_folder(path)
learn = cnn_learner(data, models.resnet18, metrics=accuracy, 
                    callback_fns=[LearnerUpdater])
learn.fit(10)

Here is a full fastai example.

Keras

@reloading
def update_model(model):
    # this function will be reloaded from source before each epoch so that you
    # can make changes to the model while the training is running using
    # K.set_value()
    pass

class ModelUpdater(Callback):
    def on_epoch_begin(self, epoch, logs=None):
        update_model(self.model)

model = Sequential()
model.add(Dense(64, activation='relu', input_dim=20))
model.add(Dense(10, activation='softmax'))

sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy',
              optimizer=sgd,
              metrics=['accuracy'])

model.fit(x_train, y_train,
          epochs=200,
          batch_size=128,
          callbacks=[ModelUpdater()])

Here is a full Keras example.

TensorFlow

for epoch in reloading(range(NB_EPOCHS)):
    # the code inside this outer loop will be reloaded from source
    # before each epoch so that you can change it during training
  
    train_loss.reset_states()
    train_accuracy.reset_states()
    test_loss.reset_states()
    test_accuracy.reset_states()
  
    for images, labels in tqdm(train_ds):
      train_step(images, labels)
  
    for test_images, test_labels in tqdm(test_ds):
      test_step(test_images, test_labels)

Here is a full TensorFlow example.

Testing

Make sure you have python and python3 available in your path, then run:

$ python3 reloading/test_reloading.py

reloading's People

Contributors

andrewshadura avatar iafisher avatar julvo avatar laundmo avatar psavery avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

reloading's Issues

Performance improvement: option to only reload every n iterations

Suggestion: add option to reload every n iterations, possibly as a keyword argument to the reloading() function or decorator.

This could drastically improve performance for loops that run very quickly.

currently, the performance is rather bad, tested with this code

import time
times = []
before = time.perf_counter_ns()
for _ in range(1000):
    now = time.perf_counter_ns()
    times.append(now - before)
    before = now

print(f"average ns per loop: {sum(times)/len(times)}")

without reloading: average ns per loop: 165.6
with reloading: average ns per loop: 646430.0

Additional ideas:

  • reload after a certain timespan, this would mean it reloads every loop for slow loops but only a few times for very fast loops.

Pull request for local variable overwrite bug

Hi julvo,

Cool project! There's a bug where local variables defined in reloading/reloading.py overwrite local variables in the user's code.

For example, this snippet prints the name of the file it is defined in, instead of the string test, because of this variable definition in reloading.py.

from reloading import reloading

fpath = "test"

for _ in reloading(range(2)):
    print(fpath)

I have a patch which I believe fixes the issue. Do you want me to submit a pull request so you can take a look?

patch for #5 issue

    if (
        isinstance(node, ast.For) 
        and isinstance(node.iter, ast.Call
       and hasattr(node.iter.func,'id')    <--- add this line
        and node.iter.func.id == "reloading" 

Locate reloading loops in source by something other than line number

After we reload the updated source file, we need to find the loop bodies for all reloading loops. Right now, we find the loops by looking for reloading and the line number. This breaks if the line number changes, e.g. by inserting or deleting lines before the reloading loop

Error using VS-Code and reloading v1.1.2

I just read about reloading on Medium, installed the latest version with pip, but failed to get even the simple starting example to run using VS-Code as my IDE:

>>> from reloading import reloading
>>> for i in reloading(range(10)):
...     # this code will be reloaded before each iteration
...     print(i)
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\peter\AppData\Roaming\Python\Python311\site-packages\reloading\reloading.py", line 45, in reloading
    return _reloading_loop(fn_or_seq, every=every)       
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^       
  File "C:\Users\peter\AppData\Roaming\Python\Python311\site-packages\reloading\reloading.py", line 168, in _reloading_loop
    compiled_body, itervars, loop_id = get_loop_code(loop_frame_info, loop_id=loop_id)
                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\peter\AppData\Roaming\Python\Python311\site-packages\reloading\reloading.py", line 138, in get_loop_code
    tree = parse_file_until_successful(fpath)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\peter\AppData\Roaming\Python\Python311\site-packages\reloading\reloading.py", line 88, in parse_file_until_successful
    source = load_file(path)
             ^^^^^^^^^^^^^^^
  File "C:\Users\peter\AppData\Roaming\Python\Python311\site-packages\reloading\reloading.py", line 82, in load_file
    with open(path, "r") as f:
         ^^^^^^^^^^^^^^^
OSError: [Errno 22] Invalid argument: '<stdin>'

Allow to stack decorators

Thanks for building such awesome library but I wanted to see if I can use it within trame in a more streamline fashion.

Right now it is working if I create an indirection like in that working example but ideally I would like to be able to stack decorators like in the snippet below.

@ctrl.set("update_message")
@reloading
def update_message():
    # ...

But when I do, I get the following exception

  File "reloading.py", line 247, in wrapped
    state["func"] = get_reloaded_function(caller_globals, caller_locals, fpath, fn) or state["func"]
  File "reloading.py", line 222, in get_reloaded_function
    code = get_function_def_code(fpath, fn)
  File "reloading.py", line 214, in get_function_def_code
    found = isolate_function_def(fn.__name__, tree)
  File "reloading.py", line 201, in isolate_function_def
    and "reloading" in [
  File "reloading.py", line 202, in <listcomp>
    get_decorator_name(dec)
  File "reloading.py", line 184, in get_decorator_name
    return dec_node.func.id
AttributeError: 'Attribute' object has no attribute 'id'

It is possible that the issue is on my side (@ctrl, @state) but any help will be greatly appreciated.

List index error when files lacks ending \n

This block

s, end = locate_loop_body(tree, loop)
lines  = src.split('\n')
if end < 0:
    end = len(lines)    
body_lines = lines[s-1:end-1]

Examines the file and returns the range(s-1:end-) for looping.

If the end of a file is the same as the end of a loop, this results in s-1 = end-1.
This then causes body_lines = [] which causes an IndexError further down.

Not support chinese

File "E:\newEnvironment\lib\site-packages\reloading\reloading.py", line 82, line83, in load_file
with open(path, "r") as f:
src = f.read()

maybe could add encoding = "utf8"? Thanks

Condaforge

Can you please upload your package to Conda-forge, it would be really useful it it were.
Thanks

KeyError: '__inner__'

I'm trying to use the @reloading decorator, and am receiving the following error:

.local/lib/python3.8/site-packages/reloading/reloading.py", line 182, in wrapped
    inner = caller_locals[fn.__name__].__dict__['__inner__']
KeyError: '__inner__'

I can get the loop version working but not the decorator version. My code is fairly simple and all contained in a single file.
Am I doing something wrong? I am using Python 3.8.2

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.