From 3949ebeecbe84669f09f1984ef91741d485b4b6f Mon Sep 17 00:00:00 2001 From: SurajSSingh <surajss@uci.edu> Date: Thu, 12 May 2022 22:48:51 -0700 Subject: [PATCH] Finalizing Update to Code and Models --- .gitignore | 1 + .model/attention/keras_metadata.pb | 20 +- .model/attention/saved_model.pb | Bin 126157 -> 144170 bytes .../variables/variables.data-00000-of-00001 | Bin 9432 -> 16170 bytes .model/attention/variables/variables.index | Bin 814 -> 1599 bytes .model/attention_model.tflite | Bin 0 -> 8448 bytes alarm.py | 11 +- simple_alarm_clock.py | 90 +++- smart_alarm_clock mac_copy.py | 178 ++++++++ smart_alarm_clock.py | 192 ++++++-- tf_model.ipynb | 431 +++++++++++++++--- 11 files changed, 793 insertions(+), 130 deletions(-) create mode 100644 .model/attention_model.tflite create mode 100644 smart_alarm_clock mac_copy.py diff --git a/.gitignore b/.gitignore index 988c81e..6c0f027 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ .data/ *.pyc colab_copy.ipynb +.model/Viennese Poets.mp3 diff --git a/.model/attention/keras_metadata.pb b/.model/attention/keras_metadata.pb index 1306f14..7237968 100755 --- a/.model/attention/keras_metadata.pb +++ b/.model/attention/keras_metadata.pb @@ -1,15 +1,15 @@ -ÿ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, 10, 7]}, "dtype": "float32", "sparse": false, "ragged": false, "name": "input_1"}}, {"class_name": "CustomAttention", "config": {"name": "custom_attention", "trainable": true, "dtype": "float32", "units": 32}}, {"class_name": "Dense", "config": {"name": "dense", "trainable": true, "dtype": "float32", "units": 4, "activation": "linear", "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": 5, "input_spec": [{"class_name": "InputSpec", "config": {"dtype": null, "shape": {"class_name": "__tuple__", "items": [null, 10, 7]}, "ndim": 3, "max_ndim": null, "min_ndim": null, "axes": {}}}], "build_input_shape": {"class_name": "TensorShape", "items": [null, 10, 7]}, "is_graph_network": true, "full_save_spec": {"class_name": "__tuple__", "items": [[{"class_name": "TypeSpec", "type_spec": "tf.TensorSpec", "serialized": [{"class_name": "TensorShape", "items": [null, 10, 7]}, "float32", "input_1"]}], {}]}, "save_spec": {"class_name": "TypeSpec", "type_spec": "tf.TensorSpec", "serialized": [{"class_name": "TensorShape", "items": [null, 10, 7]}, "float32", "input_1"]}, "keras_version": "2.8.0", "backend": "tensorflow", "model_config": {"class_name": "Sequential", "config": {"name": "sequential", "layers": [{"class_name": "InputLayer", "config": {"batch_input_shape": {"class_name": "__tuple__", "items": [null, 10, 7]}, "dtype": "float32", "sparse": false, "ragged": false, "name": "input_1"}, "shared_object_id": 0}, {"class_name": "CustomAttention", "config": {"name": "custom_attention", "trainable": true, "dtype": "float32", "units": 32}, "shared_object_id": 1}, {"class_name": "Dense", "config": {"name": "dense", "trainable": true, "dtype": "float32", "units": 4, "activation": "linear", "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}]}}, "training_config": {"loss": {"class_name": "CategoricalCrossentropy", "config": {"reduction": "auto", "name": "categorical_crossentropy", "from_logits": true, "label_smoothing": 0.0, "axis": -1}, "shared_object_id": 7}, "metrics": [[{"class_name": "CategoricalCrossentropy", "config": {"name": "categorical_crossentropy", "dtype": "float32", "from_logits": true, "label_smoothing": 0}, "shared_object_id": 8}, {"class_name": "CategoricalAccuracy", "config": {"name": "categorical_accuracy", "dtype": "float32"}, "shared_object_id": 9}, {"class_name": "CategoricalHinge", "config": {"name": "categorical_hinge", "dtype": "float32"}, "shared_object_id": 10}]], "weighted_metrics": null, "loss_weights": null, "optimizer_config": {"class_name": "Adam", "config": {"name": "Adam", "learning_rate": 0.001, "decay": 0.0, "beta_1": 0.9, "beta_2": 0.999, "epsilon": 1e-07, "amsgrad": false}}}}2 -Éroot.layer_with_weights-0"_tf_keras_layer*’{"name": "custom_attention", "trainable": true, "expects_training_arg": true, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "CustomAttention", "config": {"name": "custom_attention", "trainable": true, "dtype": "float32", "units": 32}, "shared_object_id": 1, "build_input_shape": {"class_name": "TensorShape", "items": [null, 10, 7]}}2 -Âroot.layer_with_weights-1"_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": 4, "activation": "linear", "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": 32}}, "shared_object_id": 11}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 32]}}2 -ø-root.layer_with_weights-0.attention_score_vec"_tf_keras_layer*{"name": "attention_score_vec", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Dense", "config": {"name": "attention_score_vec", "trainable": true, "dtype": "float32", "units": 7, "activation": "linear", "use_bias": false, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 12}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 13}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 14, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 2, "axes": {"-1": 7}}, "shared_object_id": 15}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 10, 7]}}2 +³root"_tf_keras_sequential*Ž{"name": "sequential_1", "trainable": true, "expects_training_arg": true, "dtype": "float32", "batch_input_shape": null, "must_restore_from_config": false, "class_name": "Sequential", "config": {"name": "sequential_1", "layers": [{"class_name": "InputLayer", "config": {"batch_input_shape": {"class_name": "__tuple__", "items": [null, 5, 7]}, "dtype": "float32", "sparse": false, "ragged": false, "name": "input_2"}}, {"class_name": "CustomAttention", "config": {"name": "custom_attention_1", "trainable": true, "dtype": "float32", "units": 32}}, {"class_name": "Dense", "config": {"name": "dense_1", "trainable": true, "dtype": "float32", "units": 4, "activation": "linear", "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": 5, "input_spec": [{"class_name": "InputSpec", "config": {"dtype": null, "shape": {"class_name": "__tuple__", "items": [null, 5, 7]}, "ndim": 3, "max_ndim": null, "min_ndim": null, "axes": {}}}], "build_input_shape": {"class_name": "TensorShape", "items": [null, 5, 7]}, "is_graph_network": true, "full_save_spec": {"class_name": "__tuple__", "items": [[{"class_name": "TypeSpec", "type_spec": "tf.TensorSpec", "serialized": [{"class_name": "TensorShape", "items": [null, 5, 7]}, "float32", "input_2"]}], {}]}, "save_spec": {"class_name": "TypeSpec", "type_spec": "tf.TensorSpec", "serialized": [{"class_name": "TensorShape", "items": [null, 5, 7]}, "float32", "input_2"]}, "keras_version": "2.8.0", "backend": "tensorflow", "model_config": {"class_name": "Sequential", "config": {"name": "sequential_1", "layers": [{"class_name": "InputLayer", "config": {"batch_input_shape": {"class_name": "__tuple__", "items": [null, 5, 7]}, "dtype": "float32", "sparse": false, "ragged": false, "name": "input_2"}, "shared_object_id": 0}, {"class_name": "CustomAttention", "config": {"name": "custom_attention_1", "trainable": true, "dtype": "float32", "units": 32}, "shared_object_id": 1}, {"class_name": "Dense", "config": {"name": "dense_1", "trainable": true, "dtype": "float32", "units": 4, "activation": "linear", "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}]}}, "training_config": {"loss": {"class_name": "CategoricalCrossentropy", "config": {"reduction": "auto", "name": "categorical_crossentropy", "from_logits": true, "label_smoothing": 0.0, "axis": -1}, "shared_object_id": 7}, "metrics": [[{"class_name": "CategoricalCrossentropy", "config": {"name": "categorical_crossentropy", "dtype": "float32", "from_logits": true, "label_smoothing": 0}, "shared_object_id": 8}, {"class_name": "CategoricalAccuracy", "config": {"name": "categorical_accuracy", "dtype": "float32"}, "shared_object_id": 9}, {"class_name": "CategoricalHinge", "config": {"name": "categorical_hinge", "dtype": "float32"}, "shared_object_id": 10}]], "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_with_weights-0"_tf_keras_layer*•{"name": "custom_attention_1", "trainable": true, "expects_training_arg": true, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "CustomAttention", "config": {"name": "custom_attention_1", "trainable": true, "dtype": "float32", "units": 32}, "shared_object_id": 1, "build_input_shape": {"class_name": "TensorShape", "items": [null, 5, 7]}}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": 4, "activation": "linear", "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": 32}}, "shared_object_id": 11}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 32]}}2 +÷-root.layer_with_weights-0.attention_score_vec"_tf_keras_layer*¬{"name": "attention_score_vec", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Dense", "config": {"name": "attention_score_vec", "trainable": true, "dtype": "float32", "units": 7, "activation": "linear", "use_bias": false, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 12}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 13}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 14, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 2, "axes": {"-1": 7}}, "shared_object_id": 15}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 5, 7]}}2 Ý root.layer_with_weights-0.h_t"_tf_keras_layer*¢{"name": "last_hidden_state", "trainable": true, "expects_training_arg": true, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Lambda", "config": {"name": "last_hidden_state", "trainable": true, "dtype": "float32", "function": {"class_name": "__tuple__", "items": ["4wEAAAAAAAAAAAAAAAEAAAAFAAAAUwAAAHMWAAAAfABkAGQAhQJkAWQAZACFAmYDGQBTACkCTun/\n////qQApAdoBeHICAAAAcgIAAAD6TS9Vc2Vycy9ub3dhZG1pbi9Eb2N1bWVudHMvU2Nob29sIEZv\nbGRlci9DUyA0MzcvTGFiL0ZpbmFsIFByb2plY3QvYXR0ZW50aW9uLnB52gg8bGFtYmRhPhoAAABz\nAgAAABYA\n", null, null]}, "function_type": "lambda", "module": "attention", "output_shape": {"class_name": "__tuple__", "items": [7]}, "output_shape_type": "raw", "output_shape_module": null, "arguments": {}}, "shared_object_id": 16}2 -™)root.layer_with_weights-0.attention_score"_tf_keras_layer*Ò{"name": "attention_score", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Dot", "config": {"name": "attention_score", "trainable": true, "dtype": "float32", "axes": [1, 2], "normalize": false}, "shared_object_id": 17, "build_input_shape": [{"class_name": "TensorShape", "items": [null, 7]}, {"class_name": "TensorShape", "items": [null, 10, 7]}]}2 +˜)root.layer_with_weights-0.attention_score"_tf_keras_layer*Ñ{"name": "attention_score", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Dot", "config": {"name": "attention_score", "trainable": true, "dtype": "float32", "axes": [1, 2], "normalize": false}, "shared_object_id": 17, "build_input_shape": [{"class_name": "TensorShape", "items": [null, 7]}, {"class_name": "TensorShape", "items": [null, 5, 7]}]}2 —*root.layer_with_weights-0.attention_weight"_tf_keras_layer*Ï{"name": "attention_weight", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Activation", "config": {"name": "attention_weight", "trainable": true, "dtype": "float32", "activation": "softmax"}, "shared_object_id": 18}2 -—(root.layer_with_weights-0.context_vector"_tf_keras_layer*Ñ{"name": "context_vector", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Dot", "config": {"name": "context_vector", "trainable": true, "dtype": "float32", "axes": [1, 1], "normalize": false}, "shared_object_id": 19, "build_input_shape": [{"class_name": "TensorShape", "items": [null, 10, 7]}, {"class_name": "TensorShape", "items": [null, 10]}]}2 +•(root.layer_with_weights-0.context_vector"_tf_keras_layer*Ï{"name": "context_vector", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Dot", "config": {"name": "context_vector", "trainable": true, "dtype": "float32", "axes": [1, 1], "normalize": false}, "shared_object_id": 19, "build_input_shape": [{"class_name": "TensorShape", "items": [null, 5, 7]}, {"class_name": "TensorShape", "items": [null, 5]}]}2 ˆ*root.layer_with_weights-0.attention_output"_tf_keras_layer*À{"name": "attention_output", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Concatenate", "config": {"name": "attention_output", "trainable": true, "dtype": "float32", "axis": -1}, "shared_object_id": 20, "build_input_shape": [{"class_name": "TensorShape", "items": [null, 7]}, {"class_name": "TensorShape", "items": [null, 7]}]}2 ì*root.layer_with_weights-0.attention_vector"_tf_keras_layer*¤{"name": "attention_vector", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Dense", "config": {"name": "attention_vector", "trainable": true, "dtype": "float32", "units": 32, "activation": "tanh", "use_bias": false, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 21}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 22}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 23, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 2, "axes": {"-1": 14}}, "shared_object_id": 24}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 14]}}2 -¹_root.keras_api.metrics.0"_tf_keras_metric*‚{"class_name": "Mean", "name": "loss", "dtype": "float32", "config": {"name": "loss", "dtype": "float32"}, "shared_object_id": 25}2 -ž`root.keras_api.metrics.1"_tf_keras_metric*ç{"class_name": "CategoricalCrossentropy", "name": "categorical_crossentropy", "dtype": "float32", "config": {"name": "categorical_crossentropy", "dtype": "float32", "from_logits": true, "label_smoothing": 0}, "shared_object_id": 8}2 -çaroot.keras_api.metrics.2"_tf_keras_metric*°{"class_name": "CategoricalAccuracy", "name": "categorical_accuracy", "dtype": "float32", "config": {"name": "categorical_accuracy", "dtype": "float32"}, "shared_object_id": 9}2 -ßbroot.keras_api.metrics.3"_tf_keras_metric*¨{"class_name": "CategoricalHinge", "name": "categorical_hinge", "dtype": "float32", "config": {"name": "categorical_hinge", "dtype": "float32"}, "shared_object_id": 10}2 \ No newline at end of file +¹droot.keras_api.metrics.0"_tf_keras_metric*‚{"class_name": "Mean", "name": "loss", "dtype": "float32", "config": {"name": "loss", "dtype": "float32"}, "shared_object_id": 25}2 +žeroot.keras_api.metrics.1"_tf_keras_metric*ç{"class_name": "CategoricalCrossentropy", "name": "categorical_crossentropy", "dtype": "float32", "config": {"name": "categorical_crossentropy", "dtype": "float32", "from_logits": true, "label_smoothing": 0}, "shared_object_id": 8}2 +çfroot.keras_api.metrics.2"_tf_keras_metric*°{"class_name": "CategoricalAccuracy", "name": "categorical_accuracy", "dtype": "float32", "config": {"name": "categorical_accuracy", "dtype": "float32"}, "shared_object_id": 9}2 +ßgroot.keras_api.metrics.3"_tf_keras_metric*¨{"class_name": "CategoricalHinge", "name": "categorical_hinge", "dtype": "float32", "config": {"name": "categorical_hinge", "dtype": "float32"}, "shared_object_id": 10}2 \ No newline at end of file diff --git a/.model/attention/saved_model.pb b/.model/attention/saved_model.pb index f6723fe642fc128973775f2a31a00316c259dabe..15845c1e0175ab2d73e2a3128b84d08f98fab6cd 100644 GIT binary patch literal 144170 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 literal 126157 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 QprY+h9gpN)#dNIxKd0*QXaE2J diff --git a/.model/attention/variables/variables.data-00000-of-00001 b/.model/attention/variables/variables.data-00000-of-00001 index 34dad5eb6ebaa13a8fbc124005614d9298a1ccf3..6143d14fc3e2a8e2b048ee2f5eae0406d7d8b1ad 100644 GIT binary patch literal 16170 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 literal 9432 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 diff --git a/.model/attention/variables/variables.index b/.model/attention/variables/variables.index index 656368049b507b76cdb628c7e9ca686b324b69f9..eb48bac38ec4829ec957a0bec7f83a8b4e3a52e8 100755 GIT binary patch literal 1599 zcmZQzVB=tvV&Y(Akl~Ma_HcFf4)FK%3vqPvagFzP@^W<!iFXfj4DjG!7h+J@Vy*Gb z$#i?^ozn~^eA%f*iN*1W1)2J}sU=03$;J8x`pNmFc_sRKjv*mIo=%}5uEF|YjzOMa z!@?YWLR~o+fu?*A)?hI;x!Ia8qQF;@Uy_(ZNW&YDhI0S?M}?I542iSj2dQ>^L9)Y$ zI6E3dNc6`akR30Mg!%&gVN9GI9i-aP0@C1mg`J(jL?|b*GPNkaJhLPtzC1NEJ)@*p z*HAwxGqD(dfU^iOaj+;fuxJRFPG)-^FKsI19}wc{>lx)56d&y4AEKXMP?DLOS(RF( zpG%BMJrY2ZB+{o9n8*l~5u@ROHc-Q=-^@{>iXy;NmX}H(g>V2JtN?PfMgxm!Lvxgx ztf@G;PKKMM&?5pe?s93jzL|_T0e2&GJx~Yf;z@e4oI#rp5l~5~C5iEd_&v{{FoOjc zd4FFYzt1njXGBQx9FXGOZ-3q7Qs7HTO-`&Nq+tO_!?J2YD=vAy%o1Si;mN0*z<fG^ zMT5ii*4(BpE)Bk%)Wo8^%)IpYqQsI^d>TO+d<n>+%+sMp3~J(KiA9--Nja&Y(gBZs zj6$FwWCvk|6)YM@7){UoZ9U3MSv*3Fn<D`-PR;ALp&C)~2+{RH8>B07F1Iw7j5vXa z138@!h!qsxuxd2$nVzisn?|A2A;vwB1R3YIX(<<RPKW5)q6^ZsI{t_h0}w<pGcYiL y80p7$Jp|E=AmYHMg&P<cnadeoa>K<ooKb9k$IbDZn;#^EAB6vI=vFCpzYPGr%B52P delta 257 zcmdnbvyN?oF4q@fjVGq23om8wooH^uc|%x(#dO7wOHLCXXmDNuakj5wVV}5Gi}L}9 zBfU|7ElB1Lh-1*35;R$mQH%2hk`(U~5a+M4$zLHQKI4fS)i^&O$#T8{aT?YMT%UZC z(UoPxlfS1Y&t)=U;oh?+b8;+;8Q%mJjU$Yv*ZRElxMai)Cx2j3a^VwV;!sey!m820 zXIdg$<jepBj3A=v@xxR&=fJ0h8yFaw%NcI4!o~V-O-i`S%JGVof3hN**kl7Xb|7Zu N2>;#Cty1cK8vuPtQK$d_ diff --git a/.model/attention_model.tflite b/.model/attention_model.tflite new file mode 100644 index 0000000000000000000000000000000000000000..760ce93b62c639c2122cad3e6a0dc41046b07c18 GIT binary patch literal 8448 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 literal 0 HcmV?d00001 diff --git a/alarm.py b/alarm.py index deb6a22..7e90526 100644 --- a/alarm.py +++ b/alarm.py @@ -1,5 +1,6 @@ from enum import Enum, auto from datetime import time, datetime +from typing import Optional class AlarmState(Enum): @@ -12,10 +13,10 @@ class AlarmState(Enum): class BaseAlarmClock: _current_state: AlarmState - _wake_time: time + _wake_time: datetime - def __init__(self, wake_time: time = datetime.now().time()): - self._wake_time = wake_time + def __init__(self, wake_time: Optional[datetime] = None): + self._wake_time = wake_time if wake_time else datetime.utcnow() self._current_state = AlarmState.DEACTIVATED @property @@ -26,7 +27,7 @@ class BaseAlarmClock: def wake_time(self): return self._wake_time - def set_alarm(self, wake_time: time) -> time: + def set_alarm(self, wake_time: datetime) -> datetime: # print(f"SETTING ALARM to: {wake_time}") self._current_state = AlarmState.SET self._wake_time = wake_time @@ -50,5 +51,5 @@ class BaseAlarmClock: # print("STOPPED PLAYING ALARM") self._current_state = AlarmState.DEACTIVATED if deactivate else AlarmState.SET - def alarm_check_reached(self, current_time: time) -> bool: + def alarm_check_reached(self, current_time: datetime) -> bool: return current_time >= self._wake_time if self._current_state is AlarmState.RUNNING else False diff --git a/simple_alarm_clock.py b/simple_alarm_clock.py index 0f9f997..413f51f 100644 --- a/simple_alarm_clock.py +++ b/simple_alarm_clock.py @@ -1,7 +1,12 @@ +import subprocess +from typing import Optional + from alarm import BaseAlarmClock, AlarmState -from datetime import time, datetime +from datetime import time, datetime, timezone, timedelta from time import sleep -from pynput import keyboard +# from pynput import keyboard +import keyboard as kb +# SONG = ".model/Viennese_Poets.mp3" # Simple Alarm Clock has 5 functionalities: # 1. Set Alarm Time - Set the time for the alarm to sound, does NOT make the alarm active @@ -10,14 +15,22 @@ from pynput import keyboard # 4. Snooze Alarm - Stop the alarm sound and wait for some time to play the alarm again # 5. Stop Alarm - If the alarm is active or is playing, stop the alarm (deactivate state) -ALARM_TIME = time(15, 5, 0) -SNOOZE_KEY = keyboard.Key.up -ALARM_OFF_KEY = keyboard.Key.esc +# ALARM_TIME = datetime.combine( +# datetime.today(), +# # (datetime.today() + timedelta(days=1)).date(), +# time(16, 40, 0) +# ).astimezone(tz=timezone.utc) +# SNOOZE_KEY = keyboard.Key.up +# ALARM_OFF_KEY = keyboard.Key.esc SNOOZE_SEC = 5 class SimpleAlarmClock(BaseAlarmClock): - def set_alarm(self, wake_time: time) -> time: + def __init__(self, wake_time: Optional[datetime] = None): + super().__init__(wake_time) + # self._alarm = None + + def set_alarm(self, wake_time: datetime) -> datetime: print(f"SETTING ALARM to: {wake_time}") return super(SimpleAlarmClock, self).set_alarm(wake_time) @@ -27,37 +40,66 @@ class SimpleAlarmClock(BaseAlarmClock): def sound_alarm(self) -> None: print("SOUNDING ALARM") + # if not self._alarm: + # self._alarm = subprocess.Popen(["omxplayer", "--no-keys", SONG, "&"]) super(SimpleAlarmClock, self).sound_alarm() def snooze_alarm(self) -> None: - print("SNOOZING ALARM") - super(SimpleAlarmClock, self).snooze_alarm() + if self.current_state is AlarmState.PLAYING: + print("SNOOZING ALARM") + # print(f"{self._alarm.pid}") + # if self._alarm is not None: + # subprocess.Popen(["sudo", "kill", f"{self._alarm.pid}"]) + # self._alarm = None + super(SimpleAlarmClock, self).snooze_alarm() + sleep(SNOOZE_SEC) + print("UN-SNOOZING ALARM") + self.sound_alarm() def stop_alarm(self, deactivate: bool = True) -> None: print("STOPPING ALARM") - if self._current_state is AlarmState.PLAYING: + # if self._alarm is not None: + # subprocess.Popen(["sudo", "kill", f"{self._alarm.pid}"]) + # self._alarm = None + if self.current_state is AlarmState.PLAYING: print("STOPPED PLAYING ALARM") super(SimpleAlarmClock, self).stop_alarm() - def simple_alarm_mode(self): + def alarm_check_reached(self, current_time: datetime) -> bool: + # print(f"{self.wake_time}") + # print(f"{current_time}") + return super(SimpleAlarmClock, self).alarm_check_reached(current_time) + + def run_simple_alarm_mode(self): self.start_alarm() - while not self.alarm_check_reached(datetime.now().time()): - print(f"ALARM SLEEPING @: {datetime.now().time()}") + kb.add_hotkey("esc", lambda: self.stop_alarm()) + kb.add_hotkey("space", lambda: self.snooze_alarm()) + while not self.alarm_check_reached(datetime.now(tz=timezone.utc)): + print(f"ALARM SLEEPING @: {datetime.now(tz=timezone.utc)}") sleep(1) self.sound_alarm() while self.current_state is not AlarmState.DEACTIVATED: - with keyboard.Events() as events: - for event in events: - if event.key == ALARM_OFF_KEY: - self.stop_alarm() - break - elif event.key == SNOOZE_KEY: - self.snooze_alarm() - sleep(SNOOZE_SEC) - self.sound_alarm() - break + pass + # with keyboard.Events() as events: + # for event in events: + # if event.key == ALARM_OFF_KEY: + # self.stop_alarm() + # break + # elif event.key == SNOOZE_KEY: + # self.snooze_alarm() + # break if __name__ == '__main__': - alarm_clock = SimpleAlarmClock(ALARM_TIME) - alarm_clock.simple_alarm_mode() + alarm_hour = int(input("What hour do you want the alarm to go off at? ")) + alarm_minute = int(input("What minute do you want the alarm to go off at? ")) + run_alarm_today = map( + lambda response: response.lower() in ["y", "yes", "t", "true"], + input("Will the alarm run today? [y/N]") + ) + alarm_time = datetime.combine( + datetime.today() if run_alarm_today else (datetime.today() + timedelta(days=1)).date(), + time(alarm_hour, alarm_minute, 0) + ).astimezone(tz=timezone.utc) + alarm_clock = SimpleAlarmClock(alarm_time) + alarm_clock.run_simple_alarm_mode() diff --git a/smart_alarm_clock mac_copy.py b/smart_alarm_clock mac_copy.py new file mode 100644 index 0000000..0a8d06b --- /dev/null +++ b/smart_alarm_clock mac_copy.py @@ -0,0 +1,178 @@ +from typing import Optional, Deque + +import sys +from alarm import BaseAlarmClock, AlarmState +from datetime import time, datetime, timedelta, timezone +from time import sleep +from pynput import keyboard +from collections import deque +import numpy as np +import tensorflow as tf +import vlc + +# Lower threshold means it only needs to be somewhat probable to be early wake up +# >= 1 means never allow early wake up in that time +WAKE_THRESHOLD = np.array([0.5, 0.75, 0.9, 1.0]) + +SNOOZE_KEY = keyboard.Key.up +ALARM_OFF_KEY = keyboard.Key.esc +MODEL_MEMORY: int = 5 + +SECONDS_IN_MINUTE: float = 5 +SNOOZE_SEC: float = 60 +WAIT_SEC: float = 1 + +MODEL_PATH: str = ".model/attention" +VLC_INSTANCE = vlc.Instance("--input-repeat=999") +VLC_PLAYER = VLC_INSTANCE.media_player_new() +SONG = VLC_INSTANCE.media_new(".model/Viennese Poets.mp3" ) + +# Input Array: [minutes_since_start, current_hour_utc, current_minute_utc, awake_prob, rem_prob, light_prob, deep_prob] +# Output Array: [awake_prob, rem_prob, light_prob, deep_prob] + + +def softmax(arr): + val = np.exp(arr) + return val / sum(val) + + +def model_prediction(model, current_times_prob: Deque[np.array]) -> np.array: + # print(f"{np.array([current_times_prob]).shape = }") + if model: + prediction = model.predict(np.array([current_times_prob]))[0] + # print(f"{prediction = }") + # print(f"{softmax(prediction) = }") + return softmax(prediction) + else: + return np.zeros(4) + + +class SmartAlarmClock(BaseAlarmClock): + + def __init__(self, + wake_time: Optional[datetime] = None, + earliest_wake: Optional[timedelta] = None, + wake_threshold: np.array = WAKE_THRESHOLD, + vlc_player=VLC_PLAYER, + default_song=SONG): + super().__init__(wake_time) + self.earliest_wake = self.wake_time + if wake_time: + self.set_alarm(wake_time, earliest_wake) + self.wake_threshold = wake_threshold + self._vlc_player = vlc_player + self.song = default_song + if self._vlc_player and self.song: + self._vlc_player.set_media(self.song) + + def set_alarm(self, wake_time: datetime, earliest_wake: Optional[timedelta] = None) -> datetime: + print(f"SETTING ALARM to: {wake_time}") + returned_value = super(SmartAlarmClock, self).set_alarm(wake_time) + self.earliest_wake = wake_time - earliest_wake if earliest_wake else self.wake_time + return returned_value + + def start_alarm(self) -> None: + print("STARTING ALARM") + super(SmartAlarmClock, self).start_alarm() + + def sound_alarm(self, override_song=None) -> None: + print("SOUNDING ALARM") + if override_song: + self.song = override_song + if self._vlc_player: + self._vlc_player.set_media(self.song) + self._vlc_player.play() + super(SmartAlarmClock, self).sound_alarm() + + def snooze_alarm(self) -> None: + print("SNOOZING ALARM") + super(SmartAlarmClock, self).snooze_alarm() + if self._vlc_player: + self._vlc_player.pause() + sleep(SNOOZE_SEC) + if self._vlc_player: + self._vlc_player.play() + print("UN-SNOOZING ALARM") + self.sound_alarm() + + def stop_alarm(self, deactivate: bool = True) -> None: + print("STOPPING ALARM") + if self._vlc_player: + self._vlc_player.stop() + print("STOPPED PLAYING ALARM") + super(SmartAlarmClock, self).stop_alarm() + + def check_early_alarm_reached(self, current_time: datetime, prior_prediction: np.array) -> bool: + if current_time < self.earliest_wake: + return False + return np.max(prior_prediction - self.wake_threshold) > 0 + + def smart_alarm_mode(self, model, model_memory=MODEL_MEMORY): + self.start_alarm() + time_queue = deque(maxlen=model_memory) + # While not filled time_queue keep appending awake data (warm-up machine) + minutes_since_start = 0 + while len(time_queue) < time_queue.maxlen: + current_utc = datetime.utcnow() + time_queue.append(np.array( + [minutes_since_start, current_utc.hour, current_utc.minute, 1.0, 0.0, 0.0, 0.0] + )) + # Wait a minute for next timestep + while (datetime.utcnow() - current_utc).seconds < SECONDS_IN_MINUTE: + sleep(WAIT_SEC) + minutes_since_start += 1 + print(f"{time_queue = }") + + # While the alarm clock is running + last_checked = datetime.utcnow() + last_prediction = model_prediction(model, time_queue) + print(f"{last_checked}: {last_prediction = }") + print(f"{self.check_early_alarm_reached(datetime.now(tz=timezone.utc), last_prediction) = }") + while self.current_state is AlarmState.RUNNING \ + and not self.check_early_alarm_reached(datetime.now(tz=timezone.utc), last_prediction) \ + and not self.alarm_check_reached(datetime.now(tz=timezone.utc)): + print(f"ALARM SLEEPING @: {datetime.now()}") + if (datetime.utcnow() - last_checked).seconds < SECONDS_IN_MINUTE: + last_checked = datetime.utcnow() + time_queue.append( + np.concatenate( + ( + [minutes_since_start, last_checked.hour, last_checked.minute], + last_prediction + ) + ) + ) + print(f"{time_queue = }") + last_prediction = model_prediction(model, time_queue) + print(f"{datetime.utcnow()}: {last_prediction = }") + sleep(WAIT_SEC) + + # While the alarm clock is sounding off + self.sound_alarm() + while self.current_state is not AlarmState.DEACTIVATED: + with keyboard.Events() as events: + for event in events: + if event.key == ALARM_OFF_KEY: + self.stop_alarm() + break + elif event.key == SNOOZE_KEY: + self.snooze_alarm() + break + + +if __name__ == '__main__': + alarm_hour = int(input("What hour do you want the alarm to go off at? ")) + alarm_minute = int(input("What minute do you want the alarm to go off at? ")) + early_minutes = int(input("How many minute early would you have the alarm go off at? ")) + run_alarm_today = map( + lambda response: response.lower() in ["y", "yes", "t", "true"], + input("Will the alarm run today? [y/N]") + ) + alarm_time = datetime.combine( + datetime.today() if run_alarm_today else (datetime.today() + timedelta(days=1)).date(), + time(alarm_hour, alarm_minute, 0) + ).astimezone(tz=timezone.utc) + early_time = alarm_time - timedelta(minutes=early_minutes) + alarm_clock_class = SmartAlarmClock(alarm_time, earliest_wake=timedelta(minutes=early_minutes)) + ai_model = tf.keras.models.load_model(MODEL_PATH) + alarm_clock_class.smart_alarm_mode(ai_model) diff --git a/smart_alarm_clock.py b/smart_alarm_clock.py index 12c4eb5..93885cc 100644 --- a/smart_alarm_clock.py +++ b/smart_alarm_clock.py @@ -1,16 +1,38 @@ -from typing import Optional +from typing import Optional, Deque +import sys from alarm import BaseAlarmClock, AlarmState -from datetime import time, datetime +from datetime import time, datetime, timedelta, timezone from time import sleep -from pynput import keyboard +# from pynput import keyboard +import keyboard as kb +from collections import deque import numpy as np +# import tensorflow as tf +import tflite_runtime.interpreter as tflite import vlc +# Lower threshold means it only needs to be somewhat probable to be early wake up +# >= 1 means never allow early wake up in that time +WAKE_THRESHOLD = np.array([0.5, 0.75, 0.9, 1.0]) -SNOOZE_KEY = keyboard.Key.up -ALARM_OFF_KEY = keyboard.Key.esc -SNOOZE_SEC = 5 +# SNOOZE_KEY = keyboard.Key.up +SNOOZE_KEY = "space" +# ALARM_OFF_KEY = keyboard.Key.esc +ALARM_OFF_KEY = "esc" +MODEL_MEMORY: int = 5 + +SECONDS_IN_MINUTE: float = 60 +SNOOZE_SEC: float = 60 +WAIT_SEC: float = 1 + +MODEL_PATH: str = ".model/attention_model.tflite" +VLC_INSTANCE = vlc.Instance("--input-repeat=999") +VLC_PLAYER = VLC_INSTANCE.media_player_new() +SONG = VLC_INSTANCE.media_new(".model/Viennese Poets.mp3" ) + +# Input Array: [minutes_since_start, current_hour_utc, current_minute_utc, awake_prob, rem_prob, light_prob, deep_prob] +# Output Array: [awake_prob, rem_prob, light_prob, deep_prob] def softmax(arr): @@ -18,59 +40,159 @@ def softmax(arr): return val / sum(val) +def model_prediction(model_func, current_times_prob: Deque[np.array]) -> np.array: + # print(f"Prob shape: {np.array([current_times_prob]).shape}") + if model_func: + # prediction = model.predict(np.array([current_times_prob]))[0] + prediction = model_func(x=np.array([current_times_prob])) + print(prediction) + # print(f"prediction: {prediction}") + # print(f"softmax: {softmax(prediction)}") + return softmax(prediction) + else: + return np.zeros(4) + + class SmartAlarmClock(BaseAlarmClock): - def __init__(self, wake_time: Optional[time] = None, vlc_player=None): + def __init__(self, + wake_time: Optional[datetime] = None, + earliest_wake: Optional[timedelta] = None, + wake_threshold: np.array = WAKE_THRESHOLD, + vlc_player=VLC_PLAYER, + default_song=SONG): + super().__init__(wake_time) + self.earliest_wake = self.wake_time if wake_time: - self.set_alarm(wake_time) - super().__init__() - - def set_alarm(self, wake_time: time) -> time: + self.set_alarm(wake_time, earliest_wake) + self.wake_threshold = wake_threshold + self._vlc_player = vlc_player + self.song = default_song + if self._vlc_player and self.song: + self._vlc_player.set_media(self.song) + + def set_alarm(self, wake_time: datetime, earliest_wake: Optional[timedelta] = None) -> datetime: print(f"SETTING ALARM to: {wake_time}") - return super(SmartAlarmClock, self).set_alarm(wake_time) + returned_value = super(SmartAlarmClock, self).set_alarm(wake_time) + self.earliest_wake = wake_time - earliest_wake if earliest_wake else self.wake_time + print(returned_value) + return returned_value def start_alarm(self) -> None: print("STARTING ALARM") super(SmartAlarmClock, self).start_alarm() - def sound_alarm(self) -> None: + def sound_alarm(self, override_song=None) -> None: print("SOUNDING ALARM") + if override_song: + self.song = override_song + if self._vlc_player: + self._vlc_player.set_media(self.song) + self._vlc_player.play() super(SmartAlarmClock, self).sound_alarm() def snooze_alarm(self) -> None: print("SNOOZING ALARM") super(SmartAlarmClock, self).snooze_alarm() + if self._vlc_player: + self._vlc_player.pause() + sleep(SNOOZE_SEC) + if self._vlc_player: + self._vlc_player.play() + print("UN-SNOOZING ALARM") + self.sound_alarm() def stop_alarm(self, deactivate: bool = True) -> None: print("STOPPING ALARM") - if self._current_state is AlarmState.PLAYING: + if self._vlc_player: + self._vlc_player.stop() print("STOPPED PLAYING ALARM") super(SmartAlarmClock, self).stop_alarm() - def smart_alarm_mode(self, model): + def check_early_alarm_reached(self, current_time: datetime, prior_prediction: np.array) -> bool: + if current_time < self.earliest_wake: + return False + return np.max(prior_prediction - self.wake_threshold) > 0 + + def smart_alarm_mode(self, fn, model_memory=MODEL_MEMORY): + print("STARTING IN SMART MODE") + kb.on_press_key("c", lambda x: sys.exit()) + kb.on_press_key(SNOOZE_KEY, lambda x: self.snooze_alarm()) + kb.on_press_key(ALARM_OFF_KEY, lambda x: self.stop_alarm()) self.start_alarm() - while not self.alarm_check_reached(datetime.now().time()): - print(f"ALARM SLEEPING @: {datetime.now().time()}") - sleep(1) + time_queue = deque(maxlen=model_memory) + # While not filled time_queue keep appending awake data (warm-up machine) + minutes_since_start = 0 + while len(time_queue) < time_queue.maxlen: + current_utc = datetime.utcnow() + time_queue.append(np.array( + [minutes_since_start, current_utc.hour, current_utc.minute, 1.0, 0.0, 0.0, 0.0] + )) + print(f"time_queue: {time_queue}") + # Wait a minute for next timestep + while (datetime.utcnow() - current_utc).seconds < SECONDS_IN_MINUTE: + sleep(WAIT_SEC) + minutes_since_start += 1 + + # While the alarm clock is running + last_checked = datetime.utcnow() + last_prediction = model_prediction(fn, time_queue) + print(f"{last_checked}: last_prediction = {last_prediction}") + print(f"check early: {self.check_early_alarm_reached(datetime.now(tz=timezone.utc), last_prediction)}") + while self.current_state is AlarmState.RUNNING \ + and not self.check_early_alarm_reached(datetime.now(tz=timezone.utc), last_prediction) \ + and not self.alarm_check_reached(datetime.now(tz=timezone.utc)): + print(f"ALARM SLEEPING @: {datetime.now()}") + if (datetime.utcnow() - last_checked).seconds < SECONDS_IN_MINUTE: + last_checked = datetime.utcnow() + time_queue.append( + np.concatenate( + ( + [minutes_since_start, last_checked.hour, last_checked.minute], + last_prediction + ) + ) + ) + print(f"time_queue = {time_queue}") + last_prediction = model_prediction(fn, time_queue) + print(f"{datetime.utcnow()}: last_prediction = {last_prediction}") + sleep(WAIT_SEC) + + # While the alarm clock is sounding off self.sound_alarm() while self.current_state is not AlarmState.DEACTIVATED: - with keyboard.Events() as events: - for event in events: - if event.key == ALARM_OFF_KEY: - self.stop_alarm() - break - elif event.key == SNOOZE_KEY: - self.snooze_alarm() - sleep(SNOOZE_SEC) - self.sound_alarm() - break + pass + # event = kb.read_event() + # if event.event_type == kb.KEY_DOWN: + # # with keyboard.Events() as events: + # # for event in events: + # # if event.key == ALARM_OFF_KEY: + # if event.name == ALARM_OFF_KEY: + # self.stop_alarm() + # break + # elif event.name == SNOOZE_KEY: + # # elif event.key == SNOOZE_KEY: + # self.snooze_alarm() + # break if __name__ == '__main__': - alarm_hour = int(input("What hour do you want the alarm to go off at?")) - alarm_minute = int(input("What minute do you want the alarm to go off at?")) - alarm_second = int(input("What second do you want the alarm to go off at?")) - alarm_time = time(alarm_hour, alarm_minute, alarm_second) - alarm_clock_class = SmartAlarmClock(alarm_time) - ai_model = None - alarm_clock_class.smart_alarm_mode(ai_model) + alarm_hour = int(input("What hour do you want the alarm to go off at? ")) + alarm_minute = int(input("What minute do you want the alarm to go off at? ")) + early_minutes = int(input("How many minute early would you have the alarm go off at? ")) + run_alarm_today = map( + lambda response: response.lower() in ["y", "yes", "t", "true"], + input("Will the alarm run today? [y/N]") + ) + alarm_time = datetime.combine( + datetime.today() if run_alarm_today else (datetime.today() + timedelta(days=1)).date(), + time(alarm_hour, alarm_minute, 0) + ).astimezone(tz=timezone.utc) + early_time = alarm_time - timedelta(minutes=early_minutes) + alarm_clock_class = SmartAlarmClock(alarm_time, earliest_wake=timedelta(minutes=early_minutes)) + print(f"Loading model from: {MODEL_PATH}") + ai_model = tflite.Interpreter(model_path=MODEL_PATH) + ai_model.allocate_tensors() # tf.keras.models.load_model(MODEL_PATH) + model_fn = ai_model.get_signature_runner() + print(f"Initialized Model") + alarm_clock_class.smart_alarm_mode(model_fn) diff --git a/tf_model.ipynb b/tf_model.ipynb index dbce03e..a8b45ad 100644 --- a/tf_model.ipynb +++ b/tf_model.ipynb @@ -1045,7 +1045,7 @@ }, { "cell_type": "code", - "execution_count": 54, + "execution_count": 49, "metadata": {}, "outputs": [], "source": [ @@ -1061,7 +1061,7 @@ "outputs": [], "source": [ "def noisy_randomizer(confusion_matrix_index: int, sample_count: int = SAMPLE_COUNT, confusion_matrix = CONFUSION_MATRIX):\n", - " return np.random.multinomial(sample_count, confusion_matrix[confusion_matrix_index], size=1)[0]/sample_count" + " return softmax(np.random.multinomial(sample_count, confusion_matrix[confusion_matrix_index], size=1)[0])" ] }, { @@ -1194,7 +1194,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 28, "metadata": {}, "outputs": [], "source": [ @@ -1688,7 +1688,7 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 88, "metadata": {}, "outputs": [], "source": [ @@ -1698,20 +1698,20 @@ }, { "cell_type": "code", - "execution_count": 33, + "execution_count": 89, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Model: \"sequential_1\"\n", + "Model: \"sequential_2\"\n", "_________________________________________________________________\n", " Layer (type) Output Shape Param # \n", "=================================================================\n", " gru (GRU) (None, 16) 1200 \n", " \n", - " dense_1 (Dense) (None, 4) 68 \n", + " dense_2 (Dense) (None, 4) 68 \n", " \n", "=================================================================\n", "Total params: 1,268\n", @@ -1733,19 +1733,31 @@ }, { "cell_type": "code", - "execution_count": 46, + "execution_count": 91, "metadata": {}, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "9647/9647 [==============================] - 97s 10ms/step - loss: 0.4700 - categorical_crossentropy: 0.4700 - categorical_accuracy: 0.8416 - categorical_hinge: 0.4278 - val_loss: 0.2088 - val_categorical_crossentropy: 0.2087 - val_categorical_accuracy: 0.9595 - val_categorical_hinge: 0.1954\n" + "ename": "KeyboardInterrupt", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "\u001b[1;32m/Users/nowadmin/Documents/School Folder/CS 437/Lab/Final Project/tf_model.ipynb Cell 65'\u001b[0m in \u001b[0;36m<cell line: 1>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> <a href='vscode-notebook-cell:/Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/tf_model.ipynb#ch0000054?line=0'>1</a>\u001b[0m gru_history \u001b[39m=\u001b[39m compile_and_fit(model\u001b[39m=\u001b[39;49mgru_model, window\u001b[39m=\u001b[39;49mwg)\n", + "\u001b[1;32m/Users/nowadmin/Documents/School Folder/CS 437/Lab/Final Project/tf_model.ipynb Cell 42'\u001b[0m in \u001b[0;36mcompile_and_fit\u001b[0;34m(model, window, loss, optimizer, metrics, early_stop, patience, baseline, epochs)\u001b[0m\n\u001b[1;32m <a href='vscode-notebook-cell:/Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/tf_model.ipynb#ch0000033?line=13'>14</a>\u001b[0m callbacks\u001b[39m.\u001b[39mappend(early_stopping)\n\u001b[1;32m <a href='vscode-notebook-cell:/Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/tf_model.ipynb#ch0000033?line=15'>16</a>\u001b[0m model\u001b[39m.\u001b[39mcompile(\n\u001b[1;32m <a href='vscode-notebook-cell:/Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/tf_model.ipynb#ch0000033?line=16'>17</a>\u001b[0m loss\u001b[39m=\u001b[39mloss,\n\u001b[1;32m <a href='vscode-notebook-cell:/Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/tf_model.ipynb#ch0000033?line=17'>18</a>\u001b[0m optimizer\u001b[39m=\u001b[39moptimizer,\n\u001b[1;32m <a href='vscode-notebook-cell:/Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/tf_model.ipynb#ch0000033?line=18'>19</a>\u001b[0m metrics\u001b[39m=\u001b[39mmetrics,\n\u001b[1;32m <a href='vscode-notebook-cell:/Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/tf_model.ipynb#ch0000033?line=19'>20</a>\u001b[0m )\n\u001b[0;32m---> <a href='vscode-notebook-cell:/Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/tf_model.ipynb#ch0000033?line=21'>22</a>\u001b[0m \u001b[39mreturn\u001b[39;00m model\u001b[39m.\u001b[39;49mfit(window\u001b[39m.\u001b[39;49mtraining_ds, epochs\u001b[39m=\u001b[39;49mepochs, validation_data\u001b[39m=\u001b[39;49mwindow\u001b[39m.\u001b[39;49mvalidation_ds, callbacks\u001b[39m=\u001b[39;49mcallbacks)\n", + "File \u001b[0;32m~/Documents/School Folder/CS 437/Lab/Final Project/venv/lib/python3.10/site-packages/keras/utils/traceback_utils.py:64\u001b[0m, in \u001b[0;36mfilter_traceback.<locals>.error_handler\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/keras/utils/traceback_utils.py?line=61'>62</a>\u001b[0m filtered_tb \u001b[39m=\u001b[39m \u001b[39mNone\u001b[39;00m\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/keras/utils/traceback_utils.py?line=62'>63</a>\u001b[0m \u001b[39mtry\u001b[39;00m:\n\u001b[0;32m---> <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/keras/utils/traceback_utils.py?line=63'>64</a>\u001b[0m \u001b[39mreturn\u001b[39;00m fn(\u001b[39m*\u001b[39;49margs, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwargs)\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/keras/utils/traceback_utils.py?line=64'>65</a>\u001b[0m \u001b[39mexcept\u001b[39;00m \u001b[39mException\u001b[39;00m \u001b[39mas\u001b[39;00m e: \u001b[39m# pylint: disable=broad-except\u001b[39;00m\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/keras/utils/traceback_utils.py?line=65'>66</a>\u001b[0m filtered_tb \u001b[39m=\u001b[39m _process_traceback_frames(e\u001b[39m.\u001b[39m__traceback__)\n", + "File \u001b[0;32m~/Documents/School Folder/CS 437/Lab/Final Project/venv/lib/python3.10/site-packages/keras/engine/training.py:1372\u001b[0m, in \u001b[0;36mModel.fit\u001b[0;34m(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, validation_batch_size, validation_freq, max_queue_size, workers, use_multiprocessing)\u001b[0m\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/keras/engine/training.py?line=1368'>1369</a>\u001b[0m data_handler\u001b[39m.\u001b[39m_initial_epoch \u001b[39m=\u001b[39m ( \u001b[39m# pylint: disable=protected-access\u001b[39;00m\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/keras/engine/training.py?line=1369'>1370</a>\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_maybe_load_initial_epoch_from_ckpt(initial_epoch))\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/keras/engine/training.py?line=1370'>1371</a>\u001b[0m logs \u001b[39m=\u001b[39m \u001b[39mNone\u001b[39;00m\n\u001b[0;32m-> <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/keras/engine/training.py?line=1371'>1372</a>\u001b[0m \u001b[39mfor\u001b[39;00m epoch, iterator \u001b[39min\u001b[39;00m data_handler\u001b[39m.\u001b[39menumerate_epochs():\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/keras/engine/training.py?line=1372'>1373</a>\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mreset_metrics()\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/keras/engine/training.py?line=1373'>1374</a>\u001b[0m callbacks\u001b[39m.\u001b[39mon_epoch_begin(epoch)\n", + "File \u001b[0;32m~/Documents/School Folder/CS 437/Lab/Final Project/venv/lib/python3.10/site-packages/keras/engine/data_adapter.py:1191\u001b[0m, in \u001b[0;36mDataHandler.enumerate_epochs\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/keras/engine/data_adapter.py?line=1188'>1189</a>\u001b[0m \u001b[39m\"\"\"Yields `(epoch, tf.data.Iterator)`.\"\"\"\u001b[39;00m\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/keras/engine/data_adapter.py?line=1189'>1190</a>\u001b[0m \u001b[39mwith\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_truncate_execution_to_epoch():\n\u001b[0;32m-> <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/keras/engine/data_adapter.py?line=1190'>1191</a>\u001b[0m data_iterator \u001b[39m=\u001b[39m \u001b[39miter\u001b[39;49m(\u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49m_dataset)\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/keras/engine/data_adapter.py?line=1191'>1192</a>\u001b[0m \u001b[39mfor\u001b[39;00m epoch \u001b[39min\u001b[39;00m \u001b[39mrange\u001b[39m(\u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_initial_epoch, \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_epochs):\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/keras/engine/data_adapter.py?line=1192'>1193</a>\u001b[0m \u001b[39mif\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_insufficient_data: \u001b[39m# Set by `catch_stop_iteration`.\u001b[39;00m\n", + "File \u001b[0;32m~/Documents/School Folder/CS 437/Lab/Final Project/venv/lib/python3.10/site-packages/tensorflow/python/data/ops/dataset_ops.py:486\u001b[0m, in \u001b[0;36mDatasetV2.__iter__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/tensorflow/python/data/ops/dataset_ops.py?line=483'>484</a>\u001b[0m \u001b[39mif\u001b[39;00m context\u001b[39m.\u001b[39mexecuting_eagerly() \u001b[39mor\u001b[39;00m ops\u001b[39m.\u001b[39minside_function():\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/tensorflow/python/data/ops/dataset_ops.py?line=484'>485</a>\u001b[0m \u001b[39mwith\u001b[39;00m ops\u001b[39m.\u001b[39mcolocate_with(\u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_variant_tensor):\n\u001b[0;32m--> <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/tensorflow/python/data/ops/dataset_ops.py?line=485'>486</a>\u001b[0m \u001b[39mreturn\u001b[39;00m iterator_ops\u001b[39m.\u001b[39;49mOwnedIterator(\u001b[39mself\u001b[39;49m)\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/tensorflow/python/data/ops/dataset_ops.py?line=486'>487</a>\u001b[0m \u001b[39melse\u001b[39;00m:\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/tensorflow/python/data/ops/dataset_ops.py?line=487'>488</a>\u001b[0m \u001b[39mraise\u001b[39;00m \u001b[39mRuntimeError\u001b[39;00m(\u001b[39m\"\u001b[39m\u001b[39m`tf.data.Dataset` only supports Python-style \u001b[39m\u001b[39m\"\u001b[39m\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/tensorflow/python/data/ops/dataset_ops.py?line=488'>489</a>\u001b[0m \u001b[39m\"\u001b[39m\u001b[39miteration in eager mode or within tf.function.\u001b[39m\u001b[39m\"\u001b[39m)\n", + "File \u001b[0;32m~/Documents/School Folder/CS 437/Lab/Final Project/venv/lib/python3.10/site-packages/tensorflow/python/data/ops/iterator_ops.py:755\u001b[0m, in \u001b[0;36mOwnedIterator.__init__\u001b[0;34m(self, dataset, components, element_spec)\u001b[0m\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/tensorflow/python/data/ops/iterator_ops.py?line=750'>751</a>\u001b[0m \u001b[39mif\u001b[39;00m (components \u001b[39mis\u001b[39;00m \u001b[39mnot\u001b[39;00m \u001b[39mNone\u001b[39;00m \u001b[39mor\u001b[39;00m element_spec \u001b[39mis\u001b[39;00m \u001b[39mnot\u001b[39;00m \u001b[39mNone\u001b[39;00m):\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/tensorflow/python/data/ops/iterator_ops.py?line=751'>752</a>\u001b[0m \u001b[39mraise\u001b[39;00m \u001b[39mValueError\u001b[39;00m(\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/tensorflow/python/data/ops/iterator_ops.py?line=752'>753</a>\u001b[0m \u001b[39m\"\u001b[39m\u001b[39mWhen `dataset` is provided, `element_spec` and `components` must \u001b[39m\u001b[39m\"\u001b[39m\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/tensorflow/python/data/ops/iterator_ops.py?line=753'>754</a>\u001b[0m \u001b[39m\"\u001b[39m\u001b[39mnot be specified.\u001b[39m\u001b[39m\"\u001b[39m)\n\u001b[0;32m--> <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/tensorflow/python/data/ops/iterator_ops.py?line=754'>755</a>\u001b[0m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49m_create_iterator(dataset)\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/tensorflow/python/data/ops/iterator_ops.py?line=756'>757</a>\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_get_next_call_count \u001b[39m=\u001b[39m \u001b[39m0\u001b[39m\n", + "File \u001b[0;32m~/Documents/School Folder/CS 437/Lab/Final Project/venv/lib/python3.10/site-packages/tensorflow/python/data/ops/iterator_ops.py:787\u001b[0m, in \u001b[0;36mOwnedIterator._create_iterator\u001b[0;34m(self, dataset)\u001b[0m\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/tensorflow/python/data/ops/iterator_ops.py?line=781'>782</a>\u001b[0m \u001b[39melse\u001b[39;00m:\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/tensorflow/python/data/ops/iterator_ops.py?line=782'>783</a>\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_iterator_resource, \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_deleter \u001b[39m=\u001b[39m (\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/tensorflow/python/data/ops/iterator_ops.py?line=783'>784</a>\u001b[0m gen_dataset_ops\u001b[39m.\u001b[39manonymous_iterator_v2(\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/tensorflow/python/data/ops/iterator_ops.py?line=784'>785</a>\u001b[0m output_types\u001b[39m=\u001b[39m\u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_flat_output_types,\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/tensorflow/python/data/ops/iterator_ops.py?line=785'>786</a>\u001b[0m output_shapes\u001b[39m=\u001b[39m\u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_flat_output_shapes))\n\u001b[0;32m--> <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/tensorflow/python/data/ops/iterator_ops.py?line=786'>787</a>\u001b[0m gen_dataset_ops\u001b[39m.\u001b[39;49mmake_iterator(ds_variant, \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49m_iterator_resource)\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/tensorflow/python/data/ops/iterator_ops.py?line=787'>788</a>\u001b[0m \u001b[39m# Delete the resource when this object is deleted\u001b[39;00m\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/tensorflow/python/data/ops/iterator_ops.py?line=788'>789</a>\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_resource_deleter \u001b[39m=\u001b[39m IteratorResourceDeleter(\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/tensorflow/python/data/ops/iterator_ops.py?line=789'>790</a>\u001b[0m handle\u001b[39m=\u001b[39m\u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_iterator_resource,\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/tensorflow/python/data/ops/iterator_ops.py?line=790'>791</a>\u001b[0m deleter\u001b[39m=\u001b[39m\u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_deleter)\n", + "File \u001b[0;32m~/Documents/School Folder/CS 437/Lab/Final Project/venv/lib/python3.10/site-packages/tensorflow/python/ops/gen_dataset_ops.py:3315\u001b[0m, in \u001b[0;36mmake_iterator\u001b[0;34m(dataset, iterator, name)\u001b[0m\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/tensorflow/python/ops/gen_dataset_ops.py?line=3312'>3313</a>\u001b[0m \u001b[39mif\u001b[39;00m tld\u001b[39m.\u001b[39mis_eager:\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/tensorflow/python/ops/gen_dataset_ops.py?line=3313'>3314</a>\u001b[0m \u001b[39mtry\u001b[39;00m:\n\u001b[0;32m-> <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/tensorflow/python/ops/gen_dataset_ops.py?line=3314'>3315</a>\u001b[0m _result \u001b[39m=\u001b[39m pywrap_tfe\u001b[39m.\u001b[39;49mTFE_Py_FastPathExecute(\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/tensorflow/python/ops/gen_dataset_ops.py?line=3315'>3316</a>\u001b[0m _ctx, \u001b[39m\"\u001b[39;49m\u001b[39mMakeIterator\u001b[39;49m\u001b[39m\"\u001b[39;49m, name, dataset, iterator)\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/tensorflow/python/ops/gen_dataset_ops.py?line=3316'>3317</a>\u001b[0m \u001b[39mreturn\u001b[39;00m _result\n\u001b[1;32m <a href='file:///Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/venv/lib/python3.10/site-packages/tensorflow/python/ops/gen_dataset_ops.py?line=3317'>3318</a>\u001b[0m \u001b[39mexcept\u001b[39;00m _core\u001b[39m.\u001b[39m_NotOkStatusException \u001b[39mas\u001b[39;00m e:\n", + "\u001b[0;31mKeyboardInterrupt\u001b[0m: " ] } ], "source": [ - "gru_history = compile_and_fit(model=gru_model, window=wg, epochs=1)" + "gru_history = compile_and_fit(model=gru_model, window=wg)" ] }, { @@ -1757,7 +1769,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 29, "metadata": {}, "outputs": [], "source": [ @@ -1766,21 +1778,21 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 32, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Model: \"sequential\"\n", + "Model: \"sequential_1\"\n", "_________________________________________________________________\n", " Layer (type) Output Shape Param # \n", "=================================================================\n", - " custom_attention (CustomAtt (None, 32) 497 \n", - " ention) \n", + " custom_attention_1 (CustomA (None, 32) 497 \n", + " ttention) \n", " \n", - " dense (Dense) (None, 4) 132 \n", + " dense_1 (Dense) (None, 4) 132 \n", " \n", "=================================================================\n", "Total params: 629\n", @@ -1802,16 +1814,16 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "<tensorflow.python.training.tracking.util.CheckpointLoadStatus at 0x12aaebe50>" + "<tensorflow.python.training.tracking.util.CheckpointLoadStatus at 0x111063e80>" ] }, - "execution_count": 15, + "execution_count": 31, "metadata": {}, "output_type": "execute_result" } @@ -1822,56 +1834,70 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 38, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch 1/20\n", + "4682/4682 [==============================] - 67s 14ms/step - loss: 0.9233 - categorical_crossentropy: 0.9233 - categorical_accuracy: 0.5880 - categorical_hinge: 0.9024 - val_loss: 0.4996 - val_categorical_crossentropy: 0.4996 - val_categorical_accuracy: 0.9040 - val_categorical_hinge: 0.3196\n", + "Epoch 2/20\n", + "4682/4682 [==============================] - 56s 12ms/step - loss: 0.3929 - categorical_crossentropy: 0.3929 - categorical_accuracy: 0.8920 - categorical_hinge: 0.3280 - val_loss: 0.4142 - val_categorical_crossentropy: 0.4142 - val_categorical_accuracy: 0.8625 - val_categorical_hinge: 0.3925\n", + "Epoch 3/20\n", + "4682/4682 [==============================] - 76s 16ms/step - loss: 0.3686 - categorical_crossentropy: 0.3686 - categorical_accuracy: 0.8872 - categorical_hinge: 0.3478 - val_loss: 0.2700 - val_categorical_crossentropy: 0.2700 - val_categorical_accuracy: 0.9252 - val_categorical_hinge: 0.2614\n", + "Epoch 4/20\n", + "4682/4682 [==============================] - 72s 15ms/step - loss: 0.3373 - categorical_crossentropy: 0.3373 - categorical_accuracy: 0.9026 - categorical_hinge: 0.3137 - val_loss: 0.2795 - val_categorical_crossentropy: 0.2796 - val_categorical_accuracy: 0.9248 - val_categorical_hinge: 0.2698\n", + "Epoch 5/20\n", + "4682/4682 [==============================] - 68s 15ms/step - loss: 0.3296 - categorical_crossentropy: 0.3296 - categorical_accuracy: 0.9050 - categorical_hinge: 0.3312 - val_loss: 0.2372 - val_categorical_crossentropy: 0.2372 - val_categorical_accuracy: 0.9532 - val_categorical_hinge: 0.2263\n", + "Epoch 6/20\n", + "4682/4682 [==============================] - 69s 15ms/step - loss: 0.3081 - categorical_crossentropy: 0.3081 - categorical_accuracy: 0.9170 - categorical_hinge: 0.2994 - val_loss: 0.2517 - val_categorical_crossentropy: 0.2517 - val_categorical_accuracy: 0.9449 - val_categorical_hinge: 0.2452\n", + "Epoch 7/20\n", + "4682/4682 [==============================] - 67s 14ms/step - loss: 0.2663 - categorical_crossentropy: 0.2663 - categorical_accuracy: 0.9360 - categorical_hinge: 0.2524 - val_loss: 0.2238 - val_categorical_crossentropy: 0.2238 - val_categorical_accuracy: 0.9565 - val_categorical_hinge: 0.2128\n", + "Epoch 8/20\n", + "4682/4682 [==============================] - 68s 15ms/step - loss: 0.2747 - categorical_crossentropy: 0.2747 - categorical_accuracy: 0.9330 - categorical_hinge: 0.2739 - val_loss: 0.2166 - val_categorical_crossentropy: 0.2166 - val_categorical_accuracy: 0.9571 - val_categorical_hinge: 0.2089\n", + "Epoch 9/20\n", + "4682/4682 [==============================] - 72s 15ms/step - loss: 0.2510 - categorical_crossentropy: 0.2510 - categorical_accuracy: 0.9430 - categorical_hinge: 0.2354 - val_loss: 0.2189 - val_categorical_crossentropy: 0.2189 - val_categorical_accuracy: 0.9560 - val_categorical_hinge: 0.1976\n", + "Epoch 10/20\n", + "4682/4682 [==============================] - 71s 15ms/step - loss: 0.2810 - categorical_crossentropy: 0.2810 - categorical_accuracy: 0.9311 - categorical_hinge: 0.2874 - val_loss: 0.2320 - val_categorical_crossentropy: 0.2321 - val_categorical_accuracy: 0.9555 - val_categorical_hinge: 0.2230\n" + ] + } + ], "source": [ - "am_history = compile_and_fit(model=am_model, window=wg, epochs=0)" + "am_history = compile_and_fit(model=am_model, window=wg)" ] }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 42, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "1442/1442 [==============================] - 14s 4ms/step - loss: 0.1957 - categorical_crossentropy: 0.1957 - categorical_accuracy: 0.9598 - categorical_hinge: 0.1911\n" + "1450/1450 [==============================] - 13s 4ms/step - loss: 0.2333 - categorical_crossentropy: 0.2333 - categorical_accuracy: 0.9552 - categorical_hinge: 0.2243\n" ] - }, - { - "data": { - "text/plain": [ - "[0.19572481513023376,\n", - " 0.19574123620986938,\n", - " 0.9597873687744141,\n", - " 0.1910863220691681]" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" } ], "source": [ - "am_model.evaluate(wg.testing_ds)" + "results = am_model.evaluate(wg.testing_ds)" ] }, { "cell_type": "code", - "execution_count": 47, + "execution_count": 46, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "array([[ 0.59796184, -0.20803624, -0.2916372 , -0.7170148 ]],\n", + "array([[-0.4693893 , -0.7194527 , 0.18727879, -0.47643274]],\n", " dtype=float32)" ] }, - "execution_count": 47, + "execution_count": 46, "metadata": {}, "output_type": "execute_result" } @@ -1883,12 +1909,7 @@ " [ 151., 10., 21., 0.5, 0.2, 0., 0.3],\n", " [ 152., 10., 22., 0.5, 0.3, 0., 0.2],\n", " [ 153., 10., 23., 0.5, 0.4, 0., 0.1],\n", - " [ 154., 10., 24., 0.2, 0.1, 0., 0.],\n", - " [ 155., 10., 25., 0.2, 0.2, 0., 0.],\n", - " [ 156., 10., 26., 0.2, 0.2, 0.1, 0.],\n", - " [ 157., 10., 27., 0.2, 0.25, 0.15, 0.],\n", - " [ 158., 10., 28., 0.2, 0.3, 0.2, 0.],\n", - " [ 159., 10., 29., 0.2, 0.3, 0.3, 0.]\n", + " [ 154., 10., 24., 0.2, 0.1, 0.7, 0.],\n", " ]]\n", "))\n", "norm = np.linalg.norm(answer)\n", @@ -1898,11 +1919,44 @@ }, { "cell_type": "code", - "execution_count": 43, + "execution_count": 52, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "(array([[-2.8096135, -4.3064127, 1.1209906, -2.8517733]], dtype=float32),\n", + " array([0.0188252 , 0.00421393, 0.95891285, 0.01804803], dtype=float32))" + ] + }, + "execution_count": 52, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "pd.DataFrame.from_dict(am_history.history).to_csv(f\"{HISTORY_DIR}/am_220512.csv\", index=False)" + "answer, softmax(answer[0])" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'HISTORY_DIR' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "\u001b[1;32m/Users/nowadmin/Documents/School Folder/CS 437/Lab/Final Project/tf_model.ipynb Cell 73'\u001b[0m in \u001b[0;36m<cell line: 1>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> <a href='vscode-notebook-cell:/Users/nowadmin/Documents/School%20Folder/CS%20437/Lab/Final%20Project/tf_model.ipynb#ch0000069?line=0'>1</a>\u001b[0m pd\u001b[39m.\u001b[39mDataFrame\u001b[39m.\u001b[39mfrom_dict(am_history\u001b[39m.\u001b[39mhistory)\u001b[39m.\u001b[39mto_csv(\u001b[39mf\u001b[39m\u001b[39m\"\u001b[39m\u001b[39m{\u001b[39;00mHISTORY_DIR\u001b[39m}\u001b[39;00m\u001b[39m/am_noisy_run_hist.csv\u001b[39m\u001b[39m\"\u001b[39m, index\u001b[39m=\u001b[39m\u001b[39mFalse\u001b[39;00m)\n", + "\u001b[0;31mNameError\u001b[0m: name 'HISTORY_DIR' is not defined" + ] + } + ], + "source": [ + "pd.DataFrame.from_dict(am_history.history).to_csv(f\"{HISTORY_DIR}/am_noisy_run_hist.csv\", index=False)" ] }, { @@ -1985,14 +2039,14 @@ }, { "cell_type": "code", - "execution_count": 35, + "execution_count": 136, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "2022-05-12 12:12:02.267722: W tensorflow/python/util/util.cc:368] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.\n", + "2022-05-12 18:50:44.183309: W tensorflow/python/util/util.cc:368] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.\n", "WARNING:absl:Found untraced functions such as attention_score_vec_layer_call_fn, attention_score_vec_layer_call_and_return_conditional_losses, last_hidden_state_layer_call_fn, last_hidden_state_layer_call_and_return_conditional_losses, attention_score_layer_call_fn while saving (showing 5 of 14). These functions will not be directly callable after loading.\n" ] }, @@ -2024,7 +2078,7 @@ }, { "cell_type": "code", - "execution_count": 34, + "execution_count": 43, "metadata": {}, "outputs": [], "source": [ @@ -2160,12 +2214,277 @@ " pass" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Model Conversion" + ] + }, + { + "cell_type": "code", + "execution_count": 139, + "metadata": {}, + "outputs": [], + "source": [ + "import tensorflow as tf" + ] + }, + { + "cell_type": "code", + "execution_count": 140, + "metadata": {}, + "outputs": [], + "source": [ + "model = tf.keras.models.load_model(f\"{MODEL_DIR}/attention\")" + ] + }, + { + "cell_type": "code", + "execution_count": 141, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Model: \"sequential_1\"\n", + "_________________________________________________________________\n", + " Layer (type) Output Shape Param # \n", + "=================================================================\n", + " custom_attention_1 (CustomA (None, 32) 497 \n", + " ttention) \n", + " \n", + " dense_1 (Dense) (None, 4) 132 \n", + " \n", + "=================================================================\n", + "Total params: 629\n", + "Trainable params: 629\n", + "Non-trainable params: 0\n", + "_________________________________________________________________\n" + ] + } + ], + "source": [ + "model.summary()" + ] + }, + { + "cell_type": "code", + "execution_count": 142, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING:absl:Found untraced functions such as attention_score_vec_layer_call_fn, attention_score_vec_layer_call_and_return_conditional_losses, last_hidden_state_layer_call_fn, last_hidden_state_layer_call_and_return_conditional_losses, attention_score_layer_call_fn while saving (showing 5 of 14). These functions will not be directly callable after loading.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "INFO:tensorflow:Assets written to: /var/folders/bm/yzlckp6x6vl9_bm329kms7680000gp/T/tmpvx4lpz4_/assets\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:tensorflow:Assets written to: /var/folders/bm/yzlckp6x6vl9_bm329kms7680000gp/T/tmpvx4lpz4_/assets\n", + "2022-05-12 20:51:22.624411: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:357] Ignored output_format.\n", + "2022-05-12 20:51:22.624442: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:360] Ignored drop_control_dependency.\n", + "WARNING:absl:Buffer deduplication procedure will be skipped when flatbuffer library is not properly loaded\n", + "2022-05-12 20:51:22.635394: I tensorflow/cc/saved_model/reader.cc:43] Reading SavedModel from: /var/folders/bm/yzlckp6x6vl9_bm329kms7680000gp/T/tmpvx4lpz4_\n", + "2022-05-12 20:51:22.637424: I tensorflow/cc/saved_model/reader.cc:78] Reading meta graph with tags { serve }\n", + "2022-05-12 20:51:22.637987: I tensorflow/cc/saved_model/reader.cc:119] Reading SavedModel debug info (if present) from: /var/folders/bm/yzlckp6x6vl9_bm329kms7680000gp/T/tmpvx4lpz4_\n", + "2022-05-12 20:51:22.648488: I tensorflow/cc/saved_model/loader.cc:228] Restoring SavedModel bundle.\n", + "2022-05-12 20:51:22.709625: I tensorflow/cc/saved_model/loader.cc:212] Running initialization op on SavedModel bundle at path: /var/folders/bm/yzlckp6x6vl9_bm329kms7680000gp/T/tmpvx4lpz4_\n", + "2022-05-12 20:51:22.730280: I tensorflow/cc/saved_model/loader.cc:301] SavedModel load for tags { serve }; Status: success: OK. Took 94895 microseconds.\n", + "2022-05-12 20:51:22.759351: I tensorflow/compiler/mlir/tensorflow/utils/dump_mlir_util.cc:237] disabling MLIR crash reproducer, set env var `MLIR_CRASH_REPRODUCER_DIRECTORY` to enable.\n" + ] + } + ], + "source": [ + "# Convert the model.\n", + "converter = tf.lite.TFLiteConverter.from_keras_model(model)\n", + "tflite_model = converter.convert()\n", + "\n", + "# Save the model.\n", + "with open(f'{MODEL_DIR}/attention_model.tflite', 'wb') as f:\n", + " f.write(tflite_model)" + ] + }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Scratch" ] + }, + { + "cell_type": "code", + "execution_count": 100, + "metadata": {}, + "outputs": [], + "source": [ + "from collections import deque\n", + "import datetime" + ] + }, + { + "cell_type": "code", + "execution_count": 96, + "metadata": {}, + "outputs": [], + "source": [ + "d = deque(maxlen=10)" + ] + }, + { + "cell_type": "code", + "execution_count": 97, + "metadata": {}, + "outputs": [], + "source": [ + "while len(d) < d.maxlen:\n", + " d.append(np.array([1,2,3, 4.0]))" + ] + }, + { + "cell_type": "code", + "execution_count": 87, + "metadata": {}, + "outputs": [], + "source": [ + "d.append(5)" + ] + }, + { + "cell_type": "code", + "execution_count": 98, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1., 2., 3., 4.],\n", + " [1., 2., 3., 4.],\n", + " [1., 2., 3., 4.],\n", + " [1., 2., 3., 4.],\n", + " [1., 2., 3., 4.],\n", + " [1., 2., 3., 4.],\n", + " [1., 2., 3., 4.],\n", + " [1., 2., 3., 4.],\n", + " [1., 2., 3., 4.],\n", + " [1., 2., 3., 4.]])" + ] + }, + "execution_count": 98, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.array(d)" + ] + }, + { + "cell_type": "code", + "execution_count": 115, + "metadata": {}, + "outputs": [], + "source": [ + "curr_time = datetime.datetime.utcnow()" + ] + }, + { + "cell_type": "code", + "execution_count": 118, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "23" + ] + }, + "execution_count": 118, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "curr_time.hour" + ] + }, + { + "cell_type": "code", + "execution_count": 135, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 135, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "datetime.datetime.now() < datetime.datetime.now() - datetime.timedelta(minutes=30)" + ] + }, + { + "cell_type": "code", + "execution_count": 121, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([120. , 15. , 2. , 0.25, 0.25, 0.25, 0.25])" + ] + }, + "execution_count": 121, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.concatenate([[120, 15, 2], np.array([0.25,0.25,0.25,0.25])]) -" + ] + }, + { + "cell_type": "code", + "execution_count": 138, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([0.40961474, 0.20340866, 0.1934883 , 0.1934883 ])" + ] + }, + "execution_count": 138, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "softmax(np.array([0.25,0.25,0.25,0.25]) - np.array([0.25,0.95,1.0,1.0]))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { -- GitLab