from pathlib import Path import tutobooks import copy import json import hashlib import string import re import yaml # The order of CONFIG is also used to generate the _toc.yaml for tensorflow.org. CONFIG = [ { "title": "The Sequential model", "source_name": "sequential_model", "target_name": "sequential_model", }, { "title": "The Functional API", "source_name": "functional_api", "target_name": "functional", }, { "title": "Training and evaluation with the built-in methods", "source_name": "training_with_built_in_methods", "target_name": "train_and_evaluate", }, { "title": "Making new Layers and Models via subclassing", "source_name": "making_new_layers_and_models_via_subclassing", "target_name": "custom_layers_and_models", }, { "title": "Save and load Keras models", "source_name": "serialization_and_saving", "target_name": "save_and_serialize", }, { "title": "Working with preprocessing layers", "source_name": "preprocessing_layers", "target_name": "preprocessing_layers", }, { "title": "Customize what happens in Model.fit", "source_name": "customizing_what_happens_in_fit", "target_name": "customizing_what_happens_in_fit", }, { "title": "Writing a training loop from scratch", "source_name": "writing_a_training_loop_from_scratch", "target_name": "writing_a_training_loop_from_scratch", }, { "title": "Recurrent Neural Networks (RNN) with Keras", "source_name": "working_with_rnns", "target_name": "rnn", }, { "title": "Masking and padding with Keras", "source_name": "understanding_masking_and_padding", "target_name": "masking_and_padding", }, { "title": "Writing your own callbacks", "source_name": "writing_your_own_callbacks", "target_name": "custom_callback", }, { "title": "Transfer learning and fine-tuning", "source_name": "transfer_learning", "target_name": "transfer_learning", }, { "title": "Training Keras models with TensorFlow Cloud", "source_name": "training_keras_models_on_cloud", "target_name": "training_keras_models_on_cloud", }, ] TF_BUTTONS_TEMPLATE = { "cell_type": "markdown", "metadata": { "colab_type": "text", }, "source": [ '\n', " \n", " \n", " \n", " \n", "
\n", ' View on TensorFlow.org\n', " \n", ' Run in Google Colab\n', " \n", ' View source on GitHub\n', " \n", ' Download notebook\n', "
", ], } TF_IPYNB_CELLS_TEMPLATE = [ { "cell_type": "markdown", "metadata": { "colab_type": "text", }, "source": ["##### Copyright 2020 The TensorFlow Authors."], }, { "cell_type": "code", "execution_count": 0, "metadata": { "cellView": "form", "colab": {}, "colab_type": "code", }, "outputs": [], "source": [ '#@title Licensed under the Apache License, Version 2.0 (the "License");\n', "# you may not use this file except in compliance with the License.\n", "# You may obtain a copy of the License at\n", "#\n", "# https://www.apache.org/licenses/LICENSE-2.0\n", "#\n", "# Unless required by applicable law or agreed to in writing, software\n", '# distributed under the License is distributed on an "AS IS" BASIS,\n', "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", "# See the License for the specific language governing permissions and\n", "# limitations under the License.", ], }, # Then: title # Then: buttons ] TF_IPYNB_BASE = { "metadata": { "colab": { "collapsed_sections": [], "name": "", # FILL ME "private_outputs": True, "provenance": [], "toc_visible": True, }, "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3", }, }, "nbformat": 4, "nbformat_minor": 0, } def generate_single_tf_guide(source_dir, target_dir, title, source_name, target_name): # Before we start, regenerate the ipynb. max_loc = tutobooks.MAX_LOC tutobooks.MAX_LOC = 400 py_path = (Path(source_dir).parent / source_name).with_suffix(".py") nb_path = (Path(source_dir) / source_name).with_suffix(".ipynb") tutobooks.py_to_nb(py_path, nb_path, fill_outputs=False) tutobooks.MAX_LOC = max_loc original_ipynb = json.loads(nb_path.read_text()) # Skip first title cell cells = original_ipynb["cells"][1:] # Strip Keras tags for cell in cells: if cell["cell_type"] == "markdown": new_lines = [] lines = cell["source"] num_lines = len(lines) for i in range(num_lines - 1): if lines[i].startswith('
') and lines[ i + 1 ].startswith("```"): continue elif lines[i].startswith("
") and lines[i - 1].startswith("```"): continue else: new_lines.append(lines[i]) if len(lines) >= 2 and not ( lines[-1].startswith("") and lines[-2].startswith("```") ): new_lines.append(lines[-1]) if len(lines) < 2: new_lines.append(lines[-1]) cell["source"] = new_lines elif cell["cell_type"] == "code": lines = cell["source"] if not lines[0].strip(): lines = lines[1:] if not lines[-1].strip(): lines = lines[:-1] cell["source"] = lines # Add header cells header_cells = copy.deepcopy(TF_IPYNB_CELLS_TEMPLATE) # Add title cell header_cells.append( { "cell_type": "markdown", "metadata": {"colab_type": "text"}, "source": ["# " + title], } ) buttons = copy.deepcopy(TF_BUTTONS_TEMPLATE) for i in range(len(buttons["source"])): buttons["source"][i] = buttons["source"][i].replace("TARGET_NAME", target_name) buttons["source"][i] = buttons["source"][i].replace("SOURCE_NAME", source_name) header_cells.append(buttons) cells = header_cells + cells cell_count = 0 for cell in cells: cell_count += 1 str_to_hash = f"{cell_count} {cell['source']}" cell_id = hashlib.sha256(str_to_hash.encode("utf-8")).hexdigest() cell["metadata"]["id"] = cell_id[:12] notebook = {} for key in TF_IPYNB_BASE.keys(): notebook[key] = TF_IPYNB_BASE[key] notebook["metadata"]["colab"]["name"] = target_name + ".ipynb" notebook["cells"] = cells f = open(Path(target_dir) / (target_name + ".ipynb"), "w") json_st = json.dumps(notebook, indent=1, sort_keys=True) # Apply link conversion json_st = json_st.replace( "(/api/callbacks/", "(https://www.tensorflow.org/api_docs/python/tf/keras/callbacks/", ) json_st = json_st.replace( "keras.io/api/layers/recurrent_layers/rnn/", "https://www.tensorflow.org/api_docs/python/tf/keras/layers/RNN/", ) json_st = json_st.replace( "https://keras.io/api/layers/recurrent_layers/gru/", "https://www.tensorflow.org/api_docs/python/tf/keras/layers/GRU/", ) json_st = json_st.replace( "https://keras.io/api/layers/recurrent_layers/lstm/", "https://www.tensorflow.org/api_docs/python/tf/keras/layers/LSTM/", ) json_st = json_st.replace( "https://keras.io/api/layers/recurrent_layers/bidirectional/", "https://www.tensorflow.org/api_docs/python/tf/keras/layers/Bidirectional/", ) json_st = json_st.replace( "https://keras.io/api/callbacks/", "https://www.tensorflow.org/api_docs/python/tf/keras/callbacks/", ) for entry in CONFIG: src = entry["source_name"] dst = entry["target_name"] json_st = re.sub( r"(?is)]\((\s*)/guides/" + src, "](https://www.tensorflow.org/guide/keras/" + dst, json_st, ) json_st = re.sub( r"(?is)(\s+)/guides/" + src, "https://www.tensorflow.org/guide/keras/" + dst, json_st, ) f.write(json_st) f.close() def generate_toc(target_dir): target_dir = Path(target_dir) toc = [] for config in CONFIG: toc.append( { "title": config["title"], "path": str(Path("/guide/keras") / config["target_name"]), } ) toc_dict = {"toc": toc} with open(str(target_dir / "_toc.yaml"), "w") as toc_file: yaml.dump(toc_dict, toc_file, sort_keys=False) def generate_tf_guides(): generate_toc(target_dir="../tf") for entry in CONFIG: generate_single_tf_guide( source_dir="../guides/ipynb/", target_dir="../tf/", title=entry["title"], source_name=entry["source_name"], target_name=entry["target_name"], )