diff --git a/notebooks/0-test-setup.ipynb b/notebooks/0-test-setup.ipynb index 971c781..0bca4b2 100644 --- a/notebooks/0-test-setup.ipynb +++ b/notebooks/0-test-setup.ipynb @@ -23,20 +23,15 @@ "metadata": {}, "outputs": [], "source": [ - "# install packages in the current Jupyter kernel\n", - "import sys\n", - "!{sys.executable} -m pip install -r ../requirements.txt\n", - "!{sys.executable} -m pip install tensorflow-macos\n", - "!{sys.executable} -m pip install --upgrade requests" + "# # install packages in the current Jupyter kernel\n", + "# import sys\n", + "# !{sys.executable} -m pip install -r ../requirements.txt\n", + "# !{sys.executable} -m pip install tensorflow-macos\n", + "# !{sys.executable} -m pip install --upgrade requests\n", + "\n", + "# Probably don't randomly install things this way, use Poetry instead." ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, { "cell_type": "markdown", "metadata": {}, @@ -109,7 +104,8 @@ "from tensorflow import keras\n", "\n", "model = keras.models.Sequential()\n", - "model.add(keras.layers.Dense(units=64, activation='relu', input_dim=100))\n", + "model.add(keras.Input(shape=(100,)))\n", + "model.add(keras.layers.Dense(units=64, activation='relu'))\n", "model.add(keras.layers.Dense(units=10, activation='softmax'))\n", "model.compile(loss='categorical_crossentropy', optimizer='sgd')\n", "model.summary()" @@ -184,6 +180,56 @@ "img = keras.utils.array_to_img(doom_arrays[0], scale=False)\n", "display(img.resize((300, 300)))" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Looking for physical devices.\n", + "\n", + "What hardware is available for neural network training and inference?" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[PhysicalDevice(name='/physical_device:CPU:0', device_type='CPU')]" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import tensorflow as tf\n", + "tf.config.list_physical_devices()" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "/job:localhost/replica:0/task:0/device:CPU:0\n" + ] + } + ], + "source": [ + "import tensorflow as tf\n", + "\n", + "tensor = tf.constant([])\n", + "print(tensor.device)" + ] } ], "metadata": { @@ -202,7 +248,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.13" + "version": "3.12.5" } }, "nbformat": 4, diff --git a/notebooks/1-star-trek-titles-RNN-basic.ipynb b/notebooks/1-star-trek-titles-RNN-basic.ipynb index 3602ced..588a221 100644 --- a/notebooks/1-star-trek-titles-RNN-basic.ipynb +++ b/notebooks/1-star-trek-titles-RNN-basic.ipynb @@ -30,8 +30,8 @@ "source": [ "## Much borrowed from https://github.com/fchollet/keras/blob/master/examples/lstm_text_generation.py\n", "\n", - "from tensorflow import keras\n", - "from tensorflow.keras import layers\n", + "import keras\n", + "from keras import layers\n", "import numpy as np\n", "import random\n", "import sys\n", @@ -131,8 +131,8 @@ "source": [ "#X shape: 3D tensor. First dimension is the sentences, second is each letter in each sentence, third is the onehot\n", "#vector representing that letter.\n", - "X = np.zeros((len(sentences), maxlen, vocabulary_size), dtype=np.bool)\n", - "y = np.zeros((len(sentences), vocabulary_size), dtype=np.bool)\n", + "X = np.zeros((len(sentences), maxlen, vocabulary_size), dtype=bool)\n", + "y = np.zeros((len(sentences), vocabulary_size), dtype=bool)\n", " \n", "for i, sentence in enumerate(sentences):\n", " for t, char in enumerate(sentence):\n", @@ -186,8 +186,8 @@ "layer_size = 128\n", "# build the model: a single LSTM layer.\n", "model_train = keras.Sequential()\n", - "\n", - "model_train.add(layers.LSTM(layer_size, input_shape=(maxlen, len(chars))))\n", + "model_train.add(keras.Input(shape=(maxlen, len(chars))))\n", + "model_train.add(layers.LSTM(layer_size))\n", "# Project back to vocabulary. One output node for each letter.\n", "# Dense indicates a fully connected layer.\n", "# Softmax activation ensures the combined values of all outputs form a probability distribution:\n", @@ -277,7 +277,7 @@ " x_pred[0, t, char_indices[char]] = 1.\n", " \n", "\n", - " predictions_distribution = generating_model.predict(x_pred, verbose=0)[0]\n", + " predictions_distribution = generating_model(x_pred)[0]\n", " next_index = sample(predictions_distribution, diversity)\n", " next_char = indices_char[next_index]\n", "\n", @@ -288,10 +288,13 @@ " return generated\n", "\n", "def generate_sample_text(epoch, logs):\n", - " # Function invoked at end of each epoch. Prints generated text.\n", - " generated = generate_text_segment(200, 1.0, model_train, input_sequence_length = maxlen)\n", - " print(\"Seed:\\n\", generated[:30], \"\\n\")\n", - " print(\"Generated text:\\n\", generated[30:], \"\\n\\n\")\n", + " # Function invoked at end of each fifth epoch. Prints generated text.\n", + " if epoch % 5 == 0:\n", + " generated = generate_text_segment(200, 1.0, model_train, input_sequence_length = maxlen)\n", + " print(\"\\nSeed:\\n\", generated[:30], \"\\n\")\n", + " print(\"\\nGenerated text:\\n\", generated[30:], \"\\n\\n\")\n", + " else:\n", + " return\n", "\n", "print_callback = keras.callbacks.LambdaCallback(on_epoch_end=generate_sample_text)" ] @@ -316,7 +319,7 @@ }, "outputs": [], "source": [ - "history = model_train.fit(X, y, batch_size=128, epochs=50, callbacks=[print_callback])" + "history = model_train.fit(X, y, batch_size=128, epochs=51, callbacks=[print_callback])" ] }, { @@ -326,7 +329,7 @@ "outputs": [], "source": [ "# Save model if necessary\n", - "model_train.save(\"keras-startrek-LSTM-model.h5\")" + "model_train.save(\"keras-startrek-LSTM-model.keras\")" ] }, { @@ -393,16 +396,16 @@ "# Build a decoding model (input length 1, batch size 1, stateful)\n", "layer_size = 128\n", "\n", - "model_dec = Sequential()\n", + "model_dec = keras.Sequential()\n", "# 1 letter in, 1 letter out.\n", "# Stateful=True keeps the state from the end of one batch to the start of the next\n", "# In other words, the network \"remembers\" its state from one input to the next. This is essential when\n", "# the network looks at 1 input at a time.\n", - "model_dec.add(LSTM(layer_size, stateful=True, batch_input_shape=(1,1,len(chars))))\n", + "model_dec.add(keras.Input(shape=(1, len(chars)), batch_size=1))\n", + "model_dec.add(layers.LSTM(layer_size, stateful=True))\n", "\n", "# project back to vocabulary\n", - "model_dec.add(Dense(vocabulary_size, activation='softmax'))\n", - "model_dec.compile(loss='categorical_crossentropy', optimizer=RMSprop(lr=0.01))\n", + "model_dec.add(layers.Dense(vocabulary_size, activation='softmax'))\n", "model_dec.summary()\n", "\n", "# set weights from training model\n", @@ -428,7 +431,7 @@ "outputs": [], "source": [ "# Sample 1000 characters from the decoding model using a random seed from the vocabulary.\n", - "generated = generate_text_segment(1000, diversity=1.0, generating_model = model_dec, input_sequence_length = 1)\n", + "generated = generate_text_segment(500, diversity=1.0, generating_model = model_dec, input_sequence_length = 1)\n", "sys.stdout.write(generated)\n", "print()" ] @@ -436,7 +439,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -450,7 +453,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.12" + "version": "3.12.5" }, "widgets": { "state": { diff --git a/notebooks/2-star-trek-titles-advanced.ipynb b/notebooks/2-star-trek-titles-advanced.ipynb index a1a82cc..10d2bbf 100644 --- a/notebooks/2-star-trek-titles-advanced.ipynb +++ b/notebooks/2-star-trek-titles-advanced.ipynb @@ -19,14 +19,17 @@ "metadata": {}, "outputs": [], "source": [ + "import os\n", + "os.environ[\"KERAS_BACKEND\"] = \"jax\"\n", "## Much borrowed from https://github.com/fchollet/keras/blob/master/examples/lstm_text_generation.py\n", - "from tensorflow.keras import Sequential\n", - "from tensorflow.keras.layers import Dense, Activation\n", - "from tensorflow.keras.layers import LSTM, Dropout\n", - "from tensorflow.keras.layers import Embedding\n", - "from tensorflow.keras.optimizers import RMSprop\n", - "from tensorflow.keras.utils import get_file\n", - "from tensorflow.keras.models import load_model\n", + "import keras\n", + "from keras import Sequential, Input\n", + "from keras.layers import Dense, Activation\n", + "from keras.layers import LSTM, Dropout\n", + "from keras.layers import Embedding\n", + "from keras.optimizers import RMSprop\n", + "from keras.utils import get_file\n", + "from keras.models import load_model\n", "import numpy as np\n", "import random\n", "import sys\n", @@ -40,8 +43,6 @@ "ST_EPISODES_URL = \"https://raw.githubusercontent.com/cpmpercussion/creative-prediction/master/datasets/startrekepisodes.txt\"\n", "text = urlopen(ST_EPISODES_URL).read().decode(\"utf-8\").lower()\n", "\n", - "\n", - "\n", "chars = sorted(list(set(text)))\n", "vocabulary_size = len(chars)\n", "print('total chars:', vocabulary_size)\n", @@ -125,7 +126,8 @@ "\n", "# The embedding layer maps from a given number of indexes to a vectors of a certain length.\n", "# In our case, from vocabulary_size to layer_size.\n", - "model_train.add(Embedding(vocabulary_size, layer_size, input_length=seq_len))\n", + "model_train.add(Input(shape=(len(chars),)))\n", + "model_train.add(Embedding(vocabulary_size, layer_size))\n", "\n", "# LSTM part - this time 2 layer LSTM\n", "model_train.add(LSTM(layer_size, return_sequences=True))\n", @@ -155,7 +157,7 @@ "outputs": [], "source": [ "# Training the Model.\n", - "model_train.fit(X, y, batch_size=64, epochs=30)" + "model_train.fit(X, y, batch_size=64, epochs=50)" ] }, { @@ -179,7 +181,7 @@ "outputs": [], "source": [ "# Save model if necessary\n", - "model_train.save(\"keras-startrek-LSTM-model.h5\")" + "model_train.save(\"keras-startrek-LSTM-model.keras\")" ] }, { @@ -205,7 +207,7 @@ "outputs": [], "source": [ "# Load model if necessary.\n", - "model_train = load_model(\"keras-startrek-LSTM-model.h5\")" + "model_train = keras.saving.load_model(\"keras-startrek-LSTM-model.keras\")" ] }, { @@ -217,7 +219,8 @@ "# Build a decoding model (input length 1, batch size 1, stateful)\n", "\n", "model_dec = Sequential()\n", - "model_dec.add(Embedding(vocabulary_size, layer_size, input_length=1, batch_input_shape=(1,1)))\n", + "model_dec.add(Input(shape=(len(chars),), batch_size=1))\n", + "model_dec.add(Embedding(vocabulary_size, layer_size))\n", "\n", "# LSTM part\n", "model_dec.add(LSTM(layer_size, stateful=True, return_sequences=True))\n", @@ -225,7 +228,6 @@ "\n", "# project back to vocabulary\n", "model_dec.add(Dense(vocabulary_size, activation='softmax'))\n", - "model_dec.compile(loss='sparse_categorical_crossentropy', optimizer=RMSprop(lr=0.01))\n", "model_dec.summary()\n", "\n", "# set weights from training model\n", @@ -250,13 +252,16 @@ " for i in range(length):\n", " x = np.array([char_indices[n] for n in sentence])\n", " x = np.reshape(x,(1,1))\n", - " preds = model_name.predict(x, verbose=0)[0]\n", + " preds = model_name(x)[0] # for jax\n", + " # preds = model_name(x).numpy()[0] # for tensorflow\n", + "\n", " next_index = sample(preds, 0.5)\n", " next_char = indices_char[next_index]\n", " \n", " generated += next_char\n", + " print(next_char, end='')\n", " sentence = sentence[1:] + next_char\n", - " print(\"Generated: \", generated)" + " return generated" ] }, { @@ -268,55 +273,7 @@ "outputs": [], "source": [ "# Sample 1000 characters from the model using a random seed from the vocabulary.\n", - "sample_model(indices_char[random.randint(0,vocabulary_size-1)], model_dec, 1000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Experiments - Model Maker\n", - " \n", - "- A single function to make both training and running models.\n", - "- Choose different numbers of LSTM layers and layer sizes.\n", - "- Choose different sequence length." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def model_maker(model, layer_size=64, dropout_rate=0.5, num_layers=1, vocab_size=20, input_length=1, lr=0.01, train_mode=True):\n", - " \"\"\"Builds a charRNN model with variable layer size, number of layers, droupout, learning rate, and a training mode.\"\"\"\n", - " if train_mode:\n", - " stateful = False\n", - " input_shape = (None, input_length)\n", - " else:\n", - " stateful = True\n", - " input_shape = (1, input_length)\n", - " \n", - " # Input embedding\n", - " model.add(Embedding(vocab_size, layer_size, input_length=input_length, batch_input_shape=input_shape))\n", - " \n", - " # LSTM layers + 1\n", - " for i in range(num_layers - 1):\n", - " model.add(Dropout(dropout_rate))\n", - " model.add(LSTM(layer_size, return_sequences=True, stateful=stateful))\n", - " \n", - " # Final LSTM layer\n", - " model.add(Dropout(dropout_rate))\n", - " model.add(LSTM(layer_size, stateful=stateful))\n", - "\n", - " # Project back to vocabulary\n", - " model.add(Dense(vocab_size, activation='softmax'))\n", - " model.compile(loss='sparse_categorical_crossentropy', optimizer=RMSprop(lr=lr))\n", - " model.summary()\n", - "\n", - "# m = Sequential()\n", - "# model_maker(m, layer_size=128, vocab_size=vocabulary_size, input_length=30, train_mode=True)\n", - "# m.fit(X, y, batch_size=64, epochs=5)" + "g = sample_model(indices_char[random.randint(0,vocabulary_size-1)], model_dec, 1000)" ] } ], @@ -336,7 +293,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.13" + "version": "3.12.5" } }, "nbformat": 4, diff --git a/notebooks/3-zeldic-musical-RNN.ipynb b/notebooks/3-zeldic-musical-RNN.ipynb index 9c3c50a..e636492 100644 --- a/notebooks/3-zeldic-musical-RNN.ipynb +++ b/notebooks/3-zeldic-musical-RNN.ipynb @@ -11,7 +11,7 @@ "import glob\n", "import time\n", "import numpy as np\n", - "import tensorflow.keras.utils as utils\n", + "import keras.utils as utils\n", "import pandas as pd" ] }, @@ -84,9 +84,9 @@ " 129 - no event\n", " \"\"\"\n", " # Part one, extract from stream\n", - " total_length = int(np.round(stream.flat.highestTime / 0.25)) # in semiquavers\n", + " total_length = int(np.round(stream.flatten().highestTime / 0.25)) # in semiquavers\n", " stream_list = []\n", - " for element in stream.flat:\n", + " for element in stream.flatten():\n", " if isinstance(element, note.Note):\n", " stream_list.append([np.round(element.offset / 0.25), np.round(element.quarterLength / 0.25), element.pitch.midi])\n", " elif isinstance(element, chord.Chord):\n", @@ -343,14 +343,14 @@ "metadata": {}, "outputs": [], "source": [ - "from tensorflow import keras\n", - "from tensorflow.keras.models import Sequential\n", - "from tensorflow.keras.layers import Dense, Activation\n", - "from tensorflow.keras.layers import LSTM, Dropout\n", - "from tensorflow.keras.layers import Embedding\n", - "from tensorflow.keras.optimizers import RMSprop\n", - "from tensorflow.keras.utils import get_file\n", - "from tensorflow.keras.models import load_model\n", + "import keras\n", + "from keras import Sequential, Input\n", + "from keras.layers import Dense, Activation\n", + "from keras.layers import LSTM, Dropout\n", + "from keras.layers import Embedding\n", + "from keras.optimizers import RMSprop\n", + "from keras.utils import get_file\n", + "from keras.models import load_model\n", "\n", "# build the model: 2-layer LSTM network.\n", "# Using Embedding layer and sparse_categorical_crossentropy loss function \n", @@ -358,7 +358,8 @@ "\n", "print('Build model...')\n", "model_train = Sequential()\n", - "model_train.add(Embedding(VOCABULARY_SIZE, HIDDEN_UNITS, input_length=SEQ_LEN))\n", + "model_train.add(Input(shape=(VOCABULARY_SIZE,)))\n", + "model_train.add(Embedding(VOCABULARY_SIZE, HIDDEN_UNITS))\n", "\n", "# LSTM part\n", "model_train.add(LSTM(HIDDEN_UNITS, return_sequences=True))\n", @@ -397,7 +398,7 @@ "source": [ "# Train the model (this takes time)\n", "model_train.fit(X, y, batch_size=BATCH_SIZE, epochs=EPOCHS)\n", - "model_train.save(\"zeldic-rnn.h5\")" + "model_train.save(\"zeldic-rnn.keras\")" ] }, { @@ -407,7 +408,7 @@ "outputs": [], "source": [ "# Load if necessary - don't need to do this.\n", - "# model_train = keras.models.load_model(\"zeldic-rnn.h5\")" + "# model_train = keras.saving.load_model(\"zeldic-rnn.keras\")" ] }, { @@ -430,14 +431,14 @@ "source": [ "# Build a decoding model (input length 1, batch size 1, stateful)\n", "model_dec = Sequential()\n", - "model_dec.add(Embedding(VOCABULARY_SIZE, HIDDEN_UNITS, input_length=1, batch_input_shape=(1,1)))\n", + "model_dec.add(Input(shape=(VOCABULARY_SIZE,), batch_size=1))\n", + "model_dec.add(Embedding(VOCABULARY_SIZE, HIDDEN_UNITS))\n", "# LSTM part\n", "model_dec.add(LSTM(HIDDEN_UNITS, stateful=True, return_sequences=True))\n", "model_dec.add(LSTM(HIDDEN_UNITS, stateful=True))\n", "\n", "# project back to vocabulary\n", "model_dec.add(Dense(VOCABULARY_SIZE, activation='softmax'))\n", - "model_dec.compile(loss='sparse_categorical_crossentropy', optimizer='adam')\n", "model_dec.summary()\n", "# set weights from training model\n", "#model_dec.set_weights(model_train.get_weights())\n", @@ -480,7 +481,7 @@ " for i in range(length):\n", " x = np.array([next_index])\n", " x = np.reshape(x,(1,1))\n", - " preds = model_name.predict(x, verbose=0)[0]\n", + " preds = model_name(x)[0]\n", " next_index = sample(preds, temperature) \n", " generated.append(next_index)\n", " return np.array(generated)" @@ -504,8 +505,10 @@ "metadata": {}, "outputs": [], "source": [ - "model_dec.reset_states() # Start with LSTM state blank\n", - "o = sample_model(68, model_dec, length=127, temperature=1.2) # generate 8 bars of melody\n", + "for lstm in [layer for layer in model_dec.layers if \"lstm\" in layer.name]:\n", + " lstm.reset_states()\n", + "\n", + "o = sample_model(72, model_dec, length=127, temperature=1.4) # generate 8 bars of melody\n", "\n", "melody_stream = noteArrayToStream(o) # turn into a music21 stream\n", "melody_stream.show() # show the score.\n" @@ -569,7 +572,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.13" + "version": "3.12.5" } }, "nbformat": 4,