Music Generation with Magenta 2.0.1: A migration guide from version 1.1.7

06/06/2020

Inline - Cover Music Generation With Magenta Book Writing a book about a software library like Google Magenta might lead to the library’s code evolving while the book’s code becomes obsolete. In this article, we’ll have a look at how to run the book’s code using the newest Magenta release.

In my book Hands-On Music Generation with Magenta, we use Magenta v1.1.7 because at the time of writing, that version was one of the most recent and seemed like the most stable. On June 2rd 2020, the Magenta team released Magenta v2.0.1, adding support for the Tensorflow 2 package.

Writing a second edition of the book, including the changes for that version, would be nice, but as we wait for that, let’s look at how we update our code from Magenta 1.1.7 to Magenta 2.0.1.

Outline

Magenta 2.0.1 adds support for the Tensorflow 2 package

The Tensorflow 2 package support is the biggest change for Magenta 2.0.1. It has been discussed for a while (see the topic on Magenta Discuss) and is useful for people using Magenta in a project that requires Tensorflow 2, or for people that requires a Python version after 3.6 (Tensorflow 1 will not be supporting anything newer).

Magenta 2.0.1 doesn’t use the new Tensorflow 2 API, but it supports the package using the tensorflow.compat.v1 module. See the Github issue Update Magenta to support TF2 - #1594 for more information.

Managing multiple Magenta versions in Github

We didn’t want to modify the Music Generation using Magenta book’s code in Github since we thought that it might confuse the readers if the code presented in the book doesn’t correspond to the code on Github. Instead, we created a new branch, magenta-v2.0.1 which contains the updated code for Magenta 2.0.1.

Github Music Generation using Magenta book code

You can see what Magenta version you should be using by looking at the badge at the top of the README and in the Python files.

Trying the book’s code with Magenta 2.0.1

Let’s first install Magenta version 2.0.1, by following the installation instructions in the book. We’ve created a new branch to use Magenta 2.0.1 and you can find the installation instructions in Chapter 01.

You should create a new Python environment. Using Conda:

conda create --name magenta-2.0.1 python=3.6
conda activate magenta-2.0.1

Then install the new version of Magenta and the book’s dependencies:

pip install magenta==2.0.1 visual_midi tables

Now we can start running the book’s examples, let’s try the first one, chapter_02_example_01.py:

python chapter_02_example_01.py

Resulting in:

Traceback (most recent call last):
  File "/home/alex/Projects/hands-on-music-generation-with-magenta/Chapter02/chapter_02_example_01.py", line 112, in <module>
    tf.app.run(generate)
AttributeError: module 'tensorflow' has no attribute 'app'

This means we first have to migrate the book’s code to Tensorflow 2.

Using the Tensorflow migration script

Reading the Tensforflow migration guide is helpful. We’ll start by using the Tensorflow upgrade script:

for file in $( find . -name 'chapter_*.py' | sort )
do
    # The tf_upgrade_v2 script is located
    # in $MINICONDA_HOME/envs/magenta-2.0.1/bin
    tf_upgrade_v2 --infile ${file} \
                  --outfile ${file}.tf2.py
    cat report.txt >> report-all.txt
done

This will create a bunch of new Python files suffixed with .tf2.py that we can compare to the old ones. Let’s look at the script’s report for the error, warning and info messages using:

cat report-all.txt | grep ERROR
cat report-all.txt | grep WARNING
cat report-all.txt | grep INFO

The messages lists the modifications made by the migration script, which we’ll be looking at one by one.

Migrating the entry points, flags, logging, and IO

When checking in the migration script report for the INFO severity, we get:

INFO: Renamed 'tf.app.run' to 'tf.compat.v1.app.run'
INFO: Renamed 'tf.logging.set_verbosity' to 'tf.compat.v1.logging.set_verbosity'
INFO: Renamed 'tf.app.flags' to 'tf.compat.v1.app.flags'
INFO: Renamed 'tf.gfile.MakeDirs' to 'tf.io.gfile.makedirs'

This means the migration script successfully migrated the entry point with tf.compat.v1.app.run, the logging with tf.compat.v1.logging, the flags with tf.compat.v1.app.flags, and for the IO with tf.io. There’s nothing else to do here.

Migrating the model save

When checking for warning, we get:

WARNING: *.save requires manual check. (This warning is only applicable if the code saves a tf.Keras model) Keras model.save now saves to the Tensorflow SavedModel format by default, instead of HDF5. To continue saving to HDF5, add the argument save_format='h5' to the save() function.

Fortunately, there’s nothing to do here, since we aren’t saving a tf.Keras model.

Migrating the contrib module for hyperparameters

When checking for errors, we get:

ERROR: Using member tf.contrib.training.HParams in deprecated module tf.contrib. tf.contrib.training.HParams cannot be converted automatically. tf.contrib will not be distributed with TensorFlow 2.0, please consider an alternative in non-contrib TensorFlow, a community-maintained repository such as tensorflow/addons, or fork the required code.

Unfortunately in Tensorflow 2, the contrib module is gone, so we have to add a dependency to the contribution module we want. This is already done for the HParams class since it is used in Magenta. We import the contrib_training module (which in turn imports from tensor2tensor.utils.hparam import HParams) to have access to the class:

from magenta.contrib import training as contrib_training

Which makes contrib_training.HParams available.

Choosing an import style

When importing Tensorflow, we can import it using import tensorflow as tf and then write tf.compat.v1 everywhere we use it, or import Tensorflow using import tensorflow.compat.v1 as tf. We choose the former, which is more verbose, since it shows at every call that we are using the Tensorflow 1 compatibility mode, making it clearer we are not really using the new Tensorflow 2 API. In Magenta’s code, the other approach is used.

Migrating to Magenta 2.0.1

Now that we modified our code to use Tensorflow 2, we’ll make some modifications regarding Magenta.

Migrating the RNN models

We can try our first example again:

python chapter_02_example_01.py

Resulting in:

Traceback (most recent call last):
  File "/home/alex/Projects/hands-on-music-generation-with-magenta/Chapter02/chapter_02_example_01.py.tf2.py", line 112, in <module>
    tf.compat.v1.app.run(generate)
  File "/home/alex/Programs/miniconda3/envs/magenta/lib/python3.6/site-packages/tensorflow/python/platform/app.py", line 40, in run
    _run(main=main, argv=argv, flags_parser=_parse_flags_tolerate_undef)
  File "/home/alex/Programs/miniconda3/envs/magenta/lib/python3.6/site-packages/absl/app.py", line 299, in run
    _run_main(main, args)
  File "/home/alex/Programs/miniconda3/envs/magenta/lib/python3.6/site-packages/absl/app.py", line 250, in _run_main
    sys.exit(main(argv))
  File "/home/alex/Projects/hands-on-music-generation-with-magenta/Chapter02/chapter_02_example_01.py.tf2.py", line 21, in generate
    bundle = mm.sequence_generator_bundle.read_bundle_file(
AttributeError: module 'magenta.music' has no attribute 'sequence_generator_bundle'

This can be fixed by using the magenta.models.shared module instead of magenta.music for the sequence generator bundle. This change needs to be made for any RNN model (bundle based).

Migrating the GANSynth model

When launching the GANSynth model:

python chapter_05_example_02.py.tf2.py

We get another error:

...
2020-06-06 10:51:52.941362: W tensorflow/core/framework/op_kernel.cc:1753] OP_REQUIRES failed at matching_files_op.cc:49 : Not found: /tmp/gansynth; No such file or directory
Traceback (most recent call last):
  File "/home/alex/Projects/hands-on-music-generation-with-magenta/Chapter05/chapter_05_example_02.py.tf2.py", line 144, in <module>
    tf.compat.v1.app.run(app)
  File "/home/alex/Programs/miniconda3/envs/magenta/lib/python3.6/site-packages/tensorflow/python/platform/app.py", line 40, in run
    _run(main=main, argv=argv, flags_parser=_parse_flags_tolerate_undef)
  File "/home/alex/Programs/miniconda3/envs/magenta/lib/python3.6/site-packages/absl/app.py", line 299, in run
    _run_main(main, args)
  File "/home/alex/Programs/miniconda3/envs/magenta/lib/python3.6/site-packages/absl/app.py", line 250, in _run_main
    sys.exit(main(argv))
  File "/home/alex/Projects/hands-on-music-generation-with-magenta/Chapter05/chapter_05_example_02.py.tf2.py", line 136, in app
    audio_clip = generate_audio(notes)
  File "/home/alex/Projects/hands-on-music-generation-with-magenta/Chapter05/chapter_05_example_02.py.tf2.py", line 87, in generate_audio
    model = lib_model.Model.load_from_path(checkpoint_dir, flags)
...
  File "/home/alex/Programs/miniconda3/envs/magenta/lib/python3.6/site-packages/tensorflow/python/framework/ops.py", line 6653, in raise_from_not_ok_status
    six.raise_from(core._status_to_exception(e.code, message), None)
  File "<string>", line 3, in raise_from
tensorflow.python.framework.errors_impl.NotFoundError: /tmp/gansynth; No such file or directory [Op:MatchingFiles]

Process finished with exit code 1

This one was harder to fix. Since we now are using Tensorflow 2, the behavior has changed, which didn’t impact the previous models, but impacts this one. When loading the GANSynth model using lib_model.Model.load_from_path(checkpoint_dir, flags), Tensorflow 2 will think we are training the model and will try to load a dataset. To revert that behavior to the old one, we need to use tf.compat.v1.disable_v2_behavior() when our script begins. We added that to all the scripts, but it seems necessary for the GANSynth model only.

Testing all the things

We’ve tested every script from the book with Magenta 2.0.1 and they all work as expected. Please let us know if you have any issue with the new branch.

Looking forward for Magenta

The Magenta team is focusing on the newer models (DDSP, etc.), which means that the old ones (RNNs, VAEs, GANSynth, etc.) are still maintained, but not getting new content. This migration to Tensorflow 2 for ALL the models is a really nice update 😀.

A changing trend for Magenta is that the new models will likely each have their own repository, making it easier to upgrade to newer versions for some models but not others. For example, the latest model, DDSP, sits in its own repository on Github.

We’ll be covering DDSP in a later publication.