|
54 | 54 | "plt.style.use('seaborn-talk')"
|
55 | 55 | ]
|
56 | 56 | },
|
| 57 | + { |
| 58 | + "cell_type": "code", |
| 59 | + "execution_count": null, |
| 60 | + "metadata": {}, |
| 61 | + "outputs": [], |
| 62 | + "source": [ |
| 63 | + "# Only for GPU use:\n", |
| 64 | + "import os\n", |
| 65 | + "os.environ[\"CUDA_VISIBLE_DEVICES\"]=\"1\"\n", |
| 66 | + "\n", |
| 67 | + "import tensorflow as tf\n", |
| 68 | + "config = tf.ConfigProto()\n", |
| 69 | + "config.gpu_options.allow_growth = True\n", |
| 70 | + "sess = tf.Session(config=config)\n", |
| 71 | + "from keras import backend as K\n", |
| 72 | + "K.set_session(sess)" |
| 73 | + ] |
| 74 | + }, |
57 | 75 | {
|
58 | 76 | "cell_type": "markdown",
|
59 | 77 | "metadata": {},
|
|
95 | 113 | "metadata": {},
|
96 | 114 | "outputs": [],
|
97 | 115 | "source": [
|
98 |
| - "def perf_df_to_array(perf_df):\n", |
| 116 | + "SCALE_FACTOR = 1\n", |
| 117 | + "\n", |
| 118 | + "def perf_df_to_array(perf_df, include_moving=False):\n", |
99 | 119 | " \"\"\"Converts a dataframe of a performance into array a,b,dt format.\"\"\"\n",
|
100 | 120 | " perf_df['dt'] = perf_df.time.diff()\n",
|
101 | 121 | " perf_df.dt = perf_df.dt.fillna(0.0)\n",
|
102 | 122 | " # Clean performance data\n",
|
103 | 123 | " # Tiny Performance bounds defined to be in [[0,1],[0,1]], edit to fix this.\n",
|
104 |
| - " perf_df.set_value(perf_df[perf_df.dt > 5].index, 'dt', 5.0)\n", |
105 |
| - " perf_df.set_value(perf_df[perf_df.dt < 0].index, 'dt', 0.0)\n", |
106 |
| - " perf_df.set_value(perf_df[perf_df.x > 1].index, 'x', 1.0)\n", |
107 |
| - " perf_df.set_value(perf_df[perf_df.x < 0].index, 'x', 0.0)\n", |
108 |
| - " perf_df.set_value(perf_df[perf_df.y > 1].index, 'y', 1.0)\n", |
109 |
| - " perf_df.set_value(perf_df[perf_df.y < 0].index, 'y', 0.0)\n", |
110 |
| - " return np.array(perf_df[['x', 'y', 'dt']])\n", |
| 124 | + " perf_df.at[perf_df[perf_df.dt > 5].index, 'dt'] = 5.0\n", |
| 125 | + " perf_df.at[perf_df[perf_df.dt < 0].index, 'dt'] = 0.0\n", |
| 126 | + " perf_df.at[perf_df[perf_df.x > 1].index, 'x'] = 1.0\n", |
| 127 | + " perf_df.at[perf_df[perf_df.x < 0].index, 'x'] = 0.0\n", |
| 128 | + " perf_df.at[perf_df[perf_df.y > 1].index, 'y'] = 1.0\n", |
| 129 | + " perf_df.at[perf_df[perf_df.y < 0].index, 'y'] = 0.0\n", |
| 130 | + " if include_moving:\n", |
| 131 | + " output = np.array(perf_df[['x', 'y', 'dt', 'moving']])\n", |
| 132 | + " else:\n", |
| 133 | + " output = np.array(perf_df[['x', 'y', 'dt']])\n", |
| 134 | + " return output\n", |
111 | 135 | "\n",
|
112 | 136 | "\n",
|
113 | 137 | "def perf_array_to_df(perf_array):\n",
|
114 |
| - " \"\"\"Converts an array of a performance (a,b,dt format) into a dataframe.\"\"\"\n", |
| 138 | + " \"\"\"Converts an array of a performance (a,b,dt(,moving) format) into a dataframe.\"\"\"\n", |
115 | 139 | " perf_array = perf_array.T\n",
|
116 | 140 | " perf_df = pd.DataFrame({'x': perf_array[0], 'y': perf_array[1], 'dt': perf_array[2]})\n",
|
| 141 | + " if len(perf_array) == 4:\n", |
| 142 | + " perf_df['moving'] = perf_array[3]\n", |
| 143 | + " else:\n", |
| 144 | + " # As a rule of thumb, could classify taps with dt>0.1 as taps, dt<0.1 as moving touches.\n", |
| 145 | + " perf_df['moving'] = 1\n", |
| 146 | + " perf_df.at[perf_df[perf_df.dt > 0.1].index, 'moving'] = 0\n", |
117 | 147 | " perf_df['time'] = perf_df.dt.cumsum()\n",
|
118 | 148 | " perf_df['z'] = 38.0\n",
|
119 |
| - " # As a rule of thumb, could classify taps with dt>0.1 as taps, dt<0.1 as moving touches.\n", |
120 |
| - " perf_df['moving'] = 1\n", |
121 |
| - " perf_df.set_value(perf_df[perf_df.dt > 0.1].index, 'moving', 0)\n", |
122 | 149 | " perf_df = perf_df.set_index(['time'])\n",
|
123 | 150 | " return perf_df[['x', 'y', 'z', 'moving']]\n",
|
124 | 151 | "\n",
|
125 | 152 | "\n",
|
126 |
| - "def random_touch():\n", |
| 153 | + "def random_touch(with_moving=False):\n", |
127 | 154 | " \"\"\"Generate a random tiny performance touch.\"\"\"\n",
|
128 |
| - " return np.array([np.random.rand(), np.random.rand(), 0.01])\n", |
| 155 | + " if with_moving:\n", |
| 156 | + " return np.array([np.random.rand(), np.random.rand(), 0.01, 0])\n", |
| 157 | + " else:\n", |
| 158 | + " return np.array([np.random.rand(), np.random.rand(), 0.01])\n", |
129 | 159 | "\n",
|
130 | 160 | "\n",
|
131 |
| - "def constrain_touch(touch):\n", |
| 161 | + "def constrain_touch(touch, with_moving=False):\n", |
132 | 162 | " \"\"\"Constrain touch values from the MDRNN\"\"\"\n",
|
133 | 163 | " touch[0] = min(max(touch[0], 0.0), 1.0) # x in [0,1]\n",
|
134 | 164 | " touch[1] = min(max(touch[1], 0.0), 1.0) # y in [0,1]\n",
|
135 | 165 | " touch[2] = max(touch[2], 0.001) # dt # define minimum time step\n",
|
| 166 | + " if with_moving:\n", |
| 167 | + " touch[3] = np.greater(touch[3], 0.5) * 1.0\n", |
136 | 168 | " return touch\n",
|
137 | 169 | "\n",
|
138 |
| - "def generate_random_tiny_performance(model, n_mixtures, first_touch, time_limit=5.0, steps_limit=1000, temp=1.0):\n", |
| 170 | + "\n", |
| 171 | + "def generate_random_tiny_performance(model, n_mixtures, first_touch, time_limit=5.0, steps_limit=1000, temp=1.0, sigma_temp=0.0, predict_moving=False):\n", |
139 | 172 | " \"\"\"Generates a tiny performance up to 5 seconds in length.\"\"\"\n",
|
| 173 | + " if predict_moving:\n", |
| 174 | + " out_dim = 4\n", |
| 175 | + " else:\n", |
| 176 | + " out_dim = 3\n", |
140 | 177 | " time = 0\n",
|
141 | 178 | " steps = 0\n",
|
142 | 179 | " previous_touch = first_touch\n",
|
143 |
| - " performance = [previous_touch.reshape((3,))]\n", |
| 180 | + " performance = [previous_touch.reshape((out_dim,))]\n", |
144 | 181 | " while (steps < steps_limit and time < time_limit):\n",
|
145 |
| - " params = model.predict(previous_touch.reshape(1,1,3))\n", |
146 |
| - " previous_touch = mdn.sample_from_output(params[0], 3, n_mixtures, temp=temp)\n", |
147 |
| - " output_touch = previous_touch.reshape(3,)\n", |
148 |
| - " output_touch = constrain_touch(output_touch)\n", |
149 |
| - " performance.append(output_touch.reshape((3,)))\n", |
| 182 | + " params = model.predict(previous_touch.reshape(1,1,out_dim) * SCALE_FACTOR)\n", |
| 183 | + " previous_touch = mdn.sample_from_output(params[0], out_dim, n_mixtures, temp=temp, sigma_temp=sigma_temp) / SCALE_FACTOR\n", |
| 184 | + " output_touch = previous_touch.reshape(out_dim,)\n", |
| 185 | + " output_touch = constrain_touch(output_touch, with_moving=predict_moving)\n", |
| 186 | + " performance.append(output_touch.reshape((out_dim,)))\n", |
150 | 187 | " steps += 1\n",
|
151 | 188 | " time += output_touch[2]\n",
|
152 | 189 | " return np.array(performance)\n",
|
153 | 190 | "\n",
|
154 | 191 | "\n",
|
155 |
| - "def condition_and_generate(model, perf, n_mixtures, time_limit=5.0, steps_limit=1000, temp=1.0):\n", |
| 192 | + "def condition_and_generate(model, perf, n_mixtures, time_limit=5.0, steps_limit=1000, temp=1.0, sigma_temp=0.0, predict_moving=False):\n", |
156 | 193 | " \"\"\"Conditions the network on an existing tiny performance, then generates a new one.\"\"\"\n",
|
| 194 | + " if predict_moving:\n", |
| 195 | + " out_dim = 4\n", |
| 196 | + " else:\n", |
| 197 | + " out_dim = 3\n", |
157 | 198 | " time = 0\n",
|
158 | 199 | " steps = 0\n",
|
159 | 200 | " # condition\n",
|
160 | 201 | " for touch in perf:\n",
|
161 |
| - " params = model.predict(touch.reshape(1,1,3))\n", |
162 |
| - " previous_touch = mdn.sample_from_output(params[0], 3, n_mixtures, temp=temp)\n", |
163 |
| - " output = [previous_touch.reshape((3,))]\n", |
| 202 | + " params = model.predict(touch.reshape(1, 1, out_dim) * SCALE_FACTOR)\n", |
| 203 | + " previous_touch = mdn.sample_from_output(params[0], out_dim, n_mixtures, temp=temp, sigma_temp=sigma_temp) / SCALE_FACTOR\n", |
| 204 | + " output = [previous_touch.reshape((out_dim,))]\n", |
| 205 | + " # generate\n", |
164 | 206 | " while (steps < steps_limit and time < time_limit):\n",
|
165 |
| - " params = model.predict(previous_touch.reshape(1,1,3))\n", |
166 |
| - " previous_touch = mdn.sample_from_output(params[0], 3, n_mixtures, temp=temp)\n", |
167 |
| - " output_touch = previous_touch.reshape(3,)\n", |
168 |
| - " output_touch = constrain_touch(output_touch)\n", |
169 |
| - " output.append(output_touch.reshape((3,)))\n", |
| 207 | + " params = model.predict(previous_touch.reshape(1, 1, out_dim) * SCALE_FACTOR)\n", |
| 208 | + " previous_touch = mdn.sample_from_output(params[0], out_dim, n_mixtures, temp=temp, sigma_temp=sigma_temp) / SCALE_FACTOR\n", |
| 209 | + " output_touch = previous_touch.reshape(out_dim,)\n", |
| 210 | + " output_touch = constrain_touch(output_touch, with_moving=predict_moving)\n", |
| 211 | + " output.append(output_touch.reshape((out_dim,)))\n", |
170 | 212 | " steps += 1\n",
|
171 | 213 | " time += output_touch[2]\n",
|
172 | 214 | " net_output = np.array(output)\n",
|
173 | 215 | " return net_output\n",
|
174 | 216 | "\n",
|
| 217 | + "\n", |
175 | 218 | "def divide_performance_into_swipes(perf_df):\n",
|
176 | 219 | " \"\"\"Divides a performance into a sequence of swipe dataframes for plotting.\"\"\"\n",
|
177 | 220 | " touch_starts = perf_df[perf_df.moving == 0].index\n",
|
|
184 | 227 | " performance_swipes.append(remainder)\n",
|
185 | 228 | " return performance_swipes\n",
|
186 | 229 | "\n",
|
187 |
| - "def plot_2D(perf_df, name=\"foo\", saving=False):\n", |
| 230 | + "\n", |
| 231 | + "input_colour = 'darkblue'\n", |
| 232 | + "gen_colour = 'firebrick'\n", |
| 233 | + "\n", |
| 234 | + "\n", |
| 235 | + "def plot_2D(perf_df, name=\"foo\", saving=False, figsize=(8, 8)):\n", |
188 | 236 | " \"\"\"Plot a 2D representation of a performance 2D\"\"\"\n",
|
189 | 237 | " swipes = divide_performance_into_swipes(perf_df)\n",
|
190 |
| - " plt.figure(figsize=(8, 8))\n", |
| 238 | + " plt.figure(figsize=figsize)\n", |
191 | 239 | " for swipe in swipes:\n",
|
192 | 240 | " p = plt.plot(swipe.x, swipe.y, 'o-')\n",
|
193 | 241 | " plt.setp(p, color=gen_colour, linewidth=5.0)\n",
|
|
200 | 248 | " plt.close()\n",
|
201 | 249 | " else:\n",
|
202 | 250 | " plt.show()\n",
|
203 |
| - " \n", |
204 |
| - "def plot_double_2d(perf1, perf2, name=\"foo\", saving=False):\n", |
| 251 | + "\n", |
| 252 | + "\n", |
| 253 | + "def plot_double_2d(perf1, perf2, name=\"foo\", saving=False, figsize=(8, 8)):\n", |
205 | 254 | " \"\"\"Plot two performances in 2D\"\"\"\n",
|
206 |
| - " plt.figure(figsize=(8, 8))\n", |
| 255 | + " plt.figure(figsize=figsize)\n", |
207 | 256 | " swipes = divide_performance_into_swipes(perf1)\n",
|
208 | 257 | " for swipe in swipes:\n",
|
209 | 258 | " p = plt.plot(swipe.x, swipe.y, 'o-')\n",
|
|
387 | 436 | "outputs": [],
|
388 | 437 | "source": [
|
389 | 438 | "# Train the model\n",
|
390 |
| - "history = model.fit(X, y, batch_size=BATCH_SIZE, epochs=EPOCHS, validation_split=VAL_SPLIT)\n", |
| 439 | + "\n", |
| 440 | + "# Define callbacks\n", |
| 441 | + "filepath=\"robojam_mdrnn-E{epoch:02d}-VL{val_loss:.2f}.h5\"\n", |
| 442 | + "checkpoint = keras.callbacks.ModelCheckpoint(filepath, save_weights_only=True, verbose=1, save_best_only=True, mode='min')\n", |
| 443 | + "early_stopping = keras.callbacks.EarlyStopping(monitor='val_loss', mode='min', verbose=1, patience=10)\n", |
| 444 | + "callbacks = [keras.callbacks.TerminateOnNaN(), checkpoint, early_stopping]\n", |
| 445 | + "\n", |
| 446 | + "history = model.fit(X, y, batch_size=BATCH_SIZE, epochs=EPOCHS, callbacks=callbacks, validation_split=VAL_SPLIT)\n", |
391 | 447 | "\n",
|
392 | 448 | "# Save the Model\n",
|
393 |
| - "#model.save('robojam-mdn-rnn.h5') # creates a HDF5 file of the model\n", |
| 449 | + "model.save('robojam-mdrnn.h5') # creates a HDF5 file of the model\n", |
394 | 450 | "\n",
|
395 | 451 | "# Plot the loss\n",
|
396 | 452 | "%matplotlib inline\n",
|
|
428 | 484 | "decoder.summary()\n",
|
429 | 485 | "\n",
|
430 | 486 | "# decoder.set_weights(model.get_weights())\n",
|
431 |
| - "decoder.load_weights(\"robojam-mdn-rnn.h5\")" |
| 487 | + "decoder.load_weights(\"robojam-mdrnn.h5\")" |
432 | 488 | ]
|
433 | 489 | },
|
434 | 490 | {
|
|
451 | 507 | "ex = microjam_corpus[t:t+length] #sequences[600]\n",
|
452 | 508 | "\n",
|
453 | 509 | "decoder.reset_states()\n",
|
454 |
| - "p = condition_and_generate(decoder, ex, NUMBER_MIXTURES, temp=0.2)\n", |
| 510 | + "p = condition_and_generate(decoder, ex, NUMBER_MIXTURES, temp=1.0, sigma_temp=0.05)\n", |
455 | 511 | "plot_double_2d(perf_array_to_df(ex), perf_array_to_df(p))"
|
456 | 512 | ]
|
457 | 513 | },
|
|
472 | 528 | "source": [
|
473 | 529 | "decoder.reset_states()\n",
|
474 | 530 | "t = random_touch()\n",
|
475 |
| - "p = generate_random_tiny_performance(decoder, NUMBER_MIXTURES, t, temp=0.1)\n", |
| 531 | + "p = generate_random_tiny_performance(decoder, NUMBER_MIXTURES, t, temp=1.1, sigma_temp=0.05)\n", |
476 | 532 | "plot_2D(perf_array_to_df(p))"
|
477 | 533 | ]
|
478 | 534 | },
|
|
506 | 562 | "name": "python",
|
507 | 563 | "nbconvert_exporter": "python",
|
508 | 564 | "pygments_lexer": "ipython3",
|
509 |
| - "version": "3.6.6" |
| 565 | + "version": "3.6.7" |
510 | 566 | }
|
511 | 567 | },
|
512 | 568 | "nbformat": 4,
|
|
0 commit comments