diff --git a/your-code/Challenge_2_answer.PNG b/your-code/Challenge_2_answer.PNG
new file mode 100644
index 0000000..f30a43d
Binary files /dev/null and b/your-code/Challenge_2_answer.PNG differ
diff --git a/your-code/challenge-1.ipynb b/your-code/challenge-1.ipynb
index 2487c5f..50765e2 100644
--- a/your-code/challenge-1.ipynb
+++ b/your-code/challenge-1.ipynb
@@ -34,11 +34,126 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
- "# your code here"
+ "import tensorflow as tf\n",
+ "from keras.models import Sequential\n",
+ "from keras.layers import Dense\n",
+ "from keras import losses\n",
+ "import mnist\n",
+ "from sklearn.model_selection import train_test_split\n",
+ "import pandas as pd \n",
+ "import numpy as np"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "execute_result",
+ "data": {
+ "text/plain": [
+ "TL 0\n",
+ "TM 0\n",
+ "TR 0\n",
+ "ML 0\n",
+ "MM 0\n",
+ "MR 0\n",
+ "BL 0\n",
+ "BM 0\n",
+ "BR 0\n",
+ "class 0\n",
+ "dtype: int64"
+ ]
+ },
+ "metadata": {},
+ "execution_count": 3
+ }
+ ],
+ "source": [
+ "# your code here\n",
+ "df = pd.read_csv(r'C:\\Users\\Sebas!\\Documents\\GitHub\\lab-deep-learning\\your-code\\tic-tac-toe.csv')\n",
+ "\n",
+ "df.isnull().sum()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "execute_result",
+ "data": {
+ "text/plain": [
+ "TL object\n",
+ "TM object\n",
+ "TR object\n",
+ "ML object\n",
+ "MM object\n",
+ "MR object\n",
+ "BL object\n",
+ "BM object\n",
+ "BR object\n",
+ "class bool\n",
+ "dtype: object"
+ ]
+ },
+ "metadata": {},
+ "execution_count": 4
+ }
+ ],
+ "source": [
+ "df.dtypes"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df.replace('x', value =1,inplace=True)\n",
+ "df.replace('o', value =2,inplace=True)\n",
+ "df.replace('b', value= 0, inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "execute_result",
+ "data": {
+ "text/plain": [
+ " TL TM TR ML MM MR BL BM BR class\n",
+ "0 1 1 1 1 2 2 1 2 2 True\n",
+ "1 1 1 1 1 2 2 2 1 2 True\n",
+ "2 1 1 1 1 2 2 2 2 1 True\n",
+ "3 1 1 1 1 2 2 2 0 0 True\n",
+ "4 1 1 1 1 2 2 0 2 0 True\n",
+ ".. .. .. .. .. .. .. .. .. .. ...\n",
+ "953 2 1 1 1 2 2 2 1 1 False\n",
+ "954 2 1 2 1 1 2 1 2 1 False\n",
+ "955 2 1 2 1 2 1 1 2 1 False\n",
+ "956 2 1 2 2 1 1 1 2 1 False\n",
+ "957 2 2 1 1 1 2 2 1 1 False\n",
+ "\n",
+ "[958 rows x 10 columns]"
+ ],
+ "text/html": "
\n\n
\n \n \n | \n TL | \n TM | \n TR | \n ML | \n MM | \n MR | \n BL | \n BM | \n BR | \n class | \n
\n \n \n \n | 0 | \n 1 | \n 1 | \n 1 | \n 1 | \n 2 | \n 2 | \n 1 | \n 2 | \n 2 | \n True | \n
\n \n | 1 | \n 1 | \n 1 | \n 1 | \n 1 | \n 2 | \n 2 | \n 2 | \n 1 | \n 2 | \n True | \n
\n \n | 2 | \n 1 | \n 1 | \n 1 | \n 1 | \n 2 | \n 2 | \n 2 | \n 2 | \n 1 | \n True | \n
\n \n | 3 | \n 1 | \n 1 | \n 1 | \n 1 | \n 2 | \n 2 | \n 2 | \n 0 | \n 0 | \n True | \n
\n \n | 4 | \n 1 | \n 1 | \n 1 | \n 1 | \n 2 | \n 2 | \n 0 | \n 2 | \n 0 | \n True | \n
\n \n | ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n
\n \n | 953 | \n 2 | \n 1 | \n 1 | \n 1 | \n 2 | \n 2 | \n 2 | \n 1 | \n 1 | \n False | \n
\n \n | 954 | \n 2 | \n 1 | \n 2 | \n 1 | \n 1 | \n 2 | \n 1 | \n 2 | \n 1 | \n False | \n
\n \n | 955 | \n 2 | \n 1 | \n 2 | \n 1 | \n 2 | \n 1 | \n 1 | \n 2 | \n 1 | \n False | \n
\n \n | 956 | \n 2 | \n 1 | \n 2 | \n 2 | \n 1 | \n 1 | \n 1 | \n 2 | \n 1 | \n False | \n
\n \n | 957 | \n 2 | \n 2 | \n 1 | \n 1 | \n 1 | \n 2 | \n 2 | \n 1 | \n 1 | \n False | \n
\n \n
\n
958 rows × 10 columns
\n
"
+ },
+ "metadata": {},
+ "execution_count": 6
+ }
+ ],
+ "source": [
+ "df"
]
},
{
@@ -60,11 +175,165 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "execute_result",
+ "data": {
+ "text/plain": [
+ "Index(['TL', 'TM', 'TR', 'ML', 'MM', 'MR', 'BL', 'BM', 'BR', 'class'], dtype='object')"
+ ]
+ },
+ "metadata": {},
+ "execution_count": 7
+ }
+ ],
+ "source": [
+ "df.columns"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df_randomized = df.sample(frac=1).reset_index(drop=True) #This randomize the entire dataset "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
- "# your code here"
+ "# your code here\n",
+ "\n",
+ "'''I was practically copying-pasting the documentation https://www.tensorflow.org/tutorials/load_data/pandas_dataframe since we had the same situation, but it gave me a lot of problems when we reach the training step, the main issue was the shape for the features and the layers they MUST be the same due something called scalar values.\n",
+ "\n",
+ "My solution to this issue is, since the shape of the features where (9, 2) and the labels where (None,1) I decided to reshape the labels by adding two layers, one for shape and another one applied also to the features due the scalar value'''\n",
+ "\n",
+ "features_train = tf.data.Dataset.from_tensor_slices(df_randomized[['TL', 'TM', 'TR', 'ML', 'MM', 'MR', 'BL', 'BM', 'BR']][:670].values)\n",
+ "label_train = tf.data.Dataset.from_tensor_slices(df_randomized['class'][:670].values).batch(1) #layer 2\n",
+ "\n",
+ "features_test = tf.data.Dataset.from_tensor_slices(df_randomized[['TL', 'TM', 'TR', 'ML', 'MM', 'MR', 'BL', 'BM', 'BR']][670:].values)\n",
+ "label_test = tf.data.Dataset.from_tensor_slices(df_randomized['class'][670:].values).batch(1)\n",
+ "\n",
+ "dataset_train_no_scalar = tf.data.Dataset.zip((features_train, label_train))\n",
+ "dataset_test_no_scalar = tf.data.Dataset.zip((features_test, label_test))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "Features: [0 2 1 0 2 0 1 2 1], Target: [False]\nFeatures: [2 0 2 1 1 1 2 1 0], Target: [ True]\nFeatures: [1 1 2 2 1 1 1 2 2], Target: [False]\nFeatures: [1 0 2 1 2 1 1 0 2], Target: [ True]\nFeatures: [1 1 1 2 2 1 0 0 2], Target: [ True]\n"
+ ]
+ }
+ ],
+ "source": [
+ "for feat, targ in dataset_train_no_scalar.take(5):\n",
+ " print ('Features: {}, Target: {}'.format(feat, targ))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "Features: [[0 2 1 0 2 0 1 2 1]], Target: [[False]]\nFeatures: [[2 0 2 1 1 1 2 1 0]], Target: [[ True]]\nFeatures: [[1 1 2 2 1 1 1 2 2]], Target: [[False]]\nFeatures: [[1 0 2 1 2 1 1 0 2]], Target: [[ True]]\nFeatures: [[1 1 1 2 2 1 0 0 2]], Target: [[ True]]\n"
+ ]
+ }
+ ],
+ "source": [
+ "train_dataset = dataset_train_no_scalar.batch(1) # extra layer for scalar value\n",
+ "test_dataset = dataset_test_no_scalar.batch(1)\n",
+ "\n",
+ "for feat, targ in train_dataset.take(5):\n",
+ " print ('Features: {}, Target: {}'.format(feat, targ))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "Epoch 1/5\n",
+ "670/670 [==============================] - 1s 854us/step - loss: 0.6427 - accuracy: 0.5030\n",
+ "Epoch 2/5\n",
+ "670/670 [==============================] - 1s 883us/step - loss: 0.6427 - accuracy: 0.5134\n",
+ "Epoch 3/5\n",
+ "670/670 [==============================] - 1s 886us/step - loss: 0.6427 - accuracy: 0.5075\n",
+ "Epoch 4/5\n",
+ "670/670 [==============================] - 1s 841us/step - loss: 0.6427 - accuracy: 0.5104\n",
+ "Epoch 5/5\n",
+ "670/670 [==============================] - 1s 841us/step - loss: 0.6427 - accuracy: 0.5149\n"
+ ]
+ },
+ {
+ "output_type": "execute_result",
+ "data": {
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "execution_count": 14
+ }
+ ],
+ "source": [
+ "def get_compiled_model(): \n",
+ " model = tf.keras.Sequential([\n",
+ " tf.keras.layers.Flatten(),\n",
+ " tf.keras.layers.Dense(128, activation=tf.nn.relu),\n",
+ " tf.keras.layers.Dense(128, activation=tf.nn.relu),\n",
+ " tf.keras.layers.Dense(128, activation=tf.nn.relu),\n",
+ " tf.keras.layers.Dense(128, activation=tf.nn.relu),\n",
+ " tf.keras.layers.Dense(128, activation=tf.nn.relu),\n",
+ "\n",
+ " tf.keras.layers.Dense(2, activation=tf.nn.softmax)\n",
+ " ])\n",
+ "\n",
+ " model.compile(optimizer='adam',\n",
+ " loss=tf.keras.losses.BinaryCrossentropy(from_logits=True), #https://keras.io/api/losses/probabilistic_losses/#sparse_categorical_crossentropy-function\n",
+ " metrics=['accuracy'])\n",
+ " return model\n",
+ "\n",
+ "model = get_compiled_model()\n",
+ "model.fit(train_dataset, epochs= 5)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "288/288 [==============================] - 0s 499us/step - loss: 0.6581 - accuracy: 0.0729\n"
+ ]
+ }
+ ],
+ "source": [
+ "val_loss, val_acc = model.evaluate(test_dataset)"
]
},
{
@@ -78,11 +347,55 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 13,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# your code here\n",
+ "#model.save('tic_tac_toe.model')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "new_model = tf.keras.models.load_model('tic_tac_toe.model')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
- "# your code here"
+ "prediction = new_model.predict([df_randomized[['TL', 'TM', 'TR', 'ML', 'MM', 'MR', 'BL', 'BM', 'BR']][670:]])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "108 incorrect predictions out of 288 predictions 37.5 %\n"
+ ]
+ }
+ ],
+ "source": [
+ "test = df_randomized['class'][670:].values\n",
+ "wrong_predictions = 0\n",
+ "for n in range(0,len(test)):\n",
+ " predicted_value = bool(np.argmax(prediction[n]))\n",
+ " if predicted_value != test[n]:\n",
+ " #print('Prediction:',predicted_value,' Real data:',test[n], ' In row:', n)\n",
+ " wrong_predictions += 1\n",
+ "\n",
+ "print(wrong_predictions,'incorrect predictions out of',len(test),'predictions', wrong_predictions*100/len(test),'%')"
]
},
{
@@ -104,11 +417,83 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 18,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# your code here\n",
+ "new_model.add( tf.keras.layers.Dense(128, activation=tf.nn.relu, name='new_layer_1') )\n",
+ "new_model.add(tf.keras.layers.Flatten(name='new_flattener'))\n",
+ "new_model.add( tf.keras.layers.Dense(2, activation=tf.nn.relu, name='new_output_layer') )\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 19,
"metadata": {},
"outputs": [],
"source": [
- "# your code here"
+ "new_model.compile(optimizer= tf.keras.optimizers.Adam(learning_rate=0.003, \n",
+ " beta_1=0.9, beta_2=0.999, \n",
+ " epsilon=1e-07, \n",
+ " amsgrad=False),\n",
+ " loss=tf.keras.losses.BinaryCrossentropy(from_logits=True), \n",
+ " metrics=['accuracy'])\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "Epoch 1/5\n",
+ "670/670 [==============================] - 1s 953us/step - loss: 0.6525 - accuracy: 0.4239\n",
+ "Epoch 2/5\n",
+ "670/670 [==============================] - 1s 955us/step - loss: 0.6490 - accuracy: 0.7030\n",
+ "Epoch 3/5\n",
+ "670/670 [==============================] - 1s 961us/step - loss: 0.6486 - accuracy: 0.7463\n",
+ "Epoch 4/5\n",
+ "670/670 [==============================] - 1s 1ms/step - loss: 0.6483 - accuracy: 0.7687\n",
+ "Epoch 5/5\n",
+ "670/670 [==============================] - 1s 992us/step - loss: 0.6481 - accuracy: 0.7731\n"
+ ]
+ },
+ {
+ "output_type": "execute_result",
+ "data": {
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "execution_count": 20
+ }
+ ],
+ "source": [
+ "new_model.fit(train_dataset, epochs= 5) "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "288/288 [==============================] - 0s 589us/step - loss: 0.6931 - accuracy: 1.0000\n"
+ ]
+ }
+ ],
+ "source": [
+ "val_loss, val_acc = new_model.evaluate(test_dataset)"
]
},
{
@@ -120,19 +505,19 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 21,
"metadata": {},
"outputs": [],
"source": [
- "# your answer here"
+ "# your answer here\n",
+ "# by trial and error, I suspected that since the learning rate was very low I should be more reserved in increasing it and I believe that I was reaching an overfitting if it was added another layer."
]
}
],
"metadata": {
"kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
+ "name": "python385jvsc74a57bd09efc80705562ef6f8028ba9c07828938c290468cbec0ebcf2b44f68ee94d478d",
+ "display_name": "Python 3.8.5 64-bit"
},
"language_info": {
"codemirror_mode": {
@@ -144,9 +529,9 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.7.3"
+ "version": "3.8.5"
}
},
"nbformat": 4,
"nbformat_minor": 2
-}
+}
\ No newline at end of file
diff --git a/your-code/tic_tac_toe.model/keras_metadata.pb b/your-code/tic_tac_toe.model/keras_metadata.pb
new file mode 100644
index 0000000..c9a1800
--- /dev/null
+++ b/your-code/tic_tac_toe.model/keras_metadata.pb
@@ -0,0 +1,11 @@
+
+‹<root"_tf_keras_sequential*æ;{"name": "sequential", "trainable": true, "expects_training_arg": true, "dtype": "float32", "batch_input_shape": null, "must_restore_from_config": false, "class_name": "Sequential", "config": {"name": "sequential", "layers": [{"class_name": "InputLayer", "config": {"batch_input_shape": {"class_name": "__tuple__", "items": [null, 9]}, "dtype": "int64", "sparse": false, "ragged": false, "name": "flatten_input"}}, {"class_name": "Flatten", "config": {"name": "flatten", "trainable": true, "dtype": "float32", "data_format": "channels_last"}}, {"class_name": "Dense", "config": {"name": "dense", "trainable": true, "dtype": "float32", "units": 128, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}, {"class_name": "Dense", "config": {"name": "dense_1", "trainable": true, "dtype": "float32", "units": 128, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}, {"class_name": "Dense", "config": {"name": "dense_2", "trainable": true, "dtype": "float32", "units": 128, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}, {"class_name": "Dense", "config": {"name": "dense_3", "trainable": true, "dtype": "float32", "units": 128, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}, {"class_name": "Dense", "config": {"name": "dense_4", "trainable": true, "dtype": "float32", "units": 128, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}, {"class_name": "Dense", "config": {"name": "dense_5", "trainable": true, "dtype": "float32", "units": 2, "activation": "softmax", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}]}, "shared_object_id": 20, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 1, "axes": {}}, "shared_object_id": 21}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 9]}, "is_graph_network": true, "save_spec": {"class_name": "TypeSpec", "type_spec": "tf.TensorSpec", "serialized": [{"class_name": "TensorShape", "items": [null, 9]}, "int64", "flatten_input"]}, "keras_version": "2.5.0", "backend": "tensorflow", "model_config": {"class_name": "Sequential", "config": {"name": "sequential", "layers": [{"class_name": "InputLayer", "config": {"batch_input_shape": {"class_name": "__tuple__", "items": [null, 9]}, "dtype": "int64", "sparse": false, "ragged": false, "name": "flatten_input"}, "shared_object_id": 0}, {"class_name": "Flatten", "config": {"name": "flatten", "trainable": true, "dtype": "float32", "data_format": "channels_last"}, "shared_object_id": 1}, {"class_name": "Dense", "config": {"name": "dense", "trainable": true, "dtype": "float32", "units": 128, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 2}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 3}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 4}, {"class_name": "Dense", "config": {"name": "dense_1", "trainable": true, "dtype": "float32", "units": 128, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 5}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 6}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 7}, {"class_name": "Dense", "config": {"name": "dense_2", "trainable": true, "dtype": "float32", "units": 128, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 8}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 9}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 10}, {"class_name": "Dense", "config": {"name": "dense_3", "trainable": true, "dtype": "float32", "units": 128, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 11}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 12}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 13}, {"class_name": "Dense", "config": {"name": "dense_4", "trainable": true, "dtype": "float32", "units": 128, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 14}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 15}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 16}, {"class_name": "Dense", "config": {"name": "dense_5", "trainable": true, "dtype": "float32", "units": 2, "activation": "softmax", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 17}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 18}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 19}]}}, "training_config": {"loss": {"class_name": "BinaryCrossentropy", "config": {"reduction": "auto", "name": "binary_crossentropy", "from_logits": true, "label_smoothing": 0}, "shared_object_id": 22}, "metrics": [[{"class_name": "MeanMetricWrapper", "config": {"name": "accuracy", "dtype": "float32", "fn": "categorical_accuracy"}, "shared_object_id": 23}]], "weighted_metrics": null, "loss_weights": null, "optimizer_config": {"class_name": "Adam", "config": {"name": "Adam", "learning_rate": 0.0010000000474974513, "decay": 0.0, "beta_1": 0.8999999761581421, "beta_2": 0.9990000128746033, "epsilon": 1e-07, "amsgrad": false}}}}2
+’root.layer-0"_tf_keras_layer*è{"name": "flatten", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Flatten", "config": {"name": "flatten", "trainable": true, "dtype": "float32", "data_format": "channels_last"}, "shared_object_id": 1, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 1, "axes": {}}, "shared_object_id": 21}}2
+Àroot.layer_with_weights-0"_tf_keras_layer*‰{"name": "dense", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Dense", "config": {"name": "dense", "trainable": true, "dtype": "float32", "units": 128, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 2}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 3}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 4, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 2, "axes": {"-1": 9}}, "shared_object_id": 24}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 9]}}2
+Èroot.layer_with_weights-1"_tf_keras_layer*‘{"name": "dense_1", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Dense", "config": {"name": "dense_1", "trainable": true, "dtype": "float32", "units": 128, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 5}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 6}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 7, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 2, "axes": {"-1": 128}}, "shared_object_id": 25}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 128]}}2
+Éroot.layer_with_weights-2"_tf_keras_layer*’{"name": "dense_2", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Dense", "config": {"name": "dense_2", "trainable": true, "dtype": "float32", "units": 128, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 8}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 9}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 10, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 2, "axes": {"-1": 128}}, "shared_object_id": 26}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 128]}}2
+Ëroot.layer_with_weights-3"_tf_keras_layer*”{"name": "dense_3", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Dense", "config": {"name": "dense_3", "trainable": true, "dtype": "float32", "units": 128, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 11}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 12}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 13, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 2, "axes": {"-1": 128}}, "shared_object_id": 27}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 128]}}2
+Ëroot.layer_with_weights-4"_tf_keras_layer*”{"name": "dense_4", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Dense", "config": {"name": "dense_4", "trainable": true, "dtype": "float32", "units": 128, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 14}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 15}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 16, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 2, "axes": {"-1": 128}}, "shared_object_id": 28}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 128]}}2
+Ìroot.layer_with_weights-5"_tf_keras_layer*•{"name": "dense_5", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Dense", "config": {"name": "dense_5", "trainable": true, "dtype": "float32", "units": 2, "activation": "softmax", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 17}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 18}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 19, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 2, "axes": {"-1": 128}}, "shared_object_id": 29}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 128]}}2
+¹croot.keras_api.metrics.0"_tf_keras_metric*‚{"class_name": "Mean", "name": "loss", "dtype": "float32", "config": {"name": "loss", "dtype": "float32"}, "shared_object_id": 30}2
+ìdroot.keras_api.metrics.1"_tf_keras_metric*µ{"class_name": "MeanMetricWrapper", "name": "accuracy", "dtype": "float32", "config": {"name": "accuracy", "dtype": "float32", "fn": "categorical_accuracy"}, "shared_object_id": 23}2
\ No newline at end of file
diff --git a/your-code/tic_tac_toe.model/saved_model.pb b/your-code/tic_tac_toe.model/saved_model.pb
new file mode 100644
index 0000000..0da4829
Binary files /dev/null and b/your-code/tic_tac_toe.model/saved_model.pb differ
diff --git a/your-code/tic_tac_toe.model/variables/variables.data-00000-of-00001 b/your-code/tic_tac_toe.model/variables/variables.data-00000-of-00001
new file mode 100644
index 0000000..ae7192e
Binary files /dev/null and b/your-code/tic_tac_toe.model/variables/variables.data-00000-of-00001 differ
diff --git a/your-code/tic_tac_toe.model/variables/variables.index b/your-code/tic_tac_toe.model/variables/variables.index
new file mode 100644
index 0000000..27e5047
Binary files /dev/null and b/your-code/tic_tac_toe.model/variables/variables.index differ