Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save svpino/a27f8039ce54c27b1c493ee866ee8d69 to your computer and use it in GitHub Desktop.
Save svpino/a27f8039ce54c27b1c493ee866ee8d69 to your computer and use it in GitHub Desktop.
Multiplying values using a neural network in Keras and TensorFlow 2
Display the source blob
Display the rendered blob
Raw
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "multiplying-values-using-neural-networks-keras.ipynb",
"provenance": [],
"collapsed_sections": [],
"include_colab_link": true
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
}
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/gist/svpino/a27f8039ce54c27b1c493ee866ee8d69/multiplying-values-using-neural-networks-keras.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "code",
"metadata": {
"id": "z_qGVgfrAbJv",
"colab_type": "code",
"colab": {}
},
"source": [
"try:\n",
" %tensorflow_version 2.x\n",
"except Exception:\n",
" pass\n",
"\n",
"import tensorflow as tf\n",
"\n",
"import numpy as np\n",
"import logging\n",
"import matplotlib.pyplot as plt\n",
"\n",
"logger = tf.get_logger()\n",
"logger.setLevel(logging.ERROR)"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "lIXH9TIHP4Fe",
"colab_type": "code",
"outputId": "5247a2a0-8cdd-44dc-caa2-f37ef81a11e3",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 652
}
},
"source": [
"DATASET_TRAINING_SIZE = 100\n",
"DATASET_TESTING_SIZE = 1000\n",
"NUMBER_OF_ELEMENTS_TO_PRINT = 5\n",
"\n",
"# Let's first generate the training dataset. We are going to generate \n",
"# a set of values ranging from 'low' to 'high'.\n",
"X = np.random.randint(low=1, high=9, size=(DATASET_TRAINING_SIZE, 2))\n",
"\n",
"# We can determine the training labels by multiplying each pair generated\n",
"# before.\n",
"y = np.prod(X, axis=1).reshape(DATASET_TRAINING_SIZE, 1)\n",
"\n",
"# Since we are trying to approximate multiplication, we know there will \n",
"# be a lot of variance in the results. Also, multipliying numbers can \n",
"# really quickly spin out network out of control. We can minimize this \n",
"# problem by normalizing the input values. In this case, we are using\n",
"# log normalization.\n",
"X = np.log(X)\n",
"\n",
"# Let's setup our network. \n",
"model = tf.keras.Sequential([\n",
" tf.keras.layers.Dense(units=4, input_shape=(2,)),\n",
" tf.keras.layers.Dense(units=4, activation=\"relu\"),\n",
" tf.keras.layers.Dense(units=1)\n",
"])\n",
"\n",
"model.compile(loss='mean_squared_error', \n",
" optimizer=tf.keras.optimizers.Adam(0.01))\n",
"\n",
"# Let's start training our network using the generated training set.\n",
"history = model.fit(X, y, epochs=250, batch_size=10, verbose=False)\n",
"\n",
"# At this point we already have our model fully trained. We can now \n",
"# generate some testing data (using the same method we used to generate\n",
"# our training data).\n",
"X_test = np.random.randint(low=1, high=9, size=(DATASET_TESTING_SIZE, 2))\n",
"y_test = np.prod(X_test, axis=1).reshape(DATASET_TESTING_SIZE, 1)\n",
"\n",
"# Before applying the log normalization to the training data, let's\n",
"# print a few of the pairs.\n",
"print(f\"X_test:\\n{X_test[:NUMBER_OF_ELEMENTS_TO_PRINT]}\")\n",
"print(f\"y_test:\\n{y_test[:NUMBER_OF_ELEMENTS_TO_PRINT]}\")\n",
"\n",
"# We can now apply log normalization to the training data.\n",
"X_test = np.log(X_test)\n",
"\n",
"# Let's run inference on the testing dataset.\n",
"predictions = model.predict(X_test)\n",
"print(f\"Predictions:\\n{predictions[:NUMBER_OF_ELEMENTS_TO_PRINT]}\")\n",
"\n",
"# To see how we did, we can compute the RMSE on the results of the\n",
"# testing dataset\n",
"rmse = np.sqrt(np.mean((predictions - y_test)**2))\n",
"print(f\"\\nRMSE: {rmse}\")\n",
"\n",
"# Finally, we can plot the loss during training. \n",
"plt.title(\"Loss\")\n",
"plt.xlabel('Epoch')\n",
"plt.ylabel(\"Loss\")\n",
"plt.plot(history.history['loss'])"
],
"execution_count": 0,
"outputs": [
{
"output_type": "stream",
"text": [
"X_test:\n",
"[[4 3]\n",
" [8 3]\n",
" [5 8]\n",
" [6 1]\n",
" [3 8]]\n",
"y_test:\n",
"[[12]\n",
" [24]\n",
" [40]\n",
" [ 6]\n",
" [24]]\n",
"Predictions:\n",
"[[10.943055]\n",
" [23.558733]\n",
" [40.33994 ]\n",
" [ 6.702338]\n",
" [23.941874]]\n",
"\n",
"RMSE: 0.8370817671559032\n"
],
"name": "stdout"
},
{
"output_type": "execute_result",
"data": {
"text/plain": [
"[<matplotlib.lines.Line2D at 0x7f99b16c1d30>]"
]
},
"metadata": {
"tags": []
},
"execution_count": 4
},
{
"output_type": "display_data",
"data": {
"image/png": "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\nAElFTkSuQmCC\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"tags": []
}
}
]
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment